3D - A Physics Puzzle Game (Difficulty: 3)
CreatiCode last edited by
In this tutorial, you will build a 3D puzzle game using the physics engine. The player can click on any box to remove it, and the goal is to make the ball roll into the basket.
Please create a new project in the CreatiCode playground. Remove the sprite named “Sprite1”, and rename the “Empty1” sprite to “Main”.
After that, please also add 3 empty sprites, and name them “Boxes”, “Basket” and “Ball”. This way, we can organize our code blocks using different sprites for different objects in the scene.
Now let’s work on the code for the “Main” sprite. Please add the following blocks, which will initialize an empty 3D scene and add show the 3D axis in it. We also move the camera further away from the center so we can see all objects to be added.
You can use the “+” button to quickly add these blocks from the “3D Scene” category like this:
As a result, this is what you get when you click the green flag:
To use the physics engine in the project, you need to initialize it for the scene first. Let’s use a gravity value of -1000, which will make the ball fall quickly.
Now it’s time to add the boxes. The “Main” sprite will send a message to the “Boxes” sprite, which will do the actual work of creating the boxes.
In the “Main” sprite, add the “broadcast and wait” block with a new message “add boxes”. The “wait” part will make sure the boxes are added successfully before we continue to add other objects.
In the “Boxes” sprite, we will receive that message using this block:
In the “Boxes” sprite, let’s create our first box, and apply the “grid material”. Pick any color you like for the box and the grid lines.
These blocks will give us a box of size 100 at the center of the scene:
Now let’s add a physics body to the box. Here are the parameters:
- shape: The shape should be “box”, since we are working on a box object.
- mass: We should set its mass to 0, which will make sure the box would never move or rotate.
- restitution: We will use a high value of 80%, so the ball will have a good bounce on the box.
- friction: We will use a low value of 30%, so the ball will not be slowed down much when it rolls over the box.
Now we will need to make many copies of this box into 5 rows and 5 columns. The “copy by matrix from center” block is designed for this purpose. Note there are 2 blocks starting with “copy by matrix”, so please make sure you pick the correct one.
This block will copy the box along the X-axis by 2 columns both left and right. Similarly, it will copy these columns forward and backward by 2 rows. In addition, since the first box has a physics body, all the copied boxes will also have the same type of physics body as well.
One issue we find is that the grid lines are not very helpful. We would like it to show the edges of the boxes instead of their centers. We can fix it by shifting the grid lines by 50 units in each direction:
Now we can clearly see the 5 by 5 array of boxes:
Next, we need to add another layer of boxes on top of the current layer. We will start by adding a new box and moving it right above the first box. Since the first box is at the Z position of 0, and the box height is 100, so the second box should be at the Z position of 100.
The box will appear here:
Now we can use this new box as the “seed” to make another layer of boxes. You can duplicate 3 blocks from above, and then update them to a different color:
You should now get 2 layers like this:
The third layer can also be added quickly through duplication. All that you need to change are the Z position and the color:
Now we are done with all 3 layers:
We need to allow the player to click on any box to remove it. To do that, we first need to turn on the picking event for the boxes:
This block will make sure all boxes added in the “Boxes” sprite will respond to mouse picking, so we do not need to do it for each box one by one.
Whenever any box is picked, its name will be stored in the variable “picked object name”. Therefore, we can use that name to remove that box like this:
Now you can try to click on the boxes to remove them. Note that you can still drag the mouse pointer to rotate the camera, and you won’t remove any box when you do that.
Now it’s time to add the ball. To get started, we need to send another command message from the “Main” sprite to the “Ball” sprite.
In the “Main” sprite, add this “broadcast and wait” block with the “add ball” message:
Then in the “Ball” sprite, add this block to receive the message:
Now let’s add a volleyball model in the “Ball” sprite. The size of the volleyball will be 190, so it is slightly smaller than the size of 2 boxes. We also need to set its “z position offset” to half of its height, which is 95. This is because all models have their origin point at the bottom, but we want the volleyball to rotate around its own center.
The initial position of the ball will be x of 100, y of 100 and z of 400:
The ball will appear slightly above the boxes. It won’t fall because we have not added a physics body to it yet, so it is still not managed by the physics engine.
Now let’s add a sphere-shaped physics body to the volleyball. Its mass should be set to 1, so that it will fall due to gravity. The restitution and friction values are the same as the boxes.
With the physics body added, the volleyball will fall and then bounce on the boxes. And when we remove boxes below it, it will fall again:
The last object for our game is the square basket. Similar to the other objects, we will use a new message “add basket” to add this basket.
In the “Main” sprite, broadcast this new message:
Then in the “Basket” sprite, receive that message:
Now let’s add code for the basket in the “Basket” sprite.
The basket can be represented by a rectangle tube, with 4 sides and a bottom. Its opening will be 200 by 200, which is slightly larger than the ball’s size.
We can apply a grid material to it, and move it to the bottom front of the boxes:
The basket will appear here:
The basket will need to hold the ball, so it also needs a physics body. We can use the “rectangle tube” shape, which can only be used on rectangle tube objects.
Its mass should be 0, so that it won’t move. Let’s also set a low value for restitution, so that the ball won’t bounce out of it.
Now the game is ready for playing! If the ball falls into the basket, it will be held there.
If the player fails to bring the ball into the basket, he or she can simply restart the project. However, if the ball has landed in the basket, we need a way to declare the player has succeeded.
Since the ball won’t move when it is held in the basket, we can check for 2 conditions: the speed of the ball should be 0 in the Z direction, since the ball is not falling. The Z position of the ball should be a fixed number. We can find out that Z position by running this block in the “Ball” sprite by itself:
Therefore, we just need to repeatedly check for those 2 conditions in the “Ball” sprite like this:
When the player has succeeded, we can show a big “Success” message. This can be done using the label widget. Please add the “Widget” extension, then add these blocks to the “Ball” sprite:
Note that you need to run the “add label” block first to add it to the stage. After that, you can add the “set widget background” and “set text style” blocks, and select “label1” from the dropdown.
If you run the project now, you will find that the basket is not added to the scene. It turns out that in the “Main” sprite, we are still waiting for “add ball” to complete before adding the basket. However, since the “add ball” message will trigger a forever loop in the "Ball’ sprite, we will keep waiting for it to complete.
To fix it, please go to the “Main” sprite, and switch those 2 messages:
Finally, let’s clean up the scene with 3 small changes in the “Main” sprite. First, let’s switch to the “Blue Sky” scene. Second, let’s hide the 3D axis. Third, set the camera v-angle to 65 degrees.
Here is the final demo of the game:
Now you know how to set up a basic game, there are many ways for you to modify this game:
Different Ball/Basket Positions: You can move the ball and basket to different positions, which will require a different solution.
Different Boxes: There are unlimited ways for you to design where to place the boxes.
Tilted Boxes: The boxes can be rotated slightly to create more interesting slopes.
Unremovable Boxes: To make the game more challenging, you can make some boxes unremovable. So the player has to find a path around these obstacles.
Special Rewards: You can place special reward items in the scene to make the game more fun. For example, you can place a gold coin inside a box, and whenever the ball touches this coin, the size of the ball would reduce by half, or some new boxes would appear in the scene.
Game Mechanism: You can add other game mechanisms to the project, such as a limit on time or the number of boxes that can be removed. Also, you can check the Z position of the ball to determine if the player has failed.
Level Up: When the player has completed one level, you can show a button for the player to continue to the next level.