![]() |
CPSC 110-08: Computing on Mobile Phones
|
In this lesson we will add enhancements to the Mole Mash app that you worked on for homework. We will add the following enhancements:
The homework version of Mole Mash has an ImageSprite (the mole) that jumps around to random locations on the Canvas according the signal of a Clock Timer. A score is kept and displayed, increasing by 1 every time the user touches the mole.
Some of the key concepts introduced by this app are:
To keep track of misses, we will need a global variable to keep track of the misses and we'll need a Label to display the number of misses. We'll also need an event handler that fires whenever the canvas is touched. Let's put these elements together.
In the App Inventor Designer drag a Label component onto your app and place it under the score label. Name it MissesLabel or something like that and change its text to say "Misses: ".
In the Blocks Editor define a global variable
named misses and set its initial value to 0.
A miss occurs when the user touches the Canvas, but doesn't
touch the mole. In order to handle this type of event we will need
a MyCanvas.Touched handler (in the MyBlocks > MyCanvas drawer).
In order to keep track of misses we're going to need an if/then control block, which you can find under the Control tab. This block allows us to say:
If the mole is not touched add 1 to the misses counter update the score
First let's put together the if clause by getting the if
block out of the Control drawer, the not block out
of the Logic drawer and the touchedSprite value out of
the MyBlocks > MyDefinitions drawer:
Next let's plug in the "add 1 to the misses counter" statement. In App Inventor this statement takes the following form:
Set global misses to misses + 1
To build this statement you'll need to combine blocks from the Math drawer and the MyBlocks > MyDefinitions drawer.
Let's also update the score, by calling the UpdateScore procedure we wrote in the previous version.
Procedural Abstraction: Here we see one of the advantages of defining a named procedure. We can call it or invoke it whenever we need it. Write once, use anywhere!
This is how the if/then block should look when you are done:
Finally, plug the if/then block into the MyCanvas.Touched
event handler to complete the handling of this event.
This block will keep track of the misses for our app, but it won't
update the score. In order to do that, you'll have to revise
the UpdateScore procedure.
Add a statement that will update the MissesLabel.Text. It should look very similar to the statement in the previous version that updates the ScoreLabel.Text.
Finally, don't forget to update the ButtonReset.Click
block to reset the misses variable, just as, in the
previous version, you reset the score variable:
At this point your app should include the following new or
revised blocks:
Once all of these elements have been put together, it is time to do some testing of the app. Connect the app to your phone and try playing the game, resetting periodically to make sure it is working correctly.
Recall that the Mole's speed is controlled by the MoleTimer's TimerInterval
property, which is initially set to 1000. That means that every second the Timer
will click and we will call the MoveMole procedure:
How should we vary the Mole's speed? There's lots of ways that this could be done:
And there are probably lots of other options.
To help us manage this complexity, let's define a procedure to speed up the mole:
To SpeedUpMole: Decrease the Timer.TimerInterval by 100 milliseconds
The problem with this procedure is: what happens if the TimerInterval gets too small -- e.g., less than 200 milliseconds? The Mole would be moving so fast that the game would become unplayable. To help avoid this, we can use an if statement to control when we decrease the interval:
To SpeedUpMole: if Timer.TimerInterval > 200 Decrease the Timer.TimerInterval by 100 milliseconds
Here's how this procedure looks in App Inventor:
Let's use this procedure to automatically speed up the mole whenever the user's score gets "too high". This means we have to decide where to call the procedure.
How about if we call the procedure every time we update the score. Whenever we update the score we can use an if/then block to compare misses and score and if the score is bigger by 3, we can speed up the mole:
If score - misses > 3 then do: SpeedUpMole
In App Inventor, this is how our revised UpdateScore procedure
will look:
Finally, don't forget to set the Timer.TimerInterval back to 1000
when the user clicks the ResetButton:
In this lesson we saw how procedures can help us break up our apps into parts that in turn help to reduce the app's complexity. Using procedures is an example of the divide-and-conquer principle, which we use all the time in every day life.
Some additional enhancements you might consider adding to this app: