racket/collects/teachpack/htdp/scribblings/world.scrbl
Matthias Felleisen 729fe8a286 world and key=?
svn: r11293
2008-08-16 15:24:58 +00:00

195 lines
8.6 KiB
Racket

#lang scribble/doc
@(require scribble/manual "shared.ss"
(for-label scheme
teachpack/htdp/image
teachpack/htdp/world
lang/private/imageeq))
@teachpack["world"]{Simulations and Animations}
@emph{Note}: For a quick and educational introduction to the teachpack, see
@link["http://www.ccs.neu.edu/home/matthias/HtDP/Prologue/book.html"]{How
to Design Programs, Second Edition: Prologue}. The purpose of this
documentation is to give experienced Schemers a concise overview for using
the library and for incorporating it elsewhere.
The teachpack provides two sets of tools. The first allows students to
create and display a series of animated scenes, i.e., a simulation. The
second one generalizes the first by adding interactive GUI features.
@declare-exporting[teachpack/htdp/world #:use-sources (teachpack/htdp/image)]
@section[#:tag "basics"]{Basics}
The teachpack assumes working knowledge of the basic image manipulation
primitives and introduces a special kind of image: a scene.
@deftech{Scene}@;
@schemeblock[
;; Image -> Boolean
(define (focus-at-0-0 i)
(and (= (pinhole-x i) 0) (= (pinhole-y i) 0)))
(and/c image? focus-at-0-0)]
The teachpack can display only @tech{Scene}s, which are images whose
pinholes are at position @scheme[(0,0)].
@defproc[(empty-scene [width natural-number/c]
[height natural-number/c])
(unsyntax @tech{Scene})]
{Creates a @scheme[width] x @scheme[height] @tech{Scene}.}
@defproc[(place-image [img image?] [x number?] [y number?]
[s (unsyntax @tech{Scene})])
(unsyntax @tech{Scene})]
{Creates a scene by placing @scheme[img] at @scheme[(x,y)] into @scheme[s];
@scheme[(x,y)] are comp. graph. coordinates, i.e., they count right and
down from the upper-left corner.}
@section[#:tag "simulations"]{Simple Simulations}
@defproc[(run-simulation
[w natural-number/c]
[h natural-number/c]
[r number?]
[create-image (-> natural-number/c scene)]
[gifs? boolean? #f])
true]{
creates and shows a canvas of width @scheme[w] and height @scheme[h] ,
starts a clock, making it tick every @scheme[r] (usually fractional)
seconds. Every time the clock ticks, drscheme applies @scheme[create-image] to
the number of ticks passed since this function call. The results of
these applications are displayed in the canvas.
The fifth (and last) argument is optional. Providing @scheme[true] as
the fifth argument causes drscheme to collect the scenes that the
animation generates and to create an animated GIF from the results. Both
the intermediate images as well as the final animated GIF are saved in a
user-specified directory. This is useful for writing documentation and
for describing students work.
}
In addition,
@schemeblock[
(define (create-UFO-scene height)
(place-image UFO 50 height (empty-scene 100 100)))
(define UFO
(overlay (circle 10 'solid 'green)
(rectangle 40 4 'solid 'green)))
(run-simulation 100 100 (/ 1 28) create-UFO-scene)
]
@;-----------------------------------------------------------------------------
@section[#:tag "interactive"]{Interactions}
An animation starts from a given ``world'' and generates new ones in response to events on the
computer. This teachpack keeps track of the ``current world'' and recognizes three kinds of events:
clock ticks; keyboard presses and releases; and mouse movements, mouse clicks, etc. Your program may
deal with such events via the @emph{installation} of @emph{handlers}. The teachpack provides for the
installation of three event handlers: @scheme[on-tick-event], @scheme[on-key-event], and
@scheme[on-mouse-event]. In addition, it provides for the installation of a @scheme[draw] handler,
which is called every time your program should visualize the current world.
@deftech{World} @scheme[any/c]
For animated worlds and games, using the teachpack requires that you
provide a data definition for @tech{World}. In principle, there are no
constraints on this data definition. You can even keep it implicit, even
if this violates the Design Recipe.
@defproc*[(
[(big-bang [width natural-number/c] [height natural-number/c] [r number?] [world0 (unsyntax @tech{World})]) true]
[(big-bang [width natural-number/c] [height natural-number/c] [r number?] [world0 (unsyntax @tech{World})][animated-gif? boolean?]) true]
)]{
Creates and displays a @scheme[width] x @scheme[height] canvas,
starts the clock,
makes it tick every @scheme[r] seconds,
and makes @scheme[world0] the current world.
If it is called with five instead of four arguments and the last one
(@scheme[animated-gif?]) is @scheme[true], the teachpack allows the
generation of images from the animation, including an animated GIF image. }
@defproc[(on-tick-event [tock (-> (unsyntax @tech{World}) (unsyntax @tech{World}))]) true]{
Tell DrScheme to call @scheme[tock] on the current world every time the
clock ticks. The result of the call becomes the current world.}
@deftech{KeyEvent} @scheme[(or/c char? symbol?)]
A @tech{KeyEvent} represents key board events, e.g., keys pressed or
released, by the computer's user. A @scheme[char?] @tech{KeyEvent} is
used to signal that the user has hit an alphanumeric key. Symbols such
as @scheme['left], @scheme['right], @scheme['up], @scheme['down],
@scheme['release] denote arrow keys or special events, such as releasing
the key on the keypad.
@defproc[(key-event? [x any]) boolean?]{
is @scheme[x] a @tech{KeyEvent}}
@defproc[(key=? [x key-event?][y key-event?]) boolean?]{
compares two @tech{KeyEvent} for equality}
@defproc[(on-key-event [change (-> (unsyntax @tech{World}) key-event? (unsyntax @tech{World}))]) true]{
Tell DrScheme to call @scheme[change] on the current world and a
@tech{KeyEvent} for every keystroke the user of the computer makes. The result
of the call becomes the current world.
Here is a typical key-event handler:
@(begin
#reader scribble/comment-reader
(schemeblock
(define (change w a-key-event)
(cond
[(key=? a-key-event 'left) (world-go w -DELTA)]
[(key=? a-key-event 'right) (world-go w +DELTA)]
[(char? a-key-event) w] ;; to demonstrate order-free checking
[(key=? a-key-event 'up) (world-go w -DELTA)]
[(key=? a-key-event 'down) (world-go w +DELTA)]
[else w]))
))
}
@deftech{MouseEvent} @scheme[(one-of/c 'button-down 'button-up 'drag 'move 'enter 'leave)]
A @tech{MouseEvent} represents mouse events, e.g., mouse movements or mouse clicks, by the
computer's user.
@defproc[(on-mouse-event [clack (-> (unsyntax @tech{World}) natural-number/c natural-number/c (unsyntax @tech{MouseEvent}) (unsyntax @tech{World}))]) true]{
Tell DrScheme to call @scheme[clack] on the current world, the current
@scheme[x] and @scheme[y] coordinates of the mouse, and and a
@tech{MouseEvent} for every action of the mouse by the user of the
computer. The result of the call becomes the current world.}
@defproc[(on-redraw [to-scene (-> (unsyntax @tech{World}) (unsyntax @tech{Scene}))]) true]{ Tell DrScheme to call @scheme[to-scene]
whenever the canvas must be redrawn. The canvas is usually re-drawn after a tick event, a keyboard
event, or a mouse event has occurred. The generated scene is displayed in the world's canvas.}
@defproc[(stop-when [last-world? (-> (unsyntax @tech{World}) boolean?)]) true]{
Tell DrScheme to call @scheme[last-world?] whenever the canvas is
drawn. If this call produces @scheme[true], the clock is stopped; no more
tick events, @tech{KeyEvent}s, or @tech{MouseEvent}s are forwarded to
the respective handlers. As a result, the canvas isn't updated either.}
@section{Scenes and Images}
For the creation of scenes from the world, use the functions from @secref["image"]. The following two
functions have turned out to be useful for the creation of scenes, too.
@defproc[(nw:rectangle [width natural-number/c] [height natural-number/c] [solid-or-filled Mode] [c Color]) image?]{
Creates a @scheme[width] x @scheme[height] rectangle, solid or outlined as specified by
@scheme[solid-or-filled] and colored according to @scheme[c], with a pinhole at the upper left
corner.}
@defproc[(scene+line [s (unsyntax @tech{Scene})][x0 number?][y0 number?][x1 number?][y1 number?][c Color]) (unsyntax @tech{Scene})]{
Creates a scene by placing a line of color @scheme[c] from @scheme[(x0,y0)] to
@scheme[(x1,y1)] into @scheme[scene];
@scheme[(x,y)] are comp. graph. coordinates;
in contrast to the @scheme[add-line] function, this
one cuts off those portions of the line that go beyond the boundaries of
the given @scheme[s].}