Commit Graph

9 Commits

Author SHA1 Message Date
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