diff --git a/pacman-project/adt-teken.rkt b/pacman-project/adt-teken.rkt new file mode 100644 index 0000000..7826a94 --- /dev/null +++ b/pacman-project/adt-teken.rkt @@ -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))))