| | import math |
| | import collider |
| |
|
| | FLYING_ACCEL = (0, 0, 0) |
| | GRAVITY_ACCEL = (0, -32, 0) |
| |
|
| | |
| |
|
| | FRICTION = ( 20, 20, 20) |
| |
|
| | DRAG_FLY = ( 5, 5, 5) |
| | DRAG_JUMP = (1.8, 0, 1.8) |
| | DRAG_FALL = (1.8, 0.4, 1.8) |
| |
|
| | class Entity: |
| | def __init__(self, world): |
| | self.world = world |
| |
|
| | |
| |
|
| | self.jump_height = 1.25 |
| | self.flying = False |
| |
|
| | self.position = [0, 80, 0] |
| | self.rotation = [-math.tau / 4, 0] |
| |
|
| | self.velocity = [0, 0, 0] |
| | self.accel = [0, 0, 0] |
| |
|
| | |
| |
|
| | self.width = 0.6 |
| | self.height = 1.8 |
| |
|
| | self.collider = collider.Collider() |
| | self.grounded = False |
| |
|
| | def update_collider(self): |
| | x, y, z = self.position |
| |
|
| | self.collider.x1 = x - self.width / 2 |
| | self.collider.x2 = x + self.width / 2 |
| |
|
| | self.collider.y1 = y |
| | self.collider.y2 = y + self.height |
| |
|
| | self.collider.z1 = z - self.width / 2 |
| | self.collider.z2 = z + self.width / 2 |
| |
|
| | def teleport(self, pos): |
| | self.position = list(pos) |
| | self.velocity = [0, 0, 0] |
| |
|
| | def jump(self, height = None): |
| | |
| |
|
| | if not self.grounded: |
| | return |
| |
|
| | if height is None: |
| | height = self.jump_height |
| |
|
| | self.velocity[1] = math.sqrt(-2 * GRAVITY_ACCEL[1] * height) |
| |
|
| | @property |
| | def friction(self): |
| | if self.flying: |
| | return DRAG_FLY |
| |
|
| | elif self.grounded: |
| | return FRICTION |
| |
|
| | elif self.velocity[1] > 0: |
| | return DRAG_JUMP |
| |
|
| | return DRAG_FALL |
| |
|
| | def update(self, delta_time): |
| | |
| |
|
| | self.velocity = [v + a * f * delta_time for v, a, f in zip(self.velocity, self.accel, self.friction)] |
| | self.accel = [0, 0, 0] |
| |
|
| | |
| |
|
| | self.update_collider() |
| | self.grounded = False |
| |
|
| | for _ in range(3): |
| | adjusted_velocity = [v * delta_time for v in self.velocity] |
| | vx, vy, vz = adjusted_velocity |
| |
|
| | |
| | |
| |
|
| | step_x = 1 if vx > 0 else -1 |
| | step_y = 1 if vy > 0 else -1 |
| | step_z = 1 if vz > 0 else -1 |
| |
|
| | steps_xz = int(self.width / 2) |
| | steps_y = int(self.height) |
| |
|
| | x, y, z = map(int, self.position) |
| | cx, cy, cz = [int(x + v) for x, v in zip(self.position, adjusted_velocity)] |
| |
|
| | potential_collisions = [] |
| |
|
| | for i in range(x - step_x * (steps_xz + 1), cx + step_x * (steps_xz + 2), step_x): |
| | for j in range(y - step_y * (steps_y + 2), cy + step_y * (steps_y + 3), step_y): |
| | for k in range(z - step_z * (steps_xz + 1), cz + step_z * (steps_xz + 2), step_z): |
| | pos = (i, j, k) |
| | num = self.world.get_block_number(pos) |
| |
|
| | if not num: |
| | continue |
| |
|
| | for _collider in self.world.block_types[num].colliders: |
| | entry_time, normal = self.collider.collide(_collider + pos, adjusted_velocity) |
| |
|
| | if normal is None: |
| | continue |
| |
|
| | potential_collisions.append((entry_time, normal)) |
| |
|
| | |
| |
|
| | if not potential_collisions: |
| | break |
| |
|
| | entry_time, normal = min(potential_collisions, key = lambda x: x[0]) |
| | entry_time -= 0.001 |
| |
|
| | if normal[0]: |
| | self.velocity[0] = 0 |
| | self.position[0] += vx * entry_time |
| | |
| | if normal[1]: |
| | self.velocity[1] = 0 |
| | self.position[1] += vy * entry_time |
| |
|
| | if normal[2]: |
| | self.velocity[2] = 0 |
| | self.position[2] += vz * entry_time |
| |
|
| | if normal[1] == 1: |
| | self.grounded = True |
| |
|
| | self.position = [x + v * delta_time for x, v in zip(self.position, self.velocity)] |
| |
|
| | |
| |
|
| | gravity = FLYING_ACCEL if self.flying else GRAVITY_ACCEL |
| | self.velocity = [v + a * delta_time for v, a in zip(self.velocity, gravity)] |
| |
|
| | |
| |
|
| | self.velocity = [v - min(v * f * delta_time, v, key = abs) for v, f in zip(self.velocity, self.friction)] |
| |
|
| | |
| |
|
| | self.update_collider() |