[# 3] Make Minecraft with Python. -Improvement of player movement (concept of inertia) and collision detection-

Part of pictures, articles, images on this page are copyrighted by Mojang AB.

minecraft.png

Overview

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-" **

What to do this time

Last time, we did everything from drawing a model using test textures to implementing a player perspective.

--Improved player movement --Examination of collision detection

Improved player movement

sq6py-82p4x.gif 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. bo5ie-4w21m.gif

Why is the movement unnatural?

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.

solution

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. p8r6m-2cy1g.gif With this, the unnaturalness has finally disappeared. I was able to reproduce the original movement of Minecraft.

problem

It does not support diagonal movement.

Implementation of collision detection

p4xs6-53ohi.gif 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. image.png

Continue

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