Explore MIT App Inventor - Advanced http://dev-explore.appinventor.mit.edu/tutorial-difficulty/advanced en Pizza Party with Fusion Tables for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/pizzaparty <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><div style="float:right;"><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/pizzaParty/pizza_party_screenshot.png" style="border:none; padding-left:15;" /><br /><a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/PizzaParty_MIT.aia"><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/pizzaParty/downloadSourcebutton.png" style="border:none; padding-left:65;" /></a></div> <p>In this tutorial, you will create an app that lets people enter food orders for a pizza party. Orders are stored in a Fusion Table, providing one easy to access place for the data. By reading from the table, the app can easily display the orders that have been entered.</p> <p>A <a href="http://en.wikipedia.org/wiki/Google_Fusion_Tables">Fusion Table</a> is a Google service to support the gathering, managing, sharing, and visualizing of data. Data are stored in multiple tables on Google's <a href="http://en.wikipedia.org/wiki/Cloud_computing">cloud</a>. Individual tables can be merged (or fused) if they contain a common column, and they can be easily visualized on maps and in various kinds of charts and graphs. All of the data are stored in a public table that can be accessed via Google Drive, and allows different users<a href="#note">**</a> to add information to the tables. Coupled with a location sensor, an App Inventor app could post periodic updates of each user's location to a public fusion table. Users could post notes to mark noteworthy locations. For example, a team of botanists could use a Fusion Table app to create an annotated catalog of the trees or plants within a certain geographical area.</p> <p>This tutorial introduces:</p> <ul><li>Using the <b>FusionTables</b> component</li> <li>Using a <b>WebViewer</b> component</li> </ul><p>This tutorial assumes you are familiar with the basics of App Inventor-- using the Component Designer to build a user interface, and using the Blocks Editor to specify the app's behavior. If you are not familiar with the basics, try stepping through some of the <a href="/ai2/tutorials">basic tutorials</a> before continuing.</p> <hr /><p><strong>IF YOU DOWNLOAD THE SOURCE CODE</strong> you will need to supply your own API KEY, your own Table ID, and your own TABLE URL in the global variables in the blocks editor. This source code will not work without these additions.</p> <h4 class="ai-header">Creating your own Fusion Table</h4> <p>Creating your own Fusion Tables is as easy as creating a Google document, if you are familiar with that process.</p> <p><img src="/sites/all/files/tutorials/pizzaParty/MoreEvenMoreFusion.jpg" style="float:right" /></p> <ol><li>On the web, login to your Gmail account or any other Google service (e.g., Drive, YouTube).</li> <li>Select the <strong>More &gt; Even more</strong> menu and scroll to the bottom of the page of Google services where you will find the Fusion Tables service under "Innovation", click on the Fusion Tables link.</li> <li>Click "Create New Table"</li> <li>You will be given three options for the new table: "From this computer", "Google Spreadsheets", or "Create an empty table". For the purposes of this tutorial, select <b>Create an empty table</b>.</li> <li>You will see that the new table automatically comes with four columns. Change the column names for your Pizza app by going to <strong>Edit &gt; Change Columns</strong>.You'll rename the four default columns to <em>Date</em> (type=Date), <em>Name</em> (type=Text), <em>Pizza</em> (type=Text), <em>Drink</em> (type=Text). Click save and then add a fifth column by going to the <strong>Edit &gt; Add Column</strong>. Name this fifth column <em>Comment</em> (type=Text). .</li> <li>Leave this window open so that you can come back and get the URL, which you'll need when you set up the properties of the WebViewer component in your app.</li> <li>Click on the <strong>Share</strong> button (top right) to modify the table's permissions. For this tutorial, you can specify a few friends who will use the app. Only people who are explicitly given permission will be able to enter pizza party preferences through your app.</li> </ol><pre class="ai-box"><img src="/sites/all/files/tutorials/pizzaParty/FusionTables_GoogleDrive.png" style="float:right;padding:15px;" />Another way to create a new table: go to Google Drive. Click the <strong>Create</strong> button, then go to <strong>More &gt; Fusion Table</strong>. The picture at right shows what the Create button's menu should look like. If you do not see Fusion Table in your menu, then you may need to contact your school's network administrator. (See Troubleshooting section at the bottom of this page.) </pre><p><strong><a name="note" id="note">NOTE</a> about Sharing Fusion Tables:</strong> To share a FusionTable with others, you have to share it with each person individually, or you can share with a Google Group (see footnote at the end of this tutorial), the same way you would share a private google doc. There is no way to share write privileges to a FusionTable with the public. Public access is restricted to read-only.</p> <h4 class="ai-header">Getting an API Key</h4> <p>In order to use the FusiontablesControl Component you need to acquire a Google Applications Programming Interface (API) key, an API Key. To get an API key, follow these instructions:</p> <ol><li>Go to your <a href="https://code.google.com/apis/console/">Google APIs Console</a> and login if necessary.</li> <li>Select the <strong>Services</strong> item from the menu on the upper left.</li> <li>In the list of services, find the <strong>Fusion Tables API</strong> service and click the toggle button that currently says "off".</li> <li>Read and agree to the terms of service. When you return to the APIs Console page you'll see that the on/off switch next to Fusion Tables API is now "On" and green.</li> <li>Go back up the menu on the upper left of the screen and select the <strong>API Access</strong> item.</li> <li>Your API Key will be in the rectangular box in the section called "Simple API Access". You will need set the "API Key" property of the Fusiontables Control component in any app that you make that uses Fusion Tables. (More info below.)</li> </ol><h4 class="ai-header">Building the App</h4> <p>Connect to the App Inventor web site and start a new project. Name the new project PizzaParty, set the screen's orientation to Portrait and uncheck the Screen's scrollable property. You may also wish to set the Screen's Title property to something other than 'Screen 1'.</p> <h4 class="ai-header">The User Interface</h4> <p>In addition to the FusiontablesControl component, the Pizza Party app makes use of several other types of components. It is assumed that you have learned how to use these in previous lessons. Use the component designer to create the interface for the Search Party. When completed, the designer should look like this:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/designer.png" /></p> <p>The components are: </p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> <td> Settings of Component </td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">LabelName</td> <td>Shows the text "Your Name:"</td> <td></td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">TextBoxUserName</td> <td>Gets input from user</td> <td>Set the width property to Fill Parent</td> </tr><tr><td> <b>HorizontalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">HorizontalArrangement1</td> <td>Contains Name Label and Textbox</td> <td></td> </tr><tr><td> <b>ListPicker</b> </td> <td>Basic</td> <td style="color:green;">ListPickerPizza</td> <td>Accesses the list of available pizza types</td> <td> <p>Set the Width property to Fill Parent</p> <p>Set the Text property to "What type of pizza?"</p> <p>Set the ElementsFromString to "Cheese, Pepperoni, Anchovies, Hawaiian"</p> </td> </tr><tr><td> <b>ListPicker</b> </td> <td>Basic</td> <td style="color:green;">ListPickerDrink</td> <td>Accesses the list of available drinks.</td> <td> <p>Set the Width property to Fill Parent</p> <p>Set the Text property to "What type of drink?"</p> <p>Set the ElementsFromString to "Coke, Diet Coke, Sprite, Ginger Ale"</p> </td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">LabelComment</td> <td>Shows the text "Comments:"</td> <td></td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">TextBoxComments</td> <td>Takes user input</td> <td>Set the width property to Fill Parent</td> </tr><tr><td> <b>HorizontalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">HorizontalArrangement2</td> <td>Contains Comments Label and Textbox</td> <td></td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ButtonSubmit</td> <td>Adds new data to the public fusion table</td> <td> <p>Set the Text to "Submit"</p> <p>Set the width property to Fill Parent</p> </td> </tr><tr><td> <b>WebViewer</b> </td> <td>Not ready for prime time</td> <td style="color:green;">WebViewer1</td> <td>Displays Fusion Table</td> <td>Set width and height properties to Fill Parent</td> </tr><tr><td> <b>FusiontablesControl</b> </td> <td>Not ready for prime time</td> <td style="color:green;">FusiontablesControl1</td> <td>Manages interactions with the app's Fusion Table</td> <td></td> </tr><tr><td> <b>Clock</b> </td> <td>Basic</td> <td style="color:green;">Clock1</td> <td>Used to provide a timestamp each time an order is placed.</td> <td></td> </tr><tr><td> <b>Notifier</b> </td> <td>Other stuff</td> <td style="color:green;">Notifier1</td> <td>Notifies the user of any errors</td> <td></td> </tr></table><h4 class="ai-header">Determining your Fusion Table URL and Table ID</h4> <p>In the blocks editor, you will set the WebViewer component's HomeURL property to point to the URL of your table. To find your Fusion Table's URL:</p> <ol><li>In your browser, navigate to the new Fusion Table you just created.</li> <li>Go to the menu and select <b>Tools &gt; Publish</b>.</li> <li>You'll see a notice saying: "This table is private and will not be visible". Click the blue link that says "Change Visibility".</li> <li>In the list of "Who Has Access", click the blue "Change..." link next to "Private - Only people listed below..."</li> <li>Choose"Public on the Web" or "Anyone with the link". Either of these settings will work for this tutorial. In the future, you should decide this setting based on the sensitivity of your data.</li> <li>Click the green Save button, then the blue Done button.</li> <li>Back on the Fusion Table page, go to the menu bar and select <strong>Tools &gt; Publish</strong>. Select the URL from the top text box (labeled "Send in an email or IM"), copy the URL and return to App Inventor. You will paste the URL into the definition block for the TABLE_URL (see below).</li> <li>The Table ID of the fusion table is contained within the URL after the plus sign. Look for "from+" and then copy all of the characters after the plus. This is the Table's ID. You can also find the Table ID by browsing to your table, then selecting <b>File&gt;About this table</b> in the menu.</li> </ol><h4 class="ai-header">Blocks Editor</h4> <p>Open the Blocks Editor so you can program the app's behavior. First, you will describe the app's variables. Variables whose names are ALL_CAPS are constants -- that is, variables whose values do not change while the program is running. It is good to get into the habit of using this naming convention. Define the following variables and give them the initial values shown in the table.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Variable Name </td> <td> Initial Value </td> <td> Purpose </td> </tr><tr><td> <b>TABLE_URL</b> </td> <td>text</td> <td>Initialize this global variable to the "published" URL of your fusion table. See instructions above.</td> </tr><tr><td> <b>TABLE_ID</b> </td> <td>text</td> <td>Initialize this global variable to your table ID (e.g. a long string of characters unique to your fusion table). See instructions above.<font></font></td> </tr><tr></tr><tr><td> <b>API_KEY</b> </td> <td>text</td> <td>Initialize this global variable to your own API Key for Google Fusion Tables. See instructions above.</td> </tr><tr><td> <b>UserName</b> </td> <td>text</td> <td>Records the name of the user.</td> </tr><tr><td> <b>pizza</b> </td> <td>text</td> <td>Stores the pizza choice input by the user.</td> </tr><tr><td> <b>drink</b> </td> <td>text</td> <td>Stores the drink choice input by the user.</td> </tr><tr><td> <b>comment</b> </td> <td>text</td> <td>Stores the comment input by the user.</td> </tr></table><p><b>Initializing the App</b></p> <p>It is important to perform some initialization steps whenever the app is started. These are done in the <span class="eventblock">Screen1.Initialize</span> block. For this app we need to set the initial values for the FusionTable component's API Key property (set to global API_KEY) and the WebViewer component's HomeURL property (set to global TABLE_URL). We also tell the app to forget the user's login credentials. This will prompt the user to login to their Google account and give permission to the app to access the Fusion Table. This authentication step will happen only once when the app first tries to access the Fusion Table. Remember, Fusion Tables are only writeable by users who have been given permission by the table's owner. You specify this in the Sharing settings for the Fusion Table (easy to do from the Google Drive webpage.)</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/initialblocks.png" /></p> <p>Set up the <span class="callblock-ai2">resetForm</span> procedure as shown below. After recording an entry, this procedure resets the interface back to the original state.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/resetForm.png" /></p> <p><b>List Picker Blocks</b></p> <p>In the designer, you set the choices for the pizza and drink types by filling in the "Selection" property with comma separated lists. These pre-programmed choices will be displayed on the user interface so the user can select their food and drink. Their selections are stored in the pizza and drink variables.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/listpicker.png" /></p> <p><b>Submitting Data</b><br /></p><p></p> <p>Once the user has entered their name, food choices, and comments, they will click the <b>Submit</b> button. The app tests to make sure that the name, pizza, and drink fields have values in them, and prompts the user to try again if any of the required answers are missing. Notice that the <span class="textblock-ai2">text =</span> block is used (find it under Built-in palette, Text drawer). This block compares two strings of text to see if they are equal. If all required information is present, it calls the procedure <span class="callblock-ai2">InsertDataInTable</span> (see below). The blocks for the <span class="eventblock">ButtonSubmit.Click</span> are shown here:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/submit.png" /></p> <p><b>Inserting Data into the Fusion Table</b></p> <p>The FusiontablesControl component is used to send the data to the Fusion Table. This action will create a new row in the Fusion Table, setting the values of the various columns involved. App Inventor makes this easy to do, but you have to be careful that the insert query is formatted correctly.</p> <p>This procedure involves two steps: (1) constructing the insert query and then (2) sending the query to Google's Fusion Table service. The query we want to send will take this format:</p> <p>INSERT INTO<br /><tableid> (<column1>, <column2>, ...) VALUES (<value1>, <value2>, ...)</value2></value1></column2></column1></tableid></p> <p>The words in CAPS are part of the query's syntax. The words in parentheses are values that we need to plug in. First there is a list of (column names) followed by VALUES followed by a list of (value names). The order of the column names and value names must be in the same order so that they match up. An example of what this might look like is shown below. Notice that the values must be enclosed in single quotes:</p> <p>INSERT INTO 191GHtZ_B2 (Name, Date) VALUES ('Sam', '10/10/2012')</p> <p>First, setup a new <span class="callblock-ai2">Procedure With Result</span> that takes a string and returns it surrounded by single quotes. The procedure <span class="callblock-ai2">quotify</span> is used in the InsertDataInTable procedure to place quotes around all of the values in the query. It also takes care of "escaping" any single quotes or apostrophes that are input by the user. You can send single apostrophes as part of a value in the query, so the "replace all" block adds an extra single quote. Two single quotes in a row are interpreted as one single quote.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/quotify.png" /></p> <p>To construct the query we use App Inventor's join text block. Be sure to put spaces where needed, such as before and after the words INSERT INTO and VALUES:</p> <p><img src="/sites/all/files/ai2tutorials/pizzaParty/insertTable.png" /></p> <p>For this app, the column names must match the column names of the table we created earlier (with columns Date, Name, Pizza, Drink, Comment). Their respective values are taken from the procedure's global variables. Note: If you did not use these exact words for your table's columns, then be sure to use your table's column names when you build your query.</p> <p>Don't forget the <span class="callblock-ai2">FusiontablesControl.SendQuery</span> command at the very end of this procedure. It's small in size compared to rest of the procedure, but very important.</p> <p><b>Handling the Response from the Fusion Tables Service</b></p> <p>The <span class="eventblock">FusiontablesControl.GotResult</span> event will be fired when the app receives a response from Google's Fusion Tables Service. For an insert query the service will return the rowID of the new row that was inserted or an error message if something went wrong. In this simple example, we use the "contains" block ( (find it under Built-in palette, Text drawer) to check whether the result string has the rowID in it. If so, then we know that the rowID was received, and we then invoke the <span class="callblock-ai2">WebViewer.GoHome</span> procedure, which reloads the "HomeURL" as specified in the WebViewer's properties. Note that this set of blocks also calls the <span class="callblock-ai2">resetForm</span> procedure. After recording an entry, it resets the interface back to the original state.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/gotresult.png" /></p> <p><b>You're done!</b> Package the app by going to <b>Package for Phone</b> on the Designer. You can now test the App for the purposes of the pizza party. Once you understand this tutorial, you'll be ready to make new Fusion Tables and modify the app to collect different types data from users. Remember, you have to give each user permission to access the Fusion Table. You do this through the Google Fusion Tables interface, not through App Inventor. Luckily, this means you don't have to change the app in order to add more users who can access the table.</p> <h4 class="ai-header">Challenges</h4> <p>This app has the Fusion Table hard-coded into the blocks. Find a way to let users specify their own fusion table ID so that they can host their own Pizza Party.</p> <h4 class="ai-header">Variations</h4> <p>Now that you have a simple app that uses fusion tables and a webviewer working, you might want to build some other apps with Fusion Tables. For example:</p> <ul><li>Include a <b>LocationSensor</b> so that the user's location can be added to the Fusion Table to create a map with notes</li> <li>Make the WebViewer display something other than the table of stored values; perhaps a map or a chart</li> </ul><h4 class="ai-header">Troubleshooting</h4> <p>If you are using a Google Apps for Education account, and you are not able to create a new fusion table (in the "Create" menu of Google Drive you won't even see an option for Fusion Tables), you will need to ask your system administrator to turn this option on for you. Or, you can switch to a standard gmail account. Fusion Tables are not automatically turned on for Google Apps for Education Accounts, your system administrator must make Fusion Tables available to the accounts in your domain.</p> <p>If you are receiving errors when trying to submit to the Fusion Table, especially if the error mentions Authentication, be sure that you have put the correct API Key into the API Key property field on the FusionTables component in the Design Window.</p> <p>To familiarize yourself with fusion tables, have a look around the <a href="http://support.google.com/fusiontables/bin/answer.py?hl=en&amp;answer=2571232">Fusion Tables Web Site</a>. Check out the example gallery to see what kinds of things are possible. Work through this <a href="http://earth.google.com/outreach/tutorial_fusion_sample.html">Fusion Table tutorial</a>, which shows how import some data, create a Fusion Table, and view the data on a map with your browser. You'll need to log in with your Google account.</p> <p><strong>To share a FusionTable with many people</strong>, rather than by entering email addresses individually, you can <strong>create a dedicated Google Group for your app and let all the app users know how to join the group</strong> (maybe through the web page for your app). From the moment you create your app, you share the Fusion Table once with your Google Group (using its email address), and <strong>make sure to give to the group editing rights</strong>. Every user who joins the group will inherit the editing rights automatically.</p> <pre class="ai-box"><span style="color:black;">Done with PizzaParty?</span> <a href="http://explore.appinventor.mit.edu/tutorials">Return to the other tutorials</a>.</pre><h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/pizzaParty/PizzaParty_MIT.aia">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>. Remember to add in your API KEY and Fusion Table information in the Designer and blocks.</p> </div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-2" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 2</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/data-storage" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Data Storage</a> </li> </ul> </section> Thu, 08 Aug 2013 15:19:00 +0000 joanie 381 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/pizzaparty#comments Mini Golf: Fling, TouchUp, TouchDown Gestures for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/minigolf <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><p>This Mini Golf App demonstrates how to use the Fling, TouchUp, and TouchDown gestures for Sprites<br />Note that these event handlers are also available for the Canvas.</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/minigolfscreen.png" style="float: right;border:none" width="250" /></p> <p>To play this mini golf app, the player first positions his/her ball within the confines of the tee, and then flings the ball toward the hole. The ball will bounce off of the rectangular obstacle and the sides of the course. For each fling of the ball, the stroke count goes up by one. The total score is the number of strokes it takes to complete the entire course. </p> <p>This tutorial covers:</p> <ul><li>Using the <b>Sprite</b> component and the TouchUp, TouchDown, and Flung events</li> <li>Using a <b>Clock</b> component</li> <li>Dynamic Positioning of sprites on a canvas, based on the size of the screen</li> <li>Sprite Collisions</li> </ul><p>This tutorial assumes you are familiar with the basics of App Inventor-- using the Component Designer to build a user interface, and using the Blocks Editor to specify the app's behavior. If you are not familiar with the basics, try stepping through some of the <a href="http://appinventor.mit.edu/explore/ai2/tutorials.html">basic tutorials</a> before continuing.</p> <p><a href="/sites/all/files/ai2tutorials/miniGolf/MiniGolf_MIT.aia"><img src="/sites/all/files/tutorials/miniGolf/downloadSourcebutton.png" style="float: right; border:none" width="250" /></a><br /><br /><br /><br /></p> <hr /><h3>Part I: Start a new app and make a ball that responds to fling events</h3> <p>We'll build this app in stages, adding a little bit of the game at a time. Log into App Inventor and start a new project. Name it "MiniGolf". When the Design window opens notice that App Inventor automatically names the screen "Screen1", but you can set the Title of the screen, which will show up in the top bar of the app. Think of a title related to Mini Golf, or feel free to use the suggested title "Fling It Mini Golf", and type it into the Properties pane on the right side of the Designer.</p> <p>In the Screen Properties (shown in right-hand pane): Uncheck the checkbox labeled "Scrollable" so that the screen will not scroll when the app is running. Screens that are set to scroll do not have a height. We’ll need our screen to have a defined height in order to set up the golf course properly.</p> <p><strong>Add the following components in the Designer:</strong></p> <table cellpadding="0" cellspacing="0"><tbody><tr style="background-color: #EFEFEF; font-weight: bold;"><td> <p><strong>Component Type</strong></p> </td> <td> <p><strong>Palette Group</strong></p> </td> <td> <p><strong>What You'll Name It</strong></p> </td> <td> <p><strong>Purpose</strong></p> </td> <td> <p><strong>Properties</strong></p> </td> </tr><tr><td> <p>Canvas</p> </td> <td> <p>Basic</p> </td> <td> <p>Canvas1</p> </td> <td> <p>The canvas serves as the golf course</p> </td> <td> <p>Height: 300<br />Width: FillParent<br />BackgroundColor: Green (or whatever you like!)</p> </td> </tr><tr><td> <p>BallSprite</p> </td> <td> <p>Animation</p> </td> <td> <p>GolfBall</p> </td> <td> <p>This is the ball the player will fling to try to hit the Hole</p> </td> <td> <p>Radius = 10<br />Color: White (or your choice!)<br />Speed: 0<br />Interval: 1 (ms)</p> <p>Z = 2 (when sprites are overlapping, the one with the higher z will appear on top)</p> </td> </tr><tr><td> <p>BallSprite</p> </td> <td> <p>Animation</p> </td> <td> <p>Hole</p> </td> <td> <p>This will be the target for the GolfBall</p> </td> <td> <p>Radius = 15<br />Color: Black<br />Speed: 0</p> </td> </tr><tr><td> <p>Clock</p> </td> <td> <p>Basic</p> </td> <td> <p>Clock1</p> </td> <td> <p>The clock will fire continuously to control the movement of the ball</p> </td> <td> <p>Timer Always Fires</p> <p>Timer Enabled</p> <p>TimerInterval: 100</p> </td> </tr></tbody></table><p><strong>Open the Blocks Editor</strong></p> <p><strong>Program the behavior of the Ball:</strong></p> <p>First, use the <span class="eventblock">GolfBall.Flung</span> event handler to move the golf ball when it is flung. Notice how this event handler takes in 6 different arguments: </p> <ul><li><em>x</em>, the x position on the Canvas grid of the user's finger </li> <li><em>y</em>, the y position on the Canvas grid of the user's finger</li> <li><em>speed</em>, the speed of the user's flinging gesture</li> <li><em>heading</em>, the direction (in degrees) of the user's fling gesture</li> <li><em>xvel</em>, the speed in the x direction of the user's fling</li> <li><em>yvel</em>, the speed in the y direction of the user's fling</li> </ul><p>Essentially, you want to set the GolfBall sprite’s speed and heading to match the speed and heading of the player’s fling gesture. You may want to scale up the speed a little bit because the speed of the fling is a little slower than how a golf ball would move. You can play with this "scaling factor" to make the ball more or less responsive to a fling.</p> <p> <img src="/sites/all/files/ai2tutorials/miniGolf/golfBall.flung.png" /></p> <p><strong>Program the behavior of the clock:</strong></p> <p> Use timer event to slow ball down so it doesn’t bounce around forever.</p> <p>Each time the clock fires, it will reduce the speed of the ball slightly. Notice that if the ball is not moving then these blocks will do nothing. If you don’t have this then the ball will just bounce forever.</p> <p>You'll need to use the if mutator function to change the if block into an if-else block. For a summary of mutators, check out the <a href="http://appinventor.mit.edu/explore/ai2/support/concepts/mutators">Mutators page</a></p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/clock1.timer.png" /></p> <p><strong>Program a new procedure called SetupNewHole:</strong></p> <p>This procedure will be called when a hole is scored and the ball has to be placed back at the starting point. Note that the <span class="callblock">Hole.MoveTo</span> block sets the hole up in a new random location for the next play.</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/setupNewHole.png" /></p> <p><strong>Program the Behavior of the Hole: </strong><span>When the ball collides with the hole, the ball disappears and resets at the bottom of the screen.</span></p> <p>Note: When you first drag out the <span class="eventblock">GolfBall.CollidedWith</span> event handler, the named parameter is called "other". Notice that the <span class="controlblock-ai2">if then</span> block tests to see if the object involved in the collision with the golf ball (<span class="variableblock">other</span>) is the black ball sprite representing the hole. You can't just put a text block with the word "Hole" in it, you must use the <span class="componentsetblock">component Hole</span><span> block, that can be found in the drawer for the Hole image sprite. Do not use a <span class="textblock-ai2">text block</span> here.</span></p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/golfball.collidedwith.png" /></p> <pre class="ai-testing"><strong>Test this Behavior.</strong> Connect your device to AppInventor, or start the emulator to load your app. When you fling the ball it should move in the direction of your fling, with a speed similar to the strength of your fling. The ball should slow down as it moves, eventually stopping. When the ball hits the hole, the ball should reset at the bottom of the screen and the hole should move to a new random location.</pre><p> </p> <p><strong>Does your ball get stuck if it hits the edge? </strong></p> <p>This is easy to fix with the when <span class="eventblock">EdgeReached</span> event. Note that you can find the "edge" value block by using a <span class="variableblock">get</span> block and selecting "edge" from the dropdown.</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/golfBall.edgeReached.png" /></p> <p>Double check to make sure your code is right: fling the ball a few times and see that that ball now bounces off the edges of the course.</p> <h3>Part II: Keeping Score</h3> <p>Games are more fun if you have a way to see how you’re doing. Let’s add a stroke counter. In mini golf your score goes up as you take more strokes. The goal is to have the lowest score possible. Let’s show the player how many strokes she or he has taken on this hole. Let’s also show the number of strokes taken during the whole game.</p> <p> </p> <p>Go back to the Designer and set up the following components:</p> <p><a href="#" name="84f417a34cd2d904669a10a8f96b32bf41ae274b" id="84f417a34cd2d904669a10a8f96b32bf41ae274b"></a><a href="#" name="2" id="2"></a><br /></p><table cellpadding="0" cellspacing="0"><tbody><tr style="background-color: #EFEFEF; font-weight: bold;"><td> <p><strong>Component Type</strong></p> </td> <td> <p><strong>Palette Group</strong></p> </td> <td> <p><strong>What You’ll Name It</strong></p> </td> <td> <p><strong>Purpose</strong></p> </td> <td> <p><strong>Properties</strong></p> </td> </tr><tr><td> <p>Horizontal Arrangement</p> </td> <td> <p>Screen Arrangement</p> </td> <td> <p>HorizontalArrangement1</p> </td> <td> <p>Contains LabelScore and LabelStroke</p> </td> <td> <p>Place at top of screen</p> </td> </tr><tr><td> <p>Label1</p> </td> <td> <p>Basic</p> </td> <td> <p>LabelScore</p> </td> <td> <p>Displays the total stroke count for the entire game</p> </td> <td></td> </tr><tr><td> <p>Label2</p> </td> <td> <p>Basic</p> </td> <td> <p>LabelStroke</p> </td> <td> <p>Displays the stroke count for the hole the player is currently on</p> </td> <td></td> </tr></tbody></table><p>In the Blocks Editor, you can program updates to the Score and Stroke labels. First, set two new global variables called <span class="variableblock">StrokeCount</span> and <span class="variableblock">Score</span>, and set their initial values to 0.</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/scoreto0.png" /></p> <p>Then add the following blocks to the <span class="eventblock">GolfBall.Flung</span> event (red rectangle indicates new blocks):</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/golfball.flung_final.png" /></p> <p>Next add the following blocks to the Event that handles the ball hitting the hole:</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/golfball_collidewith.png" /></p> <pre class="ai-testing"><strong>Test the behavior.</strong> With these new changes, you should have a "Total Strokes" count and "This Hole" count at the top of the screen. When you fling the ball, the "This Hole" count  and "Total Strokes" count should both increase by one, and when you make the ball go into the hole the "This Hole" count should reset to 0.</pre><h3>Part III: Positioning Ball on Tee using TouchUp and TouchDown events</h3> <p>Ok, so now you’ve got a working game! Now let’s make it a little more interesting and fun. First we’ll add a Tee and let the player position the golf ball on the tee before they fling the ball.</p> <p><strong>Go back to the Designer and add three new image sprite components:</strong></p> <p><a href="#" name="f32e9ebd8bb0c367ac6b009ebba0af05e4eb1b4e" id="f32e9ebd8bb0c367ac6b009ebba0af05e4eb1b4e"></a><a href="#" name="1" id="1"></a><br /></p><table cellpadding="0" cellspacing="0"><tbody><tr style="background-color: #EFEFEF; font-weight: bold;"><td> <p><strong>Component Type</strong></p> </td> <td> <p><strong>Palette Group</strong></p> </td> <td> <p><strong>What You’ll Name It</strong></p> </td> <td> <p><strong>Purpose</strong></p> </td> <td> <p><strong>Properties</strong></p> </td> </tr><tr><td> <p>ImageSprite</p> </td> <td> <p>Animation</p> </td> <td> <p>Tee</p> </td> <td> <p>A rectangular area in which the player can position their ball before teeing off.</p> </td> <td> <p>Upload the Tee image (<a href="/sites/all/files/tutorials/miniGolf/tee_graphic.png">right click on this link</a>, or see below).</p> </td> </tr><tr><td> <p>ImageSprite</p> </td> <td> <p>Animation</p> </td> <td> <p>LeftSprite</p> </td> <td> <p>This is a left pointing arrow that the player will use to move the ball to the left on the tee</p> </td> <td> <p>Upload the left arrow graphic (<a href="/sites/all/files/tutorials/miniGolf/left_arrow.jpg">right click on this link</a></p> </td> </tr><tr><td> <p>ImageSprite</p> </td> <td> <p>Animation</p> </td> <td> <p>RightSprite</p> </td> <td> <p>This is a right pointing arrow that the player will use to move the ball to the left on the tee</p> </td> <td> <p>Upload the right arrow graphic (<a href="/sites/all/files/tutorials/miniGolf/right_arrow.jpg">right click on this link</a></p> </td> </tr></tbody></table><p><strong>Program the size of the canvas, and the placement of the ball and image sprites on the canvas:</strong></p> <p>First, program the setup of these components on the screen. It’s best to accommodate all different screen sizes by placing the sprites on the screen relative to the size of the screen. The blocks below show how to set up the screen <em>dynamically</em><span> so that everything fits the right way. We start off by making the canvas size based on the screen size, and then we place each sprite in relation to the width and height of the canvas. We'll make a procedure to do this for us. Try to understand all of these blocks before you move on.</span></p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/preparescreen.png" /></p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/golf_screen_init.png" /></p> <p><strong>Position the Golf Ball on the Tee using TouchUp and TouchDown on the Arrow sprites:</strong></p> <p>To handle this, first set up two global variables that are toggled each time an arrow is pressed.</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/global.png" /></p> <p><strong>Program the behavior of the Right and Left Arrows</strong></p> <p>The left and right arrows are image sprites, so they come equipped with the ability to know when the player is is holding his/her finger down on them. The following blocks toggle the global variables based on whether the user is pressing either of these arrows.</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/spriteTouchDown.png" /></p> <p><strong>Procedure MoveBallOnTee:</strong></p> <p>Make a new procedure <span class="callblock-ai2">MoveBallOnTee</span> that makes the golf ball move left or right on the tee depending on the global variables. Although the math here looks complicated, it’s pretty simple. If the ball is supposed to move left, you first check to make sure that moving the ball 2 pixels left will not exceed the left-most coordinate of the Tee. If moving the golf ball to the right, you first check that moving the ball right 2 pixels will not move it past the right-most coordinate of the Tee.</p> <p><em>Note: if blocks look different in this image than on your own screen, this is because they were aligned differently. If you right click on the blocks, a list of options will appear and one of them is external inputs. When you select this, it will change how the blocks are configured. It does not change how the blocks function. If you want to change this, right click again and select internal inputs.</em></p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/moveBallOnTee.png" /></p> <p><strong>MoveBallOnCourse Procedure</strong></p> <p>Note that the blocks that we had inside the <span class="basicblock">Clock1.Timer</span> event are now moved over to a new procedure called <span class="callblock-ai2"> MoveBallOnCourse: </span></p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/moveBallOnCourse.png" /></p> <p>On each new course, players can position the ball on the tee before attempting to fling the ball toward the hole. To program this, you first have to check to make sure this is a new course and the ball has not been flung yet. If <span class="variableblock">StrokeCount</span> = 0 then we know this course is brand new and the player has not yet attempted to get the ball into the hole.</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/timer_final.png" /></p> <p>As the blocks above show, after verifying that the StrokeCount is 0, you then want to proceed to move the golf ball left or right depending on which arrow is being pressed. </p> <pre class="ai-testing"><strong>Test the behavior.</strong> Make sure your app is doing what you expect: play the game on your device or emulator. Before you tee off, are you able to move the ball left and right on the tee by using the left and right arrows? After you tee off, you should no longer be able to use the left and right arrows (pressing them will do nothing). After the ball goes into the hole and the screen resets, you should then be able to move the ball left and right on the tee before teeing off again.</pre><p><strong>Keep track of the number of holes played, and allow a game reset</strong></p> <p>The game is working pretty well now, but what about giving the player a way to reset the game? Also, it would be nice to give the player some instructions so they know how to play the game. While we’re at it, let’s also give an indication of how many holes the player has completed. Add the following components in the Designer:</p> <p><a href="#" name="0899df2ccc45cb7f22bfe41d004593ed854f9f2c" id="0899df2ccc45cb7f22bfe41d004593ed854f9f2c"></a><a href="#" name="3" id="3"></a><br /></p><table cellpadding="0" cellspacing="0"><tbody><tr style="background-color: #EFEFEF; font-weight: bold;"><td> <p><strong>Component Type</strong></p> </td> <td> <p><strong>Palette Group</strong></p> </td> <td> <p><strong>What You’ll Name It</strong></p> </td> <td> <p><strong>Purpose</strong></p> </td> <td> <p><strong>Properties</strong></p> </td> </tr><tr><td> <p>Horizontal Arrangement2</p> </td> <td> <p>Screen Arrangement</p> </td> <td> <p>Horizontal Arrangement2</p> </td> <td> <p>Contains the NewGame button and the HoleNum label</p> </td> <td></td> </tr><tr><td> <p>Button</p> </td> <td> <p>Basic</p> </td> <td> <p>ButtonNewGame</p> </td> <td> <p>Resets the game to Hole #1 with a score of 0.</p> </td> <td> <p>Text: "New Game"</p> </td> </tr><tr><td> <p>Label3</p> </td> <td> <p>Basic</p> </td> <td> <p>LabelHoleNum</p> </td> <td> <p>Displays the current hole number, increments by one each time a hole is completed.</p> </td> <td> <p>Text = "Hole # 1"<br />Font: bold, 28, blue<br /></p> </td> </tr><tr><td> <p>Label4</p> </td> <td> <p>Basic</p> </td> <td> <p>LabelInstruct</p> </td> <td> <p>Displays instructions</p> </td> <td> <p>Text = "Use arrows to position ball on tee. Hit the ball by flinging it with your finger."</p> </td> </tr></tbody></table><p>Define a new global variable to keep track of the Hole Number:</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/holecount.png" /></p> <p>Add the following blocks to the <span class="callblock-ai2">SetupNewHole</span> procedure: set <span class="setblock">global HoleCount</span> and set <span class="setblock">LabelHoleNum.Text</span>...</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/setup_final.png" /></p> <p>Program the "New Game" button’s behavior, which is pretty simple. When the button is pressed, set up a new course and reset both the hole stroke counter and total stroke counter to zero. Also set the hole number back to 1, by displaying "Hole #1" in LabelHoleNum. The blocks look like this:</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/buttonNewGame.png" /></p> <pre class="ai-testing"><strong>Test the behavior.</strong><p> Go back to your device or emulator and play the game some more. Now you should see the Hole # displayed in the lower right. Hitting "New Game" button should reset the game, returning both scores to 0, resetting the screen, and setting the Hole number to #1.</p></pre><h3>Part IV: Introduce an Obstacle</h3> <p>Most mini golf courses have obstacles on them. Let’s add a simple rectangular obstacle that will randomly position itself on the course somewhere between the Tee and the Hole. Each time a new course is presented, the obstacle will move, just the same way the Hole moves each time a new course is set up.</p> <p><strong>Add the following component in the Designer:</strong></p> <p><a href="#" name="981d9864ae92d2e44bbc01311278b4463bf01a1e" id="981d9864ae92d2e44bbc01311278b4463bf01a1e"></a><a href="#" name="4" id="4"></a></p> <table cellpadding="0" cellspacing="0"><tbody><tr style="background-color: #EFEFEF; font-weight: bold;"><td> <p><strong>Component Type</strong></p> </td> <td> <p><strong>Palette Group</strong></p> </td> <td> <p><strong>What You’ll Name It</strong></p> </td> <td> <p><strong>Purpose</strong></p> </td> <td> <p><strong>Properties</strong></p> </td> </tr><tr><td> <p>ImageSprite</p> </td> <td> <p>Animation</p> </td> <td> <p>ObstacleSprite1</p> </td> <td> <p>This sprite will be somewhere between the golf ball and hole and will make it harder to get the ball into the hole</p> </td> <td> <p>Upload the obstacle (rectangle) graphic (<a href="/sites/all/files/tutorials/miniGolf/golf_obstacle1.png">right click on this link</a>, or see below).</p> </td> </tr></tbody></table><p>Program the behavior of the obstacle in the blocks editor. First, set the behavior for when the ball hits the obstacle.  *Note: Using Heading = 0 - heading works because we are dealing with bouncing off of horizonal surfaces, this will not work for bouncing off of vertical or inclined surfaces. For our purposes, it works all right. See Challenge #2 below for more information.</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/obstaclecollide.png" /></p> <p>Each time the course is reset, position the obstacle will be positioned randomly. Add these blocks to the <span class="callblock-ai2">SetupNewHole</span> procedure:</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/addtosetup.png" /></p> <pre class="ai-testing"><strong>Test the behavior.</strong> Play the game again. Notice that the ball bounces off when it hits the obstacle. When the ball goes into the hole, or when the New Game button is pressed, the obstacle appears in a new location somewhere between the tee and the hole.</pre><p>That’s it! Share your game with friends by building an APK or by downloading the source and sharing the zip file with other App Inventors!<br /></p> <h3>Part V: Challenges</h3> <p>Here are some extra challenges to make your game better.</p> <p><strong>Challenge 1:</strong> Program the Ball to Hole collision so that the ball only goes into the hole if the golf ball’s speed is not too fast. In real mini golf, the ball will bounce right over the hole if you hit the ball too hard.</p> <p><strong>Challenge 2:</strong> There is a slight bug when the ball hits the vertical sides of obstacle. Figure out how to program the ball to obstacle collision so that it bounces the way you would expect when the ball hits the vertical sides.</p> <p><strong>Challenge 3:</strong> Limit the number of holes per game. Keep track of the number of holes and end the game after a set number. (A typical mini golf course has 18 holes.)</p> <p>Below is a summary of all of the components:</p> <p><img src="/sites/all/files/ai2tutorials/miniGolf/components.png" /></p> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/miniGolf/MiniGolfBarcode.png" /></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/miniGolf/MiniGolf_MIT.aia">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box"><span style="color:black;">Done with Mini Golf?</span> <a href="http://explore.appinventor.mit.edu/ai2/tutorials">Return to the other tutorials</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-2" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 2</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/game" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Game</a> </li> <li class="field-item even"> <a href="/tutorial-type/sprites" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Sprites</a> </li> </ul> </section> Wed, 07 Aug 2013 14:13:24 +0000 joanie 379 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/minigolf#comments StockQuotes for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/stockquotes <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">StockQuotes</span></h2> <h4 class="ai-header">What You're Building</h4> <p>Just like you can access web pages from your phone -- for example, to look up a stock price -- so can App Inventor. This app enables the user to enter a stock symbol, then looks up the price of the stock on Yahoo! Finance and displays the price on the phone.</p> <p>This tutorial assumes that you are familiar with the basics of App Inventor -- using the Component Designer to build a user interface and using the Blocks Editor to specify event handlers. If you are not familiar with the basics, try stepping through some of the <a href="http://explore.appinventor.mit.edu/content/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial includes</p> <ol><li>Accepting text input from the user to specify the stock symbol.</li> <li>Using the Web component to ask Google Finance for the latest price for the stock.</li> <li>Displaying the result.</li> </ol><h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it StockQuotes, and also set the screen’s <b style="color:green;">Title</b> to “Stock Quotes”. Open the Blocks Editor and connect it to the phone.</p> <h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the user interface. When you are done, it should look something like the picture below. Additional instructions are below the picture.</p> <p><img src="/sites/all/files/ai2tutorials/stockQuotes/components1.png" /></p> <p>Create the following components by dragging them from the Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">StockSymbolTextBox</td> <td>Where the user enters the stock symbol</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">GetQuoteButton</td> <td>To request the stock quote</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ValueLabel</td> <td>To display the stock quote</td> </tr><tr><td> <b>Web</b> </td> <td>Other stuff</td> <td style="color:green;">Web1</td> <td>To request and receive the stock quote</td> </tr></table><p>Stick with the default properties except for the following changes:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Component</td> <td>Action</td> </tr><tr><td><b>StockSymbolTextBox</b></td> <td>Set its <b style="color:green;">Hint</b> property to "Enter a stock symbol". Clear its <b style="color:green;">Text</b> property by deleting or backspacing over the contents.</td> </tr><tr><td><b>GetQuoteButton</b></td> <td>Set its <b style="color:green;">Text</b> property to "Get Stock Quote".</td> </tr><tr><td><b>ValueLabel</b></td> <td>Clear its <b style="color:green;">Text</b> property.</td> </tr></table><h4 class="ai-header">The Yahoo! Finance API</h4> <p>Many web services provide an <em>application programmer interface</em> (API) for developers to enable their programs to access the service. Some ways to discover APIs are through the website <a href="http://programmableweb.com">http://programmableweb.com</a> or just by doing a web search for the service name and “API”.</p> <p>The Yahoo! Finance API is documented in gory detail at <a href="http://www.gummy-stuff.org/Yahoo-data.htm">http://www.gummy-stuff.org/Yahoo-data.htm</a> . The highlights are that you can get the latest price for the stock with the symbol "GOOG", for example, with the URL <a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=GOOG">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=GOOG</a> . The section "f=l1" (lower-case letter L, followed by the number 1) says we would like the latest price, and the section “s=GOOG” says we would like information about the stock whose symbol is “GOOG”. The result is returned in comma-separated value (CSV) format, which you may be familiar with from spreadsheets. Since only one value will be returned for our query, the result will be a plain old number, such as “511.5”, without any commas. (Commas would be used if we requested multiple pieces of data from Yahoo!, such as the name of the company and the daily trade volume.)</p> <h4 class="ai-header">Add Behaviors to the Components</h4> <h5 class="ai-header">Requesting the Data</h5> <p>The blocks to make the web request are shown here and detailed below:</p> <p><img src="/sites/all/files/ai2tutorials/stockQuotes/request-data.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="eventblock">GetQuoteButton.Click</span></td> <td>GetQuoteButton</td> <td>Handle a click of the "Get Quote" button.</td> </tr><tr><td><span class="componentsetblock">set Web1.Url to</span></td> <td>Web1</td> <td>Specify the URL to request.</td> </tr><tr><td><span class="textblock-ai2">call make text</span></td> <td>Text</td> <td>Concatenate the parts of the URL.</td> </tr><tr><td><span class="textblock-ai2">text</span> (<a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=</a>)</td> <td>Text</td> <td>Specify the first unchanging part of the URL.</td> </tr><tr><td><span class="componentsetblock">StockSymbolTextBox.Text</span></td> <td>StockSymbolTextBox</td> <td>Get the stock symbol from the text box.</td> </tr><tr><td><span class="eventblock">call Web1.Get</span></td> <td>Web1</td> <td>Make the web request.</td> </tr></table><p>The meaning is: When GetQuoteButton is clicked:</p> <ol><li>Build the Web component’s URL by concatenating “<a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=</a>” (which you should copy and paste into the text block) and the symbol entered by the user (StockSymbolTextBox.Text).</li> <li>Request the page specified by the URL. (This is like pressing return after entering a URL in your web browser.)</li> </ol><h5 class="ai-header">Receiving the Data </h5><p>When the response to the web request arrives, the <span class="eventblock">Web.GotText</span> event is raised with four parameters (only some of which we’ll use in this app):</p> <ol><li><b>url</b>: the URL of the original request (which is useful if requests are made with many different URLs).</li> <li><b>responseCode</b>: <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">the HTTP status code</a>, which indicates whether the web request succeeded or how it failed; for example, 200 means that the request succeeded, 404 that the page could not be found, etc.</li> <li><b>responseType</b>: <a href="http://en.wikipedia.org/wiki/Mime_type">the MIME type</a> of the response, such as “text/csv” in this app, “image/jpeg”, etc.</li> <li><b>responseContent</b>: the data being returned, such as “511.5”.</li> </ol><p>Here are a picture and table of the blocks you need to create:</p> <p><img src="/sites/all/files/ai2tutorials/stockQuotes/receive-data.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="eventblock">Web1.GotText</span></td> <td>Web1</td> <td>Specify what to do when the reply comes back from the web.</td> </tr><tr><td><span class="controlblock-ai2">ifelse</span></td> <td>Control</td> <td>Provide different behavior depending on whether the request succeeded.</td> </tr><tr><td><span class="variableblock">get responseCode</span></td> <td>Variables</td> <td>Gets the response code returned for the web request, which...</td> </tr><tr><td><span class="mathblock-ai2"> = </span>(equals) block</td> <td>Math</td> <td>...is checked for equality with...</td> </tr><tr><td><span class="eventblock">number</span> (200)</td> <td>Math</td> <td>...200, the code for valid web responses.</td> </tr><tr><td><span class="componentsetblock">set ValueLabel.Text to</span></td> <td>ValueLabel</td> <td>Display the result on the screen.</td> </tr><tr><td><span class="textblock-ai2">call make text</span></td> <td>Text</td> <td>Build the result by concatenating...</td> </tr><tr><td><span class="textblock-ai2">text</span> ("Current value: ")</td> <td>Text</td> <td>...the text “Current value: “ and...</td> </tr><tr><td><span class="variableblock">get responseContent</span></td> <td>Variables</td> <td>Gets the value returned from the web.</td> </tr><tr><td><span class="componentsetblock">set ValueLabel.Text to</span></td> <td>ValueLabel</td> <td>Display an error message.</td> </tr><tr><td><span class="textblock-ai2">text</span> ("Error getting stock quote")</td> <td>Text</td> <td>The error message</td> </tr></table><p>Here's a description of the block's behavior:</p> <ol><li>If the response code indicates that the web request succeeded (= 200), set the label to the concatenation of “Current value: “ and the returned data (e.g., 511.5).</li> <li>Otherwise, set the label to “Error getting stock quote”.</li> </ol><h4 class="ai-header">Review</h4> <p>Here are some ideas introduced in this tutorial:</p> <ol><li>Using an application programmer interface (API)</li> <li>Making a request with the Web component</li> <li>Checking whether a web request was successful</li> <li>Displaying information returned from the web</li> </ol><p>These ideas will be developed further in the second part of this tutorial, which is under development.</p> <h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/ai2tutorials/stockQuotes/StockQuotesBarcode.png" /></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/ai2tutorials/stockQuotes/stockQuotes.aia">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <h4 class="ai-header">Credits</h4> <pre class="ai-box">This tutorial is based on <a href="http://appinventorblog.com/2011/06/02/app-inventor-has-a-new-component-the-web/">an app created by Prof. David Wolber</a> and relies on the Yahoo! Finance API. Done with <span style="color:black;">StockQuotes</span>? Return to the other tutorials <a href="http://explore.appinventor.mit.edu/ai2/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-2" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 2</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/external-api" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">External API</a> </li> </ul> </section> Tue, 02 Jul 2013 20:35:01 +0000 aaron 354 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/stockquotes#comments VideoWall for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/videowall <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What you're building</h4> <p>The VideoWall app tutorial demonstrates how you can control the size of a video playing in an app by using the <strong>Video Player</strong> component's <b style="color:green;">Width</b>, <b style="color:green;">Height</b>, and <b style="color:green;">FullScreen</b> features. The VideoWall uses media assets (videos stored in the app itself), but you can use the app to display videos from the internet as well.</p> <p>This tutorial assumes you are familiar with the basics of App Inventor-- using the Component Designer to build a user interface, and using the Blocks Editor to specify the app's behavior. If you are not familiar with the basics, try stepping through some of the <a href="http://appinventor.mit.edu/explore/ai2/tutorials.html">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name the new project VideoWall and set the screen's Orientation to Landscape.</p> <p>Download the following video files* for use later on:</p> <ul><li><a href="/sites/all/files/ai2tutorials/videoWall/bigbuckbunny.3gp">BigBuckBunny (bigbuckbunny.3gp)</a></li> <li><a href="/sites/all/files/ai2tutorials/videoWall/nasa.3gp">NASA (nasa.3gp)</a></li> <li><a href="/sites/all/files/ai2tutorials/videoWall/sintel.3gp">Sintel (sintel.3gp)</a></li> </ul><p>*Attributions for these videos are included at the end of this tutorial.</p> <h4 class="ai-header">Introduction</h4> <p>The finished VideoWall app will display a wall of three videos that can be expanded to their true size and then shrunk back down again. The app will also allow you to display the videos in fullscreen. This tutorial assumes you have followed earlier tutorials to learn how the following blocks work:</p> <ul><li><span class="variableblock">Variables</span></li> <li><span class="callblock-ai2">Procedures</span></li> <li><span class="eventblock">Button.Click blocks</span></li> <li><span class="controlblock-ai2">Control (if-else) blocks</span></li> </ul><p>This tutorial introduces the following:</p> <ul><li>Resizing the VideoPlayer</li> <li>Showing the VideoPlayer video in fullscreen mode</li> </ul><h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the interface for the <span style="color:green;">VideoWall</span>. When completed, the designer should look similar to the snapshot below.</p> <p><img src="/sites/all/files/ai2tutorials/videoWall/setupcomponents.png" /></p> <p>First, you need to upload the video files. Click on the Add... button and select a video file downloaded earlier. Repeat this step to add the other two video files. Now create the interface by dragging and dropping the components from the Palette to the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>HorizontalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">HorizontalArrangement1</td> <td>Holds all other components: makes the three vertical arrangements line up side by side</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement1</td> <td>Holds the left-most VideoPlayer and controls</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement2</td> <td>Holds the middle VideoPlayer and controls</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement3</td> <td>Holds the right-most VideoPlayer and controls</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer1</td> <td>Displays the BigBuckBunny video</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer2</td> <td>Displays the NASA video</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer3</td> <td>Displays the Sintel video</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton1</td> <td>Resizes VideoPlayer1</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton2</td> <td>Resizes VideoPlayer2</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton3</td> <td>Resizes VideoPlayer3</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton1</td> <td>Shows the VideoPlayer1 video in fullscreen</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton2</td> <td>Shows the VideoPlayer2 video in fullscreen</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton3</td> <td>Shows the VideoPlayer3 video in fullscreen</td> </tr></table><p>Set the properties as described below:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Component</td> <td>Action</td> </tr><tr><td style="color:green;">HorizontalArrangement1</td> <td>Set Width to Fill parent...</td> </tr><tr><td style="color:green;">VerticalArrangement1, VerticalArrangement2, <span style="color:black;">and</span> VerticalArrangement3</td> <td>Set Width to Fill parent...</td> </tr><tr><td style="color:green;">ResizeButton1, ResizeButton2, <span style="color:black;">and</span> ResizeButton3</td> <td>Set Text to "Grow" and set Width to Fill parent...</td> </tr><tr><td style="color:green;">FullScreenButton1, FullScreenButton2, <span style="color:black;">and</span> FullScreenButton3 </td> <td>Set Text to Show FullScreen and set Width to Fill parent...</td> </tr><tr><td style="color:green;">VideoPlayer1</td> <td>Set Source to bigbuckbunny.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr><tr><td style="color:green;">VideoPlayer2</td> <td>Set Source to nasa.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr><tr><td style="color:green;">VideoPlayer3</td> <td>Set Source to sintel.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr></table><h4 class="ai-header">Add Behaviors to the Components</h4> <p>The interface is complete, but the buttons don't resize the videos yet. Open the Blocks Editor to add the behavior to the buttons. First, you'll define three variable blocks to keep track of the size of the VideoPlayers:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="variableblock">initialize global name to</span></td> <td>Variables</td> <td>Defines the vid1_zoomed variable (rename it)</td> </tr><tr><td><span class="variableblock">initialize global name to</span></td> <td>Variables</td> <td>Defines the vid2_zoomed variable (rename it)</td> </tr><tr><td><span class="variableblock">initialize global name to</span></td> <td>Variables</td> <td>Defines the vid3_zoomed variable (rename it)</td> </tr></table><p>The three variables should like this:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/videoWall/flagblocks.png" /></p> <p>Create the <span class="callblock">resizeVideoPlayer Procedure</span> block. There are three VideoPlayers in the app, but you'll use one Procedure block to resize all three. To accomplish this simplicity, you will use the Any Component blocks component <strong>Any VideoPlayer</strong> blocks. Create the <span class="callblock-ai2">resizeVideoPlayer Procedure</span> block using the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="callblock-ai2">Procedure</span></td> <td>Procedures</td> <td>Defines the resizeVideoPlayer procedure. Use the mutator ability of the procedure to add three arguments: x2, x3, x5.</td> </tr><tr><td><span class="controlblock-ai2">ifelse</span></td> <td>Control</td> <td>Defines the ifelse block that chooses whether the VideoPlayer is shrunk or expanded</td> </tr><tr><td><span class="logicblock-ai2">=</span> block</td> <td>Logic</td> <td>Defines the equals block for testing if the zoomed block is true</td> </tr><tr><td><span class="logicblock-ai2">true</span></td> <td>Logic</td> <td>Defines the block that zoomed is compared to</td> </tr><tr><td><span class="componentsetblock">VideoPlayer.Width</span> (x2)</td> <td>Any VideoPlayer</td> <td>Sets the VideoPlayer Width to a number</td> </tr><tr><td><span class="mathblock-ai2">Number (-1)</span> (x2)</td> <td>Math</td> <td>Width to set VideoPlayer to</td> </tr><tr><td><span class="componentsetblock">VideoPlayer.Height </span> (x2)</td> <td>Any VideoPlayer</td> <td>Sets the VideoPlayer Height to a number</td> </tr><tr><td><span class="mathblock-ai2">Number</span> (x2), values of 26 and 144</td> <td>Math</td> <td>Height to set VideoPlayer to</td> </tr><tr><td><span class="componentsetblock">Button.text</span></td> <td>Any Button</td> <td>Changes the button text</td> </tr><tr><td><span class="textblock-ai2">Text</span></td> <td>Text</td> <td>Text to set button to. Make one text block text's Shrink and the other's Grow.</td> </tr></table><p>The <span class="callblock-ai2">resizeVideoPlayer</span> block should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/videoWall/resize_block.png" /></p> <p>The <span class="callblock-ai2">resizeVideoPlayer</span> block will be explained later after you create the blocks for responding to button clicks.</p> <h4 class="ai-header">Create the Click Blocks</h4> <p>The blocks you will create respond to clicks on the ResizeButton buttons. To build the three blocks, you will need the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="eventblock">ResizeButton1.Click</span></td> <td>ResizeButton1</td> <td>Defines the block for responding to clicks on ResizeButton1</td> </tr><tr><td><span class="eventblock">ResizeButton2.Click</span></td> <td>ResizeButton2</td> <td>Defines the block for responding to clicks on ResizeButton2</td> </tr><tr><td><span class="eventblock">ResizeButton3.Click</span></td> <td>ResizeButton3</td> <td>Defines the block for responding to clicks on ResizeButton3</td> </tr><tr><td><span class="callblock-ai2">ResizeVideoPlayer</span> (x3)</td> <td>Procedures</td> <td>Starts the resizeVideoPlayer block for resizing a VideoPlayer</td> </tr><tr><td><span class="logicblock-ai2">not</span> (x3)</td> <td>Logic</td> <td>Defines the block for switching the various zoomed block values</td> </tr><tr><td><span class="variableblock">set global vid1_zoomed</span></td> <td>Variables</td> <td>Sets the vid1_zoomed block to a different value</td> </tr><tr><td><span class="variableblock">set global vid2_zoomed</span></td> <td>Variables</td> <td>Sets the vid2_zoomed block to a different value</td> </tr><tr><td><span class="variableblock">set global vid3_zoomed</span></td> <td>Variables</td> <td>Sets the vid3_zoomed block to a different value</td> </tr><tr><td><span class="variableblock">global vid1_zoomed</span></td> <td>Variables</td> <td>Used to change the vid1_zoomed value.</td> </tr><tr><td><span class="variableblock">global vid2_zoomed</span></td> <td>Variables</td> <td>Used to change the vid2_zoomed value.</td> </tr><tr><td><span class="variableblock">global vid3_zoomed</span></td> <td>Variables</td> <td>Used to change the vid3_zoomed value.</td> </tr><tr><td><span class="componentsetblock">component ResizeButton1</span></td> <td>ResizeButton1</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="componentsetblock">component ResizeButton2</span></td> <td>ResizeButton2</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="componentsetblock">component ResizeButton3</span></td> <td>ResizeButton3</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="componentsetblock">component VideoPlayer1</span></td> <td>VideoPlayer1</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="componentsetblock">component VideoPlayer2</span></td> <td>VideoPlayer2</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="componentsetblock">component VideoPlayer3</span></td> <td>VideoPlayer3</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr></table><p>The blocks should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/videoWall/resize_blocks.png" /></p> <p>Most blocks in App Inventor require you to know exactly what component your app will manipulate when you design the app. For some apps, you will have several of the same type of component and you want to program the same behavior for all of the similar components (like the VideoPlayer blocks in this app). The blocks in the Any component section allow you to build some general manipulation on some type of component. When you built the <span class="callblock">resizeVideoPlayer procedure</span> block, you didn't know specifically which VideoPlayer would be used in the procedure. The <span class="callblock">resizeVideoPlayer</span> works on VideoPlayers; but not until the <span class="callblock">resizeVideoPlayer</span> block is used in the <span class="basicblock">ResizeButton1.Click</span> block (for example) is the specific VideoPlayer known.</p> <p><b>Note:</b> The <span style="color:green;">VideoWall</span> app could have been designed with a specific resizing procedure for each VideoPlayer. By using the Advanced blocks in a single resizing procedure, the app is much simpler.</p> <h4 class="ai-header">How the Blocks Work</h4> <p>Setting the Width and Height property for a VideoPlayer works exactly the same way as setting the Width and Height of a Button. For whatever positive number is set, the video playing will resize its appearance to fit that value. There are two values that are exceptions to the using positive values rule: -1 and -2. Setting VideoPlayer.Width or VideoPlayer.Height to -1 is like setting the Width or Height to <em>Fill parent</em> in the designer. Setting VideoPlayer.Width or VideoPlayer.Height to -2 is like setting the Width or Height to <em>Automatic</em> in the designer.</p> <pre class="ai-warning"><b>Warning:</b> You can set the VideoPlayer Width and Height to any positive number you want. The VideoPlayer will change its size to match the values you set; but on some devices, the VideoPlayer does not change its size correctly. The behavior on such devices is usually unpredictable.</pre><pre class="ai-testing"><b>Test this behavior.</b> Click on the Grow button below the BigBuckBunny video. The video's size should expand, and the text of the button should change to "Shrink". Click on the Shrink button below the BigBuckBunny video. The video's size should shrink back to its original size and the text should change back to "Grow".</pre><h4 class="ai-header">Create the blocks for showing fullscreen video</h4> <p>You will now add the blocks for showing the videos in fullscreen mode. Use the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="logicblock-ai2">true</span> (x3)</td> <td>Logic</td> <td>Value to set FullScreen as</td> </tr><tr><td><span class="eventblock">FullScreenButton1.Click</span></td> <td>FullScreenButton1</td> <td>Responds to clicks on FullScreenButton1</td> </tr><tr><td><span class="componentsetblock">set VideoPlayer1.FullScreen</span></td> <td>VideoPlayer1</td> <td>Used to show fullscreen video</td> </tr><tr><td><span class="eventblock">FullScreenButton2.Click</span></td> <td>FullScreenButton2</td> <td>Responds to clicks on FullScreenButton2</td> </tr><tr><td><span class="componentsetblock">set VideoPlayer2.FullScreen</span></td> <td>VideoPlayer2</td> <td>Used to show fullscreen video</td> </tr><tr><td><span class="eventblock">FullScreenButton3.Click</span></td> <td>FullScreenButton3</td> <td>Responds to clicks on FullScreenButton3</td> </tr><tr><td><span class="componentsetblock">set VideoPlayer3.FullScreen</span></td> <td>VideoPlayer3</td> <td>Used to show fullscreen video</td> </tr></table><p>The blocks should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/videoWall/fullscreen_blocks.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>The <span class="componentsetblock">VideoPlayer.FullScreen</span> block takes a true/false value (also called a boolean) to tell it whether to go full screen or not. Setting a <span class="componentsetblock">VideoPlayer.FullScreen</span> block to true causes that VideoPlayer to be displayed in fullscreen mode. If there is another VideoPlayer in fullscreen mode, that VideoPlayer's .FullScreen value is set to false and it is replaced with the current VideoPlayer. If a <span class="componentsetblock">VideoPlayer.FullScreen</span> is true, setting a <span class="componentsetblock">VideoPlayer.FullScreen</span> block to false causes the fullscreen mode to be exited and the app's interface to display. Test this behavior. Start playing the BigBuckVideo, and click on the Show FullScreen button below the BigBuckBunny video. The app's interface should disappear and some media controls with the BigBuckBunny video should appear. Use the Back button on your device or the emulator to exit fullscreen. The app's interface should appear.</p> <h4 class="ai-header">Final Program</h4> <p>VideoWall Final Version</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/videoWall/blockseditor_full.png" /></p> <p>Package the final version of the app by choosing <b>Package For Phone | Barcode</b> from the Component Designer menu. When the barcode appears, use the barcode scanner on your phone to download and install the app. </p> <h4 class="ai-header">Variations</h4> <p>Now that you have finished the first <span style="color:green;">VideoWall</span> app, you might want to build some variations. For example:</p> <ul><li>Get more video files and add a second row to create a real VideoWall</li> <li>Use videos from an online server.</li> <li>Expand the resizeVideoPlayer procedure to resize VideoPlayers by small increments to create an animation effect. You could use multiple Clocks to start the resizeVideoPlayer procedure and animate multiple VideoPlayers at once.</li> </ul><p><b>If you distribute your app to others, make sure you respect any license requirements for the videos you use.</b></p> <p>Below are the attributions to the video files included in this demo app. The creators of the source videos that these clips are from do not endorse App Inventor.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Video File</td> <td>Information</td> <td>Attribution</td> </tr><tr><td>bigbuckbunny.3gp</td> <td>A clip from the full length film</td> <td>(c) copyright 2008, Blender Foundation / <a href="http://www.bigbuckbunny.org">http://www.bigbuckbunny.org</a></td> </tr><tr><td>nasa.3gp</td> <td>A formatted version of the Mars' Whirling Dust Devil clip.</td> <td>Here is the <a>original video.</a></td> </tr><tr><td>sintel.3gp</td> <td>A clip from the full length film </td> <td>(c) copyright Blender Foundation | <a href="http://durian.blender.org">http://durian.blender.org</a></td> </tr></table><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/ai2tutorials/videoWall/VideoWallBarcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/videoWall/VideoWall.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/ai2tutorials/videoWall/VideoWall.aia">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box">MIT is grateful to <a href="http://explore.appinventor.mit.edu/people/vance-turnewitsch">Vance Turnewitsch</a> for developing this tutorial. Done with <span style="color:black;">VideoWall</span>? Return to the other App Inventor 2 tutorials <a href="http://explore.appinventor.mit.edu/ai2/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-2" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 2</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/video" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Video</a> </li> </ul> </section> Tue, 02 Jul 2013 20:18:30 +0000 aaron 353 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/videowall#comments MoleMash 2 for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/molemash-2 <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } .listblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FCF5D7; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What You're Building</h4> <p><img src="/sites/all/files/ai2tutorials/moleMash2/front-pic.png" style="float:right;" /></p> <p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch3MoleMash.pdf">Download Refined Version (Book Chapter PDF)</a></p> <p>This tutorial shows you how to build a game similar to the Whac-A-MoleTM arcade game. Specifically, your goal is to whack (tap) a mole that randomly pops out of one of five fixed holes. Every time you succeed, your score is increased by one point.</p> <p>In order to highlight new App Inventor features — the Advanced tab and Sprite Z-layering — this app takes a different approach than the <a href="http://explore.appinventor.mit.edu/ai2/molemash">original Mole Mash tutorial</a>, which you need not have read in order to do this one. You should, however, be familiar with the basics of App Inventor — using the Component Designer to build a user interface and using the Blocks Editor to specify event handlers. If you are not familiar with the basics, try stepping through some of the <a href="http://explore.appinventor.mit.edu/ai2/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial includes:</p> <ol><li>Creating a list of components</li> <li>Using functionality from the Advanced section of the Blocks Editor to get and set properties of arbitrary components</li> <li>Having game events controlled by the <b>Clock</b> component</li> <li>Using Sprite Z-layering to ensure that one sprite (<b>ImageSprite</b> or <b>Ball</b>) appears in front of another</li> </ol><h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Set the screen's <b style="color:green;">Title</b> property to an appropriate name, such as "Mole Mash". Open the Blocks Editor and connect it to the phone. Download these image files (created by Yun Miao) by right-clicking on them, then add them to the project by pressing the "Add..." button in the Media pane.</p> <p><a href="/sites/all/files/ai2tutorials/moleMash2/hole.png"><img src="/sites/all/files/ai2tutorials/moleMash2/hole.png" /></a><a href="/sites/all/files/ai2tutorials/moleMash2/mole.png"><img src="/sites/all/files/ai2tutorials/moleMash2/mole.png" /></a></p> <h4 class="ai-header">Set up the Components</h4> <p>The user interface will contain a total of 6 ImageSprites: 5 unmoving holes and 1 mole, which will move on top of the holes. Use the component designer to create the user interface. When you are done, it should look something like the picture below. Don't worry about lining up the holes evenly. You will specify their locations through their <b style="color:green;">X</b> and <b style="color:green;">Y</b> properties. Additional instructions are below the picture.</p> <p><img src="/sites/all/files/ai2tutorials/moleMash2/designer1.png" /></p> <p>Create the following components by dragging them from the Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>Canvas</b> </td> <td>Basic</td> <td style="color:green;">GameCanvas</td> <td>The game field</td> </tr><tr><td> <b>ImageSprite</b> (5) </td> <td>Animation</td> <td style="color:green;">Hole1 ... Hole5</td> <td>Holes from which the mole can appear</td> </tr><tr><td> <b>ImageSprite</b> </td> <td>Animation</td> <td style="color:green;">Mole</td> <td>The mole</td> </tr><tr><td> <b>HorizontalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">ScoreArrangement</td> <td>To display the score</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ScoreTextLabel</td> <td>To hold "Score: "</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ScoreValueLabel</td> <td>To hold the score (# of times the mole was hit)</td> </tr><tr><td> <b>Clock</b> </td> <td>Basic</td> <td style="color:green;">MoleClock</td> <td>To control the mole's movement</td> </tr><tr><td> <b>Sound</b> </td> <td>Media</td> <td style="color:green;">Buzzer</td> <td>To vibrate when the mole is touched</td> </tr></table><p>Make the following changes to the components' properties:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component </td> <td> Action </td> </tr><tr><td>Canvas1</td> <td>Set <b style="color:green;">BackgroundColor</b> to Green. Set <b style="color:green;">Width</b> to 320 pixels. Set <b style="color:green;">Height</b> to 320 pixels.</td> </tr><tr><td>Hole1</td> <td>Set <b style="color:green;">X</b> to 20 and <b style="color:green;">Y</b> to 60 (upper left).</td> </tr><tr><td>Hole2</td> <td>Set <b style="color:green;">X</b> to 130 and <b style="color:green;">Y</b> to 60 (upper center).</td> </tr><tr><td>Hole3</td> <td>Set <b style="color:green;">X</b> to 240 and <b style="color:green;">Y</b> to 60 (upper right)</td> </tr><tr><td>Hole4</td> <td>Set <b style="color:green;">X</b> to 75 and <b style="color:green;">Y</b> to 140 (lower left).</td> </tr><tr><td>Hole5</td> <td>Set <b style="color:green;">X</b> to 185 and <b style="color:green;">Y</b> to 140 (lower right).</td> </tr><tr><td>Mole</td> <td>Set <b style="color:green;">Picture</b> to "mole.png". Set <b style="color:green;">Z</b> to 2 so the mole appears in front of the other <b style="color:green;">ImageSprite</b> s, which have the default <b style="color:green;">Z</b> value of 1.</td> </tr><tr><td>ScoreTextLabel</td> <td>Set <b style="color:green;">Text</b> to "Score: ".</td> </tr><tr><td>ScoreTextValue</td> <td>Set <b style="color:green;">Text</b> to "0".</td> </tr></table><p>Don't worry now about setting the <b style="color:green;">Picture</b> property for the holes; we'll set the property in the Blocks Editor.</p> <h4 class="ai-header">Add Behaviors to the Components</h4> <p>Here is an overview of what we need to create blocks to do:</p> <ol><li>Create variables: <ol><li><b style="color:green;">holes</b>: a list of holes</li> <li><b style="color:green;">currentHole</b>: the hole the mole is currently coming out of</li> </ol></li> <li>When the app starts: <ol><li>Populate the list of holes.</li> <li>Set each hole's <b style="color:green;">Picture</b> property to "hole.png".</li> <li>Call procedure <span class="callblock">MoveMole</span> (below).</li> </ol></li> <li>Create a procedure <span class="callblock">MoveMole</span> to: <ol><li>Set <b style="color:green;">currentHole</b> to a random hole from the list <b style="color:green;">holes</b>.</li> <li>Move the mole to the location of <b style="color:green;">currentHole</b>.</li> </ol></li> <li>Make <b>MoleClock</b> call <span class="callblock">MoveMole</span> whenever its timer goes off (every second). </li> <li>Implement a handler that does the following when the mole is touched: <ol><li>Add one to the score.</li> <li>Make the phone briefly vibrate.</li> <li>Call <span class="callblock">MoveMole</span>.</li> </ol></li> </ol><p>To proceed, switch to the Blocks Editor.</p> <h4 class="ai-header">Creating Variables</h4> <p>Create the variables <b style="color:green;">holes</b> and <b style="color:green;">currentHole</b>. For now, we will give them "dummy" initial values; we'll set their real initial values in the <span class="basicblock">Screen1.Initialize</span> event handler, which is run when the app starts. (For technical reasons, components cannot be referred to in def blocks, which are run before the app has started.) Here is a picture and list of the blocks you will need:</p> <p><img src="/sites/all/files/ai2tutorials/moleMash2/blocks1.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">def variable as</span> (holes)</td> <td>Definition</td> <td>Hold a list of holes.</td> </tr><tr><td><span class="listblock">make a list</span></td> <td>Lists</td> <td>Create an empty list, to be filled in when the program starts.</td> </tr><tr><td><span class="setblock">def variable as</span> (currentHole)</td> <td>Definition</td> <td>Hold the mole's current hole.</td> </tr><tr><td><span class="basicblock">number</span> (0)</td> <td>Numbers</td> <td>Provide a required initial value for <b style="color:green;">currentHole</b>.</td> </tr></table><p>As always, comments (created by right-clicking on a block) are encouraged but not required.</p> <h4 class="ai-header">Starting the App</h4> <p>The first event to occur in any program in <span class="basicblock">Screen1.Initialize</span>, so we will put start-up code in that handler. Specifically, we will add the hole components to the list holes, set each hole's <b style="color:green;">Picture</b> property to "hole.png", and call <span class="callblock">MoveMole</span>. Since we have not yet written MoveMole, we will create an empty procedure with that name, which we will fill in later.</p> <p>Below are a picture and table of the blocks you need to create. Note that the "Any ImageSprite" drawer is found under the "Advanced" tab to the right of "Built-In" and "My Blocks" in the Blocks Editor.</p> <p><img src="/sites/all/files/ai2tutorials/moleMash2/blocks2.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Screen1.Initialize</span></td> <td>Screen1</td> <td>Specify what should happen when the app starts.</td> </tr><tr><td><span class="listblock">add items to list</span></td> <td>Lists</td> <td>Add the following values to...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...the list of holes:</td> </tr><tr><td><span class="argblock">component Hole1</span></td> <td>Hole1</td> <td>-the upper left hole</td> </tr><tr><td><span class="argblock">component Hole2</span></td> <td>Hole2</td> <td>-the upper center hole</td> </tr><tr><td><span class="argblock">component Hole3</span></td> <td>Hole3</td> <td>-the upper right hole</td> </tr><tr><td><span class="argblock">component Hole4</span></td> <td>Hole4</td> <td>-the lower left hole</td> </tr><tr><td><span class="argblock">component Hole5</span></td> <td>Hole5</td> <td>-the lower right hole</td> </tr><tr><td><span class="controlblock">foreach</span></td> <td>Control</td> <td>Specify that we would like...</td> </tr><tr><td><span class="argblock">name</span> (hole)</td> <td>Definitions</td> <td>...a variable named "hole"...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...to take on each of the values in the list holes .</td> </tr><tr><td><span class="setblock">ImageSprite.Picture</span></td> <td>Any Image Sprite</td> <td>Set the Picture property of...</td> </tr><tr><td><span class="argblock">value hole</span></td> <td>My Definitions</td> <td>...the ImageSprite referred to by the variable hole ...</td> </tr><tr><td><span class="textblock">text (hole.png)</span></td> <td>Text</td> <td>...to the picture of the empty hole.</td> </tr><tr><td><span class="callblock">to procedure</span> (MoveMole)</td> <td>Definition</td> <td>Create an procedure, to be filled in later, for moving the mole.</td> </tr><tr><td><span class="callblock">MoveMole</span></td> <td>My Definitions</td> <td>Call MoveMole to make the first placement of the mole.</td> </tr></table><p>Compare the <span class="controlblock">foreach</span> block to the equivalent blocks that would be necessary without it:</p> <p><img src="/sites/all/files/ai2tutorials/moleMash2/blocks_new_old.png" /></p> <p>Not only is the left set of blocks shorter, it is less repetitious, sparing the programmer from semi-mindless copy-and-pasting and making it easier to modify, for example, if the name of the picture is changed.</p> <h4 class="ai-header">Moving the Mole</h4> <p>Now let's fill in the body of the procedure MoveMole, which we'll call when the program starts, when the mole gets touched, and when our timer goes off every second. What we want it to do is to pick a random hole and move the mole on top of it. Here are a picture and list of the new blocks:</p> <p><img src="/sites/all/files/ai2tutorials/moleMash2/blocks4.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">set currentHole to</span></td> <td>My Definitions</td> <td>Save the...</td> </tr><tr><td><span class="listblock">call pick random item</span></td> <td>Lists</td> <td>...randomly selected...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...hole.</td> </tr><tr><td><span class="basicblock">call Mole.MoveTo</span></td> <td>Mole</td> <td>Move the mole to the...</td> </tr><tr><td><span class="argblock">ImageSprite.X</span></td> <td>Advanced/ImageSprite</td> <td>..x-coordinate of...</td> </tr><tr><td><span class="argblock">currentHole</span></td> <td>My Definitions</td> <td>...the chosen hole...</td> </tr><tr><td><span class="argblock">ImageSprite.Y</span></td> <td>Advanced/ImageSprite</td> <td>...and the y-coordinate of...</td> </tr><tr><td><span class="argblock">current Hole</span></td> <td>My Definitions</td> <td>...the chosen hole.</td> </tr></table><p>We now need to specify that MoveMole should be called whenever MoleClock's Timer goes off. We just need two blocks to accomplish that:</p> <p><img src="/sites/all/files/ai2tutorials/moleMash2/blocks5.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">MoleClock.Timer</span></td> <td>MoleClock</td> <td>When the timer goes off...</td> </tr><tr><td><span class="callblock">call MoveMole</span></td> <td>My Definitions</td> <td>...move the mole.</td> </tr></table><h4 class="ai-header">Registering Touches</h4> <p>Finally, we need to specify what happens when the mole is touched. Specifically, we want to:</p> <ol><li>Increment the score.</li> <li>Make the phone vibrate briefly.</li> <li>Move the mole.</li> </ol><p>We can easily translate these to blocks:</p> <p><img src="/sites/all/files/ai2tutorials/moleMash2/blocks6.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Mole.Touched</span></td> <td>Mole</td> <td>When the mole is touched...</td> </tr><tr><td><span class="setblock">set ScoreValueLabel.Text to</span></td> <td>ScoreValueLabel</td> <td>...update the visible score to...</td> </tr><tr><td><span class="basicblock"> block</span></td> <td>Math</td> <td>...the result of adding...</td> </tr><tr><td><span class="basicblock">number</span> (1)</td> <td>Math</td> <td>...1 [and]...</td> </tr><tr><td><span class="argblock">ScoreValueLabel.Text</span></td> <td>ScoreValueLabel</td> <td>...the previous score.</td> </tr><tr><td><span class="callblock">call Buzzer.Vibrate</span></td> <td>Buzzer</td> <td>Make the phone vibrate for...</td> </tr><tr><td><span class="basicblock">number</span> (100)</td> <td>Math</td> <td>...100 milliseconds.</td> </tr><tr><td><span class="callblock">call MoveMole</span></td> <td>My Definitions</td> <td>Move the mole to a new location.</td> </tr></table><h4 class="ai-header">Final Program</h4> <p><img src="/sites/all/files/ai2tutorials/moleMash2/blocks-final.png" /></p> <h4 class="ai-header">Variations</h4> <p>Here are some variations you might want to implement:</p> <ul><li>Adding a Reset button to set the score back to 0.</li> <li>Having the score depend not just on the number of hits but also the number of misses and escaped moles.</li> <li>Increasing the speed of the game of mole movement if the player is doing well and decreasing it if the player is doing poorly.</li> <li>Adding a second mole on a different timer.</li> </ul><p>You can see how to implement the first two variations in the <a href="http://explore.appinventor.mit.edu/ai2/molemash">original Mole Mash tutorial</a>.</p> <h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this tutorial:</p> <ul><li>Putting components in a <b>List</b>.</li> <li>Performing an operation on every component in a <b>List</b> using the <span class="controlblock">foreach</span> block and Advanced features.</li> <li>Placing an <b>ImageSprite</b> on top of another, using their <b style="color:green;">Z</b> properties to control which goes in front.</li> <li>Using the <b>Clock</b> component to control game play.</li> <li>Creating a procedure and calling it from multiple places.</li> </ul><pre class="ai-box">Done with <span style="color:black;">MoleMash 2</span>? Return to the other tutorials <a href="http://explore.appinventor.mit.edu/ai2/tutorials">here</a>.</pre><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/ai2tutorials/moleMash2/MoleMash2Barcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/moleMash2/MoleMash2.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/moleMash2/MoleMash2.aia">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> </div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-2" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 2</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/game" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Game</a> </li> <li class="field-item even"> <a href="/tutorial-type/sprites" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Sprites</a> </li> </ul> </section> Tue, 02 Jul 2013 14:47:11 +0000 aaron 349 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/molemash-2#comments Get the Gold for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/get-gold <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ .ButtonText { color:green; font-weight: bold; } li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } .listblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FCF5D7; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What You're Building</h4> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/GetTheGoldMain.png" style="float:right; height: 453px; width: 197px;" /></p> <p> By building the <span style="color:green;">Get The Gold App</span> you will get practice with setting visibility, using Clock components and Timers, and detecting collisions in App Inventor. You'll program an application that has a pirate ship whose goal is to collect all the gold on the screen.</p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it <span style="color:green;">GetTheGold</span>, and also set the screen's <strong style="color:green;">Title</strong> to "GetTheGold". Switch to the Blocks view and connect to a device or emulator.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial introduces the following skills, useful for future game development:</p> <ul><li>Using the Clock component</li> <li>Using Clock.Timer to move sprites</li> <li>Using Sprite.Flung to move a sprite </li> <li>Using collision detection</li> </ul><h4 class="ai-header">Getting Ready</h4> <p>For this game, you will have two types of imagesprites: pirate and gold coin. Click below to download the image file for your sprites.</p> <p><a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/pirateship.jpeg"><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/pirateship.jpeg" /></a><br /><a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/goldcoin.jpeg"><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/goldcoin.jpeg" /></a></p> <h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the interface for <span style="color:green;">GetTheGold</span>. When you finish, it should look something like the snapshot below (more detailed instructions below the snapshot).</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/GetTheGoldDesigner.png" /></p> <p>To create this interface, put the following components into the Designer by dragging them from the Component Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td><strong>Canvas</strong></td> <td>Basic</td> <td style="color:green;">Canvas1</td> <td>The background that we will be putting our imagesprites on</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">PirateSprite</td> <td>The pirate ship in our game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite2</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite3</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite4</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite5</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite6</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>Clock</strong></td> <td>Basic</td> <td style="color:green;">Clock1</td> <td>We use the Clock for its Timer method to move the coins</td> </tr><tr><td><strong>Button</strong></td> <td>Basic</td> <td style="color:green;">ResetButton</td> <td>To reset the game so the player can play again</td> </tr></table><p>Set the properties of the components as described below:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td><strong>Component</strong></td> <td><strong>Action</strong></td> <td> </td> </tr><tr><td><span style="color:green;">ResetButton</span> </td> <td> Change <span class="ButtonText">Text</span> property to "Reset". </td> <td> </td> </tr><tr><td><span style="color:green;">PirateSprite</span> </td> <td> Change <span class="ButtonText">Speed</span> property to 6. </td> <td> Upload the pirateship image and set <span class="ButtonText">Picture</span> property to pirateship. </td> </tr><tr><td><span style="color:green;">ImageSprite(2,3,4,5,6)</span> </td> <td> Upload the goldcoin image and set <span class="ButtonText">Picture</span> property to goldcoin. </td> <td> </td> </tr><tr><td><span style="color:green;">Clock</span> </td> <td> Change <span class="ButtonText">TimerInterval</span> property to 2000. </td> <td> </td> </tr></table><h4 class="ai-header">Moving the Pirate</h4> <p> To move the PirateSprite, we want the user to be able to "fling" the sprite in the direction that they choose. To do this, we will use the <span class="eventblock">PirateSprite.Flung</span> event handler. </p> <p> You may notice that <span class="eventblock">PirateSprite.Flung</span> takes in 6 attributes: x, y, xvel, yvel, speed, and heading. We want to reassign PirateSprite's current heading to the heading given to us from PirateSprite.Flung. This means that the user can now control the direction of the pirate ship with their fingers by flinging on the screen. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/PirateSpriteFlung.png" /></p> <p>To prevent the pirate from moving off the screen, we will also use PirateSprite.Bounce when an edge is reached. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/PirateSpriteBounce.png" /></p> <h4 class="ai-header">Moving the Coins</h4> <p> We want the coins to move to random positions on the screen. We will use <span class="eventblock">Clock1.Timer </span> and the ImageSprite's MoveTo method to do this. </p> <p> When the Clock1.Timer goes off, we want all of our gold coin ImageSprites to move to a new random location on the Canvas. We will do this by using the <span class="callblock-ai2">Sprite.MoveTo</span> block. </p> <p>MoveTo takes in two arguments: the x and y coordinates on the canvas of the new position we want the sprite to move to. We want the Sprite to move to a new <i>random</i> location so we will use the <span class="mathblock-ai2">random integer</span> block found in the Math box. Since we want each Gold ImageSprite to move to a new location, we repeat this process for each sprite's MoveTo function. </p> <p>For ImageSprite2, we want x to be a random integer from 0 to <i>Canvas1.Width-ImageSprite2.Width</i> and y to be a random integer from 0 to <i>Canvas1.Height-ImageSprite2.Height</i>. This is to be repeated for all the Gold Image Sprites.</p> <p>Remember that sprites are measured at the upper left corner as (0,0) so if we don't want them to go off the screen, we need to take the sprite's height/width into account when setting the range for our random numbers.</p> <p>We will do this by setting up our blocks as in the image below:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/ClockTimer.png" /></p> <h4 class="ai-header">Detecting Collisions</h4> <p> App Inventor detects collisions by checking for an intersection between the bounding rectangles of each ImageSprite. We call this rectangle-based collision detection. As you can see in the image below, sprites with circular or polygon shape will appear to collide because of the rectangular bounds around them when they might not actually be colliding.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/CollisionDetection.png" /></p> <p>We can use the <span class="eventblock">PirateSprite.CollidedWith </span> event handler to detect whenever the pirate ship collides with another sprite or gold coin. You may notice that <span class="eventblock">PirateSprite.CollidedWith </span> takes in an argument. This argument is the object that PirateSprite just collided with. We will be testing inside the handler for which object so the name of this argument is not significant. You can name it other. </p> <p>Whenever the pirate collides with a gold coin, we want the coin to disappear. We can do this by setting the coin's visibility to false. To find which coin the pirate collided with, we will use the <span class="eventblock">PirateSprite.CollidingWith</span>. </p> <p> We can use <span class="eventblock">PirateSprite.CollidingWith</span> to take in a component (each of the gold coin sprites) to detect which sprite was hit. This is a component block and NOT a text block with the words ImageSprite inside. The component block can be found in the drawer for each component. If a sprite was hit, we will set its visibility to false. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/CollisionSprites.png" /></p> <h4 class="ai-header">Reset Button</h4> <p>After the user hits all of the gold sprites with the pirate ship, none of them will be visible. The reset button should set all of the gold sprites' visibility to true. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/ResetVis.png" /></p> <h4 class="ai-header">Complete Program</h4> <p>Here's the complete <strong><span style="color:green;">GetTheGold</span></strong> program.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/GetTheGoldAll.png" /></p> <p>Package the final version of the app by choosing <strong>Package For Phone | Barcode</strong> from the Component Designer menu. When the barcode appears, use the barcode scanner on your phone to download and install the app.</p> <h4 class="ai-header">Variations</h4> <p>Once you get this program running, you may want to do the following additional features to extend it. For example,</p> <ul><li>Create a label to display the time that it took you to get all the gold</li> <li>Change the speed of the ship or gold coins</li> <li>Add an enemy sprite that when collided with, causes your pirate to lose speed</li> <li>Use one of the phone's sensors to control movement of the pirate ship </li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/GetTheGoldBarcode.png" /></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/ai2tutorials/GetTheGold/GetTheGold.aia">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <p>Done with <span style="color:black;">GetTheGold</span>? Return to to the other App Inventor 2 tutorials <a href="http://explore.appinventor.mit.edu/ai2/tutorials">here</a>.</p> </div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-2" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 2</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/game" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Game</a> </li> <li class="field-item even"> <a href="/tutorial-type/sprites" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Sprites</a> </li> </ul> </section> Mon, 01 Jul 2013 18:09:32 +0000 aaron 347 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/get-gold#comments Get the Gold http://dev-explore.appinventor.mit.edu/get-gold <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ .ButtonText { color:green; font-weight: bold; } li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } .listblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FCF5D7; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What You're Building</h4> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGoldMain.png" style="float:right; height: 453px; width: 197px;" /></p> <p> By building the <span style="color:green;">Get The Gold App</span> you will get practice with setting visibility, using Clock components and Timers, and detecting collisions in App Inventor. You'll program an application that has a pirate ship whose goal is to collect all the gold on the screen.</p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it <span style="color:green;">GetTheGold</span>, and also set the screen's <strong style="color:green;">Title</strong> to "GetTheGold". Open the Blocks Editor and connect to a device or emulator.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial introduces the following skills, useful for future game development:</p> <ul><li>Using the Clock component</li> <li>Using Clock.Timer to move sprites</li> <li>Using Sprite.Flung to move a sprite </li> <li>Using collision detection</li> </ul><h4 class="ai-header">Getting Ready</h4> <p>For this game, you will have two types of imagesprites: pirate and gold coin. Click below to download the image file for your sprites.</p> <p><a href="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/pirateship.jpeg"><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/pirateship.jpeg" /></a><br /><a href="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/goldcoin.jpeg"><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/goldcoin.jpeg" /></a></p> <h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the interface for <span style="color:green;">GetTheGold</span>. When you finish, it should look something like the snapshot below (more detailed instructions below the snapshot).</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGoldDesigner.png" /></p> <p>To create this interface, put the following components into the Designer by dragging them from the Component Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td><strong>Canvas</strong></td> <td>Basic</td> <td style="color:green;">Canvas1</td> <td>The background that we will be putting our imagesprites on</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">PirateSprite</td> <td>The pirate ship in our game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite2</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite3</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite4</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite5</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>ImageSprite</strong></td> <td>Animation</td> <td style="color:green;">ImageSprite6</td> <td>One of the gold coins in the game</td> </tr><tr><td><strong>Clock</strong></td> <td>Basic</td> <td style="color:green;">Clock1</td> <td>We use the Clock for its Timer method to move the coins</td> </tr><tr><td><strong>Button</strong></td> <td>Basic</td> <td style="color:green;">ResetButton</td> <td>To reset the game so the player can play again</td> </tr></table><p>Set the properties of the components as described below:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td><strong>Component</strong></td> <td><strong>Action</strong></td> </tr><tr><td><span style="color:green;">ResetButton</span> </td> <td> Change <span class="ButtonText">Text</span> property to "Reset". </td> <td> </td> </tr><tr><td><span style="color:green;">PirateSprite</span> </td> <td> Change <span class="ButtonText">Speed</span> property to 6. </td> <td> Upload the pirateship image and set <span class="ButtonText">Picture</span> property to pirateship. </td> </tr><tr><td><span style="color:green;">ImageSprite(2,3,4,5,6)</span> </td> <td> Upload the goldcoin image and set <span class="ButtonText">Picture</span> property to goldcoin. </td> <td> </td> </tr><tr><td><span style="color:green;">Clock</span> </td> <td> Change <span class="ButtonText">TimerInterval</span> property to 2000. </td> <td> </td> </tr></table><h4 class="ai-header">Moving the Pirate</h4> <p> To move the PirateSprite, we want the user to be able to "fling" the sprite in the direction that they choose. To do this, we will use the <span class="basicblock">PirateSprite.Flung</span> event handler. </p> <p> You may notice that <span class="basicblock">PirateSprite.Flung</span> takes in 6 attributes: x, y, xvel, yvel, speed, and heading. We want to reassign PirateSprite's current heading to the heading given to us from PirateSprite.Flung. This means that the user can now control the direction of the pirate ship with their fingers by flinging on the screen. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/PirateSpriteFlung.png" /></p> <p>To prevent the pirate from moving off the screen, we will also use PirateSprite.Bounce when an edge is reached. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/PirateSpriteBounce.png" /></p> <h4 class="ai-header">Moving the Coins</h4> <p> We want the coins to move to random positions on the screen. We will use <span class="basicblock">Clock1.Timer </span> and the ImageSprite's MoveTo method to do this. </p> <p> When the Clock1.Timer goes off, we want all of our gold coin ImageSprites to move to a new random location on the Canvas. We will do this by using the <span class="basicblock">Sprite.MoveTo</span> block. </p> <p>MoveTo takes in two arguments: the x and y coordinates on the canvas of the new position we want the sprite to move to. We want the Sprite to move to a new <i>random</i> location so we will use the <span class="basicblock">random integer</span> block found in the Math box. Since we want each Gold ImageSprite to move to a new location, we repeat this process for each sprite's MoveTo function. </p> <p>For ImageSprite2, we want x to be a random integer from 0 to <i>Canvas1.Width-ImageSprite2.Width</i> and y to be a random integer from 0 to <i>Canvas1.Height-ImageSprite2.Height</i>. This is to be repeated for all the Gold Image Sprites.</p> <p>Remember that sprites are measured at the upper left corner as (0,0) so if we don't want them to go off the screen, we need to take the sprite's height/width into account when setting the range for our random numbers.</p> <p>We will do this by setting up our blocks as in the image below:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/ClockTimer.png" /></p> <h4 class="ai-header">Detecting Collisions</h4> <p> App Inventor detects collisions by checking for an intersection between the bounding rectangles of each ImageSprite. We call this rectangle-based collision detection. As you can see in the image below, sprites with circular or polygon shape will appear to collide because of the rectangular bounds around them when they might not actually be colliding.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/CollisionDetection.png" /></p> <p>We can use the <span class="basicblock">PirateSprite.CollidedWith </span> event handler to detect whenever the pirate ship collides with another sprite or gold coin. You may notice that <span class="basicblock">PirateSprite.CollidedWith </span> takes in an argument. This argument is the object that PirateSprite just collided with. We will be testing inside the handler for which object so the name of this argument is not significant. You can name it other. </p> <p>Whenever the pirate collides with a gold coin, we want the coin to disappear. We can do this by setting the coin's visibility to false. To find which coin the pirate collided with, we will use the <span class="basicblock">PirateSprite.CollidingWith</span>. </p> <p> We can use <span class="basicblock">PirateSprite.CollidingWith</span> to take in a component (each of the gold coin sprites) to detect which sprite was hit. This is a component block and NOT a text block with the words ImageSprite inside. The component block can be found in the drawer for each component. If a sprite was hit, we will set its visibility to false. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/CollisionSprites.png" /></p> <h4 class="ai-header">Reset Button</h4> <p>After the user hits all of the gold sprites with the pirate ship, none of them will be visible. The reset button should set all of the gold sprites' visibility to true. </p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/ResetVis.png" /></p> <h4 class="ai-header">Complete Program</h4> <p>Here's the complete <strong><span style="color:green;">GetTheGold</span></strong> program.</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGoldAll.png" /></p> <p>Package the final version of the app by choosing <strong>Package For Phone | Barcode</strong> from the Component Designer menu. When the barcode appears, use the barcode scanner on your phone to download and install the app.</p> <h4 class="ai-header">Variations</h4> <p>Once you get this program running, you may want to do the following additional features to extend it. For example,</p> <ul><li>Create a label to display the time that it took you to get all the gold</li> <li>Change the speed of the ship or gold coins</li> <li>Add an enemy sprite that when collided with, causes your pirate to lose speed</li> <li>Use one of the phone's sensors to control movement of the pirate ship </li> </ul><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGoldBarcode.png" /></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/Teach/GetTheGold/GetTheGold.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <p>Done with <span style="color:black;">GetTheGold</span>? Return to to the other modules <a href="/teach/module-2-2">here</a> or the tutorials <a href="/tutorials">here</a>.</p> </div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/game" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Game</a> </li> <li class="field-item even"> <a href="/tutorial-type/sprites" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Sprites</a> </li> </ul> </section> Fri, 28 Jun 2013 21:35:19 +0000 aaron 346 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/get-gold#comments MoleMash 2 http://dev-explore.appinventor.mit.edu/content/molemash-2 <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } .listblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FCF5D7; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What You're Building</h4> <p><img src="/sites/all/files/tutorials/moleMash2/front-pic.png" style="float:right;" /></p> <p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch3MoleMash.pdf">Download Refined Version (Book Chapter PDF)</a></p> <p>This tutorial shows you how to build a game similar to the Whac-A-MoleTM arcade game. Specifically, your goal is to whack (tap) a mole that randomly pops out of one of five fixed holes. Every time you succeed, your score is increased by one point.</p> <p>In order to highlight new App Inventor features — the Advanced tab and Sprite Z-layering — this app takes a different approach than the <a href="http://explore.appinventor.mit.edu/content/molemash">original Mole Mash tutorial</a>, which you need not have read in order to do this one. You should, however, be familiar with the basics of App Inventor — using the Component Designer to build a user interface and using the Blocks Editor to specify event handlers. If you are not familiar with the basics, try stepping through some of the <a href="/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial includes:</p> <ol><li>Creating a list of components</li> <li>Using functionality from the Advanced section of the Blocks Editor to get and set properties of arbitrary components</li> <li>Having game events controlled by the <b>Clock</b> component</li> <li>Using Sprite Z-layering to ensure that one sprite (<b>ImageSprite</b> or <b>Ball</b>) appears in front of another</li> </ol><h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Set the screen's <b style="color:green;">Title</b> property to an appropriate name, such as "Mole Mash". Open the Blocks Editor and connect it to the phone. Download these image files (created by Yun Miao) by right-clicking on them, then add them to the project by pressing the "Add..." button in the Media pane.</p> <p><a href="/sites/all/files/tutorials/moleMash2/hole.png"><img src="/sites/all/files/tutorials/moleMash2/hole.png" /></a><a href="/sites/all/files/tutorials/moleMash2/mole.png"><img src="/sites/all/files/tutorials/moleMash2/mole.png" /></a></p> <h4 class="ai-header">Set up the Components</h4> <p>The user interface will contain a total of 6 ImageSprites: 5 unmoving holes and 1 mole, which will move on top of the holes. Use the component designer to create the user interface. When you are done, it should look something like the picture below. Don't worry about lining up the holes evenly. You will specify their locations through their <b style="color:green;">X</b> and <b style="color:green;">Y</b> properties. Additional instructions are below the picture.</p> <p><img src="/sites/all/files/tutorials/moleMash2/designer1.png" /></p> <p>Create the following components by dragging them from the Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>Canvas</b> </td> <td>Basic</td> <td style="color:green;">GameCanvas</td> <td>The game field</td> </tr><tr><td> <b>ImageSprite</b> (5) </td> <td>Animation</td> <td style="color:green;">Hole1 ... Hole5</td> <td>Holes from which the mole can appear</td> </tr><tr><td> <b>ImageSprite</b> </td> <td>Animation</td> <td style="color:green;">Mole</td> <td>The mole</td> </tr><tr><td> <b>HorizontalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">ScoreArrangement</td> <td>To display the score</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ScoreTextLabel</td> <td>To hold "Score: "</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ScoreValueLabel</td> <td>To hold the score (# of times the mole was hit)</td> </tr><tr><td> <b>Clock</b> </td> <td>Basic</td> <td style="color:green;">MoleClock</td> <td>To control the mole's movement</td> </tr><tr><td> <b>Sound</b> </td> <td>Media</td> <td style="color:green;">Buzzer</td> <td>To vibrate when the mole is touched</td> </tr></table><p>Make the following changes to the components' properties:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component </td> <td> Action </td> </tr><tr><td>Canvas1</td> <td>Set <b style="color:green;">BackgroundColor</b> to Green. Set <b style="color:green;">Width</b> to 320 pixels. Set <b style="color:green;">Height</b> to 320 pixels.</td> </tr><tr><td>Hole1</td> <td>Set <b style="color:green;">X</b> to 20 and <b style="color:green;">Y</b> to 60 (upper left).</td> </tr><tr><td>Hole2</td> <td>Set <b style="color:green;">X</b> to 130 and <b style="color:green;">Y</b> to 60 (upper center).</td> </tr><tr><td>Hole3</td> <td>Set <b style="color:green;">X</b> to 240 and <b style="color:green;">Y</b> to 60 (upper right)</td> </tr><tr><td>Hole4</td> <td>Set <b style="color:green;">X</b> to 75 and <b style="color:green;">Y</b> to 140 (lower left).</td> </tr><tr><td>Hole5</td> <td>Set <b style="color:green;">X</b> to 185 and <b style="color:green;">Y</b> to 140 (lower right).</td> </tr><tr><td>Mole</td> <td>Set <b style="color:green;">Picture</b> to "mole.png". Set <b style="color:green;">Z</b> to 2 so the mole appears in front of the other <b style="color:green;">ImageSprite</b> s, which have the default <b style="color:green;">Z</b> value of 1.</td> </tr><tr><td>ScoreTextLabel</td> <td>Set <b style="color:green;">Text</b> to "Score: ".</td> </tr><tr><td>ScoreTextValue</td> <td>Set <b style="color:green;">Text</b> to "0".</td> </tr></table><p>Don't worry now about setting the <b style="color:green;">Picture</b> property for the holes; we'll set the property in the Blocks Editor.</p> <h4 class="ai-header">Add Behaviors to the Components</h4> <p>Here is an overview of what we need to create blocks to do:</p> <ol><li>Create variables: <ol><li><b style="color:green;">holes</b>: a list of holes</li> <li><b style="color:green;">currentHole</b>: the hole the mole is currently coming out of</li> </ol></li> <li>When the app starts: <ol><li>Populate the list of holes.</li> <li>Set each hole's <b style="color:green;">Picture</b> property to "hole.png".</li> <li>Call procedure <span class="callblock">MoveMole</span> (below).</li> </ol></li> <li>Create a procedure <span class="callblock">MoveMole</span> to: <ol><li>Set <b style="color:green;">currentHole</b> to a random hole from the list <b style="color:green;">holes</b>.</li> <li>Move the mole to the location of <b style="color:green;">currentHole</b>.</li> </ol></li> <li>Make <b>MoleClock</b> call <span class="callblock">MoveMole</span> whenever its timer goes off (every second). </li> <li>Implement a handler that does the following when the mole is touched: <ol><li>Add one to the score.</li> <li>Make the phone briefly vibrate.</li> <li>Call <span class="callblock">MoveMole</span>.</li> </ol></li> </ol><p>To proceed, open the Blocks Editor.</p> <h4 class="ai-header">Creating Variables</h4> <p>Create the variables <b style="color:green;">holes</b> and <b style="color:green;">currentHole</b>. For now, we will give them "dummy" initial values; we'll set their real initial values in the <span class="basicblock">Screen1.Initialize</span> event handler, which is run when the app starts. (For technical reasons, components cannot be referred to in def blocks, which are run before the app has started.) Here is a picture and list of the blocks you will need:</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks1.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">def variable as</span> (holes)</td> <td>Definition</td> <td>Hold a list of holes.</td> </tr><tr><td><span class="listblock">make a list</span></td> <td>Lists</td> <td>Create an empty list, to be filled in when the program starts.</td> </tr><tr><td><span class="setblock">def variable as</span> (currentHole)</td> <td>Definition</td> <td>Hold the mole's current hole.</td> </tr><tr><td><span class="basicblock">number</span> (0)</td> <td>Numbers</td> <td>Provide a required initial value for <b style="color:green;">currentHole</b>.</td> </tr></table><p>As always, comments (created by right-clicking on a block) are encouraged but not required.</p> <h4 class="ai-header">Starting the App</h4> <p>The first event to occur in any program in <span class="basicblock">Screen1.Initialize</span>, so we will put start-up code in that handler. Specifically, we will add the hole components to the list holes, set each hole's <b style="color:green;">Picture</b> property to "hole.png", and call <span class="callblock">MoveMole</span>. Since we have not yet written MoveMole, we will create an empty procedure with that name, which we will fill in later.</p> <p>Below are a picture and table of the blocks you need to create. Note that the "Any ImageSprite" drawer is found under the "Advanced" tab to the right of "Built-In" and "My Blocks" in the Blocks Editor.</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks2.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Screen1.Initialize</span></td> <td>Screen1</td> <td>Specify what should happen when the app starts.</td> </tr><tr><td><span class="listblock">add items to list</span></td> <td>Lists</td> <td>Add the following values to...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...the list of holes:</td> </tr><tr><td><span class="argblock">component Hole1</span></td> <td>Hole1</td> <td>-the upper left hole</td> </tr><tr><td><span class="argblock">component Hole2</span></td> <td>Hole2</td> <td>-the upper center hole</td> </tr><tr><td><span class="argblock">component Hole3</span></td> <td>Hole3</td> <td>-the upper right hole</td> </tr><tr><td><span class="argblock">component Hole4</span></td> <td>Hole4</td> <td>-the lower left hole</td> </tr><tr><td><span class="argblock">component Hole5</span></td> <td>Hole5</td> <td>-the lower right hole</td> </tr><tr><td><span class="controlblock">foreach</span></td> <td>Control</td> <td>Specify that we would like...</td> </tr><tr><td><span class="argblock">name</span> (hole)</td> <td>Definitions</td> <td>...a variable named "hole"...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...to take on each of the values in the list holes .</td> </tr><tr><td><span class="setblock">ImageSprite.Picture</span></td> <td>Any Image Sprite</td> <td>Set the Picture property of...</td> </tr><tr><td><span class="argblock">value hole</span></td> <td>My Definitions</td> <td>...the ImageSprite referred to by the variable hole ...</td> </tr><tr><td><span class="textblock">text (hole.png)</span></td> <td>Text</td> <td>...to the picture of the empty hole.</td> </tr><tr><td><span class="callblock">to procedure</span> (MoveMole)</td> <td>Definition</td> <td>Create an procedure, to be filled in later, for moving the mole.</td> </tr><tr><td><span class="callblock">MoveMole</span></td> <td>My Definitions</td> <td>Call MoveMole to make the first placement of the mole.</td> </tr></table><p>Compare the <span class="controlblock">foreach</span> block to the equivalent blocks that would be necessary without it:</p> <p><img src="/sites/all/files/tutorials/moleMash2/molemash2.JPG" /></p> <p>Not only is the left set of blocks shorter, it is less repetitious, sparing the programmer from semi-mindless copy-and-pasting and making it easier to modify, for example, if the name of the picture is changed.</p> <h4 class="ai-header">Moving the Mole</h4> <p>Now let's fill in the body of the procedure MoveMole, which we'll call when the program starts, when the mole gets touched, and when our timer goes off every second. What we want it to do is to pick a random hole and move the mole on top of it. Here are a picture and list of the new blocks:</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks4.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="setblock">set currentHole to</span></td> <td>My Definitions</td> <td>Save the...</td> </tr><tr><td><span class="listblock">call pick random item</span></td> <td>Lists</td> <td>...randomly selected...</td> </tr><tr><td><span class="argblock">holes</span></td> <td>My Definitions</td> <td>...hole.</td> </tr><tr><td><span class="basicblock">call Mole.MoveTo</span></td> <td>Mole</td> <td>Move the mole to the...</td> </tr><tr><td><span class="argblock">ImageSprite.X</span></td> <td>Advanced/ImageSprite</td> <td>..x-coordinate of...</td> </tr><tr><td><span class="argblock">currentHole</span></td> <td>My Definitions</td> <td>...the chosen hole...</td> </tr><tr><td><span class="argblock">ImageSprite.Y</span></td> <td>Advanced/ImageSprite</td> <td>...and the y-coordinate of...</td> </tr><tr><td><span class="argblock">current Hole</span></td> <td>My Definitions</td> <td>...the chosen hole.</td> </tr></table><p>We now need to specify that MoveMole should be called whenever MoleClock's Timer goes off. We just need two blocks to accomplish that:</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks5.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">MoleClock.Timer</span></td> <td>MoleClock</td> <td>When the timer goes off...</td> </tr><tr><td><span class="callblock">call MoveMole</span></td> <td>My Definitions</td> <td>...move the mole.</td> </tr></table><h4 class="ai-header">Registering Touches</h4> <p>Finally, we need to specify what happens when the mole is touched. Specifically, we want to:</p> <ol><li>Increment the score.</li> <li>Make the phone vibrate briefly.</li> <li>Move the mole.</li> </ol><p>We can easily translate these to blocks:</p> <p><img src="/sites/all/files/tutorials/moleMash2/blocks6.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Mole.Touched</span></td> <td>Mole</td> <td>When the mole is touched...</td> </tr><tr><td><span class="setblock">set ScoreValueLabel.Text to</span></td> <td>ScoreValueLabel</td> <td>...update the visible score to...</td> </tr><tr><td><span class="basicblock"> block</span></td> <td>Math</td> <td>...the result of adding...</td> </tr><tr><td><span class="basicblock">number</span> (1)</td> <td>Math</td> <td>...1 [and]...</td> </tr><tr><td><span class="argblock">ScoreValueLabel.Text</span></td> <td>ScoreValueLabel</td> <td>...the previous score.</td> </tr><tr><td><span class="callblock">call Buzzer.Vibrate</span></td> <td>Buzzer</td> <td>Make the phone vibrate for...</td> </tr><tr><td><span class="basicblock">number</span> (100)</td> <td>Math</td> <td>...100 milliseconds.</td> </tr><tr><td><span class="callblock">call MoveMole</span></td> <td>My Definitions</td> <td>Move the mole to a new location.</td> </tr></table><h4 class="ai-header">Final Program</h4> <p><img src="/sites/all/files/tutorials/moleMash2/blocks-final.png" /></p> <h4 class="ai-header">Variations</h4> <p>Here are some variations you might want to implement:</p> <ul><li>Adding a Reset button to set the score back to 0.</li> <li>Having the score depend not just on the number of hits but also the number of misses and escaped moles.</li> <li>Increasing the speed of the game of mole movement if the player is doing well and decreasing it if the player is doing poorly.</li> <li>Adding a second mole on a different timer.</li> </ul><p>You can see how to implement the first two variations in the <a href="http://explore.appinventor.mit.edu/content/molemash">original Mole Mash tutorial</a>.</p> <h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this tutorial:</p> <ul><li>Putting components in a <b>List</b>.</li> <li>Performing an operation on every component in a <b>List</b> using the <span class="controlblock">foreach</span> block and Advanced features.</li> <li>Placing an <b>ImageSprite</b> on top of another, using their <b style="color:green;">Z</b> properties to control which goes in front.</li> <li>Using the <b>Clock</b> component to control game play.</li> <li>Creating a procedure and calling it from multiple places.</li> </ul><pre class="ai-box">Done with <span style="color:black;">MoleMash 2</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/moleMash2/MoleMash2Barcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/moleMash2/MoleMash2.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/moleMash2/MoleMash2.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> </div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/game" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Game</a> </li> <li class="field-item even"> <a href="/tutorial-type/sprites" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Sprites</a> </li> </ul> </section> Wed, 26 Jun 2013 19:45:48 +0000 aaron 338 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/molemash-2#comments VideoWall http://dev-explore.appinventor.mit.edu/content/videowall <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h4 class="ai-header">What you're building</h4> <p>The VideoWall app tutorial demonstrates how you can control the size of a video playing in an app by using the <strong>Video Player</strong> component's <b style="color:green;">Width</b>, <b style="color:green;">Height</b>, and <b style="color:green;">FullScreen</b> features. The VideoWall uses media assets (videos stored in the app itself), but you can use the app to display videos from the internet as well.</p> <p>This tutorial assumes you are familiar with the basics of App Inventor-- using the Component Designer to build a user interface, and using the Blocks Editor to specify the app's behavior. If you are not familiar with the basics, try stepping through some of the <a href="/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name the new project VideoWall and set the screen's Orientation to Landscape.</p> <p>Download the following video files* for use later on:</p> <ul><li><a href="/sites/all/files/tutorials/videoWall/bigbuckbunny.3gp">BigBuckBunny (bigbuckbunny.3gp)</a></li> <li><a href="/sites/all/files/tutorials/videoWall/nasa.3gp">NASA (nasa.3gp)</a></li> <li><a href="/sites/all/files/tutorials/videoWall/sintel.3gp">Sintel (sintel.3gp)</a></li> </ul><p>*Attributions for these videos are included at the end of this tutorial.</p> <h4 class="ai-header">Introduction</h4> <p>The finished VideoWall app will display a wall of three videos that can be expanded to their true size and then shrunk back down again. The app will also allow you to display the videos in fullscreen. This tutorial assumes you have followed earlier tutorials to learn how the following blocks work:</p> <ul><li><span class="argblock">Variables</span></li> <li><span class="callblock">Procedures</span></li> <li><span class="basicblock">Button.Click blocks</span></li> <li><span class="controlblock">Logic (if-else) blocks</span></li> </ul><p>This tutorial introduces the following:</p> <ul><li>Using Advanced blocks</li> <li>Resizing the VideoPlayer</li> <li>Showing the VideoPlayer video in fullscreen mode</li> </ul><h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the interface for the <span style="color:green;">VideoWall</span>. When completed, the designer should look similar to the snapshot below.</p> <p><img src="/sites/all/files/tutorials/videoWall/setupcomponents.png" /></p> <p>First, you need to upload the video files. Click on the Add... button and select a video file downloaded earlier. Repeat this step to add the other two video files. Now create the interface by dragging and dropping the components from the Palette to the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>HorizontalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">HorizontalArrangement1</td> <td>Holds all other components: makes the three vertical arrangements line up side by side</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement1</td> <td>Holds the left-most VideoPlayer and controls</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement2</td> <td>Holds the middle VideoPlayer and controls</td> </tr><tr><td> <b>VerticalArrangement</b> </td> <td>Screen Arrangement</td> <td style="color:green;">VerticalArrangement3</td> <td>Holds the right-most VideoPlayer and controls</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer1</td> <td>Displays the BigBuckBunny video</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer2</td> <td>Displays the NASA video</td> </tr><tr><td> <b>VideoPlayer</b> </td> <td>Media</td> <td style="color:green;">VideoPlayer3</td> <td>Displays the Sintel video</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton1</td> <td>Resizes VideoPlayer1</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton2</td> <td>Resizes VideoPlayer2</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">ResizeButton3</td> <td>Resizes VideoPlayer3</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton1</td> <td>Shows the VideoPlayer1 video in fullscreen</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton2</td> <td>Shows the VideoPlayer2 video in fullscreen</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">FullScreenButton3</td> <td>Shows the VideoPlayer3 video in fullscreen</td> </tr></table><p>Set the properties as described below:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Component</td> <td>Action</td> </tr><tr><td style="color:green;">HorizontalArrangement1</td> <td>Set Width to Fill parent...</td> </tr><tr><td style="color:green;">VerticalArrangement1, VerticalArrangement2, <span style="color:black;">and</span> VerticalArrangement3</td> <td>Set Width to Fill parent...</td> </tr><tr><td style="color:green;">ResizeButton1, ResizeButton2, <span style="color:black;">and</span> ResizeButton3</td> <td>Set Text to "Grow" and set Width to Fill parent...</td> </tr><tr><td style="color:green;">FullScreenButton1, FullScreenButton2, <span style="color:black;">and</span> FullScreenButton3 </td> <td>Set Text to Show FullScreen and set Width to Fill parent...</td> </tr><tr><td style="color:green;">VideoPlayer1</td> <td>Set Source to bigbuckbunny.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr><tr><td style="color:green;">VideoPlayer2</td> <td>Set Source to nasa.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr><tr><td style="color:green;">VideoPlayer3</td> <td>Set Source to sintel.3gp , set Width to Fill parent... , and set Height to 36 pixels</td> </tr></table><h4 class="ai-header">Add Behaviors to the Components</h4> <p>The interface is complete, but the buttons don't resize the videos yet. Open the Blocks Editor to add the behavior to the buttons. First, you'll define three variable blocks to keep track of the size of the VideoPlayers:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="ai-blocks">def variable</span></td> <td>Definition</td> <td>Defines the vid1_zoomed variable (rename it)</td> </tr><tr><td><span class="ai-blocks">def variable</span></td> <td>Definition</td> <td>Defines the vid2_zoomed variable (rename it)</td> </tr><tr><td><span class="ai-blocks">def variable</span></td> <td>Definition</td> <td>Defines the vid3_zoomed variable (rename it)</td> </tr></table><p>The three variables should like this:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/flagblocks.png" /></p> <p>Create the <span class="callblock">resizeVideoPlayer Procedure</span> block. There are three VideoPlayers in the app, but you'll use one Procedure block to resize all three. To accomplish this simplicity, you will use the Advance blocks component <span class="setblock">Any VideoPlayer</span> blocks. Create the <span class="callblock">resizeVideoPlayer Procedure</span> block using the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="ai-blocks">Procedure</span></td> <td>Definition</td> <td>Defines the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">name</span> (x5)</td> <td>Definition</td> <td>Defines the VideoPlayer argument for the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">name</span> (x2)</td> <td>Definition</td> <td>Defines the zoomed argument for the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">name</span> (x3)</td> <td>Definition</td> <td>Defines the button argument for the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">ifelse</span></td> <td>Control</td> <td>Defines the ifelse block that chooses whether the VideoPlayer is shrunk or expanded</td> </tr><tr><td><span class="ai-blocks">=</span> block</td> <td>Logic</td> <td>Defines the equals block for testing if the zoomed block is true</td> </tr><tr><td><span class="ai-blocks">true</span></td> <td>Logic</td> <td>Defines the block that zoomed is compared to</td> </tr><tr><td><span class="ai-blocks">VideoPlayer.Width</span> (x2)</td> <td>Any VideoPlayer</td> <td>Sets the VideoPlayer Width to a number</td> </tr><tr><td><span class="ai-blocks">Number (-1)</span> (x2)</td> <td>Math</td> <td>Width to set VideoPlayer to</td> </tr><tr><td><span class="ai-blocks">VideoPlayer.Height </span> (x2)</td> <td>Any VideoPlayer</td> <td>Sets the VideoPlayer Height to a number</td> </tr><tr><td><span class="ai-blocks">Number</span> (x2), values of 26 and 144</td> <td>Math</td> <td>Height to set VideoPlayer to</td> </tr><tr><td><span class="ai-blocks">Button.text</span></td> <td>Any Button</td> <td>Changes the button text</td> </tr><tr><td><span class="ai-blocks">Text</span></td> <td>Text</td> <td>Text to set button to. Make one text block text's Shrink and the other's Grow.</td> </tr></table><p>The <span class="callblock">resizeVideoPlayer</span> block should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/resize_block.png" /></p> <p>The <span class="callblock">resizeVideoPlayer</span> block will be explained later after you create the blocks for responding to button clicks.</p> <h4 class="ai-header">Create the Click Blocks</h4> <p>The blocks you will create respond to clicks on the ResizeButton buttons. To build the three blocks, you will need the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="ai-blocks">ResizeButton1.Click</span></td> <td>ResizeButton1</td> <td>Defines the block for responding to clicks on ResizeButton1</td> </tr><tr><td><span class="ai-blocks">ResizeButton2.Click</span></td> <td>ResizeButton2</td> <td>Defines the block for responding to clicks on ResizeButton2</td> </tr><tr><td><span class="ai-blocks">ResizeButton3.Click</span></td> <td>ResizeButton3</td> <td>Defines the block for responding to clicks on ResizeButton3</td> </tr><tr><td><span class="ai-blocks">ResizeVideoPlayer</span> (x3)</td> <td>My Definitions</td> <td>Starts the resizeVideoPlayer block for resizing a VideoPlayer</td> </tr><tr><td><span class="ai-blocks">not</span> (x3)</td> <td>Logic</td> <td>Defines the block for switching the various zoomed block values</td> </tr><tr><td><span class="ai-blocks">set global vid1_zoomed</span></td> <td>My Definitions</td> <td>Sets the vid1_zoomed block to a different value</td> </tr><tr><td><span class="ai-blocks">set global vid2_zoomed</span></td> <td>My Definitions</td> <td>Sets the vid2_zoomed block to a different value</td> </tr><tr><td><span class="ai-blocks">set global vid3_zoomed</span></td> <td>My Definitions</td> <td>Sets the vid3_zoomed block to a different value</td> </tr><tr><td><span class="ai-blocks">global vid1_zoomed</span></td> <td>My Definitions</td> <td>Used to change the vid1_zoomed value.</td> </tr><tr><td><span class="ai-blocks">global vid2_zoomed</span></td> <td>My Definitions</td> <td>Used to change the vid2_zoomed value.</td> </tr><tr><td><span class="ai-blocks">global vid3_zoomed</span></td> <td>My Definitions</td> <td>Used to change the vid3_zoomed value.</td> </tr><tr><td><span class="ai-blocks">component ResizeButton1</span></td> <td>ResizeButton1</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component ResizeButton2</span></td> <td>ResizeButton2</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component ResizeButton3</span></td> <td>ResizeButton3</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component VideoPlayer1</span></td> <td>VideoPlayer1</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component VideoPlayer2</span></td> <td>VideoPlayer2</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr><tr><td><span class="ai-blocks">component VideoPlayer3</span></td> <td>VideoPlayer3</td> <td>Passed to the resizeVideoPlayer procedure</td> </tr></table><p>The blocks should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/resize_blocks.png" /></p> <p>Most blocks in App Inventor require you to know exactly what component your app will manipulate when you design the app. For some apps, you will have several of the same type of component and you want to program the same behavior for all of the similar components (like the VideoPlayer blocks in this app). The blocks in the Advanced section allow you to build some general manipulation on some type of component. When you built the <span class="callblock">resizeVideoPlayer procedure</span> block, you didn't know specifically which VideoPlayer would be used in the procedure. The <span class="callblock">resizeVideoPlayer</span> works on VideoPlayers; but not until the <span class="callblock">resizeVideoPlayer</span> block is used in the <span class="basicblock">ResizeButton1.Click</span> block (for example) is the specific VideoPlayer known.</p> <p><b>Note:</b> The <span style="color:green;">VideoWall</span> app could have been designed with a specific resizing procedure for each VideoPlayer. By using the Advanced blocks in a single resizing procedure, the app is much simpler.</p> <h4 class="ai-header">How the Blocks Work</h4> <p>Setting the Width and Height property for a VideoPlayer works exactly the same way as setting the Width and Height of a Button. For whatever positive number is set, the video playing will resize its appearance to fit that value. There are two values that are exceptions to the using positive values rule: -1 and -2. Setting VideoPlayer.Width or VideoPlayer.Height to -1 is like setting the Width or Height to <em>Fill parent</em> in the designer. Setting VideoPlayer.Width or VideoPlayer.Height to -2 is like setting the Width or Height to <em>Automatic</em> in the designer.</p> <pre class="ai-warning"><b>Warning:</b> You can set the VideoPlayer Width and Height to any positive number you want. The VideoPlayer will change its size to match the values you set; but on some devices, the VideoPlayer does not change its size correctly. The behavior on such devices is usually unpredictable.</pre><pre class="ai-testing"><b>Test this behavior.</b> Click on the Grow button below the BigBuckBunny video. The video's size should expand, and the text of the button should change to "Shrink". Click on the Shrink button below the BigBuckBunny video. The video's size should shrink back to its original size and the text should change back to "Grow".</pre><h4 class="ai-header">Create the blocks for showing fullscreen video</h4> <p>You will now add the blocks for showing the videos in fullscreen mode. Use the following blocks:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Block Type</td> <td>Drawer</td> <td>Purpose</td> </tr><tr><td><span class="ai-blocks">true</span> (x3)</td> <td>Logic</td> <td>Value to set FullScreen as</td> </tr><tr><td><span class="ai-blocks">FullScreenButton1.Click</span></td> <td>FullScreenButton1</td> <td>Responds to clicks on FullScreenButton1</td> </tr><tr><td><span class="ai-blocks">set VideoPlayer1.FullScreen</span></td> <td>VideoPlayer1</td> <td>Used to show fullscreen video</td> </tr><tr><td><span class="ai-blocks">FullScreenButton2.Click</span></td> <td>FullScreenButton2</td> <td>Responds to clicks on FullScreenButton2</td> </tr><tr><td><span class="ai-blocks">set VideoPlayer2.FullScreen</span></td> <td>VideoPlayer2</td> <td>Used to show fullscreen video</td> </tr><tr><td><span class="ai-blocks">FullScreenButton3.Click</span></td> <td>FullScreenButton3</td> <td>Responds to clicks on FullScreenButton3</td> </tr><tr><td><span class="ai-blocks">set VideoPlayer3.FullScreen</span></td> <td>VideoPlayer3</td> <td>Used to show fullscreen video</td> </tr></table><p>The blocks should look like the following:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/fullscreen_blocks.png" /></p> <h4 class="ai-header">How the Blocks Work</h4> <p>The <span class="setblock">VideoPlayer.FullScreen</span> block takes a true/false value (also called a boolean) to tell it whether to go full screen or not. Setting a <span class="setblock">VideoPlayer.FullScreen</span> block to true causes that VideoPlayer to be displayed in fullscreen mode. If there is another VideoPlayer in fullscreen mode, that VideoPlayer's .FullScreen value is set to false and it is replaced with the current VideoPlayer. If a <span class="setblock">VideoPlayer.FullScreen</span> is true, setting a <span class="setblock">VideoPlayer.FullScreen</span> block to false causes the fullscreen mode to be exited and the app's interface to display. Test this behavior. Start playing the BigBuckVideo, and click on the Show FullScreen button below the BigBuckBunny video. The app's interface should disappear and some media controls with the BigBuckBunny video should appear. Use the Back button on your device or the emulator to exit fullscreen. The app's interface should appear.</p> <h4 class="ai-header">Final Program</h4> <p>VideoWall Final Version</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/blockseditor_full.png" /></p> <p>Package the final version of the app by choosing <b>Package For Phone | Barcode</b> from the Component Designer menu. When the barcode appears, use the barcode scanner on your phone to download and install the app. </p> <h4 class="ai-header">Variations</h4> <p>Now that you have finished the first <span style="color:green;">VideoWall</span> app, you might want to build some variations. For example:</p> <ul><li>Get more video files and add a second row to create a real VideoWall</li> <li>Use videos from an online server.</li> <li>Expand the resizeVideoPlayer procedure to resize VideoPlayers by small increments to create an animation effect. You could use multiple Clocks to start the resizeVideoPlayer procedure and animate multiple VideoPlayers at once.</li> </ul><p><b>If you distribute your app to others, make sure you respect any license requirements for the videos you use.</b></p> <p>Below are the attributions to the video files included in this demo app. The creators of the source videos that these clips are from do not endorse App Inventor.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Video File</td> <td>Information</td> <td>Attribution</td> </tr><tr><td>bigbuckbunny.3gp</td> <td>A clip from the full length film</td> <td>(c) copyright 2008, Blender Foundation / <a href="http://www.bigbuckbunny.org">http://www.bigbuckbunny.org</a></td> </tr><tr><td>nasa.3gp</td> <td>A formatted version of the Mars' Whirling Dust Devil clip.</td> <td>Here is the <a>original video.</a></td> </tr><tr><td>sintel.3gp</td> <td>A clip from the full length film </td> <td>(c) copyright Blender Foundation | <a href="http://durian.blender.org">http://durian.blender.org</a></td> </tr></table><h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/videoWall/VideoWallBarcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/videoWall/VideoWall.apk">download the apk</a></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/tutorials/videoWall/VideoWall_0.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <pre class="ai-box">MIT is grateful to <a href="http://explore.appinventor.mit.edu/people/vance-turnewitsch">Vance Turnewitsch</a> for developing this tutorial. Done with <span style="color:black;">VideoWall</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/video" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Video</a> </li> </ul> </section> Fri, 14 Jun 2013 16:23:45 +0000 aaron 324 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/videowall#comments StockQuotes http://dev-explore.appinventor.mit.edu/content/stockquotes <div class="field field-name-body field-type-text-with-summary field-label-hidden view-mode-rss"><div class="field-items"><div class="field-item even" property="content:encoded"><style> <!--/*--><![CDATA[/* ><!--*/ li { padding-bottom: 7px; } .basicblock { border: 1px dashed #7AA81C; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E7F2CB; font-size: 9pt; text-wrap: suppress; } .callblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E0D1FF; font-size: 9pt; text-wrap: suppress; } .argblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #E5E5FF; font-size: 9pt; text-wrap: suppress; } .textblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FADAA0; font-size: 9pt; text-wrap: suppress; } .setblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #C1D5F8; font-size: 9pt; text-wrap: suppress; } .controlblock { border: 1px dashed #000000; padding-left: 4px; padding-right: 4px; padding-top: 1px; padding-bottom: 1px; background-color: #FAEDBB; font-size: 9pt; text-wrap: suppress; } /*--><!]]>*/ </style><h2 class="ai-header"><span style="color:green;">StockQuotes</span></h2> <h4 class="ai-header">What You're Building</h4> <p>Just like you can access web pages from your phone -- for example, to look up a stock price -- so can App Inventor. This app enables the user to enter a stock symbol, then looks up the price of the stock on Yahoo! Finance and displays the price on the phone.</p> <p>This tutorial assumes that you are familiar with the basics of App Inventor -- using the Component Designer to build a user interface and using the Blocks Editor to specify event handlers. If you are not familiar with the basics, try stepping through some of the <a href="/tutorials">basic tutorials</a> before continuing.</p> <h4 class="ai-header">Introduction</h4> <p>This tutorial includes</p> <ol><li>Accepting text input from the user to specify the stock symbol.</li> <li>Using the Web component to ask Google Finance for the latest price for the stock.</li> <li>Displaying the result.</li> </ol><h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it StockQuotes, and also set the screen’s <b style="color:green;">Title</b> to “Stock Quotes”. Open the Blocks Editor and connect it to the phone.</p> <h4 class="ai-header">Set up the Components</h4> <p>Use the component designer to create the user interface. When you are done, it should look something like the picture below. Additional instructions are below the picture.</p> <p><img src="/sites/all/files/tutorials/stockQuotes/components1.png" /></p> <p>Create the following components by dragging them from the Palette into the Viewer.</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Component Type </td> <td> Palette Group </td> <td> What you'll name it </td> <td> Purpose of Component </td> </tr><tr><td> <b>TextBox</b> </td> <td>Basic</td> <td style="color:green;">StockSymbolTextBox</td> <td>Where the user enters the stock symbol</td> </tr><tr><td> <b>Button</b> </td> <td>Basic</td> <td style="color:green;">GetQuoteButton</td> <td>To request the stock quote</td> </tr><tr><td> <b>Label</b> </td> <td>Basic</td> <td style="color:green;">ValueLabel</td> <td>To display the stock quote</td> </tr><tr><td> <b>Web</b> </td> <td>Other stuff</td> <td style="color:green;">Web1</td> <td>To request and receive the stock quote</td> </tr></table><p>Stick with the default properties except for the following changes:</p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td>Component</td> <td>Action</td> </tr><tr><td><b>StockSymbolTextBox</b></td> <td>Set its <b style="color:green;">Hint</b> property to "Enter a stock symbol". Clear its <b style="color:green;">Text</b> property by deleting or backspacing over the contents.</td> </tr><tr><td><b>GetQuoteButton</b></td> <td>Set its <b style="color:green;">Text</b> property to "Get Stock Quote".</td> </tr><tr><td><b>ValueLabel</b></td> <td>Clear its <b style="color:green;">Text</b> property.</td> </tr></table><h4 class="ai-header">The Yahoo! Finance API</h4> <p>Many web services provide an <em>application programmer interface</em> (API) for developers to enable their programs to access the service. Some ways to discover APIs are through the website <a href="http://programmableweb.com">http://programmableweb.com</a> or just by doing a web search for the service name and “API”.</p> <p>The Yahoo! Finance API is documented in gory detail at <a href="http://www.gummy-stuff.org/Yahoo-data.htm">http://www.gummy-stuff.org/Yahoo-data.htm</a> . The highlights are that you can get the latest price for the stock with the symbol "GOOG", for example, with the URL <a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=GOOG">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=GOOG</a> . The section "f=l1" (lower-case letter L, followed by the number 1) says we would like the latest price, and the section “s=GOOG” says we would like information about the stock whose symbol is “GOOG”. The result is returned in comma-separated value (CSV) format, which you may be familiar with from spreadsheets. Since only one value will be returned for our query, the result will be a plain old number, such as “511.5”, without any commas. (Commas would be used if we requested multiple pieces of data from Yahoo!, such as the name of the company and the daily trade volume.)</p> <h4 class="ai-header">Add Behaviors to the Components</h4> <h5 class="ai-header">Requesting the Data</h5> <p>The blocks to make the web request are shown here and detailed below:</p> <p><img src="/sites/all/files/tutorials/stockQuotes/request-data.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">GetQuoteButton.Click</span></td> <td>GetQuoteButton</td> <td>Handle a click of the "Get Quote" button.</td> </tr><tr><td><span class="setblock">set Web1.Url to</span></td> <td>Web1</td> <td>Specify the URL to request.</td> </tr><tr><td><span class="textblock">call make text</span></td> <td>Text</td> <td>Concatenate the parts of the URL.</td> </tr><tr><td><span class="textblock">text</span> (<a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=</a>)</td> <td>Text</td> <td>Specify the first unchanging part of the URL.</td> </tr><tr><td><span class="argblock">StockSymbolTextBox.Text</span></td> <td>StockSymbolTextBox</td> <td>Get the stock symbol from the text box.</td> </tr><tr><td><span class="callblock">call Web1.Get</span></td> <td>Web1</td> <td>Make the web request.</td> </tr></table><p>The meaning is: When GetQuoteButton is clicked:</p> <ol><li>Build the Web component’s URL by concatenating “<a href="http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=">http://finance.yahoo.com/d/quotes.csv?f=l1&amp;s=</a>” (which you should copy and paste into the text block) and the symbol entered by the user (StockSymbolTextBox.Text).</li> <li>Request the page specified by the URL. (This is like pressing return after entering a URL in your web browser.)</li> </ol><h5 class="ai-header">Receiving the Data </h5><p>When the response to the web request arrives, the <span class="basicblock">Web.GotText</span> event is raised with four parameters (only some of which we’ll use in this app):</p> <ol><li><b>url</b>: the URL of the original request (which is useful if requests are made with many different URLs).</li> <li><b>responseCode</b>: <a href="http://en.wikipedia.org/wiki/List_of_HTTP_status_codes">the HTTP status code</a>, which indicates whether the web request succeeded or how it failed; for example, 200 means that the request succeeded, 404 that the page could not be found, etc.</li> <li><b>responseType</b>: <a href="http://en.wikipedia.org/wiki/Mime_type">the MIME type</a> of the response, such as “text/csv” in this app, “image/jpeg”, etc.</li> <li><b>responseContent</b>: the data being returned, such as “511.5”.</li> </ol><p>Here are a picture and table of the blocks you need to create:</p> <p><img src="/sites/all/files/tutorials/stockQuotes/receive-data.png" /></p> <table><tr style="background-color: #EFEFEF; font-weight: bold;"><td> Block type </td> <td> Drawer </td> <td> Purpose </td> </tr><tr><td><span class="basicblock">Web1.GotText</span></td> <td>Web1</td> <td>Specify what to do when the reply comes back from the web.</td> </tr><tr><td><span class="controlblock">ifelse</span></td> <td>Control</td> <td>Provide different behavior depending on whether the request succeeded.</td> </tr><tr><td><span class="argblock">value responseCode</span></td> <td>My Definitions</td> <td>The response code returned for the web request, which...</td> </tr><tr><td><span class="basicblock"> = </span>(equals) block</td> <td>Math</td> <td>...is checked for equality with...</td> </tr><tr><td><span class="basicblock">number</span> (200)</td> <td>Math</td> <td>...200, the code for valid web responses.</td> </tr><tr><td><span class="setblock">set ValueLabel.Text to</span></td> <td>ValueLabel</td> <td>Display the result on the screen.</td> </tr><tr><td><span class="textblock">call make text</span></td> <td>Text</td> <td>Build the result by concatenating...</td> </tr><tr><td><span class="textblock">text</span> ("Current value: ")</td> <td>Text</td> <td>...the text “Current value: “ and...</td> </tr><tr><td><span class="argblock">value responseContent</span></td> <td>My Definitions</td> <td>...the value returned from the web.</td> </tr><tr><td><span class="setblock">set ValueLabel.Text to</span></td> <td>ValueLabel</td> <td>Display an error message.</td> </tr><tr><td><span class="textblock">text</span> ("Error getting stock quote")</td> <td>Text</td> <td>The error message</td> </tr></table><p>Here's a description of the block's behavior:</p> <ol><li>If the response code indicates that the web request succeeded (= 200), set the label to the concatenation of “Current value: “ and the returned data (e.g., 511.5).</li> <li>Otherwise, set the label to “Error getting stock quote”.</li> </ol><h4 class="ai-header">Review</h4> <p>Here are some ideas introduced in this tutorial:</p> <ol><li>Using an application programmer interface (API)</li> <li>Making a request with the Web component</li> <li>Checking whether a web request was successful</li> <li>Displaying information returned from the web</li> </ol><p>These ideas will be developed further in the second part of this tutorial, which is under development.</p> <h4 class="ai-header">Scan the Sample App to your Phone</h4> <p>Scan the following barcode onto your phone to install and run the sample app. </p><p><img src="/sites/all/files/tutorials/stockQuotes/StockQuotesBarcode.png" /></p> <h4 class="ai-header">Download Source Code</h4> <p>If you'd like to work with this sample in App Inventor, download the <a href="/sites/all/files/tutorials/stockQuotes/StockQuotes.zip">source code</a> to your computer, then open App Inventor, go to the My Projects page, and choose <b>More Actions | Upload Source</b>.</p> <h4 class="ai-header">Credits</h4> <pre class="ai-box">This tutorial is based on <a href="http://appinventorblog.com/2011/06/02/app-inventor-has-a-new-component-the-web/">an app created by Prof. David Wolber</a> and relies on the Yahoo! Finance API. Done with <span style="color:black;">StockQuotes</span>? Return to the other tutorials <a href="/tutorials">here</a>.</pre></div></div></div><section class="field field-name-field-version field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Version:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-version/app-inventor-1" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">App Inventor 1</a> </li> </ul> </section> <section class="field field-name-field-tutorial-difficulty field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Difficulty:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-difficulty/advanced" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Advanced</a> </li> </ul> </section> <section class="field field-name-field-tutorial-type field-type-taxonomy-term-reference field-label-above view-mode-rss clearfix"> <h2 class="field-label">Tutorial Type:&nbsp;</h2> <ul class="field-items"> <li class="field-item even"> <a href="/tutorial-type/external-api" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">External API</a> </li> </ul> </section> Fri, 14 Jun 2013 16:23:17 +0000 aaron 323 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/stockquotes#comments