Explore MIT App Inventor - Clock Timer http://dev-explore.appinventor.mit.edu/tutorial-type/clock-timer 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 MoleMash for App Inventor 2 http://dev-explore.appinventor.mit.edu/ai2/molemash <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><img style="float:right;" src="/sites/all/files/ai2tutorials/moleMash/MoleOnEmulator.png" /></p> <p>In the game <span style="color:green;">MoleMash</span>, a mole pops up at random positions on a playing field, and the player scores points by hitting the mole before it jumps away. This tutorial shows how to build <span style="color:green;">MoleMash</span> as an example of a simple game that uses animation.</p> <p>The tutorial assumes that you have completed the <a href="http://explore.appinventor.mit.edu/ai2/hellopurr">HelloPurr</a> and <a href="/ai2/paintpot-part1">PaintPot</a> tutorials.</p> <p><a href="http://cs.usfca.edu/~wolber/appinventor/bookSplits/ch3MoleMash.pdf">Download Book Chapter (PDF)</a></p> <h4 class="ai-header">Getting Started</h4> <p>Connect to the App Inventor web site and start a new project. Name it "MoleMash", and also set the screen's <strong style="color:green;">Title</strong> to "MoleMash". Open the Blocks Editor and connect to the phone.</p> <p>Also download this <a href="/sites/all/files/ai2tutorials/moleMash/mole.png">picture of a mole</a> and save it on your computer.</p> <h4 class="ai-header">Introduction</h4> <p>You'll design the game so that the mole moves once every half-second. If it is touched, the score increases by one, and the phone vibrates. Pressing restart resets the score to zero.</p> <p>This tutorial introduces:</p> <ul><li>image sprites</li> <li>timers and the <strong>Clock</strong> component</li> <li>procedures</li> <li>picking random numbers between 0 and 1</li> <li>text blocks</li> <li>typeblocking</li> </ul><h4 class="ai-header">The first components</h4> <p>Several components should be familiar from previous tutorials:</p> <ul><li>A <strong>Canvas</strong> named "MyCanvas". This is the area where the mole moves.</li> <li>A <strong>Label</strong> named "ScoreLabel" that shows the score, i.e., the number of times the player has hit the mole.</li> <li>A <strong>Button</strong> named "ResetButton".</li> </ul><p>Drag these components from the Palette onto the Viewer and assign their names. Put <span style="color:green;">MyCanvas</span> on top and set its dimensions to 300 pixels wide by 300 pixels high. Set the <strong style="color:green;">Text</strong> of ScoreLabel to "Score: ---". Set the <strong style="color:green;">Text</strong> of ResetButton to "Reset". Also add a <strong>Sound</strong> component and name it "Noise". You'll use <span style="color:green;">Noise</span> to make the phone vibrate when the mole is hit, similar to the way you made the kitty purr in <span style="color:green;">HelloPurr</span>.</p> <h4 class="ai-header">Timers and the Clock component</h4> <p>You need to arrange for the mole to jump periodically, and you'll do this with the aid of a <strong>Clock</strong> component. The Clock component provides various operations dealing with time, like telling you what the date is. Here, you'll use the component as a timer that fires at regular internals. The firing interval is determined by the Clock 's <strong style="color:green;">TimerInterval</strong> property. Drag out a Clock component; it will go into the non-visible components area. Name it "MoleTimer". Set its TimeInterval to 500 milliseconds to make the mole move every half second. Make sure that <strong style="color:green;">Enabled</strong> is checked.</p> <h4 class="ai-header">Adding an Image Sprite</h4> <p>To add the moving mole we'll use a <em>sprite</em>.</p> <p>Sprites are images that can move on the screen within a Canvas. Each sprite has a <strong style="color:green;">Speed</strong> and a <strong style="color:green;">Heading</strong>, and also an <strong style="color:green;">Interval</strong> that determines how often the sprite moves at its designated speed. Sprites can also detect when they are touched. In <span style="color:green;">MoleMash</span>, the mole has a speed zero, so it won't move by itself. Instead, you'll be setting the mole's position each time the timer fires. Drag an <strong>ImageSprite</strong> component onto the Viewer. You'll find this component in the Animation category of the Palette. Place it within <span style="color:green;">MyCanvas</span> area. Set these properties for the Mole sprite:</p> <ul><li><strong style="color:green;">Picture</strong>: Use mole.png, which you downloaded to your computer at the beginning of this tutorial.</li> <li><strong style="color:green;">Enabled</strong>: checked</li> <li><strong style="color:green;">Interval</strong>: 500 (The interval doesn't matter here, because the mole's speed is zero: it's not moving by itself.)</li> <li><strong style="color:green;">Heading</strong>: 0 The heading doesn't matter here either, because the speed is 0.</li> <li><strong style="color:green;">Speed</strong>: 0.0</li> <li><strong style="color:green;">Visible</strong>: checked</li> <li><strong style="color:green;">Width</strong>: Automatic</li> <li><strong style="color:green;">Height</strong>: Automatic</li> </ul><p>You should see the <strong style="color:green;">x</strong> and <strong style="color:green;">y</strong> properties already filled in. They were determined by where you placed the mole when you dragged it onto <span style="color:green;">MyCanvas</span>. Go ahead and drag the mole some more. You should see <strong style="color:green;">x</strong> and <strong style="color:green;">y</strong> change. You should also see the mole on your connected phone, and the mole moving around on the phone as you drag it around in the Designer. You've now specified all the components. The Designer should look like this. Notice how <span style="color:green;">Mole</span> is indented under <span style="color:green;">MyCanvas</span> in the component structure list, indicating that the sprite is a sub-component of the canvas.</p> <p><img src="/sites/all/files/ai2tutorials/moleMash/MoleMashDesigner.png" /></p> <h4 class="ai-header">Component Behavior and Event Handlers</h4> <p>Now you'll specify the component behavior. This introduces some new App Inventor ideas. The first is the idea of a <em>procedure</em>. For an overview and explanation of procedures, check out the <a href="/ai2/support/concepts/procedures">Procedures page</a>.</p> <p>A procedure is a sequence of statements that you can refer to all at once as single command. If you have a sequence that you need to use more than once in a program, you can define that as a procedure, and then you don't have to repeat the sequence each time you use it. Procedures in App Inventor can take arguments and return values. This tutorial covers only the simplest case: procedures that take no arguments and return no values.</p> <h4 class="ai-header">Define Procedures</h4> <p>Define two procedures:</p> <ul><li><span class="callblock-ai2">MoveMole</span> moves the <span style="color:green;">Mole</span> sprite to a new random position on the canvas.</li> <li><span class="callblock-ai2">UpdateScore</span> shows the score, by changing the text of the <strong style="color:green;">ScoreLabel</strong></li> </ul><p>Start with MoveMole:</p> <ul><li>In the Blocks Editor, under Built-In, open the Procedures drawer. Drag out a <span class="callblock-ai2">to procedure</span> block and change the label "procedure" to "MoveMole".<br /><pre class="box">Note: There are two similar blocks: <span class="callblock-ai2">procedure then do</span> and <span class="callblock-ai2">procedure then resu;t</span>. Here you should use <span class="callblock-ai2">procedure then do</span>.</pre><p>The <span class="callblock-ai2">to MoveMole</span> block has a slot labeled "do". That's where you put the statements for the procedure. In this case there will be two statements: one to set the mole's x position and one to set its y position. In each case, you'll set the position to be a random fraction, between 0 and 1, of the difference between the size of the canvas and the size of the mole. You create that value using blocks for <span class="mathblock-ai2">random fraction</span> and multiplication and subtraction. You can find these in the Math drawer.</p></li> <li>Build the <span style="color:green;">MoveMole</span> procedure. The completed definition should look like this:<br /><img src="/sites/all/files/ai2tutorials/moleMash/MoveMole.png" /><br /><span style="color:green;">MoveMole</span> does not take any arguments so you don't have to use the <a href="/ai2/support/concepts/mutators">mutator</a> function of the procedure block. Observe how the blocks connect together: the first statement uses the <span class="setblock">Mole.X set</span> block to set mole's horizontal position. The value plugged into the block's socket is the result of multiplying: <ol><li>The result of the <span class="mathblock-ai2">call random fraction</span> block, which a value between 0 and 1</li> <li>The result of subtracting the mole's width from the canvas width</li> </ol><p>The vertical position is handled similarly.</p></li> </ul><p>With <span style="color:green;">MoveMole</span> done, the next step is to define a variable called <span style="color:green;">score</span> to hold the score (number of hits) and give it initial value 0. Also define a procedure <span class="callblock-ai2">UpdateScore</span> that shows the score in <span style="color:green;">ScoreLabel</span>. The actual contents to be shown in <span style="color:green;">ScoreLabel</span> will be the text "Score: " joined to the value of <span style="color:green;">score</span>.</p> <ul><li>To create the "Score: " part of the label, drag out a text block from the Text drawer. Change the block to read "Score: " rather than "text".</li> <li>Use a join block to attach this to a block that gives the value of the score variable. You can find the join block in the Text drawer.</li> </ul><p>Here's how <span style="color:green;">score</span> and <span class="callblock-ai2">UpdateScore</span> should look:</p> <p><img src="/sites/all/files/ai2tutorials/moleMash/UpdateScore.png" /></p> <h4 class="ai-header">Add a Timer</h4> <p>The next step is to make the mole keep moving. Here's where you'll use <span style="color:green;">MoleTimer</span>. Clock components have an event handler called <span class="eventblock">when ... Timer</span> that triggers repeatedly at a rate determined by the <strong style="color:green;">TimerInterval</strong>.</p> <p>Set up <span style="color:green;">MoleTimer</span> to call <span class="callblock-ai2">MoveMole</span> each time the timer fires, by building the event handler like this:</p> <p><img src="/sites/all/files/ai2tutorials/moleMash/MoleMashTimerEventHandler.png" /></p> <pre class="ai-box">Notice how the mole starts jumping around on the phone as soon as you define the event handler. This is an example of how things in App Inventor start happening instantaneously, as soon as you define them.</pre><h4 class="ai-header">Add a Mole Touch Handler</h4> <p>The program should increment the score each time the mole is touched. Sprites, like canvases, respond to touch events. So create a touch event handler for <span style="color:green;">Mole</span> that:</p> <ol><li>Increments the score.</li> <li>Calls <span class="callblock-ai2">UpdateScore</span> to show the new score.</li> <li>Makes the phone vibrate for 1/10 second (100 milliseconds).</li> <li>Calls <span class="callblock-ai2">MoveMole</span> so that the mole moves right away, rather than waiting for the timer.</li> </ol><p>Here's what this looks like in blocks. Go ahead and assemble the <span class="eventblock">when Mole.Touched</span> blocks as shown.</p> <p><img src="/sites/all/files/ai2tutorials/moleMash/MoleMashTouchEventHandler.png" /></p> <p>Here's a tip: You can use <a href="/tips/typeblocking">typeblocking</a>: typing to quickly create blocks.</p> <ul><li>To create a value block containing 100, just type 100 and press return.</li> <li>To create a <span class="callblock-ai2">MoveMole</span> block, just type <span class="callblock-ai2">MoveMole</span> and select the block you want from the list</li> </ul><h4 class="ai-header">Reset the Score</h4> <p>One final detail is resetting the score. That's simply a matter of making the <span style="color:green;">ResetButton</span> change the score to 0 and calling <span class="callblock-ai2">UpdateScore</span>.</p> <h4 class="ai-header">Complete Program</h4> <p>Here's the complete <span style="color:green;">MoleMash</span> program:</p> <p><img src="/sites/all/files/ai2tutorials/moleMash/MoleMashComplete.png" /></p> <h4 class="ai-header">Variations</h4> <p>Once you get the game working, you might want to explore some variations. For example:</p> <ul><li>Make the game vary the speed of the mole in response to how well the player is doing. To vary how quickly the mole moves, you'll need to change the <span style="color:green;">MoleTimer</span>'s <strong style="color:green;">Interval</strong> property.</li> <li>Keep track of when the player hits the mole and when the player misses the mole, and show a score with both hits and misses. To do this, you'll need do define touched handlers both for <span style="color:green;">Mole</span>, same as now, and for <span style="color:green;">MyCanvas</span>. One subtle issue, if the player touches the mole, does that also count as a touch for <span style="color:green;">MyCanvas</span>? The answer is yes. Both touch events will register.</li> </ul><h4 class="ai-header">Review</h4> <p>Here are some of the ideas covered in this project:</p> <ul><li>Sprites are touch-sensitive shapes that you can program to move around on a <strong>Canvas</strong>.</li> <li>The <strong>Clock</strong> component can be used as a timer to make events that happen at regular intervals.</li> <li>Procedures are defined using <span class="callblock-ai2">to</span> blocks.</li> <li>For each procedure you define, App Inventor automatically creates an associated call block and places it in the My Definitions drawer.</li> <li>Making a <span class="mathblock-ai2">random-fraction</span> block produces a number between 0 and 1.</li> <li>Text blocks specify literal text, similar to the way that number blocks specify literal numbers.</li> <li><a href="/tips/typeblocking">Typeblocking</a> is a way to create blocks quickly, by typing a block's name.</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="/sites/all/files/ai2tutorials/moleMash/MoleMashBarcode.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/moleMash/MoleMash.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">Done with <span style="color:black;">MoleMash</span>? Return to the other tutorials <a href="/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/basic" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Basic</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, 03 Jul 2013 14:29:42 +0000 aaron 356 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/ai2/molemash#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 AlertMe http://dev-explore.appinventor.mit.edu/content/alertme <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;">AlertMe: </span>Texting in the background, when app is not running</h2> <p>The <span style="color:green;">AlertMe</span> app receives alert messages, and notifies the user even when the app is not currently running. If the app is running (visible on the screen), when it receives an SMS, the message will be displayed on the screen. If it's not running, the user will receive a <em>Notification</em> in the status bar, which can be viewed by pulling down the status bar. Tapping on the notification will start the app and display the message. The user can then click the <em>Acknowledge</em> button to send an acknowledgment to the sender that the alert has been received.</p> <table><tr><td><img src="/sites/all/files/tutorials/alertMe/notification.png" width="200" /></td> <td><img src="/sites/all/files/tutorials/alertMe/notification%20bar.png" width="200" /></td> <td><img src="/sites/all/files/tutorials/alertMe/alert%20me%20running.png" width="200" /></td> </tr><tr><td colspan="3" align="center"><a href="/sites/explore.appinventor.mit.edu/files/AlertMe.zip"><img src="/sites/explore.appinventor.mit.edu/files/downloadSourcebutton.png" style="float: center;border:none" width="250" /></a></td> </tr></table><pre class="ai-box"><strong>If you are using a device that does not have regular SMS enabled through a cell phone carrier and want to do texting over the internet (IP/wifi)</strong>, make sure you have a Google Voice account and you have the Google Voice app set up on your phone or tablet. For more information on how to do this, see the <a href="http://explore.appinventor.mit.edu/content/google-voice">Google Voice for Wifi Texting</a> tutorial. When you set up the texting component in the designer, be sure you have checked the <em>GoogleVoiceEnabled</em> property.</pre><hr /><h4 class="ai-header">The Designer</h4> <p>The interface of the app is pretty simple. It displays the time, phone number, and message of each of the alerts, as well as an acknowledge button. What really drives this app is the Texting component that you will add. 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> </tr><tr><td style="color:green;">Label</td> <td>Basic</td> <td>LabelHeader</td> <td>Displays the "Alerts" header.</td> </tr><tr><td style="color:green;">Label</td> <td>Basic</td> <td>LabelAlerts</td> <td> <p>Displays the incoming messages in a log</p> <p>Set width and height to <b>Fill Parent</b></p> </td> </tr><tr><td style="color:green;">Button</td> <td>Basic</td> <td>ButtonAck</td> <td>Sends an achknowledgment to the alert sender.</td> </tr><tr><td style="color:green;">Clock</td> <td>Basic</td> <td>Clock1</td> <td>Used to generate a time stamp in the message log.</td> </tr><tr><td style="color:green;">Texting</td> <td>Social</td> <td>Texting1</td> <td> <p>Receives and sends messages over Wifi.</p> <p><em>Only if you are using texting over wifi through Google Voice:</em> <b>Check the <em>GoogleVoiceEnabled</em> property.</b></p> </td> </tr></table><p>When you're done, the designer should look like this.</p> <p><img src="/sites/all/files/tutorials/alertMe/designer_0.png" /></p> <h4 class="ai-header">The Blocks Editor</h4> <p>The blocks have to handle two events: receiving a message and sending an acknowledgment. In each of these cases, they have to know who sent the message and what it said. We'll approach each of these actions in turn.</p> <p><b>Variables</b></p> <p>Since both procedures require that we know the alert message and who sent it, we will define two globalvariables: <span class="setblock">alertPhoneNumber</span> and <span class="setblock">alertMessage</span>.</p> <p><img src="/sites/all/files/tutorials/alertMe/variables.png" /></p> <p><b>The Message Received Block</b></p> <p>Incoming messages are handled by the <span class="basicblock">MessageReceived</span> block, which takes two arguments, the <span class="argblock">number</span> and the <span class="argblock">messageText</span>. For this app, we store the values of these arguments in our global variables, <span class="setblock">alertPhoneNumber</span> and <span class="setblock">alertMessage</span> respectively, and then construct a log entry and display it on the label using <span class="setblock">LabelAlerts.Text</span>.</p> <p><img src="/sites/all/files/tutorials/alertMe/AlertMeBlock.png" /></p> <p><b>Sending an Acknowledgment</b></p> <p>The user can acknowledge an alert by sending a message back to the sender. This is done using <span class="basicblock">ButtonAck.Click</span>, which constructs the message and sends it as shown here. </p> <p><img src="/sites/all/files/tutorials/alertMe/buttonclick.png" /></p> <h4 class="ai-header">Variations</h4> <p>Now that you have AlertMe working, here are some variations on the program you can make.</p> <ul><li>Modify the function of the <em>Acknowledge</em> button so you can choose to send different text, such as choosing between "What's up?", "On my way", and "Call you later."</li> <li>Change the blocks so the user gets an automatically generated response (without you clicking a button). This could be a setting you could enable if you are away from your phone or in a meeting.</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="/sites/all/files/tutorials/alertMe/AlertMeBarcode.png" /></p> <p>Or <a href="http://explore.appinventor.mit.edu/sites/all/files/tutorials/alertMe/AlertMe.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/alertMe/AlertMe.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">Done with <span style="color:black;">AlertMe</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/clock-timer" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Clock Timer</a> </li> <li class="field-item odd"> <a href="/tutorial-type/sms-texting" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">SMS Texting</a> </li> </ul> </section> Fri, 14 Jun 2013 16:13:33 +0000 aaron 318 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/alertme#comments Pizza Party with Fusion Tables http://dev-explore.appinventor.mit.edu/content/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/tutorials/pizzaParty/PizzaParty_FillInYourKeyAndID.zip"><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> <hr /><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="http://appinventor.mit.edu/explore/tutorials.html">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 invite each person individually, 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/tutorials/pizzaParty/pp_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="basicblock">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/tutorials/pizzaParty/pp_var_init.png" /></p> <p>Set up the <span class="callblock">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/tutorials/pizzaParty/pp_reset_form.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/tutorials/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">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. Do not use the math "equals" block. If all required information is present, it calls the procedure <span class="callblock">InsertDataInTable</span> (see below). The blocks for the <span class="basicblock">ButtonSubmit.Click</span> are shown here:</p> <p><img src="http://explore.appinventor.mit.edu/sites/all/files/tutorials/pizzaParty/pp_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">Procedure With Result</span> that takes a string and returns it surrounded by single quotes. The procedure <span class="callblock">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/tutorials/pizzaParty/pp_quotify.png" /></p> <p>To construct the query we use App Inventor's make 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/tutorials/pizzaParty/pp_insert_data.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">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="basicblock">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">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">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/tutorials/pizzaParty/pp_ft_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> <pre class="ai-box"><span style="color:black;">Done with PizzaParty?</span> <a href="/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/tutorials/pizzaParty/PizzaParty.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/data-storage" typeof="skos:Concept" property="rdfs:label skos:prefLabel" datatype="">Data Storage</a> </li> </ul> </section> Fri, 14 Jun 2013 16:09:56 +0000 aaron 311 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/pizzaparty#comments Mini Golf: Fling, TouchUp, TouchDown Gestures http://dev-explore.appinventor.mit.edu/content/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/tutorials/miniGolf/GolfSampleScreen.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/tutorials.html">basic tutorials</a> before continuing.</p> <p><a href="/sites/all/files/tutorials/miniGolf/FlingitMiniGolfTutorial.zip"><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 "Flingit 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>Canvas1</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 (this makes the sprite appear on top of sprites with lower numbers)</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>Clock1</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="basicblock">GolfBall.Flung</span> event handler to move the golf ball when it is flung. Essentially, 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 height="312" src="/sites/all/files/tutorials/miniGolf/golfBall.flung.png" width="564" /></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><img height="257" src="/sites/all/files/tutorials/miniGolf/clock1.timer.png" width="554" /></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 height="301" src="/sites/all/files/tutorials/miniGolf/setupNewHole.png" width="671" /></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="basicblock">GolfBall.CollidedWith</span> event handler, the named parameter is called "other". You can rename this by clicking once on the word "other" and typing in something new. Use a name that makes sense, as in this example where we use "ObjectHitByGolfBall". Notice that the <span class="controlblock">if then</span> block tests to see if the object involved in the collision with the golf ball (<span class="argblock">ObjectHitByGolfBall</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="argblock">component Hole</span><span> block, that can be found in the Hole drawer under "My Blocks". Do not use a text block here.</span></p> <p><img height="196" src="/sites/all/files/tutorials/miniGolf/golfBall.collidedWith.png" width="502" /></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="basicblock">EdgeReached</span> event. Note that you can find the "edge" value block under My Definitions. You can also use a developer’s shortcut by clicking anywhere on the workspace background and typing the word "edge". You’ll see a dropdown box appear. If you click the word "edge" you’ll see the value edge block appear on the screen. Big time saver!</p> <p><img height="101" src="/sites/all/files/tutorials/miniGolf/golfBall.edgeReached.png" width="334" /></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="setblock">StrokeCount</span> and <span class="setblock">Score</span>, and set their initial values to 0.</p> <p><img height="101" src="/sites/all/files/tutorials/miniGolf/strokeCount.png" width="265" /></p> <p>Then add the following blocks to the <span class="basicblock">GoflBall.Flung</span> event (red rectangle indicates new blocks):</p> <p><img height="500" src="/sites/all/files/tutorials/miniGolf/golfBall.flung_final.png" width="592" /></p> <p>Next add the following blocks to the Event that handles the ball hitting the hole:</p> <p><img height="462" src="/sites/all/files/tutorials/miniGolf/golf_collidewith.png" width="607" /></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. Try to understand all of these blocks before you move on.</span></p> <p><img src="/sites/all/files/tutorials/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 height="96" src="/sites/all/files/tutorials/miniGolf/globalMoveRight.png" width="249" /></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 height="383" src="/sites/all/files/tutorials/miniGolf/leftSprite.touchDown.png" width="599" /></p> <p><strong>Procedure MoveBallOnTee:</strong></p> <p>Make a new procedure <span class="callblock">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><img height="368" src="/sites/all/files/tutorials/miniGolf/moveBallOnTee.png" width="701" /></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="argblock">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 height="188" src="/sites/all/files/tutorials/miniGolf/clock1.timer_final.png" width="448" /></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> <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">MoveBallOnCourse:</span></p> <p><strong>MoveBallOnCourse Procedure</strong></p> <p><img height="214" src="/sites/all/files/tutorials/miniGolf/moveBallOnCourse.png" width="512" /></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 height="44" src="/sites/all/files/tutorials/miniGolf/holeCount.png" width="234" /></p> <p>Add the following blocks to the <span class="callblock">SetupNewHole</span> procedure: set <span class="setblock">global HoleCount</span> and set <span class="setblock">LabelHoleNum.Text</span>...</p> <p><img height="291" src="/sites/all/files/tutorials/miniGolf/setupNewHole_add.png" width="557" /></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 height="412" src="/sites/all/files/tutorials/miniGolf/buttonNewGame.click.png" width="450" /></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 height="181" src="/sites/all/files/tutorials/miniGolf/obstacleSprite1.png" width="604" /></p> <p>Each time the course is reset, position the obstacle will be positioned randomly. Add these blocks to the <span class="callblock">SetupNewHole</span> procedure:</p> <p><img height="277" src="/sites/all/files/tutorials/miniGolf/setupNewHole_final.png" width="706" /></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, and a screen shot of all the blocks (some are collapsed to save space.)</p> <p><img height="455" src="/sites/all/files/tutorials/miniGolf/components.png" width="231" /></p> <p><img height="642" src="/sites/all/files/tutorials/miniGolf/finalCode.png" width="710" /></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/tutorials/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/tutorials/miniGolf/FlingitMiniGolfTutorial.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"><span style="color:black;">Done with Mini Golf?</span> <a href="/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-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, 14 Jun 2013 15:45:30 +0000 aaron 308 at http://dev-explore.appinventor.mit.edu http://dev-explore.appinventor.mit.edu/content/minigolf#comments