SB-world Teachpack
(require sb-world/sb-world) |
1 About this teachpack
The sb-world teachpack resembles the built-in world teachpack, but is used in a more functional, less imperative way. To wit, rather than calling big-bang to start an animation, and then calling on-tick, on-mouse-event, etc. to install its handlers, you’ll call run-animation with the handlers as arguments.
2 Installation
If you’re reading this, you’ve probably already installed the teachpack successfully, but if you need to install it on a different machine, ...
start DrScheme
switch languages to Module and click "Run"
in the Interactions pane, type
(require (planet "install.ss" ("sbloch" "sb-world.plt" 1 2)))
after a few seconds, you should see the message "Wrote file "sb-world.ss" to installed-teachpacks directory."
switch languages back to one of the HtDP languages, like Beginning Student
from the Language menu, choose "Add Teachpack..." and select "sb-world.ss"
click "Run"
3 Data types and functions
model any/c When you write an animation, one of your first decisions is usually "what type is the model?" If you don’t choose a data definition for model, it will default to "image", but this is rather limiting.
key-event or/c char? symbol? Key presses are represented as either characters (for ordinary keys: letters, digits, punctuation) or as symbols (for function keys, arrow keys, delete, page-up, page-down, etc.) In addition, when a key is released, you get a 'release event, also a symbol. The teachpack provides two useful functions for this data type: key-event?, which tells whether something is a key-event, and key=?, which compares two key events for equality.
| |||||||||||||||||||||||||||||||||||
width : number? | |||||||||||||||||||||||||||||||||||
height : number? | |||||||||||||||||||||||||||||||||||
initial-model : model | |||||||||||||||||||||||||||||||||||
tick-interval : number? | |||||||||||||||||||||||||||||||||||
handler1 : handler? |
The most important function in the teachpack. You give it the width and height that you want for the animation window, an initial model, how many seconds between clock ticks, and possibly some "handlers" (see below), and it will run an animation for you. For details, see Chapter 7 of my textbook.
| |||||||||||||||||||||||||||||||||||
width : number? | |||||||||||||||||||||||||||||||||||
height : number? | |||||||||||||||||||||||||||||||||||
initial-model : model | |||||||||||||||||||||||||||||||||||
tick-interval : number? | |||||||||||||||||||||||||||||||||||
handler1 : handler? |
Just like "run-animation", except that it records the sequence of events and, after it’s finished, allows you to save it as an animated GIF picture.
(place-image foreground x y background) → image? |
foreground : image? |
x : number? |
y : number? |
background : image? |
Places the foreground image at the specified location on the background image, treating (0,0) as the top-left corner of the background. Note: Unlike the version of "place-image" in the standard world teachpack, this version accepts any image as the background, regardless of pinholes.
(empty-scene width height) → image? |
width : number? |
height : number? |
An easy way to create a white box, outlined in black, of the specified width and height, generally to use as a background image.
(end-of-time result) → any/c |
result : any/c |
Stops the animation from which it was called, and returns the specified value (usually a string, but could be an image, a number, etc.) Note: This function should only be called from within a tick, mouse, or key handler. If you call it from "run-animation", you’ve basically stopped the animation before it can start.
(key-event? event) → boolean? |
event : any/c |
Tells whether something is a key-event.
(key=? event1 event2) → boolean? |
event1 : key-event? |
event2 : key-event? |
Compares two key-events for equality; won’t crash even if one happens to be a character and the other a symbol.
4 Handlers
handler When you run an animation, you can provide handler functions to tell the animation how to do various things: how to redraw the screen from the model, how to change the model at every clock tick, how to change the model when the user uses the mouse or keyboard, etc. Once you’ve written a function to be used as a handler, you specify what kind of handler it is by calling "on-redraw", "on-tick", "on-mouse", "on-key", or "stop-when", and passing the result to run-animation.
(on-redraw redraw-handler) → handler? |
redraw-handler : (-> model image) |
To specify how the animation is to be shown on the screen (and in particular if your model is anything other than an image), you need to write a function from model to image, and supply it as an argument to "on-redraw". This function will be called on the current model every time the model changes, and the resulting image will appear on the screen. Note: If you don’t provide a redraw handler, the system will assume that your model is simply an image, and will show that image itself in the animation window.
(on-tick tick-handler) → handler? |
tick-handler : (-> model model) |
If you want your animation to do something at regular time intervals, you need to write a function from model to model, and supply it as an argument to "on-tick". Every time the clock ticks, this function will be called on the current model, and its result will become the new model.
(on-mouse mouse-handler) → handler? |
mouse-handler : (-> model (x number?) (y number?) (event symbol?) model) |
If you want your animation to respond to the mouse, you need to write a function that takes in a model, two numbers, and a symbol, and returns a model, and provide this function as an argument to "on-mouse". Every time the mouse is moved or clicked, your function will be called on the current model, the coordinates of the mouse, and what was done to the mouse, and its result will be the new model.
Possible events are ’button-down, ’button-up, ’move, ’drag, ’wheel-up, ’wheel-down, ’enter, and ’leave.
(on-key key-handler) → handler? |
key-handler : (-> model (key (or/c char? symbol?)) model) |
If you want your animation to respond to the keyboard, you need to write a function that takes in a model and a key-event and returns a model, and provide this function as an argument to "on-key". Every time a key is pressed or released on the keyboard, your function will be called with the current model and the relevant key (or the symbol "'release"), and its result will be used as the new model.
Possible keys, in addition to ordinary characters, are ’release, ’up, ’down, ’left, ’right, ’next, ’prior, ’home, ’numpad-enter, ’separator, ’f1, ’f2, ...
(stop-when quit-tester) → handler? |
quit-tester : (-> model boolean?) |
If you want your animation to stop when a particular thing happens, you have two choices. One is to use "end-of-time", as discussed above. The other is to write a function from model to boolean, and provide this function as an argument to "stop-when". This function will be called on the current model every time the model changes; if it returns true, the animation will end. Note: There should be no problem with using both features at once, i.e. installing a "stop-when" handler and also having some other handler call "end-of-time".