Files
Pacman-Project/pacman-project/adt-teken.rkt
joren 48948a73a8 Refactor(Teken ADT): Isolate ALL graphics into single message-passing ADT
All rendering (maze, coins, key, pacman, UI, pause) consolidated here.
Grid-to-pixel conversion happens exclusively in this ADT.
Follows snake-wpo pattern with callback registration.

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

253 lines
9.3 KiB
Racket

#lang r7rs
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Teken ADT ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Alle grafische logica is geisoleerd in dit ADT. De spellogica kent niets
;; over pixels, vensters of sprites. De omzetting van grid-coordinaten naar
;; schermcoordinaten gebeurt uitsluitend hier.
(define-library (pacman-project adt-teken)
(import (scheme base)
(pp1 graphics)
(pacman-project constanten))
(export maak-teken)
(begin
;; maak-teken :: number, number -> teken
;; Maakt het teken-object aan dat alle grafische weergave verzorgt.
(define (maak-teken breedte hoogte)
(let ((venster (make-window breedte hoogte "Pacman")))
((venster 'set-background!) "black")
;;
;; Lagen aanmaken (volgorde bepaalt tekenvolgorde)
;;
(define doolhof-laag ((venster 'new-layer!)))
(define muntjes-laag ((venster 'new-layer!)))
(define sleutel-laag ((venster 'new-layer!)))
(define pacman-laag ((venster 'new-layer!)))
(define ui-laag ((venster 'new-layer!)))
(define pauze-laag ((venster 'new-layer!)))
;;
;; Doolhof tiles
;;
(define doolhof-tile (make-tile breedte hoogte))
((doolhof-laag 'add-drawable!) doolhof-tile)
;;
;; Muntjes tile
;;
(define muntjes-tile (make-tile breedte hoogte))
((muntjes-laag 'add-drawable!) muntjes-tile)
;;
;; Sleutel sprite (in het doolhof)
;;
(define sleutel-sprite (make-bitmap-tile "pacman-sprites/key.png"))
((sleutel-sprite 'set-scale!) sprite-schaal-sleutel)
((sleutel-laag 'add-drawable!) sleutel-sprite)
;; Sleutel UI indicator (naast de score)
(define sleutel-ui-sprite (make-bitmap-tile "pacman-sprites/key.png"))
((sleutel-ui-sprite 'set-scale!) sprite-schaal-sleutel-ui)
((sleutel-ui-sprite 'set-x!) sleutel-ui-x)
((sleutel-ui-sprite 'set-y!) sleutel-ui-y)
;;
;; Pac-Man sprite
;;
(define pacman-bitmap-tiles
(list (make-bitmap-tile "pacman-sprites/pacman-death-1.png")
(make-bitmap-tile "pacman-sprites/pacman-closed.png")
(make-bitmap-tile "pacman-sprites/pacman-open.png")))
(define pacman-sprite (make-tile-sequence pacman-bitmap-tiles))
((pacman-sprite 'set-scale!) sprite-schaal-pacman)
((pacman-laag 'add-drawable!) pacman-sprite)
;; Animatie state
(define tijd-sinds-laatste-animatie 0)
;;
;; UI tiles
;;
(define ui-tile (make-tile breedte hoogte))
((ui-laag 'add-drawable!) ui-tile)
;;
;; Coordinaat conversie
;;
;; grid->pixel-x :: number -> number
;; Converteert een grid kolom naar een pixel x-coordinaat.
(define (grid->pixel-x kolom)
(* cel-grootte-px kolom))
;; grid->pixel-y :: number -> number
;; Converteert een grid rij naar een pixel y-coordinaat.
(define (grid->pixel-y rij)
(+ (* rij cel-grootte-px) doolhof-offset-y))
;;
;; Teken functies
;;
;; teken-doolhof! :: doolhof -> /
;; Tekent alle muren en deuren van het doolhof.
(define (teken-doolhof! doolhof)
((doolhof 'voor-elke-cel)
(lambda (rij kolom celtype)
(cond
((= celtype cel-type-muur)
((doolhof-tile 'draw-rectangle!)
(grid->pixel-x kolom)
(grid->pixel-y rij)
(- cel-grootte-px doolhof-muur-krimp)
(- cel-grootte-px doolhof-muur-krimp)
"blue"))
((= celtype cel-type-deur)
((doolhof-tile 'draw-rectangle!)
(grid->pixel-x kolom)
(grid->pixel-y rij)
(- cel-grootte-px doolhof-muur-krimp)
(- cel-grootte-px doolhof-muur-krimp)
"pink"))))))
;; teken-muntjes! :: doolhof -> /
;; Tekent alle muntjes in het doolhof.
(define (teken-muntjes! doolhof)
((muntjes-tile 'clear!))
((doolhof 'voor-elke-cel)
(lambda (rij kolom celtype)
(when (= celtype cel-type-muntje)
((muntjes-tile 'draw-rectangle!)
(+ (grid->pixel-x kolom) muntje-inset)
(+ (grid->pixel-y rij) muntje-inset)
(- cel-grootte-px (* 2 muntje-inset) 6)
(- cel-grootte-px (* 2 muntje-inset) 6)
"yellow")))))
;; teken-sleutel! :: sleutel -> /
;; Tekent de sleutel op haar positie, of verbergt ze als opgepakt.
(define (teken-sleutel! sleutel)
(if (sleutel 'opgepakt?)
(begin
((sleutel-laag 'remove-drawable!) sleutel-sprite)
((sleutel-laag 'add-drawable!) sleutel-ui-sprite))
(let ((pos (sleutel 'positie)))
((sleutel-sprite 'set-x!) (grid->pixel-x (pos 'kolom)))
((sleutel-sprite 'set-y!) (grid->pixel-y (pos 'rij))))))
;; teken-pacman! :: pacman, number -> /
;; Tekent Pac-Man op zijn huidige positie met de juiste rotatie.
(define (teken-pacman! pacman delta-tijd)
(let* ((pos (pacman 'positie))
(richting (pacman 'richting)))
;; Positie instellen
((pacman-sprite 'set-x!) (grid->pixel-x (pos 'kolom)))
((pacman-sprite 'set-y!) (grid->pixel-y (pos 'rij)))
;; Rotatie instellen op basis van richting
(cond ((eq? richting 'rechts) ((pacman-sprite 'rotate!) rotatie-rechts))
((eq? richting 'links) ((pacman-sprite 'rotate!) rotatie-links))
((eq? richting 'omhoog) ((pacman-sprite 'rotate!) rotatie-omhoog))
((eq? richting 'omlaag) ((pacman-sprite 'rotate!) rotatie-omlaag)))
;; Animatie
(set! tijd-sinds-laatste-animatie (+ tijd-sinds-laatste-animatie delta-tijd))
(when (>= tijd-sinds-laatste-animatie animatie-interval-ms)
((pacman-sprite 'set-next!))
(set! tijd-sinds-laatste-animatie 0))))
;; teken-ui! :: score, tijdslimiet -> /
;; Tekent de score en de tijdslimiet op het scherm.
(define (teken-ui! score tijdslimiet)
((ui-tile 'clear!))
;; Score
((ui-tile 'draw-text!)
(number->string (score 'punten))
score-tekst-grootte score-tekst-x score-tekst-y "white")
;; Scheidingslijn
((ui-tile 'draw-rectangle!)
scheidingslijn-x 0 scheidingslijn-breedte hoogte "white")
;; Tijdslimiet
((ui-tile 'draw-text!)
"Time remaining:" tijd-tekst-grootte tijd-label-x tijd-label-y "white")
((ui-tile 'draw-text!)
((tijdslimiet 'formatteer-tijd))
score-tekst-grootte tijd-waarde-x tijd-waarde-y "white"))
;; teken-pauze! :: boolean -> /
;; Toont of verbergt het pauzescherm.
(define (teken-pauze! gepauzeerd?)
((pauze-laag 'empty!))
(when gepauzeerd?
(let ((pauze-tile (make-tile breedte hoogte)))
((pauze-laag 'add-drawable!) pauze-tile)
((pauze-tile 'draw-rectangle!) 0 90 670 hoogte "black")
((pauze-tile 'draw-text!) "Game Paused" 40 200 400 "red"))))
;; herteken-doolhof! :: doolhof -> /
;; Hertekent het doolhof (na deur verwijdering).
(define (herteken-doolhof! doolhof)
((doolhof-tile 'clear!))
(teken-doolhof! doolhof))
;;
;; Hoofdtekenfunctie
;;
;; teken-spel! :: spel -> /
;; Tekent het volledige spel (wordt als draw-callback geregistreerd).
(define (teken-spel! spel)
(let ((level (spel 'level)))
(teken-pacman! (level 'pacman) 0)
(teken-sleutel! (level 'sleutel))
(teken-muntjes! (level 'doolhof))
(teken-ui! (level 'score) (level 'tijdslimiet))
(teken-pauze! (level 'gepauzeerd?))))
;;
;; Callbacks instellen
;;
;; set-spel-lus-functie! :: (number -> /) -> /
;; Registreert de update-callback.
(define (set-spel-lus-functie! fun)
((venster 'set-update-callback!) fun))
;; set-toets-functie! :: (symbol, any -> /) -> /
;; Registreert de keyboard-callback.
(define (set-toets-functie! fun)
((venster 'set-key-callback!) fun))
;; start-tekenen! :: spel -> /
;; Start het tekenen door de draw-callback in te stellen.
(define (start-tekenen! spel)
;; Initieel doolhof en muntjes tekenen (eenmalig)
(teken-doolhof! ((spel 'level) 'doolhof))
(teken-muntjes! ((spel 'level) 'doolhof))
((venster 'set-draw-callback!)
(lambda () (teken-spel! spel))))
;;
;; Dispatch
;;
(define (dispatch-teken msg)
(cond ((eq? msg 'set-spel-lus-functie!) set-spel-lus-functie!)
((eq? msg 'set-toets-functie!) set-toets-functie!)
((eq? msg 'start-tekenen!) start-tekenen!)
(else (error "Teken ADT -- Onbekend bericht:" msg))))
dispatch-teken))))