Part of pictures, articles, images on this page are copyrighted by Mojang AB.
This is a project to reproduce the world-famous sandbox game "Minecraft" in the programming language "Python".
** Previous article: "[# 2] Make Minecraft with Python.-Model drawing and player implementation-" **
Last time, we did everything from drawing a model using test textures to implementing a player perspective.
--Improved player movement --Examination of collision detection
Don't you think the movement of the player you implemented last time is unnatural? This is because ** "move only when a key is pressed" **. In most 3D games, the player moves smoothly, but the movement of the player and objects is actually devised internally.
When you want to move an object or entity over time, for example, if you iterate with a for
statement or while statement
, ** the speed of each frame depends on the performance of your computer **, which is true. In a sense, it cannot be called "actual time".
Difficult to explain. I'm sorry if it's hard to understand.
The unnatural movement is probably due to ** the player's speed being constant ** and ** not slipping **. Even if you kick a cardboard box, it usually doesn't stop with "Kyu!" Unless it is a place where frictional force works.
The key to improving player movement is the ** delta time
** called ** "dt (DeltaTime)" **.
The delta time
represents ** how many seconds have passed between processing the last frame and executing this frame **.
Specifically, we will take advantage of delta time to introduce the concept of ** " Inertia "
** to players.
The function ʻon_key_press () passes information to the player from the time the keyboard button is pressed until it is released, so if a value is defined as **
n** while the key is pressed, then **
n It increases in proportion to the time you hold down `**.
In the program, we defined n
as velocity_x
and velocity_z
, respectively.
* Velocity = speed </ font>
#Player update event
def update(self, dt, keys):
if keys[key.W]:#front
self.position[0] += dx #Normal move processing
self.position[2] -= dz #Normal move processing
self.velocity_x += dt * 10 #dt is a very small value so multiply by 10
At this rate, velocity
will increase indefinitely in proportion to the time you press it.
Therefore, at the time of ʻupdate, the value of
velocity` is reduced by a certain rule.
Then set the maximum speed and check if the value is negative or exceeds the maximum speed.
If the value is negative, it returns to 0
, and if it exceeds the maximum speed, it returns to the maximum speed.
player.update()In the function
#Subtract the current value divided by 50
self.velocity_x -= self.velocity_x / 50
self.velocity_z -= self.velocity_z / 50
#If it is a negative value, it will be returned to 0.
if self.velocity_x < 0: self.velocity_x = 0
if self.velocity_z < 0: self.velocity_z = 0
max_inertia_speed = 0.2 #Sliding in proportion to the magnitude of the value
#If it exceeds the maximum speed, it will return to the maximum speed.
if self.velocity_x > max_inertia_speed: self.velocity_x = max_inertia_speed
if self.velocity_z > max_inertia_speed: self.velocity_z = max_inertia_speed
#Inertia that works to move forward
self.position[0] += self.velocity_x * dx #Add to the current coordinates, taking rotation into account
self.position[2] -= self.velocity_z * dz #Subtract from current coordinates, taking rotation into account
If you try it, you can see that it has inertia as shown below.
You can also see that the Velocity
in the upper left debug window is decreasing in proportion to the time.
With this, the unnaturalness has finally disappeared.
I was able to reproduce the original movement of Minecraft.
It does not support diagonal movement.
This is the biggest challenge in realizing Minecraft without using tools such as Unity.
If all blocks are 1.0
× 1.0
, it can be implemented relatively easily (it seems possible), but considering that collision detection (for example, stair blocks and doors) is custom-implemented for each block. I feel like it's a very big wall.
In Minecraft, ** ʻAABB (Axis-Aligned Bounding Box) `** allows you to freely define block collision detection and a bounding box just for the appearance. I want to implement it in Python as well. Is it tough on the stone? Personally, I can only think of decompiling Minecraft and reading the obfuscated source code with guts.
If anyone is familiar with collision detection, please give us some advice in the comments section.
The current situation is like this. * The gif could not be uploaded due to the video size. </ font> If the collision detection is successful, all you have to do is code.
Recommended Posts