simpler API for door games

svn: r4789
This commit is contained in:
Matthew Flatt 2006-11-06 02:01:57 +00:00
parent bd1aaac077
commit 7e08f36804
4 changed files with 283 additions and 217 deletions

View File

@ -10,7 +10,8 @@
(provide door-game% (provide door-game%
player-data player-data
thing-data) thing-data
bitmap->drawer)
(define-struct door-game (board)) (define-struct door-game (board))
@ -21,6 +22,25 @@
(define-struct wall (drawer)) (define-struct wall (drawer))
(define-struct player (data drawer i j)) (define-struct player (data drawer i j))
(define-struct thing (data drawer i j heads-up?)) (define-struct thing (data drawer i j heads-up?))
(define (bitmap->drawer bm game)
(let*-values ([(bm mask)
(cond
[(bm . is-a? . bitmap%)
(values bm (send bm get-loaded-mask))]
[(bm . is-a? . image-snip%)
(values (send bm get-bitmap)
(send bm get-bitmap-mask))]
[else (raise-type-error
'bitmap->drawer
"bitmap% or image-snip% object"
bm)])]
[(dl) (bitmap->gl-list bm
#:with-gl (lambda (f)
(send game with-gl-context f))
#:mask mask)])
(lambda ()
(gl-call-list dl))))
(define door-game% (define door-game%
(class object% (class object%
@ -36,10 +56,10 @@
(make-room #f null null)))))) (make-room #f null null))))))
(define walls (build-vector (define walls (build-vector
(add1 (* 2 x-rooms)) (add1 (* 2 (add1 x-rooms)))
(lambda (i) (lambda (i)
(build-vector (build-vector
(add1 (* 2 y-rooms)) (add1 (* 2 (add1 y-rooms)))
(lambda (j) (lambda (j)
(make-wall #f)))))) (make-wall #f))))))
@ -155,85 +175,109 @@
(define/public (with-gl-context f) (define/public (with-gl-context f)
(send board with-gl-context f)) (send board with-gl-context f))
(define/public (set-wall ri rj dir wall? door-image) (define/public (set-wall-image loc wall? door-image)
(case dir (let-values ([(ri rj dir)
[(n s e w) 'ok] (cond
[else (raise-type-error [(and (list? loc)
'set-wall (= 3 (length loc)))
"'n, 's, 'e, or 'w" (apply values loc)]
dir)]) [(and (list? loc)
(let* ([i (+ (* 2 ri) (case dir (= 2 (length loc)))
[(w) 0] (let ([i (car loc)]
[(n s) 1] [j (cadr loc)])
[(e) 2]))] (if (= 1 (+ (if (integer? i) 1 0)
[j (+ (* 2 rj) (case dir (if (integer? j) 1 0)))
[(n) 2] (values (if (integer? i)
[(w e) 1] i
[(s) 0]))] (add1 (floor (inexact->exact i))))
[wall (vector-ref (vector-ref walls i) j)] (if (integer? j)
[drawer (if wall? j
(make-wall-draw ri rj dir door-image) (add1 (floor (inexact->exact j))))
void)]) (if (integer? i) 's 'w))
(if (wall-drawer wall) (values 0 0 'bad)))]
(send board set-space-draw wall drawer) [else (values 0 0 'bad)])])
(send board add-space drawer wall)) (case dir
(set-wall-drawer! wall drawer)) [(n s e w) 'ok]
(send board refresh)) [else (raise-type-error
'set-wall
"location"
loc)])
(let* ([i (+ (* 2 ri) (case dir
[(w) 0]
[(n s) 1]
[(e) 2]))]
[j (+ (* 2 rj) (case dir
[(n) 2]
[(w e) 1]
[(s) 0]))]
[wall (vector-ref (vector-ref walls i) j)]
[door-image (if (or (door-image . is-a? . bitmap%)
(door-image . is-a? . image-snip%))
(bitmap->drawer door-image this)
door-image)]
[drawer (if wall?
(make-wall-draw ri rj dir door-image)
void)])
(if (wall-drawer wall)
(send board set-space-draw wall drawer)
(send board add-space drawer wall))
(set-wall-drawer! wall drawer))
(send board refresh)))
(define/public (set-room i j data) (define/public (set-room-data loc data)
(let ([room (vector-ref (vector-ref rooms i) j)]) (let ([room (vector-ref (vector-ref rooms (car loc)) (cadr loc))])
(set-room-data! room data))) (set-room-data! room data)))
(public [new-player make-player]) (public [new-player make-player-icon])
(define (new-player drawer data) (define (new-player drawer data)
(make-player data drawer #f #f)) (make-player data drawer #f #f))
(define/public (move-player player i j) (define/public (move-player-icon player loc)
(let ([from-room (and (player-i player) (let ([i (and loc (car loc))]
(vector-ref (vector-ref rooms (player-i player)) (player-j player)))] [j (and loc (cadr loc))])
[to-room (and i (vector-ref (vector-ref rooms i) j))]) (let ([from-room (and (player-i player)
(when from-room (vector-ref (vector-ref rooms (player-i player)) (player-j player)))]
(set-room-players! from-room (remq player (room-players from-room)))) [to-room (and loc (vector-ref (vector-ref rooms i) j))])
(when to-room (when from-room
(set-room-players! to-room (cons player (room-players to-room)))) (set-room-players! from-room (remq player (room-players from-room))))
(set-player-i! player i) (when to-room
(set-player-j! player j) (set-room-players! to-room (cons player (room-players to-room))))
(when from-room (set-player-i! player i)
(send board remove-piece player)) (set-player-j! player j)
(when to-room (when from-room
(send board add-piece (+ i 0.5) (+ j 0.5) 0.0 (player-drawer player) player)) (send board remove-piece player))
(send board refresh))) (when to-room
(send board add-piece (+ i 0.5) (+ j 0.5) 0.0 (player-drawer player) player))
(send board refresh))))
(public [new-thing make-thing]) (public [new-thing make-thing-icon])
(define (new-thing drawer data) (define (new-thing drawer data)
(make-thing data drawer #f #f #f)) (make-thing data drawer #f #f #f))
(define/private (move-thing/hu thing i j hu?) (define/public (move-thing-icon thing loc)
(let ([from-hu? (thing-heads-up? thing)] (let ([i (and (pair? loc) (car loc))]
[from-room (and (thing-i thing) [j (and (pair? loc) (cadr loc))]
(vector-ref (vector-ref rooms (thing-i thing)) (thing-j thing)))] [hu? (eq? loc 'heads-up)])
[to-room (and i (vector-ref (vector-ref rooms i) j))]) (let ([from-hu? (thing-heads-up? thing)]
(when from-room [from-room (and (thing-i thing)
(set-room-things! from-room (remq thing (room-things from-room)))) (vector-ref (vector-ref rooms (thing-i thing)) (thing-j thing)))]
(when to-room [to-room (and i (vector-ref (vector-ref rooms i) j))])
(set-room-things! to-room (cons thing (room-things to-room)))) (when from-room
(set-thing-i! thing i) (set-room-things! from-room (remq thing (room-things from-room))))
(set-thing-j! thing j) (when to-room
(set-thing-heads-up?! thing hu?) (set-room-things! to-room (cons thing (room-things to-room))))
(when from-room (set-thing-i! thing i)
(send board remove-piece thing)) (set-thing-j! thing j)
(when from-hu? (set-thing-heads-up?! thing hu?)
(send board remove-heads-up thing)) (when from-room
(when to-room (send board remove-piece thing))
(send board add-piece (+ i 0.5) (+ j 0.5) 0.0 (thing-drawer thing) thing) (when from-hu?
(send board enable-piece thing #f)) (send board remove-heads-up thing))
(when hu? (when to-room
(send board add-heads-up 1.0 1.0 (thing-drawer thing) thing)) (send board add-piece (+ i 0.5) (+ j 0.5) 0.0 (thing-drawer thing) thing)
(send board refresh))) (send board enable-piece thing #f))
(when hu?
(define/public (move-thing thing i j) (send board add-heads-up 1.0 1.0 (thing-drawer thing) thing))
(move-thing/hu thing i j #f)) (send board refresh))))
(define/public (move-thing-heads-up thing)
(move-thing/hu thing #f #f #t))
(super-new)))) (super-new))))

View File

@ -0,0 +1,148 @@
(module graph mzscheme
(require (lib "class.ss")
"private/utils.ss")
(require-for-syntax "private/utils.ss")
(provide node% edge%
grid-graph)
(define node%
(class object%
(define edges null)
(define loc #f)
(define/public (set-location l)
(set! loc l))
(define/public (get-location)
loc)
(define/public (connect e)
(set! edges (cons e edges)))
(define/public (get-edges)
edges)
(define/public (edge-to n)
(ormap (lambda (e)
(and (memq n (send e get-nodes))
e))
edges))
(super-new)))
(define edge%
(class object%
(define nodes null)
(define loc #f)
(define/public (set-location l)
(set! loc l))
(define/public (get-location)
loc)
(define/public (connect n)
(set! nodes (cons n nodes)))
(define/public (get-nodes)
nodes)
(super-new)))
(define (check <%> v)
(unless (v . is-a? . <%>)
(error 'maze
"not an instance of ~a: ~e"
<%>
v))
v)
(define (connect-all! connect-key layout)
(define-member-name connect connect-key)
(let loop ([layout layout]
[j (sub1 (quotient (length layout) 2))])
(unless (null? (cdr layout))
(let loop ([edges (car layout)]
[nodes (cadr layout)]
[next-edges (caddr layout)]
[i 0])
(unless (null? (cdr nodes))
(let ([n (car edges)]
[s (car next-edges)]
[e (caddr nodes)]
[w (car nodes)]
[r (cadr nodes)])
(send r set-location (list i j))
(send n set-location (list i (+ j 0.5)))
(send s set-location (list i (- j 0.5)))
(send e set-location (list (+ i 0.5) j))
(send w set-location (list (- i 0.5) j))
(send r connect n)
(send r connect s)
(send r connect e)
(send r connect w)
(send n connect r)
(send s connect r)
(send e connect r)
(send w connect r))
(loop (cdr edges)
(cddr nodes)
(cdr next-edges)
(add1 i))))
(loop (cddr layout) (sub1 j)))))
(define-syntax grid-graph
(lambda (stx)
(syntax-case stx ()
[(maze edge<%> node<%> (items ...) ...)
(let ([itemss (syntax->list #'((items ...) ...))])
(unless (odd? (length itemss))
(raise-syntax-error
#f
"need an odd number of rows"
stx))
(let-values ([(edgess nodess) (alternates itemss)])
(when (null? nodess)
(raise-syntax-error
#f
"no nodes supplied"
stx))
(let ([first-edges-len
(length (syntax->list (car edgess)))])
(for-each (lambda (edges)
(let ([len (length (syntax->list edges))])
(unless (= len first-edges-len)
(raise-syntax-error
#f
"N/S edges sequence length doesn't match first edges sequence"
stx
edges))))
edgess)
(for-each (lambda (nodes)
(let ([len (length (syntax->list nodes))])
(unless (= len (add1 (* 2 first-edges-len)))
(raise-syntax-error
#f
"nodes with E/W edges sequence length doesn't match first edges sequence"
stx
nodes))))
nodess))
(with-syntax ([((items ...) ...)
(interleave
(map (lambda (edges)
(map (lambda (edge)
(quasisyntax/loc edge
(instance edge<%> #,edge)))
(syntax->list edges)))
edgess)
(map (lambda (nodes)
(let-values ([(edges nodes)
(alternates (syntax->list nodes))])
(interleave
(map (lambda (edge)
(quasisyntax/loc edge
(instance edge<%> #,edge)))
edges)
(map (lambda (node)
(quasisyntax/loc node
(instance node<%> #,node)))
nodes))))
nodess))])
(syntax/loc stx
(connect-all! (member-name-key connect) (list (list items ...) ...))))))])))
(define-syntax instance
(syntax-rules ()
[(instance <%> v)
(check <%> v)])))

View File

@ -1,105 +0,0 @@
(module maze mzscheme
(require (lib "class.ss")
"private/utils.ss")
(require-for-syntax "private/utils.ss")
(provide maze)
(define (check <%> v)
(unless (v . is-a? . <%>)
(error 'maze
"not an instance of ~a: ~e"
<%>
v))
v)
(define (connect-all! connect-key layout)
(define-member-name connect connect-key)
(let loop ([layout layout]
[j (sub1 (quotient (length layout) 2))])
(unless (null? (cdr layout))
(let loop ([walls (car layout)]
[rooms (cadr layout)]
[next-walls (caddr layout)]
[i 0])
(unless (null? (cdr rooms))
(let ([n (car walls)]
[s (car next-walls)]
[e (caddr rooms)]
[w (car rooms)]
[r (cadr rooms)])
(send r connect i j n s e w))
(loop (cdr walls)
(cddr rooms)
(cdr next-walls)
(add1 i))))
(loop (cddr layout) (sub1 j)))))
(define-syntax maze
(lambda (stx)
(syntax-case stx ()
[(maze connect wall<%> room<%> (items ...) ...)
(let ([itemss (syntax->list #'((items ...) ...))])
(unless (odd? (length itemss))
(raise-syntax-error
#f
"need an odd number of rows"
stx))
(let-values ([(wallss roomss) (alternates itemss)])
(when (null? roomss)
(raise-syntax-error
#f
"no rooms supplied"
stx))
(let ([first-walls-len
(length (syntax->list (car wallss)))])
(for-each (lambda (walls)
(let ([len (length (syntax->list walls))])
(unless (= len first-walls-len)
(raise-syntax-error
#f
"N/S walls sequence length doesn't match first walls sequence"
stx
walls))))
wallss)
(for-each (lambda (rooms)
(let ([len (length (syntax->list rooms))])
(unless (= len (add1 (* 2 first-walls-len)))
(raise-syntax-error
#f
"rooms with E/W walls sequence length doesn't match first walls sequence"
stx
rooms))))
roomss))
(with-syntax ([((items ...) ...)
(interleave
(map (lambda (walls)
(map (lambda (wall)
(quasisyntax/loc wall
(instance wall<%> #,wall)))
(syntax->list walls)))
wallss)
(map (lambda (rooms)
(let-values ([(walls rooms)
(alternates (syntax->list rooms))])
(interleave
(map (lambda (wall)
(quasisyntax/loc wall
(instance wall<%> #,wall)))
walls)
(map (lambda (room)
(quasisyntax/loc room
(instance room<%> #,room)))
rooms))))
roomss))])
(syntax/loc stx
(connect-all! (member-name-key connect) (list (list items ...) ...))))))])))
(define-syntax instance
(syntax-rules (unquote)
[(instance <%> (unquote v))
(check <%> v)]
[(instance <%> %)
(check <%> (new %))])))

View File

@ -1,17 +1,15 @@
(module utils mzscheme (module utils mzscheme
(require (lib "gl-vectors.ss" "sgl") (require (lib "gl-vectors.ss" "sgl")
(prefix gl- (lib "sgl.ss" "sgl")) (prefix gl- (lib "sgl.ss" "sgl"))
(lib "bitmap.ss" "sgl")
(lib "math.ss") (lib "math.ss")
(lib "mred.ss" "mred") (lib "mred.ss" "mred")
(lib "list.ss") (lib "list.ss")
(lib "etc.ss") (lib "etc.ss")
(lib "class.ss") (lib "class.ss")
(lib "kw.ss")) (lib "kw.ss")
"doors.ss")
(provide bitmap->drawer (provide door-bm
door-bm
magic-door-bm magic-door-bm
locked-door-bm locked-door-bm
@ -20,8 +18,8 @@
magic-door-drawer magic-door-drawer
open-door-drawer open-door-drawer
make-i-player make-i-player-icon
make-key-thing) make-key-thing-icon)
(define light-black (gl-float-vector 0.0 0.0 0.0 0.25)) (define light-black (gl-float-vector 0.0 0.0 0.0 0.25))
(define green (gl-float-vector 0.0 1.0 0.0 1.0)) (define green (gl-float-vector 0.0 1.0 0.0 1.0))
@ -32,28 +30,6 @@
(define door-bm (define door-bm
(make-object bitmap% (make-object bitmap%
(build-path (collection-path "games" "checkers") "light.jpg"))) (build-path (collection-path "games" "checkers") "light.jpg")))
(define (with-gl game)
(lambda (f)
(send game with-gl-context f)))
(define (bitmap->drawer bm game)
(let*-values ([(bm mask)
(cond
[(bm . is-a? . bitmap%)
(values bm (send bm get-loaded-mask))]
[(bm . is-a? . image-snip%)
(values (send bm get-bitmap)
(send bm get-bitmap-mask))]
[else (raise-type-error
'bitmap->drawer
"bitmap% or image-snip% object"
bm)])]
[(dl) (bitmap->gl-list bm
#:with-gl (with-gl game)
#:mask mask)])
(lambda ()
(gl-call-list dl))))
(define (door-drawer game) (define (door-drawer game)
(bitmap->drawer door-bm game)) (bitmap->drawer door-bm game))
@ -130,14 +106,15 @@
(gl-end-list) (gl-end-list)
list-id)))) list-id))))
(define/kw (make-i-player game (define/kw (make-i-player-icon game
#:key #:optional
[color green] [data #f]
[data #f]) #:key
[color green] )
(let ([shadow-cylinder-dl (make-cylinder-dl game dark-gray #t)] (let ([shadow-cylinder-dl (make-cylinder-dl game dark-gray #t)]
[cylinder-dl (make-cylinder-dl game color #f)] [cylinder-dl (make-cylinder-dl game color #f)]
[sphere-dl (sphere-dl game color)]) [sphere-dl (sphere-dl game color)])
(send game make-player (send game make-player-icon
(lambda (just-shadow?) (lambda (just-shadow?)
(with-light (with-light
just-shadow? just-shadow?
@ -206,13 +183,15 @@
(gl-light-model-v 'light-model-ambient (gl-float-vector 1.0 1.0 1.0 0.0)) (gl-light-model-v 'light-model-ambient (gl-float-vector 1.0 1.0 1.0 0.0))
(gl-disable 'light0))) (gl-disable 'light0)))
(define/kw (make-key-thing game (define/kw (make-key-thing-icon game
#:key #:optional
[color yellow]) [data #f]
#:key
[color yellow])
(let ([dl (make-key-dl game color)]) (let ([dl (make-key-dl game color)])
(send game make-thing (send game make-thing-icon
(lambda/kw (#:optional [just-shadow? #f]) (lambda/kw (#:optional [just-shadow? #f])
(with-light just-shadow? (lambda () (with-light just-shadow? (lambda ()
(gl-scale 0.5 0.5 0.5) (gl-scale 0.5 0.5 0.5)
(gl-call-list dl)))) (gl-call-list dl))))
'thing)))) data))))