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:
@@ -256,27 +256,45 @@
|
||||
(for-each (lambda (gds) ((gds 'animate!))) ghost-draw-states)
|
||||
(set! time-since-last-animation 0)))
|
||||
|
||||
;; draw-pacman! :: pacman -> /
|
||||
(define (draw-pacman! pacman)
|
||||
;; lerp :: number, number, number -> number
|
||||
;; Linear interpolation between a and b by factor t (0..1).
|
||||
(define (lerp a b t)
|
||||
(+ a (* t (- b a))))
|
||||
|
||||
;; draw-pacman! :: pacman, number -> /
|
||||
;; Draws Pac-Man with smooth interpolation between tiles.
|
||||
(define (draw-pacman! pacman progress)
|
||||
(let* ((pos (pacman 'position))
|
||||
(row (pos 'row))
|
||||
(col (pos 'col))
|
||||
(prev-row (pacman 'prev-row))
|
||||
(prev-col (pacman 'prev-col))
|
||||
(t (min progress 1))
|
||||
(render-col (lerp prev-col col t))
|
||||
(render-row (lerp prev-row row t))
|
||||
(direction (pacman 'direction)))
|
||||
((pacman-sprite 'set-x!) (grid->pixel-x (pos 'col)))
|
||||
((pacman-sprite 'set-y!) (grid->pixel-y (pos 'row)))
|
||||
((pacman-sprite 'set-x!) (grid->pixel-x render-col))
|
||||
((pacman-sprite 'set-y!) (grid->pixel-y render-row))
|
||||
(cond ((eq? direction 'right) ((pacman-sprite 'rotate!) rotation-right))
|
||||
((eq? direction 'left) ((pacman-sprite 'rotate!) rotation-left))
|
||||
((eq? direction 'up) ((pacman-sprite 'rotate!) rotation-up))
|
||||
((eq? direction 'down) ((pacman-sprite 'rotate!) rotation-down)))))
|
||||
|
||||
;; draw-ghosts! :: list -> /
|
||||
;; Updates all ghost sprite positions and directions.
|
||||
;; Updates all ghost sprite positions with smooth interpolation.
|
||||
(define (draw-ghosts! ghosts)
|
||||
(for-each
|
||||
(lambda (ghost ghost-draw)
|
||||
(let* ((pos (ghost 'position))
|
||||
(row (pos 'row))
|
||||
(col (pos 'col))
|
||||
(prev-row (ghost 'prev-row))
|
||||
(prev-col (ghost 'prev-col))
|
||||
(t (min (/ (ghost 'movement-timer) ghost-speed-ms) 1))
|
||||
(render-row (lerp prev-row row t))
|
||||
(render-col (lerp prev-col col t))
|
||||
(dir (ghost 'direction)))
|
||||
((ghost-draw 'update!) row col dir)))
|
||||
((ghost-draw 'update!) render-row render-col dir)))
|
||||
ghosts ghost-draw-states))
|
||||
|
||||
;; draw-ui! :: score, timer -> /
|
||||
@@ -343,9 +361,10 @@
|
||||
;; draw-game! :: game -> /
|
||||
(define (draw-game! game)
|
||||
(let* ((level (game 'level))
|
||||
(timer (level 'timer)))
|
||||
(timer (level 'timer))
|
||||
(pac-progress (/ (level 'pacman-movement-timer) pacman-speed-ms)))
|
||||
;; Always update (lightweight sprite property sets)
|
||||
(draw-pacman! (level 'pacman))
|
||||
(draw-pacman! (level 'pacman) pac-progress)
|
||||
(draw-ghosts! (level 'ghosts))
|
||||
;; Only redraw when dirty / changed
|
||||
(draw-key! (level 'key))
|
||||
|
||||
Reference in New Issue
Block a user