2016년 12월 29일 목요일

Mole Mash 2 with Sprite Layering for App Inventor 2


What You're Building
This tutorial shows you how to build a game similar to the Whac-A-MoleTM arcade game. Specifically, your goal is to tap a mole that randomly pops out of one of five fixed holes. Every time you succeed, your score is increased by one point.
In order to highlight new App Inventor features — the Advanced tab and Sprite Z-layering — this app takes a different approach than the original Mole Mash tutorial, which you do not need to have completed 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 basic tutorials before continuing.

Introduction

This tutorial includes:

1. Creating a list of components
2. Using functionality from the Advanced section of the Blocks Editor to get and set properties of arbitrary components
3. Having game events controlled by the Clock component
4. Using Sprite Z-layering to ensure that one sprite (ImageSprite or Ball) appears in front of another

Getting Started

Connect to the App Inventor web site and start a new project. Set the screen's Title 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.

Set up the Components

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 X and Y properties. Additional instructions are below the picture.
Create the following components by dragging them from the Palette into the Viewer.
Component TypePalette GroupWhat you'll name itPurpose of Component
CanvasDrawing and AnimationGameCanvasThe game field
ImageSprite (5)Drawing and AnimationHole1 ... Hole5Holes from which the mole can appear
ImageSpriteDrawing and AnimationMoleThe mole
HorizontalArrangementLayoutScoreArrangementTo display the score
LabelUser InterfaceScoreTextLabelTo hold "Score: "
LabelUser InterfaceScoreValueLabelTo hold the score (# of times the mole was hit)
ClockUser InterfaceMoleClockTo control the mole's movement
SoundMediaBuzzerTo vibrate when the mole is touched

Make the following changes to the components' properties:


ComponentAction
Canvas1Set BackgroundColor to Green. Set Width to 320 pixels. Set Height to 320 pixels.
Hole1Set X to 20 and Y to 60 (upper left).
Hole2Set X to 130 and Y to 60 (upper center).
Hole3Set X to 240 and Y to 60 (upper right)
Hole4Set X to 75 and Y to 140 (lower left).
Hole5Set X to 185 and Y to 140 (lower right).
MoleSet Picture to "mole.png". Set Z to 2 so the mole appears in front of the other ImageSprite s, which have the default Z value of 1.
ScoreTextLabelSet Text to "Score: ".
ScoreTextValueSet Text to "0".
Don't worry now about setting the Picture property for the holes; we'll set the property in the Blocks Editor.

Add Behaviors to the Components

Here is an overview of what we need to create blocks to do:
1. Create global variable:
a. holes: a list of holes

2. When the app starts:
a. Populate the list of holes.
b. Set each hole's Picture property to "hole.png".
c. Call procedure MoveMole (below).

3. Create a procedure MoveMole to:
a. Set local variable currentHole to a random hole from the list holes.
b. Move the mole to the location of currentHole.

4. Make MoleClock call MoveMole whenever its timer goes off (every second).

5. Implement a handler that does the following when the mole is touched:
a, Add one to the score.
b. Make the phone briefly vibrate.
c. Call MoveMole.
To proceed, switch to the Blocks Editor.

Creating Variables

Create the variable holes. For now, we will give it a "dummy" initial value of an empty list; we'll set the real initial value in the Screen1.Initialize event handler, which gets executed each time the app loads the screen. (For technical reasons, components cannot be referred to in variable initialize blocks, which are run before the app has started.) Here is a picture and list of the blocks you will need:

Block typeDrawerPurpose
initialize global holes toVariablesHold a list of holes.
create empty listListsCreate an empty list, to be filled in when the program starts.
As always, comments (created by right-clicking on a block) are encouraged but not required.

Starting the App

The first event to occur in any program in Screen1.Initialize, 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 Picture property to "hole.png", and call MoveMole. Since we have not yet written MoveMole, we will create an empty procedure with that name, which we will fill in later.
Below are a picture and table of the blocks you need to create. Note that the "Any ImageSprite" drawer is found under the "Any component" tab at the bottom of the list of Blocks in the Blocks Editor.

Block typeDrawerPurpose
Screen1.InitializeScreen1Specify what should happen when the app starts.
add items to listListsAdd the following values to...
get global holesVariables...the list of holes:
Hole1Hole1-the upper left hole
Hole2Hole2-the upper center hole
Hole3Hole3-the upper right hole
Hole4Hole4-the lower left hole
Hole5Hole5-the lower right hole
for each hole in listControlSpecify that we would like a variable named "hole"....
get global holesVariables...to take on each of the values in the list holes .
set ImageSprite.Picture of component ... toAny ImageSpriteSet the Picture property of...
get global holeVariables...the ImageSprite referred to by the variable hole ...
" " (hole.png)Text...to the picture of the empty hole.
to procedure (MoveMole)ProceduresCreate an procedure, to be filled in later, for moving the mole.
call MoveMoleProceduresCall MoveMole to make the first placement of the mole.
Compare the for each block to the equivalent blocks that would be necessary without it:
Compare the for each block to the equivalent blocks that would be necessary without it:
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.

Moving the Mole

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:

Block typeDrawerPurpose
initialize local currentHole to
(there are two types of 'initialize local': take the one that fits the procedure block)
VariablesSave the...
pick a random itemLists...randomly selected...
get global holesVariables...hole.
call Mole.MoveToMoleMove the mole to the...
ImageSprite.XAny ImageSprite..x-coordinate of...
get local currentHoleVariables...the chosen hole...
ImageSprite.YAny ImageSprite...and the y-coordinate of...
get local currentHoleVariables...the chosen hole.

We now need to specify that MoveMole should be called whenever MoleClock's Timer goes off. We just need two blocks to accomplish that:


Block typeDrawerPurpose
MoleClock.TimerMoleClockWhen the timer goes off...
call MoveMoleProcedures...move the mole.

Registering Touches

Finally, we need to specify what happens when the mole is touched. Specifically, we want to:Registering Touches

1. Increment the score.
2. Make the phone vibrate briefly.
3. Move the mole.
We can easily translate these to blocks:

Block typeDrawerPurpose
Mole.TouchedMoleWhen the mole is touched...
set ScoreValueLabel.Text toScoreValueLabel...update the visible score to...
+Math...the result of adding...
1Math...1 [and]...
ScoreValueLabel.TextScoreValueLabel...the previous score.
call Buzzer.VibrateBuzzerMake the phone vibrate for...
100Math...100 milliseconds.
call MoveMoleProceduresMove the mole to a new location.

Final Program



Final Program

Variations

Here are some variations you might want to implement:

⦁ Adding a Reset button to set the score back to 0.
⦁ Having the score depend not just on the number of hits but also the number of misses and escaped moles.
⦁ Increasing the speed of the game of mole movement if the player is doing well and decreasing it if the player is doing poorly.
⦁ Adding a second mole on a different timer.
You can see how to implement the first two variations in the original Mole Mash tutorial.

Review

Here are some of the ideas covered in this tutorial:

⦁ Putting components in a List.
⦁ Performing an operation on every component in a List using the for each block and Advanced features.
⦁ Placing an ImageSprite on top of another, using their Z properties to control which goes in front.
⦁ Using the Clock component to control game play.
⦁ Creating a procedure and calling it from multiple places.
Looking for more information about Mole Mash? Check out the Book Chapter for more explanation and background information.

Done with MoleMash 2? Return to the other tutorials here.

Scan the Sample App to your Phone

Scan the following barcode onto your phone to install and run the sample app.

Download Source Code

If you'd like to work with this sample in App Inventor, download the source code to your computer, then open App Inventor, click Projects, choose Import project (.aia) from my computer..., and select the source code you just downloaded.
Tutorial Version: App Inventor 2


Tutorial Difficulty: Intermediate Tutorial Type: Sprites Clock Timer Game

댓글 없음:

댓글 쓰기