From 32b7a1b418f827daf30fc7838695d7ab2f3e3846 Mon Sep 17 00:00:00 2001 From: Matthias Felleisen Date: Sat, 31 Dec 2011 11:24:43 -0500 Subject: [PATCH] created pad=, exported it, documented game pad minimally --- collects/2htdp/private/pad.rkt | 5 ++ collects/2htdp/universe.rkt | 10 +++ .../2htdp/scribblings/universe.scrbl | 68 ++++++++++++++++-- collects/teachpack/gamepad.png | Bin 0 -> 15175 bytes 4 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 collects/teachpack/gamepad.png diff --git a/collects/2htdp/private/pad.rkt b/collects/2htdp/private/pad.rkt index f34295ffcf..c3f344995e 100644 --- a/collects/2htdp/private/pad.rkt +++ b/collects/2htdp/private/pad.rkt @@ -10,6 +10,9 @@ ;; KeyEvent -> Boolean ;; is the given key-event also a pad-event? pad-event? + ;; PadEvent PadEvent -> Boolean + ;; are the two pad-events equal? + pad=? ) ;; --------------------------------------------------------------------------------------------------- @@ -30,3 +33,5 @@ (define (pad-event? ke) (pair? (member ke pad-buttons))) +(define (pad=? ke) + (pair? (member ke pad-buttons))) diff --git a/collects/2htdp/universe.rkt b/collects/2htdp/universe.rkt index 9a5b6ba186..45c206ff5c 100644 --- a/collects/2htdp/universe.rkt +++ b/collects/2htdp/universe.rkt @@ -25,6 +25,7 @@ (only-in "private/launch-many-worlds.rkt" launch-many-worlds launch-many-worlds/proc) (only-in "private/stop.rkt" make-stop-the-world) (only-in "private/check-aux.rkt" sexp?) + (only-in "private/pad.rkt" pad-event? pad=?) htdp/error (rename-in lang/prim (first-order->higher-order f2h))) @@ -40,6 +41,15 @@ launch-many-worlds/proc ) +(provide + ;; KeyEvent -> Boolean + ;; is the given key-event also a pad-event? + pad-event? + ;; PadEvent PadEvent -> Boolean + ;; are the two pad-events equal? + pad=? + ) + (provide-primitive sexp? ;; Any -> Boolean ) diff --git a/collects/teachpack/2htdp/scribblings/universe.scrbl b/collects/teachpack/2htdp/scribblings/universe.scrbl index 42df009141..a8c8e01323 100644 --- a/collects/teachpack/2htdp/scribblings/universe.scrbl +++ b/collects/teachpack/2htdp/scribblings/universe.scrbl @@ -127,8 +127,9 @@ The step from simulations to interactive programs is relatively Your program may deal with such events via the @emph{designation} of @emph{handler} functions. Specifically, the teachpack provides for the - installation of three event handlers: @racket[on-tick], @racket[on-key], - and @racket[on-mouse]. In addition, a @tech{world} program may specify a + installation of four event handlers: @racket[on-tick], @racket[on-key], + @racket[on-mouse], and @racket[on-pad]. In addition, a @tech{world} + program must specify a @racket[draw] function, which is called every time your program should visualize the current world, and a @racket[done] predicate, which is used to determine when the @tech{world} program should shut down. @@ -142,7 +143,7 @@ The following picture provides an intuitive overview of the workings of a @image["nuworld.png"] - The @racket[big-bang] form installs @racket[World_0] as the initial @tech{WorldState}. + The @racket[big-bang] form installs @racket[World_0] as the initial @tech{WorldState}.w The handlers @racket[tock], @racket[react], and @racket[click] transform one world into another one; each time an event is handled, @racket[done] is used to check whether the world is final, in which case the program is @@ -161,7 +162,7 @@ The design of a world program demands that you come up with a data @defform/subs[#:id big-bang #:literals - (on-tick to-draw on-draw on-key on-release on-mouse on-receive stop-when + (on-tick to-draw on-draw on-key on-pad on-release on-mouse on-receive stop-when check-with register record? state name) (big-bang state-expr clause ...) ([clause @@ -169,6 +170,7 @@ The design of a world program demands that you come up with a data (on-tick tick-expr rate-expr) (on-tick tick-expr rate-expr limit-expr) (on-key key-expr) + (on-pad pad-expr) (on-release release-expr) (on-mouse mouse-expr) (to-draw draw-expr) @@ -397,6 +399,64 @@ Second, some keys have multiple-character string representations. Strings } } +@item{A @tech{PadEvent} is a @tech{KeyEvent} for a game-pad simulation via +@racket[big-bang]. The presence of an @racket[on-pad] clause superimposes +the game-pad image onto the current scene, suitably scaled to its size: + +@image["gamepad.png"] + +@deftech{PadEvent} : @racket[key-event?] + +It is one of the following: +@itemize[ +@item{@racket["left"] is the left arrow;} +@item{@racket["right"] is the right arrow;} +@item{@racket["up"] is the up arrow;} +@item{@racket["down"] is the down arrow;} +@item{@racket["w"] to be interpreted as up arrow;} +@item{@racket["s"] to be interpreted as down arrow;} +@item{@racket["a"] to be interpreted as left arrow;} +@item{@racket["d"] to be interpreted as right arrow;} +@item{@racket[" "] is the space bar;} +@item{@racket["shift"] is the left shift key;} +@item{@racket["rshift"] is the right shift key;} +] + +@defproc[(pad-event? [x any]) boolean?]{ + determines whether @racket[x] is a @tech{PadEvent}} + +@defproc[(pad=? [x pad-event?][y pad-event?]) boolean?]{ + compares two @tech{PadEvent} for equality} + +@defform[(on-pad pad-expr) + #:contracts + ([pad-expr (-> (unsyntax @tech{WorldState}) pad-event? (unsyntax @tech{WorldState}))])]{ + tells DrRacket to call the @racket[pad-expr] function on the current world and the + @tech{KeyEvent} for every keystroke that is also a @tech{PadEvent}. The result + of the call becomes the current world. + + Here is a typical pad-event handler: +@racketblock[ +;; ComplexNumber PadEvent -> ComplexNumber +(define (pad-handler x k) + (case (string->symbol k) + [(up w) (- x 0+10i)] + [(down s) (+ x 0+10i)] + [(left a) (- x 10)] + [(right d) (+ x 10)] + [(| |) x0] + [(shift) (conjugate x)] + [(rshift) (stop-with (conjugate x))])) +] + } + +When a @racket[big-bang] expression specifies an @racket[on-pad] clause, +all @tech{PadEvent}s are sent to the @racket[on-pad] handler. All other +key events are discarded, unless an @racket[on-key] and/or an +@racket[on-release] clause are specified, in which case all remaining +@tech{KeyEvent}s are sent there. +} + @item{ A @tech{MouseEvent} represents mouse events, e.g., mouse movements or mouse clicks, by the computer's user. diff --git a/collects/teachpack/gamepad.png b/collects/teachpack/gamepad.png new file mode 100644 index 0000000000000000000000000000000000000000..434f65df9841739c5864d2f75a83f4252fbe443b GIT binary patch literal 15175 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 If;xWx2eGI{YXATM literal 0 HcmV?d00001