Add smooth sub-tile interpolation for Pac-Man and ghosts
Entities now move smoothly between tiles instead of snapping. Previous positions are tracked in pacman and ghost ADTs; the draw layer linearly interpolates between prev and current based on movement timer progress. Residual time is carried across movement ticks for consistent speed at varying frame rates. Teleportation and ghost house exits call sync-prev! to prevent cross-map interpolation artifacts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -263,9 +263,11 @@
|
||||
;; Handle tunnel teleportation
|
||||
(cond
|
||||
((< next-col 0)
|
||||
((pos 'col!) (- (maze 'cols) 1)))
|
||||
((pos 'col!) (- (maze 'cols) 1))
|
||||
((ghost 'sync-prev!)))
|
||||
((>= next-col (maze 'cols))
|
||||
((pos 'col!) 0))
|
||||
((pos 'col!) 0)
|
||||
((ghost 'sync-prev!)))
|
||||
(else
|
||||
((ghost 'move!) (car delta) (cdr delta))))))
|
||||
|
||||
@@ -289,6 +291,7 @@
|
||||
((pos 'row!) ghost-house-exit-row)
|
||||
((pos 'col!) ghost-house-exit-col)
|
||||
((ghost 'direction!) 'left)
|
||||
((ghost 'sync-prev!))
|
||||
(on-ghosts-changed!)))
|
||||
|
||||
;;
|
||||
@@ -348,12 +351,12 @@
|
||||
(when (and was-in-house? (not (ghost 'in-house?)))
|
||||
(exit-ghost-house! ghost)
|
||||
((ghost 'mode!) global-mode)))
|
||||
;; Movement tick for active ghosts
|
||||
;; Movement tick for active ghosts (carry residual time)
|
||||
(when (not (ghost 'in-house?))
|
||||
(let ((mt ((ghost 'advance-movement-timer!) delta-time)))
|
||||
(when (>= mt ghost-speed-ms)
|
||||
(advance-ghost! ghost)
|
||||
((ghost 'reset-movement-timer!))))))
|
||||
((ghost 'set-movement-timer!) (- mt ghost-speed-ms))))))
|
||||
ghosts))
|
||||
|
||||
;;
|
||||
@@ -389,7 +392,9 @@
|
||||
((pac-pos 'row!) row))
|
||||
((>= col (maze 'cols))
|
||||
((pac-pos 'col!) 0)
|
||||
((pac-pos 'row!) row)))))
|
||||
((pac-pos 'row!) row)))
|
||||
;; Prevent interpolation across the entire map
|
||||
((pacman 'sync-prev!))))
|
||||
|
||||
;;
|
||||
;; Movement logic
|
||||
@@ -427,13 +432,19 @@
|
||||
;; advance-pacman! :: -> /
|
||||
(define (advance-pacman!)
|
||||
(when (not (or ((timer 'time-up?)) game-over?))
|
||||
(let ((current-dir (pacman 'direction)))
|
||||
(let* ((current-dir (pacman 'direction))
|
||||
(pos-before-row ((pacman 'position) 'row))
|
||||
(pos-before-col ((pacman 'position) 'col)))
|
||||
(cond
|
||||
((and queued-direction (can-move? queued-direction))
|
||||
(move-pacman! queued-direction)
|
||||
(set! queued-direction #f))
|
||||
((can-move? current-dir)
|
||||
(move-pacman! current-dir))))))
|
||||
(move-pacman! current-dir)))
|
||||
;; If pacman didn't actually move, sync prev to avoid drift
|
||||
(when (and (= ((pacman 'position) 'row) pos-before-row)
|
||||
(= ((pacman 'position) 'col) pos-before-col))
|
||||
((pacman 'sync-prev!))))))
|
||||
|
||||
;;
|
||||
;; Pause logic
|
||||
@@ -465,11 +476,11 @@
|
||||
(define (update! delta-time)
|
||||
(when (not (or paused? game-over?))
|
||||
((timer 'decrease!) delta-time)
|
||||
;; Pac-Man movement
|
||||
;; Pac-Man movement (carry residual for smoother interpolation)
|
||||
(set! movement-timer (+ movement-timer delta-time))
|
||||
(when (>= movement-timer pacman-speed-ms)
|
||||
(advance-pacman!)
|
||||
(set! movement-timer 0)
|
||||
(set! movement-timer (- movement-timer pacman-speed-ms))
|
||||
(check-ghost-collision!))
|
||||
;; Ghost mode cycling and movement
|
||||
(update-ghost-mode! delta-time)
|
||||
@@ -502,6 +513,7 @@
|
||||
((eq? msg 'timer) timer)
|
||||
((eq? msg 'paused?) paused?)
|
||||
((eq? msg 'game-over?) game-over?)
|
||||
((eq? msg 'pacman-movement-timer) movement-timer)
|
||||
((eq? msg 'key-press!) key-press!)
|
||||
((eq? msg 'update!) update!)
|
||||
((eq? msg 'set-on-coins-changed!) set-on-coins-changed!)
|
||||
|
||||
Reference in New Issue
Block a user