3D - A Jumping Game (Difficulty: 5)
CreatiCode last edited by
In this tutorial, you will build an exciting jumping game:
The player will jump through the platforms to reach the goal area, and a leaderboard of the fastest players will be displayed at the end.
To get started, please create a new project on the CreatiCode playground, remove the Sprite1 with the dog, and rename the “Empty1” sprite as “Player”.
In the Player sprite, add the following blocks. They will create a 3D scene with a grassland and show the 3D axes.
This is what you should get:
The Player sprite will contain all the code for controlling the running player. There are 3 other key components of this game:
- Platform: All the jumping boards
- Goal: The goal area
- Controller: The game control logic
Therefore, please add 3 empty sprites, and name them “Platform”, “Goal” and “Controller”.
Before we add code to create the player avatar, let’s first set up the game in the other 3 sprites. We can do that by sending out 3 messages and waiting until they are all handled completely.
Now let’s add the first board in the “Platform” sprite. It will be a large square box that is 400 by 400, with a thickness of 10. You can pick any texture for it, such as “Wood 07”.
It should look like this:
The boards will be floating in the air, so if the player avatar drops off the boards, it will lose the game. However, at this point, we are not sure yet how high these boards should be. Therefore, we can use a new variable called “Z Start”, and use this variable to set the z position of our boards. We will set this variable to 100 for now, which makes testing easier, and we can change this variable to a larger number later.
Now the board is floating at Z of 100:
To add the second board, instead of adding a new box, we will make a copy of the first board. This will not only be faster, but also save some storage space.
After copying the second board, we can still change its shape using the “update size” block. For example, we can make it 200 wide in the X direction and 800 long in the Y direction.
Now the new board will overlap mostly with the first board:
Now let’s decide where to move the second board. If you are not sure what’s its new coordinates, you can use the position tool to drag the board first. In the example below, we drag the second board forward, then add the "move to“ block, which will have the position values filled in automatically. We can still change the numbers, such as rounding up the Y position to 800. To keep it at the same level as the first board, we will still use “Z Start” for its Z position.
Whenever we add a new board, we use the same set of blocks: copy, update size and move. Therefore, it will make our program much shorter if we define a new block for these steps. We can still use a few input parameters to allow us to customize the size and position of each board.
Please make a new block named “add board” with 5 inputs like this:
Then move the 3 blocks into the new block’s definition stack, and plug in the 5 input blocks.
Now we can reproduce the second board using this new block:
Now you can freely add a few more boards using the new block “add board”. Here are some examples. Note that you can set the Z position above or below the starting board by adding a positive or negative number to “Z Start”.
They will look like this:
Now the platform is ready, we can switch back to work on the “Player” sprite.
First, let’s add a new avatar. You can pick any avatar provided by the system. Add 3 animations to it: “Jump in Air”, “Run” and “Victory”. Move it to Z position of 200, which is above the first board.
Also, let’s add a follow-camera to track the avatar. Its “z offset” should be 50, which is half the height of the avatar. This makes sure the camera will target at the waist of the avatar instead of its feet.
The avatar will look like this now:
To make the avatar fall down, we need to assign gravity to it. We can start with a value of 800. If you use a larger number, the avatar will fall faster.
To make the avatar stand on the jumping boards (instead of falling through them), we need to turn on the “collision” between the avatar and all the other sprites, which includes the platform and the goal. Note that for avatars and models, we need to set the “z offset” to half of the object’s height.
Now the avatar will fall onto the board and stay there:
Now we are ready to add the main forever loop for controlling the player avatar using keyboard events (in the Player sprite). Since the avatar may be running on the board or jumping in the air, it is easier if we define 2 separate blocks to handle these 2 scenarios: “in air” and “landed”.
To tell whether the avatar is touching the jumping board. we can use the “sprite object blocked below” block, which will report a value of 1 if the avatar is blocked by any obstacle below it.
In the “landed” block’s definition (still in the Player sprite), we will first need to set the direction of the avatar, then set its speed. We can make a new block “set direction” that’s dedicated to setting the direction, which will make our program easier to read and change.
Now let’s define the “set direction” block. When the “w” key is pressed down, we would want the avatar to face the same direction as the camera. This way, the player can rotate the camera to control which way the avatar will move forward.
We can read out the direction of the camera using its “H-Angle” property (horizontal angle), and then make the avatar point in that direction.
Now if we run the project again, we can drag the left mouse button to rotate the camera, then press “w” to point the avatar in the same direction. In fact, if we keep pressing down the “w” key, the avatar will stay in the same direction as the camera when we rotate the camera.
The logic for the other 3 directions is very similar. “s” key will make the avatar face the camera, which is the opposite of the camera’s direction. “a” and “d” keys will make the avatar face the left or right sideways.
Now the avatar can turn in these 4 directions based on the current camera direction:
To give the player more control over the avatar, let’s add the 4 diagonal directions. For example, when the player presses down both “w” and “a” at the same time, we can turn the avatar towards the left forward direction, which will be the camera’s direction plus 315 degrees.
Note that we need to check for these 2-key combinations before checking single key presses. For example, we should check if “w” and “a” are both pressed, and only when that’s not true, then we can check if only “w” is pressed. If we check for “w” by itself first, then we would turn the avatar forward, and fail to handle the “w+a” combination.
Here is the result when we press 2 keys together:
Now we can control the avatar’s direction, we should make it move whenever any of the 4 keys are pressed. If none of them are pressed, we should make the avatar stop.
Note that the “forward speed” will make the avatar move in the direction it is currently facing.
Now our avatar can move around when we press the keys:
When the player is running, we should also set its animation to “Run”. And when no key is pressed, we should switch back to the “Idle” animation.
Now we get a running avatar:
When the SPACE key is pressed, we will make the avatar jump up. We can set the “rising speed” for this purpose.
Recall that in step 11, we have already set the avatar’s “gravity”. Here is how gravity and rising speed work together:
- When we press SPACE, the rising speed becomes 300, which will make the avatar go up.
- Over time, gravity will reduce the rising speed gradually, so the rising speed will become smaller and smaller. As a result, we will see that the avatar will still be rising, but it is slowing down.
- When the avatar’s rising speed becomes 0, it has reached the highest point for this jump, and it will begin to fall.
- The gravity will continue to reduce the rising speed, which makes the avatar fall faster and faster.
- When the avatar reaches an obstacle or the Z position of 0, it will stop falling, and its rising speed is reset to 0.
Here is what the jump looks like:
When the avatar is in the air, we need to change its animation to “Jump in Air”. We can do it in the “in air” block’s definition:
Now the jumping animation is displayed. However, you will notice a small issue: the avatar’s body is shifted to the right a little bit when it jumps.
This is most likely caused by an error in the avatar’s animation data. To fix it, we can add an offset of -7 in the x direction, which will shift the avatar to the left by 7 units:
Here is the corrected jump animation:
When the avatar is in the air, should we allow the player to change its facing direction? If we want to keep the game close to reality, then we should not allow it, since no one can change the body’s moving direction halfway through the jump. However, if we allow this, it will make the game much more fun to play, since the player will have more control on the avatar.
In this game, let’s allow it. This can be simply done by reusing the “set direction” block:
Now after the avatar has jumped up, we can still change its flying direction using the w/s/a/d keys:
Now we need to answer a similar question: if the avatar jumps straight up (with a forward speed of 0), should we allow the player to add a forward speed to the avatar mid-air? Again, to make the game more fun, let’s enable this control. We can just duplicate these blocks from the “landed” block:
Note that we don’t need to change the animation, since the avatar will stay in the “Jump in Air” animation when it is in the air. Now we can press SPACE to make the avatar jump straight up, then press one of the w/s/a/d keys to make it move:
Currently, the avatar always moves at a speed of 300 units per second. To make the game more fun, we can allow the player to run faster if the “w” key is pressed down continuously. It will feel like the avatar gains some “momentum” when it keeps running forward.
To make the running speed changeable, we need to use a new variable “player speed” to represent it. This variable should be set to 300 initially, which will be the default speed of the avatar. It is a good idea to place all variable initialization code at the very beginning, so it is easy to find these blocks.
Next, we should use the “player speed” variable when we set the avatar’s forward speed and rising speed. If the player’s speed is larger, then the avatar will run faster and jump higher. We need to do it in both “landed” and “in air”.
Now let’s speed up the avatar by changing the "player speed“ variable. We can simply check if the “w” key is pressed in the “landed” block’s definition.
- If it is pressed, we increase the “player speed” variable by 5, unless it is already at 900 or higher.
- If it is not pressed, we reset “player speed” to 300.
Now we can clearly observe the speed up of the avatar. Note that if we press “w + a” or “w + d”, the “w” key is still pressed down, so the avatar will also speed up.
When the player is running faster, its animation still remains at the same speed. We can make the running animation run faster as well, which will make it easier for the player to observe the speed up.
Please create a new variable named “animation speed”, and use it as the speed ratio for the “Run” animation. We can calculate its value using the “player speed”. For example, when the player’s speed is 300, the animation should play at 100% speed ratio. When the player’s speed is 900, the animation should play at 300% speed ratio. Therefore, the animation speed equals 100 times the ratio of player speed over 300.
You can now observe that the animation also speeds up when the avatar runs faster:
Now let’s make the avatar cast a shadow onto the jumping board. This will not only make the game look more realistic, but also give the player some hint on where the avatar will land when it jumps up in the air.
To use shadows, we need to do 3 things: add a light source, make the avatar cast shadow, and make the jumping board receive the shadow.
The light source should be added at the very beginning, before we add any new object. Since the “grass land” scene already contain some fairly bright lights, we need to remove them first.
To cast the shadow, we should add a directional light to simulate the sunlight. We can call it “light1”. The direction of the light is x = -0.1, y = 0, z = -1: it will be from top to bottom, but slightly skewed to the left (negative x direction), so we can see some shadow even when the avatar is standing still.
After adding these 2 blocks, the avatar becomes pretty dark:
To lighten it up, let’s add another ambient light source. Its intensity should be low, such as 50, otherwise, it will make the shadow hard to see later.
Now the avatar looks pretty clear:
To make the avatar cast shadows, we should do it right after we add the avatar:
To make the jumping board receive and display the shadow, we need to change each board right after it is added. This has to be done in 2 places in the Platform sprite:
Now you should get a nice shadow like this:
Now we are ready with the avatar and the platform, the next step is to handle game completion. First, we need to add a goal area at the end of the platform.
In the Goal sprite, when we receive the “Add Goal” message, we can add a cylinder with a rainbow texture behind the last jumping board. It should be given the name of “goal”, and it should receive and display shadows as well. Here are some example blocks:
This goal area will look like this:
Before we add more code, it’s time to clean up our code a little bit, since the main stack of blocks in the Player sprite is getting too long.
Let’s define a new block named “main loop”, and move the forever loop there:
To win the game, the avatar has to be standing on the goal. In the main loop, whenever the avatar has landed on some obstacle, we should check if that obstacle is the goal.
If that obstacle’s name is “goal”, then we know the player has completed the challenge. We should broadcast a “Victory” message, and then exit the forever loop using a “break” block.
Note that these new blocks are all added under the condition that the avatar is blocked below. Also, after the “break” block, the forever loop will stop repeating, so the player will no longer be able to use the keyboard to control the avatar.
After the player has completed the challenge, we should show some celebration animations. We need to stop the avatar by setting its speed to 0, then start the “Victory” animation. We should also turn the avatar towards the camera so we can see the front face of the avatar. Lastly, we should zoom in the camera to show a close-up view of the avatar.
Here is the celebration scene:
Since the game is about who can complete the entire run in the shortest time, we need to use a timer to count how many seconds the player has used.
We need to show a “Start” button at the beginning of the game, so the player can start the timer when he or she is ready.
We should add this button in the “Controller” sprite, using a button widget. Note that you need to run the “add button” block first to add it to the stage, then when you add the 2 bocks below it, you will see the button in their dropdowns.
The button will look like this:
Before the “Start” button is clicked, the player should not be able to control the avatar. After the player clicks the “Start” button, the player gains control of the avatar, and we should start the timer.
To make sure we control the different stages of the game correctly, we can make a new variable “game stage”. It will be set to “waiting to start” at the very beginning. After the “Start” button is clicked, we change the game stage variable to “started”. Later, when the player arrives at the goal area, we would receive the “Victory” message, and that’s when we will move the game to the next stage, which is “finished”.
Before the game starts, the player should not be able to control the avatar, since we have not started the timer yet. In the “Player” sprite, we will wait until the game stage is changed to “started” (triggered by the button click) before we enter the forever loop.
When the “Start” button is clicked, we should remove that button, and add a label at the bottom to show the timer value.
It will look like this when we click the “Start” button:
After we add the timer label, we can reset the timer to 0, and start showing the current time using the timer label. We can repeatedly update the timer every 0.1 seconds. We will keep doing this until the game stage changes to “finished”.
Here is a test run for the timer. You will see that the timer starts after the “Start” button is clicked, and stops when the avatar lands on the goal board.
After a player finishes the game, we need to record the game time as his/her “score", which will be used to rank that player on the leaderboard.
To do that, we can use the “record player score” block from the “Game” category, which is one of the extensions.
After that, we should add another button to allow the player to look at the leaderboard.
Here is what the button would look like:
When the new button is clicked, we should display the leaderboard. We would want to show the top players who have used the least amount of time to arrive at the goal area. Since each player’s “score” is just the game time, we should show the players with the “lowest” scores.
Note that if a player runs the game multiple times, all game times will be recorded, but the leaderboard will only show the best record for each player.
The leaderboard will look like this, which shows the ranking, the player name, the best game time for that player, and the date when this record is created.
The player can close this leaderboard by clicking the “x” on the top right.
Now our game is complete. For the last step, let’s move all platforms and the avatar higher to a z position of 5000. We can also hide the 3D axis now.
And here is the final demo of the game:
You can extend this game in many ways. Here are some example ideas:
Platform Shape, Size and Position: You can add platforms in different shapes, such as cylinders and spheres. They can be in different sizes and they do not have to be center aligned.
Rotated Platforms: You can rotate the platforms so that the avatar will be running up-slope or down-slope.
Models: Instead of using simple shapes for the platforms, you can also use models, such as sofa beds or hamburgers.
Rewards: You can add additional objects on the platforms, so they will provide additional help to the player when the avatar reaches them. For example, one such type of reward item can be a bottle of power drink, which would double the avatar’s speed for 10 seconds.