#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))))