Chapter 4.2 - LightsOff Tutorial
Time Estimate: 45 minutes
4.2.1. Introduction and Goals
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 a Sprite) 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 Timer, and randomness to move the Sprite around the canvas. This tutorial guides you through the basic steps in creating the animation.
Objectives: In this lesson, you will learn to :
follow an instructor-led walkthrough to create the TurnOffLights app on a mobile device;
continue learning how to navigate the Thunkable online programming platform;
develop your understanding of what a Thunkable program is;
develop your understanding of how timing, animation, and randomness are programmed;
develop your understanding of functions and procedural abstraction;
deepen your understanding of event-driven programming.

Getting Ready
Start a new project in Thunkable. Download the following files. You can upload them at the start via Assets on the left menu bar or upload them when you need to use them in the project.
The Turn Off Lights User Interface (UI)
Our app will consist of the following Components: Canvas, Label, Sprite. It will also need the following blocks (via the blocks tab): Timer and Sound.
The Canvas Stage serves as the background where the light bulb jumps around. The light bulb is represented by a Sprite that is contained in the Canvas component. We’ll come back to this. The Timer is used as a timer to move the Sprite to a random spot on the Canvas every time the Timer ticks. The Sound is used to play a sound whenever the player hits the Sprite.
Adding the Canvas
You have used the Canvas component for drawing in the Paint Pot tutorials. In this app, Canvas is used to support animation. Thunkable uses Sprites as components that can move for animation which are contained within a Canvas component. First, we’ll add the Canvas component.
Drag and drop a Canvas component from the Palette.
Set the Canvas’s width and height to 350.
Set the Canvas’s Stage1 Background Picture to kitchen-island-ideas-18-min.jpg.
Set the Stage1 height and width to 350.
Adding the Sprite
As mentioned before, the light bulb is represented by a Sprite, a component that can move and can also display an image. Sprites can only be used on a Canvas. A sprite is automatically included on a Canvas.
Set the Sprite_Type1’s Picture property to the lightbulb.jpg image file.
Set the Sprite_Type1’s Height to 48 and Width to 30 pixels.
Rename the Sprite to “LightBulbSprite”.
Adding the Save Electricity Label
Add the Label to the UI, right underneath the Canvas. Name the label LabelSaveElectricity and set its Text property to “Help Save Electricity!”
Adding the Timer
The Sprite 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 Timer block to move the Sprite to a random location on the canvas whenever the Timer ticks. The Timer has a Fires 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.
Add a Timer block from the Blocks tab of your Thunkable project. Under the App Features header, click the ⊕ icon next to Timers to add a Timer to your app. It will be named Timer1.
Set the Timer’s Interval property to 1 second. This will make the Timer tick every second.
Set the Timer’s Loops to true and Enabled to true.
Test the App as you Build It
As you build this app, test it by connecting to Thunkable Live on your device (phone or tablet) with the Thunkable Live app or using the Web Preview.
Coding the App’s Behavior
In order to get the Sprite moving we'll first set up a Timer Fires 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 play a sound each time the user touches the Sprite (light bulb).
Moving the Sprite
Consider the following blocks:

To construct this, you will pull the when Timer1 Fires block from the Timer1 drawer, the Move block from the Canvas Blocks Motion drawer, and two number blocks from the Math drawer.
The Timer Fires event is triggered periodically. If you have set the Timer’s Interval property to 1 second, this event will trigger 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 Timer triggers. For this, drag out two random integer blocks from the Math drawer and plug them in as follows:

Now you should see the Sprite move around randomly every second, 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 Stage1’s Width, Stage1’s Height from the Canvas drawer and modify your blocks as follows:

Now you should see the LightBulb jumping randomly all over the Canvas.
Giving the Sprite a Random Starting Place
When the app starts, and even before the Timer ticks start, we should place the Sprite randomly. We can do this by pulling out a Screen1 Starts block from the Screen drawer, copying the blocks within the Timer Fires event, and then pasting them in Screen1 Starts:

Refactoring: The moveRandom Function
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 function and call it to manage moving the Sprite to a random location.

Abstraction: When you define a function in a programming language, you are creating an abstraction. The function represents a particular algorithm. Once you define the function, it encapsulates the details of the algorithm. To execute the algorithm, you only need to call the function. When calling the function, you aren’t necessarily aware of the details of the algorithm. Thus, defining and using functions helps reduce the complexity of our programs and makes them easier to read, modify, and maintain.
In our app, the Screen Start and Timer Fires events both call the same blocks to move the Sprite randomly. Whenever you copy-paste, as we did, a little bell should go off in your head -- I need a function! In this case, the moveRandom function is appropriate.
Drag out a Function block from the Functions drawer.
Name the Function “moveRandom”.
Drag the blocks from Screen Starts and place them in “moveRandom”.
Open the Functions drawer again. You should now see a block, “moveRandom”. Pull it out and place it in Screen Starts. Take out the blocks for Timer Fires as well and replace them with a call moveRandom block.
Your app should work exactly the same, with the Sprite moving around randomly.
Handling the is clicked event
The Turn Off Lights app will also use a when is clicked event. However, this when is clicked 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 app play a sound whenever the Sprite is clicked:
Get a when Sprite_Type1 is clicked block from the Canvas Blocks Events drawer.
Get a Sound play block from the Sound drawer.
Place the Sound play block inside the is clicked block and change the sound to beep.mp3.
Add a moveRandom block to move the Sprite after it is clicked.
The finished block should look like this:

Test the app’s behavior by trying to touch the sprite as it jumps around. Does the device play a sound when you touch it?
4.2.3. Summary
In this lesson, you learned how to:
Learning Objective AAP-3.A.a: For procedure calls: a. Write statements to call procedures.
Learning Objective AAP-3.A.b: For procedure calls: b. Determine the result or effect of a procedure call.
Learning Objective AAP-3.B: Explain how the use of procedural abstraction manages complexity in a program.
Learning Objective AAP-3.C: Develop procedural abstractions to manage complexity in a program by writing procedures.
4.2.4. Self-Check
Q-1: An ImageSprite component can only be inserted into what other component?
A. Label
B. Ball
C. Button
D. Canvas
Q-2: True or False: You can drag and drop the ImageSprite Component from Animation tab directly onto the screen?
A. True
B. False
Q-3: What event causes the ImageSprite to move to a new random location?
A. When the Sound beeps.
B. When the user shakes the phone.
C. When the Clock.Timer ticks.
D. When the user tilts the phone.
Q-4: What value would you give the Clock’s TimerInterval property to have the ImageSprite move every 1.5 seconds?
A. 1.5
B. 150
C. 1500
D. 15
4.2.5. Reflection: For Your Portfolio
Answer the following portfolio reflection questions as directed by your instructor. Questions are also available in this Google Doc where you may use File > Make a Copy to make your own editable copy.
Last updated