Pacman movement! Basically.

This commit is contained in:
Jeremy Penner 2021-04-13 19:56:23 -04:00
parent ab69260091
commit 66fcd6a3cf
2 changed files with 68 additions and 10 deletions

View file

@ -2,7 +2,7 @@
(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*} (util.require :game.helpers)) (local {: vec* : vec+ : edge : edge-crosses} (util.require :game.helpers))
(local map (require :game.tilemap)) (local map (require :game.tilemap))
(local pacman (util.hot-table ...)) (local pacman (util.hot-table ...))
@ -37,13 +37,67 @@
; their edges filed off!) ; their edges filed off!)
; I think Bomberman actually does this too ; I think Bomberman actually does this too
(defmethod update :pacman (fn [entity dt rules] (fn tile-at [x y rules]
(-?> [x y]
(map.world-to-tile)
(rules.tile-at)))
(fn collides? [[x y] rules]
(let [tile (tile-at x y rules)]
(and tile (or tile.bomb tile.wall))))
(fn horizontal [c copp] [c copp])
(fn vertical [c copp] [copp c])
(fn perp-move? [dprev doppnext] (and (not= dprev 0) (not= doppnext 0)))
(fn try-perp-turn [entity d make-xy rules]
(let [[c copp] (make-xy (table.unpack entity.pos))
posperp (vec+ entity.pos (make-xy (if (> d 0) dim.tilesize (- dim.tilesize)) 0))
[xcenter ycenter] (vec+ (vec* (map.world-to-tile posperp) dim.tilesize) dim.halftile)
[ccenter coppcenter] (make-xy xcenter ycenter)
turn-allowed? (and (> copp (- coppcenter (/ dim.tilesize 4)))
(< copp (+ coppcenter (/ dim.tilesize 4))))]
(when (and turn-allowed? (not (collides? posperp rules)))
(set entity.vel (make-xy d 0))
(set entity.opp-target coppcenter))))
(fn rev-move? [dprev dprevopp dnext]
; currently moving on this axis or not moving at all
(and (or (not= dprev 0) (and (= dprev 0) (= dprevopp 0)))
; attempting to move in a new direction
(not= dnext 0) (not= dprev dnext)))
(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] (direct pacman.keymap (* dim.tilesize 4))]
turn-attempted (and (or (not= dxkey 0) (not= dykey 0)) ; two possible movement cases:
(or (not= dxkey dx) (not= dykey dy)))] ; 1. Pacman wants to change direction perpendicular to how he is currently moving
(when turn-attempted ; 2. Pacman wants to change direction on the axis he is currently moving on
(set entity.vel [dxkey dykey]))))) ; Case 1 takes priority over case 2
(if (perp-move? dy dxkey) (try-perp-turn entity dxkey horizontal rules)
(perp-move? dx dykey) (try-perp-turn entity dykey vertical rules)
(rev-move? dx dy dxkey) (set entity.vel [dxkey 0])
(rev-move? dy dx dykey) (set entity.vel [0 dykey]))))
(fn move [entity dt rules]
(let [[dx dy] (vec* entity.vel dt)
make-xy (if (= dy 0) horizontal vertical)
[c copp] (make-xy (table.unpack entity.pos))
[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))
dcopp (if (= entity.opp-target nil) 0
(-> (- entity.opp-target copp)
(math.min (* dt dim.tilesize 4))
(math.max (* dt dim.tilesize -4))))]
(set entity.pos (make-xy cnext (+ copp dcopp)))))
(defmethod update :pacman (fn [entity dt rules]
(update-direction entity rules)
(move entity dt rules)))
(fn pacman.new [pos] (fn pacman.new [pos]
{: pos :vel [0 0] :entity :pacman}) {: pos :vel [0 0] :entity :pacman})

View file

@ -39,8 +39,12 @@
(values (+ c pos-offset) (+ c dc pos-offset)))) (values (+ c pos-offset) (+ c dc pos-offset))))
(fn edge-crosses [c1 c2 width] (fn edge-crosses [c1 c2 width]
(if (= c1 c2) false (let [t1 (math.floor (/ c1 width))
(or (= (% c1 width) 0) (= (% c2 width) 0)) true t2 (math.floor (/ c2 width))]
(not= (math.floor (/ c1 width)) (math.floor (/ c2 width))))) (if (= c1 c2) false
(= (% c1 width) 0) (values true c1)
(= (% c2 width) 0) (values true c2)
(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 : vec* : vec+ : vec-op : all-coordinates : edge : edge-crosses}