(require hy) (require hyrule *) (import pygame pytmx.util_pygame [load_pygame] pprint [pprint]) (pygame.init) (setv TILE_SCALING 1) (setv TILE_SIZE (* TILE_SCALING 16)) (setv GRAVITY 5) (defn neg [value] (* -1 value)) (defn invert [move] #((neg (get move 0)) (neg (get move 1)))) (defclass TileSet [] (defn __init__ [self image tile-w tile-h [padding 0]] (setv self.sheet (let [surf (pygame.image.load "assets/monochrome-transparent.png")] (if (!= TILE_SCALING 1) (pygame.transform.scale surf #((* (.get_width surf) TILE_SCALING) (* (.get_height surf) TILE_SCALING))) surf))) (setv self.tiles (lfor y (range 0 (.get_height self.sheet) (+ tile-h (* padding TILE_SCALING))) x (range 0 (.get_width self.sheet) (+ tile-w (* padding TILE_SCALING))) (let [tile (pygame.Surface #(tile-w tile-h))] (.blit tile self.sheet #(0 0) #(x y tile-w tile-h)) tile))))) ;; Define systems here (defn apply-gravity [entity entities] (when (not entity.fixed) (.move entity #(0 GRAVITY)))) (defn apply-collisions [entity entities] (for [ent entities] (when (and (!= ent.id entity.id) (.colliderect entity.rect ent.rect) (not entity.fixed)) (.move entity (invert (get entity.moves -1))) (.ground entity)))) ;; Define entities here (defclass LevelTile [] (setv fixed True) (defn __init__ [self id x y surf] (setv self.id id) (setv self.surf (if (!= TILE_SCALING 1) (pygame.transform.scale surf #((* (.get_width surf) TILE_SCALING) (* (.get_height surf) TILE_SCALING))) surf)) (setv self.rect (.get_rect surf :left (* x TILE_SIZE) :top (* y TILE_SIZE))))) (defclass MiniSprite [pygame.sprite.Sprite] (defn __init__ [self tile x y] (.__init__ (super)) (setv self.surf (pygame.Surface #(TILE_SIZE TILE_SIZE))) (.blit self.surf tile #(0 0)) (setv self.rect (.get_rect self.surf :left (* x TILE_SIZE) :top (* y TILE_SIZE))))) (defclass Player [pygame.sprite.Sprite] (setv fixed False) (setv SPEED 3) (setv JUMP_IMPULSE 10) (setv MAX_JUMPING 100) (defn __init__ [self tile initial-x initial-y] (.__init__ (super)) (setv self.id 1) (setv self.surf (pygame.Surface #(TILE_SIZE TILE_SIZE))) (setv self.jumping False) (setv self.jump_move 0) (.blit self.surf tile #(0 0)) (setv self.rect (.get_rect self.surf :left (* 5 TILE_SIZE)))) (defn move [self move] (.append self.moves move) (.move_ip self.rect (get move 0) (get move 1))) (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))))) (defn ground [self] (setv self.jump_move 0)) (defn flush [self] (setv self.moves []))) (setv screen (pygame.display.set_mode #((* TILE_SCALING 640) (* TILE_SCALING 480)))) (setv clock (pygame.time.Clock)) (setv running True) (setv tiles (TileSet "assets/monochrome-transparent.png" TILE_SIZE TILE_SIZE 1)) (setv player (Player (get tiles.tiles 28) 0 0)) (setv sprites-group []) (.append sprites-group player) (setv level (load_pygame "assets/level-1.tmx")) (setv macro-input-mode False) (setv macro-commands [None None None]) (for [tiledef (enumerate (.tiles (get level.layers 0)))] (.append sprites-group (LevelTile (get tiledef 0) #* (get tiledef 1)))) (setv ongoing_inputs []) (defn draw-tile [target tile-id x y] (let [tile (MiniSprite (get tiles.tiles tile-id) x y)] (.blit target tile.surf tile.rect))) (while running (.flush player) (for [event (pygame.event.get)] (case event.type pygame.QUIT (setv running False) pygame.KEYDOWN (if (= event.key pygame.K_ESCAPE) (setv running False) (if macro-input-mode (when (in event.key [pygame.K_a pygame.K_w pygame.K_a pygame.K_s pygame.K_d]) (print event.key) (setv (get macro-commands (.index macro-commands None)) event.key)) (case event.key pygame.K_SPACE (setv macro-input-mode True) else (.append ongoing_inputs event.key)))) pygame.KEYUP (when (in event.key ongoing_inputs) (.remove ongoing_inputs event.key)))) (.fill screen "#000000") (if macro-input-mode ;; If the commands list is full (if (all macro-commands) ;; Process commands (do (for [command macro-commands] (case command pygame.K_a (.move player #((neg TILE_SIZE) 0)) pygame.K_s (.move player #(0 1)) pygame.K_w (.move player #(0 (neg TILE_SIZE))) pygame.K_d (.move player #(TILE_SIZE 0)))) (setv macro-commands [None None None]) (setv macro-input-mode False)) (do (draw-tile screen 774 3 1) (for [#(num command) (enumerate macro-commands)] (let [x-pos (+ 4 num)] (case command pygame.K_w (draw-tile screen 1057 x-pos 1) pygame.K_d (draw-tile screen 1058 x-pos 1) pygame.K_s (draw-tile screen 1059 x-pos 1) pygame.K_a (draw-tile screen 1060 x-pos 1)))))) (do (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)))) (when (any ongoing_inputs) (for [sprite sprites-group] (apply-collisions sprite sprites-group))) ;; Apply systems (for [sprite sprites-group] (apply-gravity sprite sprites-group) (apply-collisions sprite sprites-group)))) (for [sprite sprites-group] (.blit screen sprite.surf sprite.rect)) (pygame.display.flip) (.tick clock 60) ) (pygame.quit)