3D Physics - A Pinball Game (Difficulty: 5)
CreatiCode last edited by info-creaticode
- Highlighting objects
- Copy to Mirror Position
- Enable Physics for 3D Scenes
- Adding Physics Bodies for 3D Objects
- Apply Force to Physics Bodies
- Limit Physics Body Movement Speed and Direction
In this tutorial, you will build a pinball game using the physics engine:
To get started, please create a new project on the CreatiCode playground, remove the Sprite1 with the dog, and rename the “Empty1” sprite as “Main”.
In the Main sprite, add the following blocks. They will create an empty 3D scene, display the 3D axes, and enable the physics engine with a gravity of -1000.
This is what you should get:
In this game, there are 4 types of objects: the surrounding walls, the ball, the trigger for bouncing the ball, and the targets to hit.
It is a good idea to organize your code using a different sprite for each type of object, similar to 2D Scratch projects. Therefore, please add 4 new empty sprites named “Walls”, “Ball”, “Trigger” and “Targets”.
To tell each sprite to build its part of the game, we need to send out 4 messages from the Main sprite:
Note that we are using “broadcast and wait” for these messages, so that we wait until each step is completed before the next step.
In each of the 4 new sprites, we should start with the “when I receive message” block, so that when the message is sent from the Main sprite, each sprite will know it’s time for it to get to work.
For example, in the “Walls” sprite, we should receive the “add walls” message like this:
The other 3 sprites should be very similar.
Now let’s work on the “Walls” sprite. The wall box can be represented by a big rectangular tube with 3 sides. We are leaving the bottom side open, so the ball may fall off the tube.
You can decide on the size and color of this box. For example, make it 500 by 1050 in width and length, and set its height to 110. The thickness can be 50:
Here is the block for adding the tube:
You can optionally attach some texture to the wall to make them look more realistic. For example, you can choose “Wood07” with a size of 1000:
Here is what you will get:
Now let’s add a physics body to the rectangle tube. It should have a mass of 0, since it will not be moving. Since we want the ball to bounce off the walls, we should give it a high restitution value, such as 80. Lastly, to make the ball spin when it touches the walls, we should add a bit of friction, such as 20.
Next, we will add a slope at the bottom right. It will be a box of size 200/50/100 in the X/Y/Z dimensions. Rotate it to -45 degrees around the Z-axis, and then move it to the X position of 160 and the Y position of -410. Lastly, add the same texture.
Here are the new blocks for this step:
We should use the same physics properties for the slope as the rectangle tube, so we get the same rebound effect when the ball hits the walls or the slope.
Now we need the same slope on the left side. It can be easily done using the “copy to mirror position” block in the “left-right” mode:
Now we have completed the “Walls” sprite:
Now let’s switch to the “Ball” sprite to add the ball. First, please add a sphere named “ball”, with a diameter of 30. Move it to the Y position of -400 and Z position of 10. Add any texture you like to it. Here is an example program:
This is what you should get:
The ball should have a mass greater than 0 since it will be bouncing around. Let’s just use the default mass of 100. Set its restitution to 100 so it will be bouncy. Give it a small friction like 20, so that it will spin when touching other objects, but won’t be slowed down much.
Now let’s view the entire board from the top. You need to switch back to the “Main” sprite, and add the “set camera” block to set its distance and view angle:
Now you get a view like this. It would appear the board is standing up, with the positive Y direction as the top direction, and the negative Y direction as the bottom direction.
Now it looks like the ball is floating. To make it move down automatically, we can apply a force to its physics body toward the negative Y direction. Switch to the “Ball” sprite, and add this block:
Now it looks like the ball is “falling” down from our view:
Next, switch to the “Trigger” sprite to add a trigger box at the bottom to hold and hit the ball. Its size should be 150/40/100 in the X/Y/Z directions, and please move it to the Y position of -480. You can pick any texture for it.
It will look like this:
Now let’s enable physics for the trigger. We will be moving it up and down, but its movement will not be affected by the ball or gravity, so we can set its mass to 0 as well. We’ll make its restitution 80, so it will bounce the ball, but also allow the player to hold the ball on it. Let’s set its friction to 100, so if the ball is spinning, then it will bounce in a different direction.
After this step, the ball will be held at the trigger box:
Now let’s switch to the “Targets” sprite, and add some cylinders to serve as targets. Whenever the ball hits any of these targets, the player will score some points.
To add the first target, please add a cylinder like this with a diameter of 60 and a height of 100. Please name it “10”, which will be the number of points the player gains whenever the ball hits this target. Move it to the top of the board, with a Y position of 300 and an X position of 50.
Here is what you should get:
Now let’s add a cylinder-shaped physics body for this target. Since it won’t be moving, its mass should be 0. We should set a restitution of 120, which will make the target very bouncy. Since it is more than 100, that means it will give the ball some extra power when the ball hits it. Also, let’s set its friction to 100, so it will make the ball spin.
Please duplicate the 3 blocks to add the first target, and use them to add some more targets. For example, here are the blocks to add 3 more cylinder targets, with names of “5”, “4” and “1”.
These targets should look like this:
When the user presses the SPACE key, we should move the trigger box “down” to a Y position of -540 in a very short time. When the user releases it, we should move it back to the starting position at Y of -480 in a slightly longer time.
Here are the blocks to be added to the “Trigger” sprite:
As a result, now we can use the trigger to hit the ball like this:
Whenever the ball hits a target, we are going to show some visual/auditory effects, and also add some points for that user.
To set up this event, we should broadcast a collision message whenever the ball collides with any object created in the Targets sprite.
First, add the “when I receive (message) with parameter” block, and use its dropdown to create a new message type of “hit target”. Also, create a new variable named “hit info”.
Next, add this block in the “Targets” sprite (below the blocks for adding the 4 targets):
This block will make sure whenever the ball touches one of the targets, this message will be broadcast.
When we receive the “hit target” message, the variable “hit info” will tell us which 2 objects have collided at which position. For this game, we only need to know the name of the target that is touched, which will be the second part of the “hit info” as separated by commas. Please create a new variable “target name”, and use it to store the name of the target:
For example, suppose “hit info” contains the text “ball,1,22.696,-78.908,9.598”, then “target name” will become “1”.
When a target is touched by the ball, let’s highlight it in white for a very short time like this:
To do that, we first need to create a highlight layer after setting up the collision message:
We also need to select the target by its name, and add it to the highlight layer for a very short time, then remove it from the highlight group:
If you keep playing the game for a while, you might find a “small” problem. Sometimes the ball is so fast that it would run through a target or the wall:
For a step-by-step breakdown, the physics engine moves the ball upward from position 1 to 3. The ball never touches the pink target, so the physics engine does not “know” they should have collided.
To fix this issue, we need to limit the ball’s speed, so that it never jumps through the target. To do that, add the following block to the Ball sprite, so that the ball’s moving speed will never exceed 1500:
Now our game is ready for play. Let’s make a few changes in the Main sprite to clean up the scene.
First, hide the 3D axis.
Second, you can choose a different scene, or add a different sky to serve as the background. That needs to be done before we set the camera’s distance.
Third, we can add some additional lights along the Y axis to make the side face of objects brighter.
Here is a final demo of the game:
You can extend this project in many ways. Here are some example ideas:
Different Targets: You can use targets of different shape/color/size/position.
Visual/Sound Effects: To make the game more fun to play, you can play a sound when the ball hits a target or the wall, or highlight the ball when that happens.
Game Over: you can check if the ball has fallen out of the board using its Z position, and if that’s true, show a “Game Over” message.
Scores: You can add a new variable “score” to keep track of the total points a player gets. You can add to this score whenever a target is touched.
Rewards: You can add new game items to the board, which will trigger some rewards when the ball hits it. For example, you can add another ball, so the player can use 2 balls to hit more targets.