diff --git a/game/entities/pacman.fnl b/game/entities/pacman.fnl index b411ee6..b03e8dd 100644 --- a/game/entities/pacman.fnl +++ b/game/entities/pacman.fnl @@ -2,15 +2,16 @@ (local dim (require :game.dim)) (local {: defmethod} (util.require :lib.multimethod)) (local {: direct : draw : update} (util.require :game.entity)) -(local {: vec* : vec+ : edge : edge-crosses} (util.require :game.helpers)) +(local {: vec* : vec+ : edge : edge-crosses : held-directions : dirs-from-dir : vec-from-dirs} + (util.require :game.helpers)) (local map (require :game.tilemap)) (local pacman (util.hot-table ...)) (set pacman.keymap {:up :up :down :down :left :left :right :right}) -(defmethod draw :pacman (fn [{:pos [x y] :vel [dx dy]}] +(defmethod draw :pacman (fn [{:pos [x y] :vel [dx dy] : dt-animation}] (let [mouthsize-max (if (and (= dx 0) (= dy 0)) 0 (/ math.pi 4)) - mouthsize-ratio (math.abs (math.sin (* (love.timer.getTime) 16))) + mouthsize-ratio (math.abs (math.sin (* (or dt-animation 0) 16))) mouthsize (* mouthsize-max mouthsize-ratio) anglestart (if (< dx 0) math.pi (> dx 0) 0 @@ -68,7 +69,7 @@ (fn update-direction [entity rules] (let [[dx dy] entity.vel - [dxkey dykey] (direct pacman.keymap (* dim.tilesize 4))] + [dxkey dykey] (vec* (vec-from-dirs (dirs-from-dir entity.dir)) (* dim.tilesize 4))] ; two possible movement cases: ; 1. Pacman wants to change direction perpendicular to how he is currently moving ; 2. Pacman wants to change direction on the axis he is currently moving on @@ -85,7 +86,6 @@ [dc _] (make-xy dx dy) (edge-prev edge-next) (edge c dc dim.halftile) (crosses? edge-snap) (edge-crosses edge-prev edge-next dim.tilesize) - _ (print edge-prev edge-next edge-snap) cnext (if (and crosses? (collides? (make-xy edge-next copp) rules)) (+ c (- edge-snap edge-prev)) (+ c dc)) @@ -95,9 +95,24 @@ (math.max (* dt dim.tilesize -4))))] (set entity.pos (make-xy cnext (+ copp dcopp))))) +(fn handle-keys [entity] + (let [prev-dirs (or entity.prev-dirs {}) + next-dirs (held-directions pacman.keymap)] + (each [dir _ (pairs next-dirs)] + (when (not (. prev-dirs dir)) + (set entity.last-dir dir))) + (set entity.prev-dirs next-dirs) + (set entity.dir (if (. next-dirs entity.last-dir) entity.last-dir + (next next-dirs))))) + (defmethod update :pacman (fn [entity dt rules] + (handle-keys entity) (update-direction entity rules) - (move entity dt rules))) + (let [[x1 y1] entity.pos + _ (move entity dt rules) + [x2 y2] entity.pos] + (when (or (not= x1 x2) (not= y1 y2)) + (set entity.dt-animation (+ (or entity.dt-animation 0) dt)))))) (fn pacman.new [pos] {: pos :vel [0 0] :entity :pacman}) diff --git a/game/helpers.fnl b/game/helpers.fnl index 622d1ce..23f1d52 100644 --- a/game/helpers.fnl +++ b/game/helpers.fnl @@ -1,10 +1,19 @@ + +(fn held-directions [keymap] + (let [dirs {}] + (each [_ dir (ipairs [:up :down :left :right])] + (when (love.keyboard.isDown (. keymap dir)) (tset dirs dir true))) + dirs)) + +(fn dirs-from-dir [dir] + (if dir {dir true} {})) + +(fn vec-from-dirs [dirs] + [(if dirs.left -1 dirs.right 1 0) + (if dirs.up -1 dirs.down 1 0)]) + (fn dir-from-key [keymap] - (var (dx dy) (values 0 0)) - (when (love.keyboard.isDown keymap.up) (set dy -1)) - (when (love.keyboard.isDown keymap.down) (set dy 1)) - (when (love.keyboard.isDown keymap.left) (set dx -1)) - (when (love.keyboard.isDown keymap.right) (set dx 1)) - [dx dy]) + (vec-from-dirs (held-directions keymap))) (fn vec-scalarop [op] (fn [vec scalar] @@ -47,4 +56,5 @@ (not= t1 t2) (values true (* (math.max t1 t2) width)) false))) -{: dir-from-key : vec* : vec+ : vec-op : all-coordinates : edge : edge-crosses} +{: dir-from-key : held-directions : vec-from-dirs : dirs-from-dir + : vec* : vec+ : vec-op : all-coordinates : edge : edge-crosses}