Renamed files: constanten→constants, adt-positie→adt-position, adt-doolhof→adt-maze, adt-sleutel→adt-key, adt-tijdslimiet→adt-timer, adt-teken→adt-draw, adt-spel→adt-game. All message names, variables, comments, and tests converted to English. Also fixed counter location bug (time-label x/y were swapped). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
189 lines
7.1 KiB
Racket
189 lines
7.1 KiB
Racket
#lang r7rs
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Teken ADT ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(define-library ()
|
|
(import (scheme base)
|
|
(pp1 graphics)
|
|
(snake-wpo constanten))
|
|
(export maak-teken)
|
|
|
|
(begin
|
|
|
|
;; maak-teken :: number, number -> teken
|
|
(define (maak-teken pixels-horizontaal pixels-verticaal)
|
|
(let ((venster (make-window pixels-horizontaal pixels-verticaal "Snake")))
|
|
|
|
;;
|
|
;; Configureren van het spelvenster
|
|
;;
|
|
|
|
((venster 'set-background!) "black")
|
|
|
|
|
|
;;
|
|
;; Slang stukken tiles beheren
|
|
;; Voor een slang te tekenen moeten we een dynamisch aantal stukken
|
|
;; tekenen. Het is dus onmogelijk om op voorhand deze 'tiles' te
|
|
;; definieren. Daarom gaan we dus een associatie-lijst bijhouden van tiles.
|
|
;; Elk element in die lijst zal dus een cons-cell zijn waarbij de car gelijk
|
|
;; is aan het object, en de cdr die tile is die gebruikt wordt om dat object
|
|
;; op het scherm te tekenen.
|
|
;;
|
|
|
|
(define slang-laag ((venster 'new-layer!)))
|
|
(define slang-tiles '())
|
|
|
|
;; voeg-slang-stuk-toe! :: slang-stuk -> tile
|
|
(define (voeg-slang-stuk-toe! slang-stuk)
|
|
(let ((nieuwe-tile
|
|
(make-bitmap-tile "images/snake.png" "images/snake-mask.png")))
|
|
(set! slang-tiles (cons (cons slang-stuk nieuwe-tile) slang-tiles))
|
|
((slang-laag 'add-drawable!) nieuwe-tile)
|
|
nieuwe-tile))
|
|
|
|
;; neem-slang-stuk :: slang-stuk -> tile
|
|
(define (neem-slang-stuk slang-stuk)
|
|
(let ((result (assoc slang-stuk slang-tiles)))
|
|
(if result
|
|
(cdr result)
|
|
(voeg-slang-stuk-toe! slang-stuk))))
|
|
|
|
|
|
;; OPGELET: Merk op dat er geen code aanwezig is om tiles te verwijderen.
|
|
;; In dit voorbeeldspel was dit niet nodig. Maar in een complex spel zal je
|
|
;; ook tiles moeten verwijderen als ze niet meer nodig zijn. Hou hier
|
|
;; rekening mee wanneer je jouw spel implementeert!
|
|
|
|
|
|
;;
|
|
;; Appel tiles beheren
|
|
;; In dit voorbeeldspel is er slechts 1 appel, dus 1 vaste tile in het Teken
|
|
;; ADT is voldoende.
|
|
;;
|
|
|
|
(define appel-laag ((venster 'new-layer!)))
|
|
(define appel-tile
|
|
(make-bitmap-tile "images/apple.png" "images/apple-mask.png"))
|
|
((appel-laag 'add-drawable!) appel-tile)
|
|
|
|
|
|
;; OPGELET: Omdat er in dit spel slechts één appel zichtbaar is hebben wij
|
|
;; de implementatie van het tekenen van appels eenvoudig gemaakt door
|
|
;; slechts één tile aan te maken die steeds hergebruikt wordt. Denk na wat
|
|
;; er gebeurd als er meerdere appels tegelijkertijd moeten verschijnen als
|
|
;; er maar één tile is... Hoe is dit probleem opgelost bij
|
|
|
|
;; OPGELET: Merk op dat de volgorde waarin lagen aangemaakt worden een
|
|
;; invloed hebben op hoe je spel getekend wordt. Lagen worden op het scherm
|
|
;; getekend van oud-naar-nieuw. Dat betekent dat de tiles op de appel-laag
|
|
;; getekend zullen worden bovenop de tiles op de slang-laag.
|
|
|
|
|
|
|
|
;;
|
|
;; Teken Functies
|
|
;;
|
|
|
|
;; Generieke teken procedure
|
|
|
|
|
|
;; teken-object! :: any tile -> /
|
|
(define (teken-object! obj tile)
|
|
(let* ((obj-x ((obj 'positie) 'x))
|
|
(obj-y ((obj 'positie) 'y))
|
|
(screen-x (* cel-breedte-px obj-x))
|
|
(screen-y (* cel-hoogte-px obj-y)))
|
|
((tile 'set-x!) screen-x)
|
|
((tile 'set-y!) screen-y)))
|
|
|
|
;; Schrijf je spellogica nooit in pixels. Dit zorgt ervoor dat je spel kan
|
|
;; werken ongeacht de specifieke resolutie of hardware (denk aan een matrix
|
|
;; van LED-lichtjes t.o.v. pixels op een computerscherm). De omzetting van
|
|
;; spellogica naar tekenlogica gebeurt hier door de coördinaten in de
|
|
;; spellogica te vermenigvuldigen met de afmetingen (in pixels) van een cel.
|
|
;;
|
|
;; Informatie over werken met tiles en lagen kan teruggevonden worden in de
|
|
;; documentatie van de grafische bibliotheek en wordt dus niet hier in
|
|
;; detail besproken.
|
|
|
|
|
|
;; Appel
|
|
;; teken-appel! :: appel -> /
|
|
(define (teken-appel! appel)
|
|
(if appel
|
|
(teken-object! appel appel-tile)))
|
|
|
|
;; Slang
|
|
;; teken-slang-stuk! :: slang-stuk -> /
|
|
(define (teken-slang-stuk! slang-stuk)
|
|
(let ((tile (neem-slang-stuk slang-stuk)))
|
|
(teken-object! slang-stuk tile)))
|
|
|
|
;; Spel
|
|
;; teken-spel! :: spel -> /
|
|
(define (teken-spel! spel)
|
|
(teken-level! (spel 'level)))
|
|
|
|
;; Level
|
|
;; teken-level! :: level -> /
|
|
(define (teken-level! level)
|
|
(teken-appel! (level 'appel))
|
|
(teken-slang! (level 'slang)))
|
|
|
|
;; Slang
|
|
;; teken-slang! :: slang -> /
|
|
|
|
|
|
(define (teken-slang! slang)
|
|
((slang 'voor-alle-stukken) teken-slang-stuk!))
|
|
|
|
|
|
|
|
;;
|
|
;; Callbacks instellen
|
|
;;
|
|
|
|
;; set-spel-lus-functie! :: (number -> /) -> /
|
|
(define (set-spel-lus-functie! fun)
|
|
((venster 'set-update-callback!) fun))
|
|
|
|
;; set-toets-functie! :: (symbol, any -> /) -> /
|
|
(define (set-toets-functie! fun)
|
|
((venster 'set-key-callback!) fun))
|
|
|
|
;; set-klik-functie! :: (symbol, symbol, number, number -> /) -> /
|
|
(define (set-klik-functie! fun)
|
|
(define (aangepaste-functie btn evt x y)
|
|
(let ((grid-x (quotient x cel-breedte-px))
|
|
(grid-y (quotient y cel-hoogte-px)))
|
|
(fun btn evt grid-x grid-y)))
|
|
((venster 'set-mouse-click-callback!) aangepaste-functie))
|
|
|
|
|
|
;; Merk op dat deze procedure, net zoals de `teken-object!` procedure
|
|
;; hierboven een omzetting doet van het coördinatensysteem. Dit gaat van
|
|
;; teken-coördinaat naar spel-coördinaat, dus in plaats van te
|
|
;; vermenigvuldigen moeten we hier delen (`quotient` is deling zonder rest).
|
|
|
|
|
|
;; start-tekenen! :: / -> /
|
|
(define (start-tekenen! spel)
|
|
((venster 'set-draw-callback!) (lambda ()
|
|
(teken-spel! spel))))
|
|
|
|
;;
|
|
;; Dispatch
|
|
;;
|
|
|
|
(define (dispatch-teken msg)
|
|
(cond ((eq? msg 'set-toets-functie!) set-toets-functie!)
|
|
((eq? msg 'set-spel-lus-functie!) set-spel-lus-functie!)
|
|
((eq? msg 'set-klik-functie!) set-klik-functie!)
|
|
((eq? msg 'start-tekenen!) start-tekenen!)
|
|
(else (error "Teken ADT -- Onbekend bericht:" msg))))
|
|
|
|
dispatch-teken))))
|