Turn off Lights - A
11
11
Turn Off Lights is a variation of the famous old Whack-a-Mole game: this one promoting the socially useful message of saving electricity. In the game, a light bulb (represented by an ImageSprite
) pops up at random positions on the screen. A player can score by touching the light bulb before it disappears.
This app uses animation, a clock, and randomness to move the ImageSprite
around the canvas. This tutorial guides you through the basic steps in creating the animation.
TurnOffLights
app on a mobile deviceThe UI for our this app will consist of four types of Components:
Canvas
, Label
, Clock
Sound
ImageSprite
Vertical Arrangement
The Canvas
serves as the background where the light bulb jumps around. The light bulb is represented by an ImageSprite
that is contained in the Canvas component. We'll come back to this. The Clock
is used as a timer to move the ImageSprite
to a random spot on the Canvas every time the Clock
ticks. The Sound
is used to vibrate the phone or play a sound whenever the player hits the ImageSprite
.
To begin with, set the various Screen1
properties as shown in the UI screenshot above, including AppName
, ScreenOrientation
, Title
and others. Next, drag and drop a VerticalArrangement
component from the Layout
drawer and set its height and width to Fill parent
. The Canvas
and other component will be contained within this arrangement and will fill the screen. By using a VerticalArrangement
, we can guarantee that all of its components will be visible on the screen without scrolling.
You have used the Canvas
component for drawing in the Paint Pot tutorials. In this app Canvas
is used to support animation. App Inventor uses two types of components that can move for animation, Balls
and ImageSprites
, both of which are contained within a Canvas
component. First, we'll add the Canvas
component.
Canvas
component from the Palette's Drawing and Animation
category into the VerticalArrangement
. . Canvas
's width and height to fill-parent. Canvas
's BackgroundImage
to kitchen-picture.jpg
. Add the Label
to the UI, right underneath the Canvas in the VerticalArrangement
. Name the label LabelSaveElectricity
and set its text property to "Help Save Electricity!"
As mentioned before, the light bulb is represented by an ImageSprite
, a component that can move (like a Ball) and can also display an Image (unlike a Ball). ImageSprites
can only be used on a Canvas
.
ImageSprite
component from the Palette's Drawing and Animation
drawer onto the Canvas
. ImageSprite
's picture property to the lightbulb.jpg
image file, which is included in the template's Media
panel.ImageSprit
's height and width properties to 50 pixels each.ImageSprite
to "LightBulbSprite".We will use a Sound
Component to vibrate the device when the player successfully touches the light bulb. Drag and drop a Sound
component from the Palette's Media
category into the Viewer. It will be named Sound1
and will appear as a non-visible component.
The ImageSprite
component has a Speed property, which controls the Sprite's movement. However, for this app, we won't be using that property. Instead, we will use the Clock
component to move the Sprite to a random location on the canvas whenever the clock ticks. The Clock
has a Timer
event that can be used to move the Sprite to a new random location whenever the Timer
event fires. In effect, every time the Timer
ticks, the Sprite will 'jump' to a new random location.
Clock
component from the Palette's Sensors
category into the Viewer. It will be named Clock1
and it will appear at the bottom of the Viewer as a non-visible component.Clock
's TimerInterval
property to 1000
milliseconds. This will make the clock tick every second.In order to get the Sprite moving, we'll first set up a Clock.Timer
event that will allow the Sprite to 'jump' to various positions randomly with the help of some Math
blocks that are used for randomness. Once the Sprite is moving we'll need to make the device vibrate each time the user touches the Sprite (light bulb).
To construct this you will pull the when Clock1.Timer
block from the Clock1 drawer, the MoveTo
block from the LightBulb
drawer, and two number blocks from the Math
drawer.
The Clock.Timer
event is triggered periodically. If you have set the Clock
's TimerInterval
property to 1000, this event will trigger every 1000 milliseconds, or every second. If you are testing the app, you'll see that the Sprite jumps to the location x=100, y=100 and just stays there. The event keeps triggering, but after the first time the Sprite is already at 100,100 so it doesn't appear as if anything is happening.
What we really want is for the Sprite to move to a random location each time the clock triggers. For this, drag out two random integer blocks from the Math drawer, and plug them in as seen to the right.
Now you should see the Sprite move around randomly every 1000 ms., but stay within the top left section of the Canvas.
Of course the upper limit of 100 is incorrect. We really want the Sprite to jump around anywhere on the Canvas. For this, we can use the Width and Height properties of the Canvas. Pull out Canvas.Width
, Canvas.Height
from the Canvas drawer and modify your blocks as seen.
Now you should see the LightBulb jumping randomly all over the canvas.
As we learned in an earlier lesson, having identical segments of code in two separate locations in the app is not a good programming practice. To fix that, let's define a moveRandom
procedure and call it to manage moving the ImageSprite
to a random location.
When you define a procedure in a programming language you are creating an abstraction. The procedure represents a particular algorithm. Once you define the procedure, it encapsulates the details of the algorithm (hides the details). To execute the algorithm, you only need to call the procedure. When calling the procedure, you aren't necessarily aware of the details of the algorithm. Thus, defining and using procedures helps reduce the complexity in our programs and makes them easier to read, modify, and maintain.
In our app, the Screen.Initialize
and Clock.Timer
events both do the same thing and call the same blocks to move the ImageSprite
randomly. Whenever you copy-paste, as we did, a little bell should go off in your head: I need a procedure! In this case, the moveRandom
procedure is appropriate.
to procedure
block from the Procedures
drawer.Screen.Initialize
and place them in "moveRandom".Open the Procedures
drawer again. You should now see a block, "call moveRandom". Pull it out and place it in Screen.Initialize
. Take out the blocks for Clock.Timer
as well and replace them with a call moveRandom block.
Your app should work exactly the same, with the Sprite moving around randomly.
Similar to Paint Pot, the Turn Off Lights app will also use a Touched
event. However, this touched event is used differently. When a player touches the Sprite we want them to get some type of feedback for their accomplishment. This helps give the user feedback when taking actions within the app. For now, let's make the phone vibrate for 500 milliseconds (half a second) whenever the Sprite is touched:
LightBulb.Touched
block from the LightBulb
drawer.Sound1.Vibrate
block from the Sound1
drawer.Vibrate
interval to 500 millisecs.Vibrate
block inside the Touched
block.NOTE that not all Android devices contain a vibration component. If your device does not vibrate, replace the Vibrate
block with a Sound1.Play
block and set the Sound1.Source
property (in the Designer) to the beep.mp3
file.
You can think of procedures like "shortcuts" in your code. Where a complicated process, such as taking the sum of a list of numbers, can simply be given a shortcut name like "sum". Once you make the procedure you will not have to worry about how it works, i.e. assume sum works correctly, instead simply use the call to the shortcut name in other code blocks.