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>
This commit is contained in:
252
pacman-project/adt-teken.rkt
Normal file
252
pacman-project/adt-teken.rkt
Normal file
@@ -0,0 +1,252 @@
|
||||
#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))))
|
||||
Reference in New Issue
Block a user