CPSC 110-08: Computing on Mobile Phones
Spring 2012

Mole Mash Part II

CS Principles

This activity addresses the concept that programming is a creative process. It also introduces the idea of a procedure, another example of abstraction. It focuses, in part, on the following learning objectives:

Introduction

In this lesson we will add enhancements to the Mole Mash app that you worked on for homework. We will add the following enhancements:

Review

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:

Keeping Track of Misses and Hits

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).

If/Then Control

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.

Updating the User Interface

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:

Testing the Revised App

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.

Varying the Mole's Speed

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.

Speeding up the Mole

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:

Automatically Speeding Up the Mole

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:

Summary and Wrap Up

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: