3D - Crazy Highway Game (Difficulty: 6)
-
Introduction
In this tutorial, you will learn to build an exciting car game called “Crazy Highway”. The player will be driving a car to cut through fast-moving cars on a highway, and try to get to the finish line as soon as possible. You will be practicing a few useful techniques, including making clones, creating a simple AI car, and collision detection.
Step 1 - Create a New Project with 4 Sprites
Please create a new project on the CreatiCode platform, and change it to contain these 4 empty sprites:
- Player: this sprite will allow us to manage the player’s car;
- AI: this sprite will be managing all the AI cars;
- Highway: this sprite will be used to create the highway and the finish line;
- Widgets: this sprite will be used for all the widgets on the stage.
Step 2 - Create an Empty 3D Scene
In the Player sprite, add the following blocks to create an empty 3D scene with the 3D axis in it:
Step 3 - Broadcast 4 Messages
To build the game scene, we need to go through 4 steps. In the Player sprite, we can broadcast 4 messages one by one to help us organize the code blocks in order:
- “Add Highway”: add the highway and the finish line in the Highway sprite;
- “Add AI”: add the AI cars in the AI sprite;
- “Add Player Car”: add the player’s car in the Player sprite;
- “Prepare to Start”: tell all sprites to prepare for the game to start;
Step 4 - Add the Highway
Now let’s add the highway in the Highway sprite. First, when we receive the “Add Highway” message, let’s add a plane to represent the highway. It will be 500 units wide in the X direction, and 40000 units long in the Y direction. We can use a grid material to cover the box with grid lines:
It should look like this:
Note that we are using a density of 0.8 so that the highway is divided into 4 lanes exactly. Each lane will have a width of 125.
Step 5 - Add Grassland on the Side
Now let’s add another large plane to represent the grassland on the 2 sides. The grassland will have the same length as the highway, but it is much wider. It should be moved to a Z position that’s below the highway for a few units, so that it does not overlap with the highway.
It should look like this:
We are done with the Highway sprite for now. Will revisit it later when we add the finish line.
Step 6 - Add an AI Car
The cars controlled by AI are the key components of the game that makes the game “crazy” and fun. These cars will appear at random positions and they will be shifting left and right to block the player’s car.
Since we will be adding many AI cars, we will make clones of the AI sprite. Also, the cars will all be copied from one original car model, which will make it fast to load the game (compared to loading many different car models).
To add this “original” car, please go to the AI sprite, and add these blocks:
We are moving the car to a very low z position so that we won’t see it. This way, all the visible AI cars will be clones of this original car.
Step 7 - New Variables and the “Add AI Car” Block
Since we will be adding many AI cars, we need to create a new block for this task. It will take 4 inputs: the “ID” of the clone, its initial x and y positions, and its moving direction (0 degrees for moving forward, and 180 degrees for moving towards us).
Each cloned sprite will have different values for these 4 parameters. The ID of a clone can be set when we create the clone, so the other 3 parameters should be carried using new variables: “my x”, “my y” and “my dir”. Note that these variables need to be set to “for this sprite only”, so that different clones of this sprite can have their own set of variables:
Now we can create the “Add AI Car” block to set these parameters and create a new clone:
Now let’s will use this block to add the first clone at x of 180, y of 500, and direction of 0 (facing forward). Its clone ID will be 1:
Step 8 - Copy the Car Object inside the Clone Sprite
When the AI sprite is cloned, we will make a copy of the original car object, then set its initial position and direction.
After this step, we can see this car at its initial position:
Step 9 - Prepare the AI Car for Game Start
When the AI sprite receives the “Prepare to Start” message, it needs to move the car to its initial position, and reset its speed to 0. This message will be sent at the beginning, and also when we are ready to restart the game.
Note that we are checking if the “clone ID” of this clone is not “originalsprite”. This is a special value for this variable. The original sprite will have a clone ID of “originalsprite”, and the other clones will have IDs that we have assigned (“1” in this case). This way, the original sprite will not respond to this message.Also, we are stopping all other scripts (stacks of code blocks) in this sprite. This is useful when we are restarting the game, since we want to stop all existing blocks and prepare to restart.
Step 10 - Add More AI Cars
Now let’s add some more AI cars using the “Add AI Car” block. We will add 8 cars going forward on the right 2 lanes, and 8 cars coming towards us on the left 2 lanes. The cars will be a few hundred units apart from each other in the Y position. The cars on the left will start from further away.
They will look like this:
Note that at this point there will be 17 “AI” sprites: one original and 16 clones of it. The original sprite controls the original car model, which is hidden at a negative Z position. Each of the 16 clones manages one copy of the car, and it also has its own private variables like “my x” and “my y”. Whenever we broadcast a message like “Prepare to Start”, all 17 sprites will receive it. Because we are checking the “clone ID” is not “originalsprite”, only the 16 clones will process the message.
Step 11 - Add the Player’s Car
Now let’s switch to the Player sprite and add the player’s car. It needs to be named as “car”, so that we can refer to it later. Feel free to pick a bright color as its main body color. Move it to the first lane on the right.
Step 12 - Add a “Follow” Camera
Since the car will be driving forward, we need to change the camera type to a “follow” camera, so that the player’s car is always in our view range.
This is how it looks:
The distance and vertical angle work together to control the view angle and how far forward can the player see. We should let the player see far enough to avoid colliding with other cars, but also not too far down the road.The “z-offset” make the camera focus at a point 100 units above the car, so the player’s car appears at the bottom of the view.
We are setting the direction of the camera to “Free” for now, so that we can easily look at the car from different directions. When the game is ready to release, we need to lock it to the forward direction for the players.
Step 13 - Initialize the Player’s Car
When the “Prepare to Start” message is received in the Player sprite, we will reset the position and speed of the player’s car:
We are stopping all other scripts (stacks of code blocks) that are running first, so the blocks in this stack will have full control of the car.We are using a new variable “player speed” to keep track of the speed of the car. Its initial value is 300.
To make sure the car is standing still, we are setting its “rising speed”, “z rotation” and “forward speed” all to 0.
Step 14 - The Start Button
Now all the cars are placed at their initial positions, we are ready to get the game started. We will let the player click a “Start” button to start the game, so that we can start the timer at that point.
In the “Widgets” sprite, add the following blocks to add a button widget (from the Widget extensions) named “button1”. It says “Start” on it. If you can’t find “button1” in the dropdown menu for setting text style, you need to run these blocks once to add the button to the stage first.
Here is the button that the player sees:
Step 15 - Start the Game
When “button1” is clicked, we will start the game by broadcasting a “Start” message. We will also create a new variable “game state” to keep track of the progress of the game. It will be set to “started” when we click the “Start” button.
Step 16 - Start the Player’s Car
In the Player sprite, when we receive the “Start” message, we will enter a repeat loop, which will continue until the “game state” changes to “finished”. That happens when the car reaches the finish line.
In the repeat loop, we will work on 2 tasks repeatedly: set the car’s speed and direction based on the player’s keyboard input. So please make those 2 new blocks, then add them to the repeat loop:
Step 17 - Set the Speed of the Player’s Car
In the definition of the “set speed” block, we first set the forward speed of the car to the value of the variable “player speed”. This way, whenever we change the value of “player speed”, the car will change its speed right away.
The player can press the “w” key to make the car go faster, and the “s” key to slow down the car. We are making the car slow down much faster than speeding up, which is usually the case for real cars.
Now the car will start to run when we click the “Start” button:
Step 18 - Set Some Speed Limits
We do not want the player to run too fast or too slow. We can check the variable “player speed”, and adjust it if it is more than the upper bound of 1000, or if it is less than the lower bound of 100.
Step 19 - Set the Direction of the Car
In the “set direction” block’s definition, we can turn the car right or left by 1.5 degrees when the “d” or “a” key is pressed.
Now you can turn the car left or right:
Step 20 - Revert the Car Direction Automatically
To make the car easier to control, we are going to make it turn forward automatically. The player simply needs to release the “d” or “a” key, and we will turn the car back until it is going forward (along the Y axis) again.
For example, suppose the direction of the car is 10 degrees when we release the “d” key. That means the car is heading to the forward right. We will need to turn left to make the car move forward. The turning amount is 0.2 times the current direction, so when the direction is large, we will turn back faster.If the direction is less than -0.01, it means the car is heading left forward. So we need to turn it right automatically. Note that since “direction” is negative, we multiply it with -0.2 to get a positive degree value for turning right.
This is how it looks when we press then release the “d” and “a” keys:
Step 21 - Keep the Car Inside the Highway
Currently, the player can drive the car off the highway to avoid the AI cars. To fix that, we need to make sure the player can not turn right if the car is already at the right edge of the highway, and he also can not turn left if the car is at the left edge.
In the “set direction” block, we can add the following logic at the bottom:
The idea is that if the direction is greater than 0, meaning the player is trying to drive the car to the right, and also the x position is already 230 or more, then we simply set the car’s direction to 0. This way, the player can still turn left, but not right.The case for turning left is very similar. We need to set the car straight forward when the direction is less than 0, and the car’s x position is less than -230.
Now you can try to drive the car to the left or right edge of the highway:
Step 22 - Turn on Collision Detection
Whenever the player’s car hits an AI car, we need to stop the player’s car, and restart the game. To turn on the collision detection, add the following block when we add the player’s car:
It is a “Blocking” collision, so that the player’s car will stop when colliding with any AI car.The “z-offset” is set to 13, which is half of the car’s height. It will make sure the collider box is centered at the car’s center.
The precision is set to be “High”, which will use 5 detection rays in the front direction to cover all corners of the player’s car. You can set the “debug” parameter to “Yes” to examine the detection rays:
Step 23 - Restart the Game Upon Collision
When the player’s car hits any AI car, it will stop right there. We need to show a special animation to let the player know there is a collision, such as making the car jump up and turn around. After that, restart the game by sending out the “Prepare to Start” message:
Here is how it looks:
Step 24 - Drive the AI Cars Forward
Now let’s switch to the AI sprite and handle the “Start” message.
First, we’ll simply make the AI cars move forward.
Again, we need to check for the “clone ID” to make sure the original AI sprite won’t respond to this message. Only the 16 cloned AI sprites will handle the message.Also, each clone of the AI sprite will set the forward speed of the car object it controls.
Now all the AI cars will be moving forward:
Step 25 - Move the AI Cars Sideways
To make the game more challenging, we will make the AI cars randomly shift left or right. Let’s use a new private variable “side move speed” to represent its speed for moving left or right. Each clone will have its own side movement speed.
We can set this variable to a random number every 1 second, so the car may change its side movement direction or speed every second:
This is the result:
Step 26 - Keep the AI Cars inside the Highway
To prevent the AI cars from moving outside the highway, we need to add some limits to the side move speed. When the car is already on the right edge of the highway (x position > 230), if the side move is also to the right, we need to flip the sign of the side move speed (make it negative), so that car would move left instead.
Similarly, if the AI car is trying to move left when its X position is already less than -230, we need to make the speed positive, so that it will shift to the right.
Step 27 - Reusing the AI Cars
So far we are only using 16 AI cars, so if the player’s car runs past all of them, there will be no obstacles. Although we can keep adding new cars, it will slow down the program over time.
A much better idea is to reuse these AI cars: whenever an AI car runs past the player’s car, we “teleport” it to a far location down the road. So long as this happens outside the view of the camera, the player will feel like there are infinite AI cars down the road.
To make this happen, we first need to add a new variable “player’s car y position” that is shared by all sprites. In the Player sprite, we initialize this variable as the Y position of the player’s car, and keep updating it as the car moves forward:
Next, in the AI sprite, we check if the AI car is at least 150 units behind the player’s car, so it has already fallen behind the player’s camera view range. Then we can move it to a random Y position ahead of the player’s car. We can also shift its X position a little bit to make it more random:
Now if we zoom out the camera a bit, we will be able to see this teleporting “magic” at work. The AI cars behind the player’s car will disappear, and they will reappear far down the road:
Step 28 - Add the Finish Line
Now the core game mechanic is ready. We just need to add the game completion logic.
First, we will add a finish line. To make it easier to test our code, we can put it right in front of our car, with a Y position of 600. Later we can change it to a location further away down the road.
In the Highway sprite, we can add a new box to represent the finish line:
We can see it on the start screen:
Step 29 - Check for the Finish Line
Next, we need to repeatedly check if the player’s car has arrived at the finish line. Since we know the finish line is at the Y position of 600, we just need to compare the player’s car’s Y position with 600. When the car has arrived at the finish line, we stop the car, set the “game state” to “finished”, and also broadcast a message to “stop all”.
Step 30 - Stop All AI Cars
When the AI sprites receive the “stop all” message, they will stop the AI cars.
Now we can test to see that all cars will stop correctly:
Step 31 - Add the Timer Label
By now the game is playable, but we still need to improve the game interface a bit to show the player some useful information. Since the game is about finishing in the shortest amount of time, we should show the timer value.
In the Widgets sprite, after the “Start” button is clicked, let’s add a timer label at the bottom:
Step 32 - Display the Current Time
After adding the timer label, we will reset the timer to 0, and enter a repeat loop to update the timer label until the game is finished. Since the timer value has many digits, we will round it to a whole number. Note that there is a space letter before the “s” letter, so we will get a space between the timer value and “s”.
Now we can see the timer value at the bottom:
Step 33 - Display the Player’s Speed
Another very important piece of information is how fast the player is driving. We can add that information to the same label as well. Since real cars use “mph” (miles per hour) as the speed measure, we can use that here as well. We will divide the car speed by 10, so the forward speed of 300 will show up as 30 mph.
It looks like this at the bottom:
Step 34 - Show a More Precise Time At the End
When the player has arrived at the finish line, we will display a more precise timer value:
It looks like this:
Step 35 - Record the Player’s Time
We will add the player’s total time to the leaderboard, so that players can compete for the shortest driving time.
Step 36 - Display the Leaderboard
After recording the score, we will also add a button to allow the player to view the current leaderboard. When this button is clicked, we display the leaderboard with the players with the lowest score, which means the shortest completion time.
Step 37 - Display the Leaderboard At the Beginning
It would also be a good idea to display the leaderboard before the game starts, so that players can check their rankings without having to complete the entire game:
Step 38 - Clean Up
Our game is complete now. Let’s clean it up a bit.
First, let’s hide the 3D axis in the Player sprite:
Second, we will move the finish line far down the road, such as at a Y position of 19000. We would need to change it in 2 places.In the Player sprite, we need to change the “check for finish line” block’s definition:
Also, in the Highway sprite, we need to change the finish line’s Y position.
Here is a final demo of the game:
Creative Ideas
Here are some ideas for making your own version of this game:
-
Jumping: you can allow the player to jump the car over the AI cars for up to 3 times during the game.
-
Instant Speed Boost: you can allow the player to press a button to instantly boost the speed to the maximum speed.
-
More Lives: you can allow 3 lives for the player. When the player’s car hits an AI car, instead of restarting the game, you can reduce a life of the player. This way, you will only restart the game when all 3 lives are used.
-
Smarter AI Cars: the current AI controller is fairly simple. You can make it smarter. For example, they can try to avoid [censored]ping into each other, and also try to run at different speeds.
-
Collecting Rewards: You can place some reward items along the highway, so if the player’s car picks them up, it will gain additional powers, such as for jumping, speed boost or more lives.
-
Sound Effects: You can add some sounds when the car speeds up or hitting another car.
-
-
Hi,
I was trying to follow this tutorial, but I got stuck on step 8. When I run the program, it hangs on the add AI block and I have to refresh the page to stop it.
I believe it has to do with the create clone block and copy object share data. Because when I replaced the create clone block with the copy object block, it did work. Am I correct to understand that clones are for 2d sprites and copy object is the equivalent for 3D?Furthermore, in step 14 and 15 the images of the example blocks are the same.
-
You are right. The clone block had an update that introduced a bug. Now it is fixed.
We also updated the images in step 14.