From 01f27da224afaac71912063a464e52152a4d85ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20W=C3=A4chter?= Date: Sun, 26 Mar 2023 17:01:25 +0200 Subject: [PATCH 1/4] added castle sprites --- project/data/sprites/castle_block_full.png | Bin 0 -> 626 bytes project/data/sprites/castle_block_wall_left.png | Bin 0 -> 611 bytes project/data/sprites/castle_block_wall_right.png | Bin 0 -> 605 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 project/data/sprites/castle_block_full.png create mode 100644 project/data/sprites/castle_block_wall_left.png create mode 100644 project/data/sprites/castle_block_wall_right.png diff --git a/project/data/sprites/castle_block_full.png b/project/data/sprites/castle_block_full.png new file mode 100644 index 0000000000000000000000000000000000000000..3e61347c0d8ca82bf43f09ae3684134d4d1f316f GIT binary patch literal 626 zcmV-&0*(ENP)kL$)qVJRZj zC36ImFhK&iNl;>)97TLm3zAuDpTFi?WJ5ff{B_D0;>eH{uUFKPbWKT3i=L7%M_J|m zKTk6~IZ^NK3_$0LWqpi7*B(?Wmi2RDS=Cc;Ji}F?>EDo?X1+wPG&Ro=3~a;2byG|1 z!{rVPKk0EJUXvU$?ddeUpF>{^2JfI}wVqXDowG-XZpjnf!oeYo$^L=0Uv3d-J!?ow z2mk;832;bRa{vG?BLDy{BLR4&KXw2B0INwvK~y*q?Nq@HfFKO4#uZqH{n&z8Sb}ks zGdWWYN_h}{*u<2?J4?@NClOi8V~z#L5Q2%2bC%hJRG{&My$9UQ8dCxGsZ>)46=RH5 z^~N{dU151rsP?X3CFoyMivK00B;I>LcFwiEL@+YK)HF$E0)VXWdkJc^;sajNSA=^_ z*3hK!gcrQT$ujLFj-yuPdOlPl82Kp<0>_Y(bw@gR30pz$B7NouHc~%XYi#}Lp8x;= M07*qoM6N<$g7Od(zW@LL literal 0 HcmV?d00001 diff --git a/project/data/sprites/castle_block_wall_left.png b/project/data/sprites/castle_block_wall_left.png new file mode 100644 index 0000000000000000000000000000000000000000..a40047447a5cf3ea66dec8fafbd5ce70017875b7 GIT binary patch literal 611 zcmV-p0-XJcP)a<3B78niSB4N*&9 zL;pdoL2E$}6hTB=dtXb)?L8S7q33e$`{Oz1c{%4fU=QcDg4q#(La}T_LP5_`eA(lC z!GW7Trg0@SQ=gB{#b`S|@35(Q>sP(n?`t`FQfX5ITbJ;prW?9(5B}y0{pX z>Xtc-NrVtVJS3^GMxHW$sYS`GwJ-4FTc9K!P5wGn3~^-1iPtA;MY^V?W<*cRm#3<7 z|DUIsnHX<$cLkyI$+F%?z_|nUnq_?*SyufR9FK5OZ2C)*)6|FPwWj7hfc{N5yKHL7 zT{z!@p$9!-Bz`1^OnW8+ucy!(hk+aDUTI|YyUxiy#5UxKu3>KNg^SXd3;b zZ5RLm010qNS#tmYE+YT{E+YYWr9XB6005gwL_t(I5$%-G4S*mFM2m45wqhN&U@OK^ zj-*L7rKt*kHZd5zv*lSDi0EjSJ9a2@&Mrf(l{S}Bh}IkW9#ES%LKA+cgp8#WmEQVI zKh9uM(&){hH2Np+dx>l1b(8_mJEa&SLCmXV=$lR{S(?kcIh0V|-%A4QKbHiI;jKzZ x_7b-}f5Ds@cQH(+K|4^ULCavyC6oY@j1w+rR@BI}XJh~X002ovPDHLkV1ipC3se9A literal 0 HcmV?d00001 diff --git a/project/data/sprites/castle_block_wall_right.png b/project/data/sprites/castle_block_wall_right.png new file mode 100644 index 0000000000000000000000000000000000000000..eb2ba55608f258b32fb5e21361db93cb2c362fe5 GIT binary patch literal 605 zcmV-j0;2tiP)Lb6$Q6C~IQHWmR3 z(Z*NdKhRdNRS*P45V5oO)rhQjj1Uo>W%hoYnRA&r1HME-FS^Y`P_)WUG9C-frx!wj zNBjh7XPls>yY}?#REmGc+ciz9UPV=}|M&el+OvkMLsP5psBSxD;R)fyO4(MtA>5_ccE(yj?Wre zW(!W%q4(C-9PLZ;%k-HhJRL!28oDo`ZLyx!_d16+kXn@|x`6E+7?Ay4OP@94Xd@=V zu15d>010qNS#tmYE+YT{E+YYWr9XB6005OqL_t(I5$%*=4uBvCh0%E#kLoSF6~`&r zdX6?SE&V53!{IaZ6Lds$l&{-DN~ufC%#?E`-=$Wf^$UXRZNyv=|EB~Znjm894?Ucr zNy#EOhmv(K-zj0A@YdgT%*Pl>#PE938dpll0B?yUHiwdAk?z{HbaCGA(o@0dxJhYk rExq-_?OhVFbY9D9$3dhs=rQI`-al&~YAuSm00000NkvXXu0mjfyQ~qI literal 0 HcmV?d00001 From f2fab23b7517bf75b00792f6b43c0c3d7248393b Mon Sep 17 00:00:00 2001 From: Yan Wittmann Date: Sun, 26 Mar 2023 17:01:28 +0200 Subject: [PATCH 2/4] New collision system --- project/data/levels/1-1.csv | 34 +++++---- project/main.py | 12 +++- project/physics/CollisionDirection.py | 14 ++++ project/physics/PhysicsElementsHandler.py | 76 ++++++++++++--------- project/physics/SpriteManager.py | 9 ++- project/physics/controllers/PlayerSprite.py | 24 ------- project/physics/sprites/DeathBox.py | 11 +++ project/physics/sprites/PlayerSprite.py | 45 ++++++++++++ project/sprite/DynamicSprite.py | 42 ++++-------- project/sprite/PositionScale.py | 4 +- project/sprite/Sprite.py | 19 ++++++ project/ui_elements/UiElement.py | 3 + 12 files changed, 185 insertions(+), 108 deletions(-) create mode 100644 project/physics/CollisionDirection.py delete mode 100644 project/physics/controllers/PlayerSprite.py create mode 100644 project/physics/sprites/DeathBox.py create mode 100644 project/physics/sprites/PlayerSprite.py diff --git a/project/data/levels/1-1.csv b/project/data/levels/1-1.csv index da5f96c..d736825 100644 --- a/project/data/levels/1-1.csv +++ b/project/data/levels/1-1.csv @@ -12,21 +12,21 @@ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,x,x,x,x,x,x,x,x,x,,,,,,,,,,,,,,,,,D,,, +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,# +#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,x,x,x,x,x,x,x,x,x,,,,,,,,,,,,,,,,,D,,,# #,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# #,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# #,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# @@ -38,6 +38,4 @@ #,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# #,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# #,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# -#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# -,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, -3,3,id=HEBEL,requires=HEBEL;HEBEL-2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,,,,,,,,,,,,,,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,#,# \ No newline at end of file diff --git a/project/main.py b/project/main.py index 8bbac7a..0c11c11 100644 --- a/project/main.py +++ b/project/main.py @@ -6,7 +6,7 @@ from level.LevelManager import LevelManager from level.elements.LoadedLevel import LoadedLevel from physics.SpriteManager import SpriteManager, DrawLayers from physics.TickData import TickData -from physics.controllers.PlayerSprite import PlayerSprite +from physics.sprites.PlayerSprite import PlayerSprite from sprite.PositionScale import PositionScale from sprite.SpritesheetManager import SpritesheetManager from sprite.Sprite import Sprite @@ -47,6 +47,16 @@ if what_to_run == 'level': generated_level = LoadedLevel(sprite_manager, spritesheet_manager) generated_level.load_level(parsed_levels_manager.levels[0]) + ghost_character = PlayerSprite(spritesheet_manager.get_sheet("ghost_character")) + ghost_character.position_scale = PositionScale((90, 50), (1, 1)) + sprite_manager.add_ui_element(DrawLayers.OBJECTS, ghost_character) + + text_1 = TextLabel("Frame: 0", 2, 110, 50, alignment="left") + text_1.position_scale.scale = (0.3, 0.3) + sprite_manager.add_ui_element(DrawLayers.UI, text_1) + + ghost_character.debug_label = text_1 + while True: clock.tick(frame_rate) diff --git a/project/physics/CollisionDirection.py b/project/physics/CollisionDirection.py new file mode 100644 index 0000000..dd98a93 --- /dev/null +++ b/project/physics/CollisionDirection.py @@ -0,0 +1,14 @@ +class CollisionDirection: + LEFT = 0 + RIGHT = 1 + TOP = 2 + BOTTOM = 3 + DIRECTION_NAMES = ['LEFT', 'RIGHT', 'TOP', 'BOTTOM'] + + def __init__(self, direction: int, primary_sprite, secondary_sprite): + self.direction = direction + self.primary_sprite = primary_sprite + self.secondary_sprite = secondary_sprite + + def to_string(self): + return 'CollisionDirection.' + CollisionDirection.DIRECTION_NAMES[self.direction] diff --git a/project/physics/PhysicsElementsHandler.py b/project/physics/PhysicsElementsHandler.py index 53005b2..26da8b3 100644 --- a/project/physics/PhysicsElementsHandler.py +++ b/project/physics/PhysicsElementsHandler.py @@ -1,5 +1,6 @@ from typing import Optional +from physics.CollisionDirection import CollisionDirection from physics.TickData import TickData from sprite.DynamicSprite import DynamicSprite from sprite.Sprite import Sprite @@ -40,6 +41,8 @@ class PhysicsElementsHandler: # 4.2.3. If it doesn't, move the sprite to the new position colliders = [sprite for sprite in sprites if isinstance(sprite, StaticSprite) and sprite.is_collider] + for collider in colliders: + collider.reset_collides_with() dynamic_sprites = [sprite for sprite in sprites if isinstance(sprite, DynamicSprite)] sorted_dynamic_sprites = sorted(dynamic_sprites, key=lambda spr: spr.position_scale.position[1]) @@ -55,56 +58,65 @@ class PhysicsElementsHandler: total_motion = sprite.motion motion_step = ((total_motion[0] * dt) / motion_steps, (total_motion[1] * dt) / motion_steps) + collides_with_last = None + collided = [False, False] + sprite.reset_collides_with() + for i in range(motion_steps): - sprite.reset_touches() - - sprite.position_scale.position = ( - sprite.position_scale.position[0] + motion_step[0], - sprite.position_scale.position[1] - ) - - collides_with = self.check_collides(sprite, colliders) - if collides_with is not None: + if not collided[0]: 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] ) - if sprite.motion[0] > 0: - sprite.set_touches_right(True) + collides_with = self.check_collides(sprite, colliders) + if collides_with is not None: + sprite.position_scale.position = ( + sprite.position_scale.position[0] - motion_step[0], + sprite.position_scale.position[1] + ) - if sprite.motion[0] < 0: - sprite.set_touches_left(True) + if sprite.motion[0] > 0: + sprite.add_collides_with(CollisionDirection(CollisionDirection.RIGHT, sprite, collides_with)) - sprite.motion = (0, sprite.motion[1]) - return collides_with + if sprite.motion[0] < 0: + sprite.add_collides_with(CollisionDirection(CollisionDirection.LEFT, sprite, collides_with)) - sprite.position_scale.position = ( - sprite.position_scale.position[0], - sprite.position_scale.position[1] + motion_step[1] - ) + sprite.motion = (0, sprite.motion[1]) - collides_with = self.check_collides(sprite, colliders) - if collides_with is not None: + collides_with_last = collides_with + collided[0] = True + + if not collided[1]: sprite.position_scale.position = ( sprite.position_scale.position[0], - sprite.position_scale.position[1] - motion_step[1] + sprite.position_scale.position[1] + motion_step[1] ) - if sprite.motion[1] > 0: - sprite.set_touches_bottom(True) + collides_with = self.check_collides(sprite, colliders) + if collides_with is not None: + sprite.position_scale.position = ( + sprite.position_scale.position[0], + sprite.position_scale.position[1] - motion_step[1] + ) - if sprite.motion[1] < 0: - sprite.set_touches_top(True) + if sprite.motion[1] > 0: + sprite.add_collides_with(CollisionDirection(CollisionDirection.BOTTOM, sprite, collides_with)) - sprite.motion = (sprite.motion[0], 0) - return collides_with + if sprite.motion[1] < 0: + sprite.add_collides_with(CollisionDirection(CollisionDirection.TOP, sprite, collides_with)) - return None + sprite.motion = (sprite.motion[0], 0) + + collides_with_last = collides_with + collided[1] = True + + return collides_with_last def check_collides(self, sprite: StaticSprite, colliders: list[StaticSprite]) -> Optional[StaticSprite]: for collider in colliders: - if sprite is not collider and sprite.collides_with(collider, TOLERANCE): - return collider + if sprite is not collider: + if sprite.collides_with(collider, TOLERANCE): + return collider return None diff --git a/project/physics/SpriteManager.py b/project/physics/SpriteManager.py index 3b3ec38..85ddc00 100644 --- a/project/physics/SpriteManager.py +++ b/project/physics/SpriteManager.py @@ -1,6 +1,5 @@ from typing import Optional -import pygame from pygame import Surface from physics.PhysicsElementsHandler import PhysicsElementsHandler @@ -57,5 +56,11 @@ class SpriteManager: return elements def collision_detected(self, sprite_a: Sprite, sprite_b: Sprite): - # print(f"Collision detected between {sprite_a} and {sprite_b}") pass + + def find_sprite_by_uuid(self, uuid: str) -> Optional[UiElement]: + for layer in DrawLayers.DRAW_ORDER: + for sprite in self.layers[layer]: + if sprite.uuid == uuid: + return sprite + return None diff --git a/project/physics/controllers/PlayerSprite.py b/project/physics/controllers/PlayerSprite.py deleted file mode 100644 index 5828166..0000000 --- a/project/physics/controllers/PlayerSprite.py +++ /dev/null @@ -1,24 +0,0 @@ -from physics.TickData import TickData -from sprite.DynamicSprite import DynamicSprite -from sprite.Spritesheet import Spritesheet -from ui_elements.KeyManager import KeyManager -from ui_elements.TextLabel import TextLabel - - -class PlayerSprite(DynamicSprite): - def __init__(self, spritesheet: Spritesheet): - super().__init__(spritesheet) - self.jump_time = -1 - self.allowed_jump_time = 20 - self.debug_label = TextLabel('', -1, -1) - - def tick(self, tick_data: TickData): - super().tick(tick_data) - - if tick_data.key_manager.is_keymap_down(KeyManager.KEY_RIGHT): - self.motion = (self.motion[0] + 2, self.motion[1]) - - if tick_data.key_manager.is_keymap_down(KeyManager.KEY_LEFT): - self.motion = (self.motion[0] - 2, self.motion[1]) - - self.debug_label.set_text(f'jump: {self.jump_time}, x: {round(self.motion[0], 2)}, y: {round(self.motion[1], 2)}, touches: {self.touches_bounding}') diff --git a/project/physics/sprites/DeathBox.py b/project/physics/sprites/DeathBox.py new file mode 100644 index 0000000..ff5bc51 --- /dev/null +++ b/project/physics/sprites/DeathBox.py @@ -0,0 +1,11 @@ +from physics.TickData import TickData +from sprite.Spritesheet import Spritesheet +from sprite.StaticSprite import StaticSprite + + +class DeathBox(StaticSprite): + def __init__(self, spritesheet: Spritesheet): + super().__init__(spritesheet) + + def tick(self, tick_data: TickData): + super().tick(tick_data) diff --git a/project/physics/sprites/PlayerSprite.py b/project/physics/sprites/PlayerSprite.py new file mode 100644 index 0000000..08666b0 --- /dev/null +++ b/project/physics/sprites/PlayerSprite.py @@ -0,0 +1,45 @@ +from physics.CollisionDirection import CollisionDirection +from physics.TickData import TickData +from sprite.DynamicSprite import DynamicSprite +from sprite.Spritesheet import Spritesheet +from ui_elements.KeyManager import KeyManager +from ui_elements.TextLabel import TextLabel + + +class PlayerSprite(DynamicSprite): + def __init__(self, spritesheet: Spritesheet): + super().__init__(spritesheet) + self.debug_label = TextLabel('', -1, -1) + + self.jump_time = -1 + self.allowed_jump_time = 12 + + self.acceleration_horizontal = 2 + + self.deceleration_horizontal_air = 0.02 + self.deceleration_horizontal_ground = 0.3 + self.gravity = 9.81 / 10 + + self.max_motion_horizontal_via_input = 5 + + def tick(self, tick_data: TickData): + super().tick(tick_data) + + if tick_data.key_manager.is_keymap_down(KeyManager.KEY_RIGHT): + if self.motion[0] < self.max_motion_horizontal_via_input: + self.motion = (self.motion[0] + self.acceleration_horizontal, self.motion[1]) + + if tick_data.key_manager.is_keymap_down(KeyManager.KEY_LEFT): + if self.motion[0] > -self.max_motion_horizontal_via_input: + self.motion = (self.motion[0] - self.acceleration_horizontal, self.motion[1]) + + if tick_data.key_manager.is_keymap_down(KeyManager.KEY_UP): + if self.jump_time < 0 and self.get_collides_with_direction(CollisionDirection.BOTTOM): + self.jump_time = self.allowed_jump_time + self.motion = (self.motion[0], self.motion[1] - 7) + if self.jump_time >= 0: + self.motion = (self.motion[0], self.motion[1] - 0.5) + if self.jump_time >= 0: + self.jump_time -= 1 + + self.debug_label.set_text(f'jump: {self.jump_time}, x: {round(self.motion[0], 2)}, y: {round(self.motion[1], 2)}, touches: {list(map(lambda x: x.to_string(), self.get_collides_with()))}') diff --git a/project/sprite/DynamicSprite.py b/project/sprite/DynamicSprite.py index 65dc1c2..357ed27 100644 --- a/project/sprite/DynamicSprite.py +++ b/project/sprite/DynamicSprite.py @@ -1,4 +1,4 @@ -from sprite.BoundingBox import BoundingBox +from physics.CollisionDirection import CollisionDirection from sprite.Spritesheet import Spritesheet from sprite.StaticSprite import StaticSprite from physics.TickData import TickData @@ -10,39 +10,23 @@ class DynamicSprite(StaticSprite): self.motion = (0, 0) + self.apply_base_deceleration = True self.deceleration_horizontal_air = 0.02 self.deceleration_horizontal_ground = 0.3 self.gravity = 9.81 / 10 - # up, right, down, left - self.touches_bounding = (False, False, False, False) - def tick(self, tick_data: TickData): super().tick(tick_data) - deceleration_horizontal = 0 - if abs(self.motion[0]) > 0: - if self.touches_bounding[2]: - deceleration_horizontal = self.deceleration_horizontal_ground - else: - deceleration_horizontal = self.deceleration_horizontal_air + if self.apply_base_deceleration: + deceleration_horizontal = 0 + if abs(self.motion[0]) > 0: + if self.get_collides_with_direction(CollisionDirection.BOTTOM): + deceleration_horizontal = self.deceleration_horizontal_ground + else: + deceleration_horizontal = self.deceleration_horizontal_air - self.motion = ( - self.motion[0] - deceleration_horizontal * self.motion[0] * tick_data.dt, - self.motion[1] + self.gravity * tick_data.dt - ) - - def set_touches_bottom(self, value: bool): - self.touches_bounding = (self.touches_bounding[0], self.touches_bounding[1], value, self.touches_bounding[3]) - - def set_touches_right(self, value: bool): - self.touches_bounding = (self.touches_bounding[0], value, self.touches_bounding[2], self.touches_bounding[3]) - - def set_touches_left(self, value: bool): - self.touches_bounding = (self.touches_bounding[0], self.touches_bounding[1], self.touches_bounding[2], value) - - def set_touches_top(self, value: bool): - self.touches_bounding = (value, self.touches_bounding[1], self.touches_bounding[2], self.touches_bounding[3]) - - def reset_touches(self): - self.touches_bounding = (False, False, False, False) + self.motion = ( + self.motion[0] - deceleration_horizontal * self.motion[0] * tick_data.dt, + self.motion[1] + self.gravity * tick_data.dt + ) diff --git a/project/sprite/PositionScale.py b/project/sprite/PositionScale.py index d3f6be2..850cfc5 100644 --- a/project/sprite/PositionScale.py +++ b/project/sprite/PositionScale.py @@ -1,7 +1,7 @@ class PositionScale: def __init__(self, position: tuple[float, float] = (0, 0), scale: tuple[float, float] = (1, 1)): - self.position = position - self.scale = scale + self.position: tuple[float, float] = position + self.scale: tuple[float, float] = scale def apply_scale_to_position(self): return self.position[0] * self.scale[0], self.position[1] * self.scale[1] diff --git a/project/sprite/Sprite.py b/project/sprite/Sprite.py index f6a5eb6..f422ace 100644 --- a/project/sprite/Sprite.py +++ b/project/sprite/Sprite.py @@ -1,5 +1,8 @@ +from typing import Optional + import pygame +from physics.CollisionDirection import CollisionDirection from physics.TickData import TickData from sprite.BoundingBox import BoundingBox from sprite.PositionScale import PositionScale @@ -22,6 +25,22 @@ class Sprite(UiElement): self.image = None self.is_collider = True + self.collides_with_elements: list[CollisionDirection] = [] + + def add_collides_with(self, collision_direction: CollisionDirection): + self.collides_with_elements.append(collision_direction) + + def reset_collides_with(self): + self.collides_with_elements = [] + + def get_collides_with(self) -> list[CollisionDirection]: + return self.collides_with_elements + + def get_collides_with_direction(self, direction: int) -> Optional[CollisionDirection]: + for collision_direction in self.collides_with_elements: + if collision_direction.direction == direction: + return collision_direction + return None def tick(self, tick_data: TickData): animation = self.spritesheet.animations[self.animation_state] diff --git a/project/ui_elements/UiElement.py b/project/ui_elements/UiElement.py index 489d02a..104874b 100644 --- a/project/ui_elements/UiElement.py +++ b/project/ui_elements/UiElement.py @@ -1,4 +1,5 @@ import abc +import uuid from typing import Optional import pygame @@ -16,6 +17,8 @@ class UiElement: self.visible = True self.click_listeners = [] + self.uuid = uuid.uuid4() + def add_click_listener(self, listener): self.click_listeners.append(listener) From 29950fb0f819bdbf60bee06fb4de550baff1a2a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20W=C3=A4chter?= Date: Sun, 26 Mar 2023 17:12:12 +0200 Subject: [PATCH 3/4] castle sprites working --- project/data/levels/levels.json | 2 +- project/data/sprites/sprites.json | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/project/data/levels/levels.json b/project/data/levels/levels.json index f67d65b..98f43d3 100644 --- a/project/data/levels/levels.json +++ b/project/data/levels/levels.json @@ -1,7 +1,7 @@ [ { "name": "1-1", - "theme": "tutorial", + "theme": "castle", "abilities": [ "dash" ], diff --git a/project/data/sprites/sprites.json b/project/data/sprites/sprites.json index 850fb5b..cb5ffcc 100644 --- a/project/data/sprites/sprites.json +++ b/project/data/sprites/sprites.json @@ -117,5 +117,34 @@ "height": 16 } ] + }, + { + "id": "castle_block_full", + "subsheets": [ + { + "id": "1", + "delays": [ + 1 + ], + "width": 12, + "height": 12 + }, + { + "id": "2", + "delays": [ + 1 + ], + "width": 12, + "height": 12 + }, + { + "id": "3", + "delays": [ + 1 + ], + "width": 12, + "height": 12 + } + ] } ] \ No newline at end of file From 7d5f37367f6e5eda3749f750ab75e7dfd1c29b13 Mon Sep 17 00:00:00 2001 From: Yan Wittmann Date: Sun, 26 Mar 2023 17:14:02 +0200 Subject: [PATCH 4/4] Random block variants --- project/level/elements/LoadedLevel.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/project/level/elements/LoadedLevel.py b/project/level/elements/LoadedLevel.py index e42351b..3804ae3 100644 --- a/project/level/elements/LoadedLevel.py +++ b/project/level/elements/LoadedLevel.py @@ -1,3 +1,5 @@ +import random + from level.Level import Level from level.LevelElementSymbols import LevelElementSymbols from level.elements.BlockElement import BlockElement @@ -25,7 +27,7 @@ class LoadedLevel: if tile_element in LevelElementSymbols.BLOCKS_LIST: spritesheet = self.spritesheet_manager.get_sheet(level.theme + tile_element['sprite_id']) sprite = BlockElement(spritesheet) - sprite.set_animation_state('1') + sprite.set_animation_state(str(random.randint(0, 3))) sprite.position_scale.position = position # tile['id'], tile['requirements']