Commit Graph

13 Commits

Author SHA1 Message Date
f2cb49ad2b Fix ghost and Pac-Man movement interpolation teleport 2026-03-23 12:38:23 +01:00
joren
0e14140db9 Fix interpolation: use offset backward lerp instead of forward extrapolation
Forward extrapolation caused visible teleporting at every direction
change (ghosts jumping ~1.3 tiles at intersections). Replace with
lerp(prev, current, 0.5 + t/2) which starts the visual at the
midpoint (max 0.5 tile / 12px lag) and smoothly reaches the
destination. No jumps, no teleporting, minimal hitbox offset.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 12:00:04 +01:00
joren
5e7456eba9 Fix visual hitbox offset with forward extrapolation
Switch from backward interpolation (lerp prev→current) to forward
extrapolation (current + (current-prev) * t). The visual now leads
toward the next tile, aligning with the logical hitbox so coins
disappear when Pac-Man visually reaches them.

When blocked (sync-prev! sets prev=current), the offset is zero
and the sprite stays at the current tile.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:56:22 +01:00
joren
f251478dd6 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>
2026-03-23 11:52:00 +01:00
joren
9028dd031c Add ghost CPUs with original Pac-Man AI targeting
Implement four ghosts (Blinky, Pinky, Inky, Clyde) with authentic
Pac-Man AI: Blinky chases directly, Pinky targets 2 tiles ahead
(with original up-direction bug), Inky uses vector doubling from
Blinky, Clyde switches to scatter within 8-tile radius.

Includes chase/scatter mode cycling, ghost house exit with staggered
delays, directional sprite rendering with animation, and ghost-pacman
collision detection.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:42:34 +01:00
joren
91b548e0bf Fix(Colors): Use standard Racket color names and round coin dots
The (pp1 graphics) library resolves colors via Racket's color database,
which doesn't support hex strings — they return #f causing a contract
violation on set-brush.

Replaced all hex colors with standard names:
  #2121DE -> "medium blue", #FFB851 -> "gold", #FFB8FF -> "hot pink",
  #FFFF00 -> "yellow", #FF0000 -> "red", #111111 -> "dark slate gray"

Also switched coins from draw-rectangle! to draw-ellipse! for round
dot rendering (arcade-accurate).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:29:14 +01:00
joren
b18aa49e8b Fix(Key) + UI: Fix key sprite position and arcade-style visual overhaul
Key bug fix:
- Key sprite position was never set on startup, appearing at (0,0)
- Added init-key-position! called in start-drawing! to place key sprite
  at its grid position on load

Arcade UI polish:
- Header bar with "PAC-MAN" title in yellow
- "SCORE" label above score value in header
- Sidebar separator uses wall color instead of white block
- "TIME" label with large countdown in sidebar area
- Coins now rendered as small centered dots (coin-size constant)
- Arcade color palette: #2121DE walls, #FFB851 coins, #FFB8FF doors
- "GAME OVER" overlay in red when time expires
- "PAUSED" overlay covers maze area only (not header)
- Window title set to "PAC-MAN"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:27:32 +01:00
joren
eb309b74b1 Optimize(Game): Wire level change events to draw dirty flags
On start!, connects level's coin/maze change callbacks to the draw
ADT's mark-coins-dirty! and mark-maze-dirty! methods. This completes
the event chain: level state change -> dirty flag -> redraw next frame.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:21:31 +01:00
joren
55f1c2a382 Optimize(Level): Add change notification callbacks for draw invalidation
Level now fires callbacks when game state changes that require redrawing:
- on-coins-changed!: fired when a coin is eaten or key is picked up
- on-maze-changed!: fired when a door is removed

Exposes set-on-coins-changed! and set-on-maze-changed! messages so the
game ADT can wire these to the draw ADT's dirty flags.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:21:26 +01:00
joren
5b43b3c8d5 Optimize(Draw): Skip unchanged elements in draw callback
Previously every frame: cleared+redrawed 868 cells for coins, cleared+
redrawed all UI text, emptied+recreated pause layer, and swapped key
sprites repeatedly.

Now uses dirty flags and cached values:
- Coins: only redrawn when coins-dirty? is set (on coin eat/key pickup)
- Maze: only redrawn when a door is removed
- UI: only redrawn when score or time string actually changes
- Key: sprite swap happens exactly once, not every frame
- Pause: layer only modified when paused? state transitions

Exposes mark-coins-dirty! and mark-maze-dirty! messages so the game
ADT can signal changes from the level.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:21:20 +01:00
joren
4c98ca61c5 Implement automatic Pac-Man movement with queued direction turning
Pac-Man now moves automatically in its current direction every
pacman-speed-ms (200ms). Arrow keys queue a desired turn direction
instead of moving directly. Each movement tick:

1. Try the queued direction — if passable, turn and move that way
2. Otherwise keep moving in the current direction
3. Stop only when hitting a wall (no direction change)

New internal state:
- queued-direction: the direction the player wants to turn next
- movement-timer: accumulates delta-time, triggers move at interval

New helper:
- can-move?: checks if a direction is passable (no wall/locked door)

Changed behavior:
- key-press! now sets queued-direction instead of calling move-pacman!
- update! now drives movement via advance-pacman! on a timer
- move-pacman! no longer checks time-up? (advance-pacman! handles it)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:15:46 +01:00
joren
1ac72f03a7 Fix(Animation): Drive Pac-Man mouth animation from game loop, not draw callback
The draw callback receives no delta-time, so animation was stuck at 0.
Split draw-pacman! into draw (position/rotation) and animate-pacman!
(sprite sequence advancement). Animation is now called from the game
loop which has the real delta-time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:12:56 +01:00
joren
caac996acd Refactor(Structure): Move ADTs into adt/ folder, rename spel.rkt to main.rkt
New structure groups all ADT modules under adt/ directory, removing
redundant adt- prefix from filenames. Library names now read as
(pacman-project adt position) etc. All imports updated accordingly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 11:11:08 +01:00