63 lines
2.5 KiB
Python
63 lines
2.5 KiB
Python
|
from pygame.surface import Surface
|
||
|
|
||
|
from sprite.DynamicSprite import DynamicSprite
|
||
|
from sprite.PositionScale import PositionScale
|
||
|
from sprite.Sprite import Sprite
|
||
|
from sprite.StaticSprite import StaticSprite
|
||
|
|
||
|
MOTION_STEPS = 10
|
||
|
|
||
|
class PhysicsElementsHandler:
|
||
|
def __init__(self):
|
||
|
self.sprites: list[Sprite] = []
|
||
|
|
||
|
def add_sprite(self, sprite: Sprite):
|
||
|
self.sprites.append(sprite)
|
||
|
|
||
|
def remove_sprite(self, sprite: Sprite):
|
||
|
self.sprites.remove(sprite)
|
||
|
|
||
|
def tick(self, dt: float):
|
||
|
for sprite in self.sprites:
|
||
|
sprite.tick(dt)
|
||
|
|
||
|
# handle motion and collisions. To do this:
|
||
|
# 1. Find all sprites that have collision enabled and store them in a list
|
||
|
# 2. Create a list of all sprites that are dynamic sprites
|
||
|
# 3. Sort the sprites by their y position
|
||
|
# 4. For each sprite:
|
||
|
# 4.1. Divide the motion into MOTION_STEPS steps
|
||
|
# 4.2. For each step:
|
||
|
# 4.2.1. Check if the sprite collides with any other sprite
|
||
|
# 4.2.2. If it does, move the sprite back to the previous position and stop the motion
|
||
|
# 4.2.3. If it doesn't, move the sprite to the new position
|
||
|
|
||
|
colliders = [sprite for sprite in self.sprites if sprite.is_collider and isinstance(sprite, StaticSprite)]
|
||
|
|
||
|
dynamic_sprites = [sprite for sprite in self.sprites if isinstance(sprite, DynamicSprite)]
|
||
|
sorted_dynamic_sprites = sorted(dynamic_sprites, key=lambda spr: spr.position_scale.position[1])
|
||
|
|
||
|
for sprite in sorted_dynamic_sprites:
|
||
|
total_motion = sprite.motion
|
||
|
motion_step = (total_motion[0] / MOTION_STEPS, total_motion[1] / MOTION_STEPS)
|
||
|
|
||
|
for i in range(MOTION_STEPS):
|
||
|
sprite.position_scale.position = (
|
||
|
sprite.position_scale.position[0] + motion_step[0],
|
||
|
sprite.position_scale.position[1] + motion_step[1]
|
||
|
)
|
||
|
|
||
|
for collider in colliders:
|
||
|
if sprite is not collider and sprite.collides_with(collider):
|
||
|
sprite.position_scale.position = (
|
||
|
sprite.position_scale.position[0] - motion_step[0],
|
||
|
sprite.position_scale.position[1] - motion_step[1]
|
||
|
)
|
||
|
|
||
|
sprite.motion = (0, 0)
|
||
|
break
|
||
|
|
||
|
def draw(self, screen: Surface, screen_transform: PositionScale):
|
||
|
for sprite in self.sprites:
|
||
|
sprite.draw(screen, screen_transform)
|