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%
player-data
thing-data)
thing-data
bitmap->drawer)
(define-struct door-game (board))
@ -21,6 +22,25 @@
(define-struct wall (drawer))
(define-struct player (data drawer i j))
(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%
(class object%
@ -36,10 +56,10 @@
(make-room #f null null))))))
(define walls (build-vector
(add1 (* 2 x-rooms))
(add1 (* 2 (add1 x-rooms)))
(lambda (i)
(build-vector
(add1 (* 2 y-rooms))
(add1 (* 2 (add1 y-rooms)))
(lambda (j)
(make-wall #f))))))
@ -155,85 +175,109 @@
(define/public (with-gl-context f)
(send board with-gl-context f))
(define/public (set-wall ri rj dir wall? door-image)
(case dir
[(n s e w) 'ok]
[else (raise-type-error
'set-wall
"'n, 's, 'e, or 'w"
dir)])
(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)]
[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-wall-image loc wall? door-image)
(let-values ([(ri rj dir)
(cond
[(and (list? loc)
(= 3 (length loc)))
(apply values loc)]
[(and (list? loc)
(= 2 (length loc)))
(let ([i (car loc)]
[j (cadr loc)])
(if (= 1 (+ (if (integer? i) 1 0)
(if (integer? j) 1 0)))
(values (if (integer? i)
i
(add1 (floor (inexact->exact i))))
(if (integer? j)
j
(add1 (floor (inexact->exact j))))
(if (integer? i) 's 'w))
(values 0 0 'bad)))]
[else (values 0 0 'bad)])])
(case dir
[(n s e w) 'ok]
[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)
(let ([room (vector-ref (vector-ref rooms i) j)])
(define/public (set-room-data loc data)
(let ([room (vector-ref (vector-ref rooms (car loc)) (cadr loc))])
(set-room-data! room data)))
(public [new-player make-player])
(public [new-player make-player-icon])
(define (new-player drawer data)
(make-player data drawer #f #f))
(define/public (move-player player i j)
(let ([from-room (and (player-i player)
(vector-ref (vector-ref rooms (player-i player)) (player-j player)))]
[to-room (and i (vector-ref (vector-ref rooms i) j))])
(when from-room
(set-room-players! from-room (remq player (room-players from-room))))
(when to-room
(set-room-players! to-room (cons player (room-players to-room))))
(set-player-i! player i)
(set-player-j! player j)
(when from-room
(send board remove-piece player))
(when to-room
(send board add-piece (+ i 0.5) (+ j 0.5) 0.0 (player-drawer player) player))
(send board refresh)))
(define/public (move-player-icon player loc)
(let ([i (and loc (car loc))]
[j (and loc (cadr loc))])
(let ([from-room (and (player-i player)
(vector-ref (vector-ref rooms (player-i player)) (player-j player)))]
[to-room (and loc (vector-ref (vector-ref rooms i) j))])
(when from-room
(set-room-players! from-room (remq player (room-players from-room))))
(when to-room
(set-room-players! to-room (cons player (room-players to-room))))
(set-player-i! player i)
(set-player-j! player j)
(when from-room
(send board remove-piece player))
(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)
(make-thing data drawer #f #f #f))
(define/private (move-thing/hu thing i j hu?)
(let ([from-hu? (thing-heads-up? thing)]
[from-room (and (thing-i thing)
(vector-ref (vector-ref rooms (thing-i thing)) (thing-j thing)))]
[to-room (and i (vector-ref (vector-ref rooms i) j))])
(when from-room
(set-room-things! from-room (remq thing (room-things from-room))))
(when to-room
(set-room-things! to-room (cons thing (room-things to-room))))
(set-thing-i! thing i)
(set-thing-j! thing j)
(set-thing-heads-up?! thing hu?)
(when from-room
(send board remove-piece thing))
(when from-hu?
(send board remove-heads-up thing))
(when to-room
(send board add-piece (+ i 0.5) (+ j 0.5) 0.0 (thing-drawer thing) thing)
(send board enable-piece thing #f))
(when hu?
(send board add-heads-up 1.0 1.0 (thing-drawer thing) thing))
(send board refresh)))
(define/public (move-thing thing i j)
(move-thing/hu thing i j #f))
(define/public (move-thing-heads-up thing)
(move-thing/hu thing #f #f #t))
(define/public (move-thing-icon thing loc)
(let ([i (and (pair? loc) (car loc))]
[j (and (pair? loc) (cadr loc))]
[hu? (eq? loc 'heads-up)])
(let ([from-hu? (thing-heads-up? thing)]
[from-room (and (thing-i thing)
(vector-ref (vector-ref rooms (thing-i thing)) (thing-j thing)))]
[to-room (and i (vector-ref (vector-ref rooms i) j))])
(when from-room
(set-room-things! from-room (remq thing (room-things from-room))))
(when to-room
(set-room-things! to-room (cons thing (room-things to-room))))
(set-thing-i! thing i)
(set-thing-j! thing j)
(set-thing-heads-up?! thing hu?)
(when from-room
(send board remove-piece thing))
(when from-hu?
(send board remove-heads-up thing))
(when to-room
(send board add-piece (+ i 0.5) (+ j 0.5) 0.0 (thing-drawer thing) thing)
(send board enable-piece thing #f))
(when hu?
(send board add-heads-up 1.0 1.0 (thing-drawer thing) thing))
(send board refresh))))
(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
(require (lib "gl-vectors.ss" "sgl")
(prefix gl- (lib "sgl.ss" "sgl"))
(lib "bitmap.ss" "sgl")
(lib "math.ss")
(lib "mred.ss" "mred")
(lib "list.ss")
(lib "etc.ss")
(lib "class.ss")
(lib "kw.ss"))
(lib "kw.ss")
"doors.ss")
(provide bitmap->drawer
door-bm
(provide door-bm
magic-door-bm
locked-door-bm
@ -20,8 +18,8 @@
magic-door-drawer
open-door-drawer
make-i-player
make-key-thing)
make-i-player-icon
make-key-thing-icon)
(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))
@ -32,28 +30,6 @@
(define door-bm
(make-object bitmap%
(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)
(bitmap->drawer door-bm game))
@ -130,14 +106,15 @@
(gl-end-list)
list-id))))
(define/kw (make-i-player game
#:key
[color green]
[data #f])
(define/kw (make-i-player-icon game
#:optional
[data #f]
#:key
[color green] )
(let ([shadow-cylinder-dl (make-cylinder-dl game dark-gray #t)]
[cylinder-dl (make-cylinder-dl game color #f)]
[sphere-dl (sphere-dl game color)])
(send game make-player
(send game make-player-icon
(lambda (just-shadow?)
(with-light
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-disable 'light0)))
(define/kw (make-key-thing game
#:key
[color yellow])
(define/kw (make-key-thing-icon game
#:optional
[data #f]
#:key
[color yellow])
(let ([dl (make-key-dl game color)])
(send game make-thing
(send game make-thing-icon
(lambda/kw (#:optional [just-shadow? #f])
(with-light just-shadow? (lambda ()
(gl-scale 0.5 0.5 0.5)
(gl-call-list dl))))
'thing))))
data))))