diff options
| author | Gene Pasquet <dev@etenil.net> | 2025-05-28 01:19:25 +0100 | 
|---|---|---|
| committer | Gene Pasquet <dev@etenil.net> | 2025-05-28 01:19:25 +0100 | 
| commit | 71ca9de9cadfcbd41327cbc37a94f54794d2316d (patch) | |
| tree | b690ded62c0cb36bb510c7c55c63366e5496e959 /src/macroknight | |
| parent | 4fd3c145865cde9f6afaddf6f1eed376ba0384bb (diff) | |
Start using pymunk for physics
Diffstat (limited to 'src/macroknight')
| -rw-r--r-- | src/macroknight/entities.hy | 45 | ||||
| -rw-r--r-- | src/macroknight/game.hy | 101 | ||||
| -rw-r--r-- | src/macroknight/systems.hy | 2 | 
3 files changed, 113 insertions, 35 deletions
| diff --git a/src/macroknight/entities.hy b/src/macroknight/entities.hy index af684c2..1979e56 100644 --- a/src/macroknight/entities.hy +++ b/src/macroknight/entities.hy @@ -22,16 +22,23 @@  (defclass PlayerKilled [Exception]) +(defclass Physics [] +  (defn __init__ [self body shape] +    (setv self.body body) +    (setv self.shape shape))) +  (defclass Entity [Sprite]  ;;; Game entity    (setv _fixed False) +  (setv _managed False)    (setv _type "none") -  (defn __init__ [self id tile tile-size x y] +  (defn __init__ [self id tile physics tile-size x y]      (.__init__ (super))      (setv self.id id)      (setv self.tile-size tile-size)      (setv self._surf (Surface #(tile-size tile-size))) +    (setv self._physics physics)      (.blit self._surf tile #(0 0))      (setv self._rect (.get_rect self._surf                                  :left (* x tile-size) @@ -40,6 +47,9 @@    (defn [property] fixed [self]      self._fixed) +  (defn [property] managed [self] +    self._managed) +    (defn [property] rect [self]      self._rect) @@ -57,24 +67,23 @@    (setv _fixed True)    (setv _type "level") -  (defn __init__ [self id tile tile-size x y scaling] +  (defn __init__ [self id tile physics tile-size x y scaling]      (let [tile-width (* (.get_width tile) scaling)            tile-height (* (.get_height tile) scaling)            tile_ (if (!= scaling 1)                      (pygame.transform.scale tile #(tile-width tile-height))                      tile)] -      (.__init__ (super) id tile_ tile-size x y)))) +      (.__init__ (super) id tile_ physics tile-size x y))))  (defclass Goal [Entity]    (setv _type "goal")    (setv _fixed True)) -  (defclass Character [Entity]    (setv _type "enemy") -  (defn __init__ [self id tiles tile-size x y] -    (.__init__ (super) id (get tiles 0) tile-size x y) +  (defn __init__ [self id tiles physics tile-size x y] +    (.__init__ (super) id (get tiles 0) physics tile-size x y)      (setv self.tiles tiles)      (setv self.facing Direction.RIGHT)      (setv self.attacking False) @@ -125,23 +134,39 @@  (defclass Player [Character]    (setv _type "player") -  (setv SPEED 3) +  (setv _managed True) +  (setv SPEED 100)    (setv JUMP_IMPULSE 10)    (setv MAX_JUMPING 100) -  (defn __init__ [self id tiles tile-size x y] -    (.__init__ (super) id tiles tile-size x y) +  (defn __init__ [self id tiles physics tile-size x y] +    (.__init__ (super) id tiles physics tile-size x y)      (setv self.jumping False)      (setv self.jump-move 0))    (defn [property] total-move [self]      (merge-moves self.moves)) +  (defn move [self move] +    ;; (.append self.moves move) +    ;; (.move_ip self._rect (get move 0) (get move 1)) +    ;; ;; (setv self._physics.body.velocity move) +    ;; (when (!= (get move 0) 0) +    ;;   (setv self.facing +    ;;         (.x-from-move Direction move))) +    ) +    (defn jump [self]      (setv self.jumping True)      (when (< self.jump-move self.MAX_JUMPING)        (setv self.jump-move (+ self.jump-move self.JUMP_IMPULSE)) -      (.move self #(0 (neg self.JUMP_IMPULSE)))))) +      (.move self #(0 (neg self.JUMP_IMPULSE))))) + + +  (defn [property] rect [self] +    (setv self._rect.x self._physics.body.position.x) +    (setv self._rect.y self._physics.body.position.y) +    self._rect))  (defclass Enemy [Character]    (setv _type "Enemy")) diff --git a/src/macroknight/game.hy b/src/macroknight/game.hy index 125768a..c6c329e 100644 --- a/src/macroknight/game.hy +++ b/src/macroknight/game.hy @@ -16,13 +16,16 @@  (require hy)  (require hyrule *)  (import pygame +        pymunk +        pymunk.pygame_util          pytmx.util_pygame [load_pygame] -        entities [Player LevelTile Goal Enemy PlayerKilled] +        entities [Player LevelTile Goal Enemy PlayerKilled Physics]          tiles [TileSet draw-tile]          utils [neg]          text [render-text]          systems [apply-gravity apply-collisions run-enemies GoalHit] -        math [floor]) +        math [floor] +        pprint [pprint])  (pygame.init) @@ -30,8 +33,10 @@  (setv TILE_SIZE (* TILE_SCALING 16))  (setv MACRO_STEP_WAIT 300)  (setv MACRO_COOLDOWN 2000) +(setv FPS 60.0)  (setv screen (pygame.display.set_mode #((* TILE_SCALING 640) (* TILE_SCALING 480)))) +(setv screen-options (pymunk.pygame_util.DrawOptions screen))  (setv clock (pygame.time.Clock))  (setv tileset (TileSet "assets/monochrome-transparent.png" TILE_SCALING TILE_SIZE TILE_SIZE 1))  (setv levels [(load_pygame "assets/level-0.tmx") @@ -55,7 +60,8 @@    (render-text screen tileset "ENTER FOR MACRO" 13 27)    (pygame.display.flip) -  (pygame.time.wait 3000)) +  ;; (pygame.time.wait 3000) ;;; TODO: reactivate +  )  (setv game-running True) @@ -65,6 +71,8 @@    (setv running True)    (setv level (get levels level-id))    (setv entities []) +  (setv space (pymunk.Space)) +  (setv space.gravity #(0.0 200.0))    (setv player-pos #(5 5))    (for [item (get level.layers 1)]      (let [tile-x (abs-to-tile-index item.x) @@ -72,18 +80,30 @@        (case item.type              "Player" (setv player-pos #(tile-x tile-y))              "Goal" (.append entities -                            (Goal (len entities) -                                  (get tileset.tiles 0) -                                  TILE_SIZE -                                  tile-x -                                  tile-y)) +                            (let [entity +                                  (Goal (len entities) +                                        (get tileset.tiles 0) +                                        (let [body (pymunk.Body :body_type pymunk.Body.STATIC)] +                                          (setv body.position #(item.x item.y)) +                                          (Physics body (pymunk.Poly.create_box body #(TILE_SIZE TILE_SIZE)))) +                                        TILE_SIZE +                                        tile-x +                                        tile-y)] +                              (.add space entity._physics.body entity._physics.shape) +                              entity))              "Enemy1" (.append entities -                              (Enemy (len entities) -                                     [(get tileset.tiles 128) -                                      (get tileset.tiles 129)] -                                     TILE_SIZE -                                     tile-x -                                     tile-y))))) +                              (let [entity +                                    (Enemy (len entities) +                                           [(get tileset.tiles 128) +                                            (get tileset.tiles 129)] +                                           (let [body (pymunk.Body 10 0.2)] +                                             (setv body.position #(item.x item.y)) +                                             (Physics body (pymunk.Poly.create_box body #(TILE_SIZE TILE_SIZE)))) +                                           TILE_SIZE +                                           tile-x +                                           tile-y)] +                                (.add space entity._physics.body entity._physics.shape) +                                entity)))))    (setv player-pos          (let [player-objects (lfor ent (get level.layers 1) :if (= ent.type "Player") ent)] @@ -92,8 +112,17 @@                  #((abs-to-tile-index player-object.x)                     (abs-to-tile-index player-object.y)))                #(5 5)))) -  (setv player (Player (len entities) [(get tileset.tiles 28) -                           (get tileset.tiles 29)] TILE_SIZE #* player-pos)) +  (setv player (Player (len entities) +                       [(get tileset.tiles 28) (get tileset.tiles 29)] +                       (let [body (pymunk.Body 10 (float "inf"))] +                         (setv body.position #((* TILE_SIZE (get player-pos 0)) +                                                (* TILE_SIZE (get player-pos 1)))) +                         (setv body.elasticity 0.2) +                         (setv body.friction 0.5) +                         (Physics body (pymunk.Poly.create_box body #(TILE_SIZE TILE_SIZE)))) +                       TILE_SIZE +                       #* player-pos)) +  (.add space player._physics.body player._physics.shape)    (.append entities player)    (setv macro-input-mode False) @@ -103,8 +132,21 @@      (for [#(id tiledef) (enumerate (.tiles (get level.layers 0)))]        (let [x (get tiledef 0)              y (get tiledef 1) -            tile (get tiledef 2)] -        (.append entities (LevelTile (+ id id-offset) tile TILE_SIZE x y TILE_SCALING))))) +            tile (get tiledef 2) +            tile-ent (LevelTile +                            (+ id id-offset) +                            tile +                            (let [body (pymunk.Body :body_type pymunk.Body.STATIC)] +                              (setv body.position #((* x TILE_SIZE) (* y TILE_SIZE))) +                              (setv body.elasticity 0.0) +                              (setv body.friction 0.6) +                              (Physics body (pymunk.Poly.create_box body #(TILE_SIZE TILE_SIZE)))) +                            TILE_SIZE +                            x +                            y +                            TILE_SCALING)] +        (.add space tile-ent._physics.body tile-ent._physics.shape) +        (.append entities tile-ent))))    (setv ongoing_inputs []) @@ -178,10 +220,14 @@                  (draw-tile screen tileset 725 (+ 4 indicator) 5))))            (for [inp ongoing_inputs]              (case inp -                  pygame.K_a (.move player #((neg player.SPEED) 0)) -                  pygame.K_s (.move player #(0 1)) -                  pygame.K_w (.jump player) -                  pygame.K_d (.move player #(player.SPEED 0)) +                  ;; pygame.K_a (.move player #((neg player.SPEED) 0)) +                  ;; pygame.K_s (.move player #(0 1)) +                  ;; pygame.K_w (.jump player) +                  ;; pygame.K_d (.move player #(player.SPEED 0)) +                  pygame.K_a (setv player._physics.body.velocity #((neg player.SPEED) 0)) +                  pygame.K_s (setv player._physics.body.velocity #(0 1)) +                  pygame.K_w (setv player._physics.body.velocity #(0 -100)) ;; (.jump player) +                  pygame.K_d (setv player._physics.body.velocity #(player.SPEED 0))                    pygame.K_SPACE (.attack player)))            (try @@ -217,17 +263,24 @@            (.flush player))) - +    (pprint player._physics.body.position) +          (for [entity entities]        (.blit screen entity.surf entity.rect)) +     +    ;; (space.debug_draw screen-options) + +          (pygame.display.flip)      (when (and (!= 0 macro-wait-time)                 (> (pygame.time.get_ticks) macro-wait-time))        (setv macro-wait-time 0)) -    (.tick clock 60))) +    (.step space (/ 1.0 FPS)) +     +    (.tick clock FPS))) diff --git a/src/macroknight/systems.hy b/src/macroknight/systems.hy index 91d4e8c..b967504 100644 --- a/src/macroknight/systems.hy +++ b/src/macroknight/systems.hy @@ -31,7 +31,7 @@         ~@body)))  (defsystem apply-gravity -  (not entity.fixed) +  (not (or entity.fixed entity.managed))    (.move entity #(0 GRAVITY)))  (defsystem apply-collisions | 
