| This article has links to websites or programs outside of Scratch and Wikipedia. Remember to stay safe while using the internet as we cannot guarantee the safety of other websites. |
| This article or section may not have content matching Scratch Wiki editing standards. Please improve it according to Scratch Wiki:Guidelines and Scratch Wiki:Editing Conventions. (February 2020) |
The game loop is a method for writing games. The entire game runs in one loop, which handles the updating and drawing of all the sprites in the game. The updating makes changes to the sprite and all the drawing happens when the draw message is received. This style of programming is called modular design and makes games easier to design and change.[1]
State Machines
Control over program execution is performed by a state machine. State machines help organize our code as the behavior being modeled grows more complicated.[2] For this tutorial, we will create a simple top-down shooter using a game loop to control all the sprites.
The Main Loop
Create a sprite called "main" and use the Scratch editor to hide it permanently. The backbone of the game loop is a loop block, which triggers the update and drawing blocks every frame by broadcasting messages. It also calculates the frame rate.
Place this code in the main loop sprite
when gf clicked set [game state v] to [start] set [old time v] to [0] forever set [delta time v] to ((timer) - (old time)) set [old time v] to (timer) broadcast [update v] broadcast [display v] end
What it Does
The game loop broadcasts the "update" message, a message to recalculate the game's data based on new information, such as pressed keys. The "display" message tells sprites to update the screen to reflect the updated data. The body of the game loop is sometimes known as a "tick". The "delta time" variable gets the execution time of a tick, to be used in calculating motion and values that change over time.
A broadcast-and-wait is not necessary as the broadcasts are queued to run in their correct order after the the loop finishes its iteration.
The Update Message
The update message updates the game's variables and handles the game logic. Every sprite will have its own update block.
Code for the player spaceship sprite
when I receive [update v]
if <(game state) = [play]> then
set [show? v] to [true]
if <key [left arrow v] pressed?> then
change [x v] by ((-10) * (delta time))
end
if <key [right arrow v] pressed?> then
change [x v] by ((10) * (delta time))
end
if <key [space v] pressed?> then
create clone of [laser v]
end
else
set [show? v] to [false]
end
What it Does
This code is basically self-explanatory; the spaceship is moved with the left and right arrow keys, and the space bar shoots a laser.
Code for the enemy sprite
when I receive [update v]
if <(game state) = [play]> then
if <(my state) = [attacking]> then
if <touching [laser v]?> then
set [my state v] to [exploding]
else
change [y v] by ((-10) * (delta time))
if <(y) < (-160)> then
set [game state v] to [lose] // If the enemy gets to the player, then the game is lost.
end
end
if <(my state) = [exploding]> then
delete this clone
end
end
else
set [show? v] to [false]
delete this clone
end
What it Does
This is the behavior of the enemy sprite. This sprite has its own state machine because it has different behaviors for advancing towards the player and dying.
Code for the laser sprite
when I receive [update v]
change [y v] by ((60) * (delta time))
if <<(y) > (180)> or <touching [enemy v]?>> then
delete this clone
end
What it Does
This is the code for the laser. The laser moves up, and disappears if it hits an enemy or goes off the top of the screen (y > 180).
Code for the play button sprite
when I receive [update v]
set [x v] to [0]
set [y v] to [-100]
if <<(game state) = [start]> or <(game state) = [lose]>> then
set [show? v] to [true]
end
What it Does
Every game tick your play button is going to check to see if you finished playing and are ready to play again.
As you can see, different sprites respond with different behavior to the same message/ state change.
The Initialization Message
Some states are not called during the main loop but they are still states that your sprites will enter during your game. The initialization state (sometimes called the 'create' or '_ready' in godot) is only called once before the sprite enters/transitions into one of the states in the main loop.
Place this code in your enemy sprite
when I receive [init enemies v]
set [clone? v] to [true]
set [y v] to [160]
repeat (5)
set [x v] to [-240]
repeat (23)
change [x v] by (20)
go to x: (x) y: (y)
create clone of (myself)
end
change [y v] by (-20)
end
set [clone? v] to [false]
What it Does
This code creates 5 rows of 20 enemy sprites at the top of the screen. You will have to adjust the size and length of the rows to support your sprites size.
Place this code in your laser sprite
when I start as a clone hide set [x v] to ([x v] of [player v]) set [y v] to ([y v] of [player v]) set [clone v] to [true] set [show? v] to [true]
What it Does
This code initializes the laser sprites (it can only be called once when the sprite starts as a clone) position and visibility.
Controlling the Game
The player needs some way to control when the game starts, so let's include this code in the play button.
Place this code in your play button sprite
when this sprite clicked broadcast [init enemies v] and wait set [game state v] to [play] set [show? v] to [false]
What it Does
It shows the button at the start and after the player loses, and clicking it transitions the game to the playing state.
These "game states" keep our code manageable, even when it grows complicated. The "game state" is held in a a global variable so that all sprites can use it to control their own behavior and the behavior of other sprites. For example, the spaceship can only moved when the "game state" is set to "play".
The State Machine
With the game loop concept, what code runs is controlled by a "state machine". A state machine is a set of logical states, and your game will move/transition from one state to another, when certain conditions are met. For example, every game tick the enemy sprite checks if <(y) < (-160)> then and if this is true then the state machine transitions from the *play* state into the *lose* state.
The Draw Message
The draw message tells the sprites to update their appearances based on the changes made in the update block.
Place this code in the player sprite and the button sprite
when I receive [draw v]
if <(show?) = [true]> then
go to [front v] layer
show
else
hide
end
go to x: (x) y: (y)
Place this script in the enemy sprite and the laser sprite
when I receive [draw v]
if <(clone?) = [true]> then
if <(show?) = [true]> then
show
else
hide
end
go to x: (x) y: (y)
end
Examples
- Game Loop Example by BDCDACCIP
- Template 2D Project by awesome-llama-test