3D Physics - A Mini Pool Game (Difficulty: 4)
CreatiCode last edited by info-creaticode
- Add Physics Bodies for 3D Objects
- Set a Physics Body’s Moving Speed
- Get Properties of a Physics Body
- Updating color
- The grid material
- The button widget
- The label widget
In this tutorial, you will create a simple pool game using the physics engine. The player will use a white cue ball to hit a red target ball into a square pocket.
Please create a new project in the CreatiCode playground. Remove “Sprite1” with the dog, as we will just need to use the “Empty1” sprite.
Please add the following blocks to initialize an empty scene, enable the physics engine, and set up the camera and 3D axes.
Please make 3 new blocks:
- add table for adding the pool table with a pocket;
- add balls for adding the balls;
- check target for checking if the target ball has fallen into the pocket.
Then run them after initializing the scene:
This is a good way to organize your code blocks based on the tasks they perform.
Now let’s start with the pool table. To keep it simple, we will make a table with a square pocket in the center.
First, please add 4 planes, and move them diagonally to the 4 corners:
Here are the blocks for adding and moving them. For example, for the blue plane, its center is at x of 5000, which is half of its width of 10000, so its left edge is overlapping with the Y axis.
Next, we’ll shift each plane by 100 units in the X and Y directions, so that they leave a square hole at the center of size 200 by 200.
Here are the code changes. For example, for the blue plane, its center is moved to the right (from x of 5000 to 5100), so its left edge has a 100-unit gap from the Y-axis.
Now let’s add some grid lines to make the 4 planes look like one:
Here are the new blocks for applying the grid material. The same block is applied to all 4 planes. Feel free to pick any color you like:
Now we just need to add physics bodies to all 4 planes. We can use the “box-shaped” bodies for planes. Their “mass” should be 0, since the pool table should not move. Also, we need to use low restitution and high friction on them to simulate a real pool table.
Here is the block to be added for each of the 4 planes:
Once the ball falls into the square pocket, we need to trap the ball there. To do that, we can add a square plane 90 units below the table surface. Since the ball diameter will be 100 units, this makes sure the ball will get stuck in the pocket:
The pocket bottom should have no restitution, so the ball won’t bounce out of the pocket. It should also be static with a ma*s of 0. Here are the 3 blocks for adding it:
Now we are done with the table, so let’s switch to work on the “add balls” block. First, let’s add a red ball named “target ball”. We can update its roughness and brightness to make it look like a plastic ball:
Here are the blocks for adding the ball:
We will assign a mass of 100 to the ball, so that it will move when it i[censored]. We will also use high restitution to get a good speed when the cue ball hits it. In addition, we will make the target ball frozen for now, so that it will not move while we set up the shot. We will unfreeze it when we make the shot.
Next, we’ll add the white “cur ball”:
The blocks for adding the cue ball are very similar. It should have exactly the same type of physics body as the target ball.
To help the player specify where to aim the cue ball, let’s add a yellow “aim ball”. We will shoot the cue ball toward this aim ball later. Since the aim ball is not real, we will make it slightly transparent, and also allow the user to drag it on the table. Note that because the aim ball also has a physics body, it will not overlap with the target ball when we drag it. Also, since the target ball is frozen, the aim ball will not affect the target ball’s position.
Here are the blocks for adding the aim ball:
By now we are ready to allow the player to shoot the ball. First, please add 3 widgets for player inputs:
- A slider to allow the player to specify how fast to hit the cue ball.
- A button “Shoot” to make a shot on the cue ball.
- A button “Reset” to try again.
Here are the blocks for adding them:
When the player clicks “Shoot”, we should shoot out the cue ball towards the aim ball. We can set the speed of the cue ball’s physics body using the value of the slider. So here is the block:
However, when we click the “Shoot” button, the cue ball would not move at all. The reason is that we have set both the cue ball and the target ball to be frozen when they are created. Therefore, we need to unfreeze them first:
Now the cue ball will shoot out:
There is one more problem. The yellow aim ball is only there to help us aim the cue ball, and it is not supposed to really hit the target ball. Therefore, we need to remove the aim ball after the cue ball is shot out. Here is the complete code:
Now the cue ball will move towards the aim ball, then it will hit the target ball:
When the “Reset” button is clicked, we should put the balls back to where they were, so that the player can try again. This step is actually very simple: we just need to run the “add balls” block again. Since the 3 balls are all named, when we try to create them again, the existing ball will be removed for us automatically.
Here is what happens when you click “Reset”:
After the player takes a shot and clicks “Reset”, it would be nice to place the aim ball where he was aiming at. This way, he can continue to improve the aim ball’s position based on the previous attempt.
To do that, we need to make 3 changes:
- Make 2 new variables “x” and “y”, and set their initial values to the initial position of the aim ball:
- Use these 2 variables to set the aim ball’s position in “add balls”:
- Store the aim ball’s new position into these 2 variables when we shoot the cue ball:
After these changes, wherever we move the aim ball, it will go back there again when we reset the balls:
When the target ball falls into the pocket, we can see that its Z position is exactly -40. That’s because the ball holder is at the Z position of -90, and the ball radius is 50.
Given this knowledge, we can repeatedly check the z position of the target ball to see if it has been pocketed:
When we know the target ball has been pocketed, we can show a success message using a new label.
Now if we run the program, the buttons are not showing up anymore. Don’t panic. The reason is that “check target” now contains a forever loop, so any block that comes after the “check target” block will not run. To fix this, we just need to move the “check target” block to the bottom of the stack:
Here is the final demo of the game:
Now you know how to set up the basic game, there are many ways to extend this project to make it more fun. Here are some example ideas:
Different Ball Positions: you can use different positions for the cue ball and target ball.
Walls and Obstacles: you can add other objects (boxes or cylinders) on the table to serve as walls or obstacles. They may block the cue ball or target ball to make it more challenging. On the other hand, the balls may need to rebound off these objects to get to the pocket.
Multiple Target Balls: you may require the player to shoot 2 or more balls into the pocket one by one.
Multiple Pockets: there may be more than one pocket, so the player needs to select which pocket to aim at.
Slopes: you can also add some slopes on the table, so that the cue ball or target ball will fly up to jump over some obstacles, or jump onto a higher layer of the table.
More Levels: Like most games, you can design multiple levels with increasing difficulties. As the players become more proficient, they will enjoy more challenges.