(local util (require :lib.util)) (local dim (require :game.dim)) (local {: defmethod} (util.require :lib.multimethod)) (local {: direct : draw : update} (util.require :game.entity)) (local {: vec*} (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]}] (let [mouthsize-max (if (and (= dx 0) (= dy 0)) 0 (/ math.pi 4)) mouthsize-ratio (math.abs (math.sin (* (love.timer.getTime) 16))) mouthsize (* mouthsize-max mouthsize-ratio) anglestart (if (< dx 0) math.pi (> dx 0) 0 (> dy 0) (/ math.pi 2) (+ math.pi (/ math.pi 2))) angle1 (+ anglestart mouthsize) angle2 (+ anglestart math.pi math.pi (- mouthsize))] (love.graphics.setColor 1 1 0) (love.graphics.arc :fill x y dim.halftile angle1 angle2)))) ; Pacman movement and collision rules ; * Pacman moves in the direction he was told until stopped by a wall ; * If the player tells Pacman to change direction but there is a wall there, ; Pacman's direction does not change ; * Turning a corner is funky: ; https://www.gamasutra.com/view/feature/132330/the_pacman_dossier.php?page=4 ; "Whenever Pac-Man makes a pre-turn or post-turn, his orientation changes, and he starts to ; move one pixel in his new direction for every pixel traveled in his old direction, effectively ; doubling his speed as he moves at a 45 degree angle. Once he reaches the centerline of the new ; direction's path, he starts moving purely in that direction and his speed returns to normal." ; The simplest way to implement this appears to be to treat turns as having a "fudge factor" - ; Pacman enters a state where he changes direction _and_ is being pulled towards the center of ; the track. (The "post-turn" correction means we can't simply treat this as the corners having ; their edges filed off!) ; I think Bomberman actually does this too (defmethod update :pacman (fn [entity dt rules] (let [[dx dy] entity.vel [dxkey dykey] (direct pacman.keymap (* dim.tilesize 4)) turn-attempted (and (or (not= dxkey 0) (not= dykey 0)) (or (not= dxkey dx) (not= dykey dy)))] (when turn-attempted (set entity.vel [dxkey dykey]))))) (fn pacman.new [pos] {: pos :vel [0 0] :entity :pacman}) pacman.hot