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 0000000000..434f65df98 Binary files /dev/null and b/collects/teachpack/gamepad.png differ