Scripting (Animation) FAQ
Notes: You will need to set the language level to Pretty Big.
In this assignment, you will use macros to implement a scripting language for animations. For example, consider the following program:
(animation (400 400) ; width and height of window, in pixels ([x 100] [y 100]) ; initial values of animation parameters (solid-rectangle (make-posn x y) 50 50 "blue") ; draw a blue 50x50 rectangle at (x, y) (motion 5.0 ; over 5 seconds, [x -> 300] ; smoothly change x to 300 [y -> 200])) ; and y to 200 (the position of the rectangle changes accordingly)
If we run this program, we should see a blue rectangle move across
the screen for 5 seconds. In general, an
expression has the following form:
(animation (width height) ([var init] ...) drawing-command motion-command ...)
The drawing command is constructed from the following:
(line p1 p2 [color])
([solid-]rectangle top-left width height [color])
([solid-]ellipse top-left width height [color])
([solid-]polygon posn-list offset [color])
(draw-multiple drawing-command ...)
Note that the color arguments are optional and default to
"black". Also, note that using the
procedures causes the shapes to be filled in (otherwise, only outlines
are drawn). The
draw-multiple procedure combines any
number of simpler drawing commands into a single command. This is
necessary since the
animation construct takes only a
single drawing command.
Each motion command has the following form:
(motion duration [var -> value] ...)
duration can be an arbitrary expression, so long
as it reduces to a number, which is interpreted as a time in seconds.
Over this duration, each variable's value should change smoothly
(linearly) from its current value to the new value. The window should
update frequently (approximately 30 times per second) to show the
changing sizes, positions, and colors of shapes that depend on the
variables. Your program should approximate the duration as closely as
possible, without falling short (i.e., in general you should exceed
the specified time, though by as little as possible). Note that a
duration of 0 (or less) is legal, in which case the variables should
change immediately. Likewise, a
motion command with no
[var -> value] clauses should pause for the given
duration without changing any variables.
The following example is more complicated. It consists of a small red octogon inside of a large blue hexagon. They move across the window together, rotating in opposite directions:
(define (reg-poly radius sides rotation) (build-list sides (lambda (i) (make-posn (* radius (cos (+ rotation (/ (* 2 pi i) sides)))) (* radius (sin (+ rotation (/ (* 2 pi i) sides)))))))) (animation (400 400) ([a 0] [b 100]) (draw-multiple (polygon (reg-poly 100 6 a) (make-posn b 200) "blue") (polygon (reg-poly 50 8 (- a)) (make-posn b 200) "red")) (motion 5 [a -> (* 4 pi)] [b -> 300]))
Here are a few screenshots:
You should use DrScheme's Viewport Graphics Library to create a
drawing window and draw shapes into it. This library defines the
posnstructure that we use to represent two-dimensional points. It also defines a basic color palette and a mechanism for creating arbitrary colors. Thorough documentation is available in the Help Desk (search for "viewport graphics").
- While macros will be necessary for this assignment, you should try to rely on them as little as possible. In other words, if you can implement something as a procedure, don't use a macro for it.
- You may find the procedures