Fix Pac-Man diagonal movement, stop animating when not moving

This commit is contained in:
Jeremy Penner 2021-04-14 21:20:16 -04:00
parent 66fcd6a3cf
commit f9dcccf773
2 changed files with 38 additions and 13 deletions

View file

@ -2,15 +2,16 @@
(local dim (require :game.dim)) (local dim (require :game.dim))
(local {: defmethod} (util.require :lib.multimethod)) (local {: defmethod} (util.require :lib.multimethod))
(local {: direct : draw : update} (util.require :game.entity)) (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 map (require :game.tilemap))
(local pacman (util.hot-table ...)) (local pacman (util.hot-table ...))
(set pacman.keymap {:up :up :down :down :left :left :right :right}) (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)) (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) mouthsize (* mouthsize-max mouthsize-ratio)
anglestart (if (< dx 0) math.pi anglestart (if (< dx 0) math.pi
(> dx 0) 0 (> dx 0) 0
@ -68,7 +69,7 @@
(fn update-direction [entity rules] (fn update-direction [entity rules]
(let [[dx dy] entity.vel (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: ; two possible movement cases:
; 1. Pacman wants to change direction perpendicular to how he is currently moving ; 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 ; 2. Pacman wants to change direction on the axis he is currently moving on
@ -85,7 +86,6 @@
[dc _] (make-xy dx dy) [dc _] (make-xy dx dy)
(edge-prev edge-next) (edge c dc dim.halftile) (edge-prev edge-next) (edge c dc dim.halftile)
(crosses? edge-snap) (edge-crosses edge-prev edge-next dim.tilesize) (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)) cnext (if (and crosses? (collides? (make-xy edge-next copp) rules))
(+ c (- edge-snap edge-prev)) (+ c (- edge-snap edge-prev))
(+ c dc)) (+ c dc))
@ -95,9 +95,24 @@
(math.max (* dt dim.tilesize -4))))] (math.max (* dt dim.tilesize -4))))]
(set entity.pos (make-xy cnext (+ copp dcopp))))) (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] (defmethod update :pacman (fn [entity dt rules]
(handle-keys entity)
(update-direction entity rules) (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] (fn pacman.new [pos]
{: pos :vel [0 0] :entity :pacman}) {: pos :vel [0 0] :entity :pacman})

View file

@ -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] (fn dir-from-key [keymap]
(var (dx dy) (values 0 0)) (vec-from-dirs (held-directions keymap)))
(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])
(fn vec-scalarop [op] (fn vec-scalarop [op]
(fn [vec scalar] (fn [vec scalar]
@ -47,4 +56,5 @@
(not= t1 t2) (values true (* (math.max t1 t2) width)) (not= t1 t2) (values true (* (math.max t1 t2) width))
false))) 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}