First implementation of physics
parent
28ea8e232b
commit
e3744241ea
|
@ -12,7 +12,18 @@ from sprite.Sprite import Sprite
|
||||||
from sprite.StaticSprite import StaticSprite
|
from sprite.StaticSprite import StaticSprite
|
||||||
from ui_elements.TextLabel import TextLabel
|
from ui_elements.TextLabel import TextLabel
|
||||||
|
|
||||||
what_to_run = 'textlabel'
|
what_to_run = 'physics'
|
||||||
|
|
||||||
|
|
||||||
|
def apply_frame_rate(number: float):
|
||||||
|
"""
|
||||||
|
this function calculates a factor that will be multiplied with the
|
||||||
|
physics of the game to provide a constant speed
|
||||||
|
:param number: The number to scale by the factor
|
||||||
|
:return: The scaled number
|
||||||
|
"""
|
||||||
|
return number / (frame_rate / 30)
|
||||||
|
|
||||||
|
|
||||||
if what_to_run == 'level':
|
if what_to_run == 'level':
|
||||||
csv_parse_test = LevelManager('data/levels')
|
csv_parse_test = LevelManager('data/levels')
|
||||||
|
@ -27,30 +38,44 @@ elif what_to_run == 'physics':
|
||||||
screen = pygame.display.set_mode((600, 500))
|
screen = pygame.display.set_mode((600, 500))
|
||||||
pygame.display.set_caption("PE GAME")
|
pygame.display.set_caption("PE GAME")
|
||||||
clock = pygame.time.Clock()
|
clock = pygame.time.Clock()
|
||||||
|
frame_rate = 50
|
||||||
|
|
||||||
spritesheet_manager = SpritesheetManager("data/sprites", "data/sprites/sprites.json")
|
spritesheet_manager = SpritesheetManager("data/sprites", "data/sprites/sprites.json")
|
||||||
|
|
||||||
test_1_sprite = DynamicSprite(spritesheet_manager.get_sheet("test_1"))
|
|
||||||
test_2_sprite = StaticSprite(spritesheet_manager.get_sheet("test_1"))
|
|
||||||
|
|
||||||
test_1_sprite.position_scale = PositionScale((10, 10), (1, 1))
|
|
||||||
test_2_sprite.position_scale = PositionScale((100, 100), (1, 1))
|
|
||||||
|
|
||||||
physics_handler = PhysicsElementsHandler()
|
physics_handler = PhysicsElementsHandler()
|
||||||
|
|
||||||
|
test_1_sprite = DynamicSprite(spritesheet_manager.get_sheet("test_1"))
|
||||||
|
test_1_sprite.position_scale = PositionScale((10, -100), (1, 1))
|
||||||
physics_handler.add_sprite(test_1_sprite)
|
physics_handler.add_sprite(test_1_sprite)
|
||||||
|
|
||||||
|
test_3_sprite = DynamicSprite(spritesheet_manager.get_sheet("test_1"))
|
||||||
|
test_3_sprite.position_scale = PositionScale((130, 100), (1, 1))
|
||||||
|
test_3_sprite.motion = (-4, -11)
|
||||||
|
physics_handler.add_sprite(test_3_sprite)
|
||||||
|
|
||||||
|
test_2_sprite = StaticSprite(spritesheet_manager.get_sheet("test_1"))
|
||||||
|
test_2_sprite.position_scale = PositionScale((10, 80), (1, 1))
|
||||||
physics_handler.add_sprite(test_2_sprite)
|
physics_handler.add_sprite(test_2_sprite)
|
||||||
|
|
||||||
while True:
|
|
||||||
clock.tick(10)
|
|
||||||
|
|
||||||
|
while True:
|
||||||
|
clock.tick(frame_rate)
|
||||||
|
|
||||||
|
skip = False
|
||||||
for event in pygame.event.get():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
pygame.quit()
|
pygame.quit()
|
||||||
exit(0)
|
exit(0)
|
||||||
|
elif event.type == pygame.KEYDOWN:
|
||||||
|
if event.key == pygame.K_RIGHT:
|
||||||
|
skip = False
|
||||||
|
|
||||||
|
if skip:
|
||||||
|
continue
|
||||||
|
|
||||||
screen.fill((0, 0, 0))
|
screen.fill((0, 0, 0))
|
||||||
|
|
||||||
physics_handler.tick(1)
|
physics_handler.tick(apply_frame_rate(1))
|
||||||
physics_handler.draw(screen, screen_transform)
|
physics_handler.draw(screen, screen_transform)
|
||||||
pygame.display.update()
|
pygame.display.update()
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@ from sprite.Sprite import Sprite
|
||||||
from sprite.StaticSprite import StaticSprite
|
from sprite.StaticSprite import StaticSprite
|
||||||
|
|
||||||
MOTION_STEPS = 10
|
MOTION_STEPS = 10
|
||||||
|
TOLERANCE = 1
|
||||||
|
|
||||||
|
|
||||||
class PhysicsElementsHandler:
|
class PhysicsElementsHandler:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -38,24 +40,27 @@ class PhysicsElementsHandler:
|
||||||
sorted_dynamic_sprites = sorted(dynamic_sprites, key=lambda spr: spr.position_scale.position[1])
|
sorted_dynamic_sprites = sorted(dynamic_sprites, key=lambda spr: spr.position_scale.position[1])
|
||||||
|
|
||||||
for sprite in sorted_dynamic_sprites:
|
for sprite in sorted_dynamic_sprites:
|
||||||
total_motion = sprite.motion
|
self.attempt_move(sprite, colliders, MOTION_STEPS)
|
||||||
motion_step = (total_motion[0] / MOTION_STEPS, total_motion[1] / MOTION_STEPS)
|
|
||||||
|
|
||||||
for i in range(MOTION_STEPS):
|
def attempt_move(self, sprite: DynamicSprite, colliders: list[StaticSprite], motion_steps: int) -> bool:
|
||||||
sprite.position_scale.position = (
|
total_motion = sprite.motion
|
||||||
sprite.position_scale.position[0] + motion_step[0],
|
motion_step = (total_motion[0] / motion_steps, total_motion[1] / motion_steps)
|
||||||
sprite.position_scale.position[1] + motion_step[1]
|
|
||||||
)
|
|
||||||
|
|
||||||
for collider in colliders:
|
for i in range(motion_steps):
|
||||||
if sprite is not collider and sprite.collides_with(collider):
|
sprite.position_scale.position = (
|
||||||
sprite.position_scale.position = (
|
sprite.position_scale.position[0] + motion_step[0],
|
||||||
sprite.position_scale.position[0] - motion_step[0],
|
sprite.position_scale.position[1] + motion_step[1]
|
||||||
sprite.position_scale.position[1] - motion_step[1]
|
)
|
||||||
)
|
|
||||||
|
|
||||||
sprite.motion = (0, 0)
|
for collider in colliders:
|
||||||
break
|
if sprite is not collider and sprite.collides_with(collider, TOLERANCE):
|
||||||
|
sprite.position_scale.position = (
|
||||||
|
sprite.position_scale.position[0] - motion_step[0],
|
||||||
|
sprite.position_scale.position[1] - motion_step[1]
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def draw(self, screen: Surface, screen_transform: PositionScale):
|
def draw(self, screen: Surface, screen_transform: PositionScale):
|
||||||
for sprite in self.sprites:
|
for sprite in self.sprites:
|
||||||
|
|
|
@ -11,3 +11,6 @@ class BoundingBox:
|
||||||
|
|
||||||
def get_position(self):
|
def get_position(self):
|
||||||
return self.x, self.y
|
return self.x, self.y
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"({self.x}, {self.y}, {self.width}, {self.height})"
|
||||||
|
|
|
@ -14,7 +14,7 @@ class DynamicSprite(StaticSprite):
|
||||||
|
|
||||||
self.motion = (0, 0)
|
self.motion = (0, 0)
|
||||||
self.deceleration_horizontal = 0
|
self.deceleration_horizontal = 0
|
||||||
self.gravity = 0
|
self.gravity = 9.81 / 10
|
||||||
|
|
||||||
def tick(self, dt: float):
|
def tick(self, dt: float):
|
||||||
super().tick(dt)
|
super().tick(dt)
|
||||||
|
|
|
@ -52,31 +52,43 @@ class Sprite:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.image is not None:
|
if self.image is not None:
|
||||||
target_position = screen_transform.apply_scale_to_position()
|
# target_position = screen_transform.apply_scale_to_position()
|
||||||
target_position = (
|
# target_position = (
|
||||||
target_position[0] + self.position_scale.position[0],
|
# target_position[0] + self.position_scale.position[0],
|
||||||
target_position[1] + self.position_scale.position[1]
|
# target_position[1] + self.position_scale.position[1]
|
||||||
)
|
# )
|
||||||
|
|
||||||
target_scale = (
|
# target_scale = (
|
||||||
screen_transform.scale[0] * self.position_scale.scale[0],
|
# screen_transform.scale[0] * self.position_scale.scale[0],
|
||||||
screen_transform.scale[1] * self.position_scale.scale[1]
|
# screen_transform.scale[1] * self.position_scale.scale[1]
|
||||||
)
|
# )
|
||||||
target_size = (
|
# target_size = (
|
||||||
int(target_scale[0] * self.image.get_width()),
|
# int(target_scale[0] * self.image.get_width()),
|
||||||
int(target_scale[1] * self.image.get_height())
|
# int(target_scale[1] * self.image.get_height())
|
||||||
)
|
# )
|
||||||
|
|
||||||
|
# target_image = self.get_scaled_image(self.image, target_size)
|
||||||
|
|
||||||
|
# screen.blit(target_image, target_position)
|
||||||
|
|
||||||
|
target_scale = (screen_transform.scale[0] * self.position_scale.scale[0],
|
||||||
|
screen_transform.scale[1] * self.position_scale.scale[1])
|
||||||
|
|
||||||
|
target_position = ((self.position_scale.position[0] + screen_transform.position[0]) * target_scale[0],
|
||||||
|
(self.position_scale.position[1] + screen_transform.position[1]) * target_scale[1])
|
||||||
|
|
||||||
|
target_size = (int(target_scale[0] * self.image.get_width()),
|
||||||
|
int(target_scale[1] * self.image.get_height()))
|
||||||
|
|
||||||
target_image = self.get_scaled_image(self.image, target_size)
|
target_image = self.get_scaled_image(self.image, target_size)
|
||||||
|
|
||||||
screen.blit(target_image, target_position)
|
screen.blit(target_image, target_position)
|
||||||
|
|
||||||
def get_bounding_box(self) -> BoundingBox:
|
def get_bounding_box(self) -> BoundingBox:
|
||||||
return BoundingBox(
|
return BoundingBox(
|
||||||
self.position_scale.position[0],
|
self.position_scale.position[0],
|
||||||
self.position_scale.position[1],
|
self.position_scale.position[1],
|
||||||
self.image.get_width(),
|
self.image.get_width() * self.position_scale.scale[0],
|
||||||
self.image.get_height()
|
self.image.get_height() * self.position_scale.scale[1]
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_scaled_image(self, image, resize):
|
def get_scaled_image(self, image, resize):
|
||||||
|
|
|
@ -11,9 +11,7 @@ class StaticSprite(Sprite):
|
||||||
def __init__(self, spritesheet: Spritesheet):
|
def __init__(self, spritesheet: Spritesheet):
|
||||||
super().__init__(spritesheet)
|
super().__init__(spritesheet)
|
||||||
|
|
||||||
self.position = (0, 0)
|
def collides_with(self, collider: 'StaticSprite', tolerance: float = 0.0):
|
||||||
|
|
||||||
def collides_with(self, collider: 'StaticSprite'):
|
|
||||||
if not self.is_collider or not collider.is_collider:
|
if not self.is_collider or not collider.is_collider:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -26,16 +24,28 @@ class StaticSprite(Sprite):
|
||||||
self_position = self_bounds.get_position()
|
self_position = self_bounds.get_position()
|
||||||
other_position = other_bounds.get_position()
|
other_position = other_bounds.get_position()
|
||||||
|
|
||||||
if self_position[0] + self_dimensions[0] < other_position[0]:
|
# if self_position[0] + self_dimensions[0] < other_position[0]:
|
||||||
|
# return False
|
||||||
|
|
||||||
|
# if self_position[0] > other_position[0] + other_dimensions[0]:
|
||||||
|
# return False
|
||||||
|
|
||||||
|
# if self_position[1] + self_dimensions[1] < other_position[1]:
|
||||||
|
# return False
|
||||||
|
|
||||||
|
# if self_position[1] > other_position[1] + other_dimensions[1]:
|
||||||
|
# return False
|
||||||
|
|
||||||
|
if self_position[0] + self_dimensions[0] < other_position[0] + tolerance:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self_position[0] > other_position[0] + other_dimensions[0]:
|
if self_position[0] > other_position[0] + other_dimensions[0] - tolerance:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self_position[1] + self_dimensions[1] < other_position[1]:
|
if self_position[1] + self_dimensions[1] < other_position[1] + tolerance:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if self_position[1] > other_position[1] + other_dimensions[1]:
|
if self_position[1] > other_position[1] + other_dimensions[1] - tolerance:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
Loading…
Reference in New Issue