| PSICS Fall 2004 Quiz #4 |
|   PSICS Home   |   Overview and base code | Description | Extra Credit | Submitting |
Submit your solutions to this quiz by dropping in your webct drop box in the box labeled "Quiz4". Let Dave know if you have problems submitting!
| Overview: using lists to create and sdisplay animations |
This quiz involves the development of scheme code to generate lists that describe an animation. Each list item is termed an animation entity and describes a simple operation like "clear a circle", "draw a square", "wait a second". You also need to develop code to create an animation by playing back a list of these animation entities.
You are provided with definitions structures that represent 5 different simple animation instructions. These are collectively referred to as animation entities in this document. Below are detailed descriptions (and the actual code) for these structures:
(define-struct circle (center radius color))
There are two kinds of circle animation entities, these correspond to drawing a circle (the outline only) and clearing a circle. Both are represented using the structure definition shown above. The inidividual fields are described below:
center: a posn structure that
indicates the center of a circle
radius: a number indicating the radius of a circle.
color: a symbol indicating the color of a circle.
If the color is 'Clear, this inidicates that the circle
should be cleared (any other color and the circle is drawn).
To create an animation entity that indicates that a circle should be drawn at 100,100 with radius 20 and color red you would do this:
(make-circle (make-posn 100 100) 20 'Red)
To create an animation entity that indicates that a circle should be cleared at 100,100 with radius 20 you would do this:
(make-circle (make-posn 100 100) 20 'Clear)
This structure definition is probably very similar to what you came
up with on an earlier exercise, although this has the addition of the
special color 'Clear that indicates whether the circle should be
drawn or cleared.
(define-struct square (center size color))
There are two kinds of square animation entities, these correspond to drawing a filled square and clearing a square. Both are represented using the structure definition shown above. The inidividual fields are described below:
center: a posn structure that
indicates the center of a square. Note that is is the center, not
the topleft of the square!
radius: a number indicating the size a square (width/height).
color: a symbol indicating the color of a square.
The special color 'Clear indicates that the square should
be cleared, anything else and the square is drawn.
To create an animation entity that indicates that a square should be drawn at 100,100 with size 20 and color Blue you would do this:
(make-square (make-posn 100 100) 20 'Blue)
To create an animation entity that indicates that a square should be cleared at 100,100 with size 20 you would do this:
(make-square (make-posn 100 100) 20 'Clear)
(define-struct delay (time))
The delay animation entity is used for slowing down an
animation. Nothing happens for a while (how long is indicated by the
time field found in this structure) whenever a delay is found in an animation.
The only field is time, this represents the delay in
seconds.
To create an animation entity that indicates that delay of 1.5 seconds should happen, you would need something like this:
(make-delay 1.5)
draw-anim-entityYou are given the code for a function that will process one animation entity, this function determines what kind of entity it is given, and takes the appropriate action. The function defintion is shown below:
;; draw-anim-entity consumes an animation-entity (a struct that is either
;; a circle, square or delay
;;
;; For square and circle, either draws or clears the entity (based on the color)
;; For delay, just waits for a while
;
(define (draw-anim-entity s)
(cond
[(circle? s)
;; it's a circle - should we draw or clear?
(cond
[ (symbol=? (circle-color s) 'Clear)
;; clear it
(clear-circle (circle-center s) (circle-radius s))]
[ else
;; draw it
(draw-circle (circle-center s) (circle-radius s) (circle-color s)) ])]
[(square? s)
;; it's a square - should we draw or clear?
(cond
[(symbol=? (square-color s) 'Clear)
;; clear it - need to translate from center to topleft
(clear-solid-rect
(make-posn
(- (posn-x (square-center s)) (/ (square-size s) 2))
(- (posn-y (square-center s)) (/ (square-size s) 2)))
(square-size s) (square-size s))]
[ else
;; draw it
(draw-solid-rect
(make-posn
(- (posn-x (square-center s)) (/ (square-size s) 2))
(- (posn-y (square-center s)) (/ (square-size s) 2)))
(square-size s) (square-size s) (square-color s))])]
[(delay? s)
;; it's a delay - wait for a while
(sleep-for-a-while (delay-time s))]
;; it's not anything we understand - report an error
[else
(error 'draw-anim-entity "I dont' know how to draw that (is it an animimation entity?)")]))
Below is some sample code that calls this function to display a circle and an inscribed square:
(start 400 400) (draw-anim-entity (make-square (make-posn 200 200) 141 'Blue)) (draw-anim-entity (make-circle (make-posn 200 200) 100 'Red)) | ![]() |
We will build animations by constructing lists of animation entities, and then giving these lists to a function that plays then back. You need to write the playback function, a function that creates a specific animation (generates a list of structures that do something specific), and any animation you want to create.
| Assignment |
You need to create a function called play that will "play back" a list of
animation entities. For example, your function could be given this
list shown below and should produce something like the animation shown:
(cons (make-circle (make-posn 100 100) 20 'Red)
(cons (make-delay 0.5)
(cons (make-circle (make-posn 100 100) 30 'Red)
(cons (make-delay 0.5)
(cons (make-circle (make-posn 100 100) 40 'Red)
(cons (make-delay 0.5)
(cons (make-circle (make-posn 100 100) 50 'Red) empty)))))))
| ![]() |
Note that all this function needs to do is step through the items
in the list, calling draw-animation-entity once for each
item in the list. (Writing this function is easy).
Your playback function is not that useful if you have to build all
the animation lists by hand, so instead we will write functions that
build lists that we can play back. You will write a function named
grow-circle that
will create an animation based on the following information:
Here is one example of how your function could be called:
(play
(grow-circle
;; initial circle
(make-circle (make-posn 400 400) 10 'Blue)
;; amount to grow
2
;; delay per step
0.1
;; total steps
200))
As you can see, grow-circle consumes a
circle structure (the initial circle), a number (how much to add to
the radius each step), a number (delay time between steps) and
another number (total number of steps). grow-circle
produces a list of animation entities, which we can give to play.
Suppose you have two different animation lists, but you want both to happen on the screen in the same window at the same time. All you need to do is to merge the two animation lists so that the playback function will process them both. By merge, I mean the following:
Given lists A ( which holds a0, a1, a2, ...) and B (which holds b0, b1, b2, ...) you create a new merged list that contains a0, b0, a1, b2, a2, b2, ...
You need to write a function named merge that consumes
two lists (lists of anything!) and produces a new list. The new list
contains alternating items from the original lists as long as that is
possible (until it finds the end of the short list), then contains the
remainder of the longer list. Below are some examples:
(define a (cons 1 (cons 2 (cons 3 (cons 4 (cons 5 (cons 6 empty)))))))
(define b (cons 'barry (cons 'bill (cons 'bob empty))))
(merge a b) =>
(cons 1
(cons 'barry
(cons 2
(cons 'bill
(cons 3
(cons 'bob
(cons 4
(cons 5
(cons 6 empty)))))))))
Once you have this function working you can do stuff like this:
(play
(merge
;; red circle at 400,400
(grow-circle
;; initial circle
(make-circle (make-posn 400 400) 10 'Red)
;; amount to grow
2
;; delay per step
0.1
;; total steps
200)
;; blue circle at 200,200
(grow-circle
;; initial circle
(make-circle (make-posn 200 200) 2 'Blue)
;; amount to grow
1
;; set time to 0 since we are merging
0
;; total steps
200)))
So far, you are required to write:
play functiongrow-circle functionmerge functionHere is where you can do something more interesting. Write a function that produces an award-winning animation. The general idea is to make sure that your function produces a list that can be given to play, but you decide on the details... Below are some ideas:
| Extra Credit |
You can earn extra credit on this quiz by writing a
function named play-forever that will cycle through
a animation list endlessly without ever calling the function
play (or something just like it). Your
play-forever function can call
draw-anim-entity, and can call itself recursively, but nothing else...
| Submitting |
Submit your code as a single program (file) to the WebCT Drop Box labeled "Quiz 4". We should be able to easily find the required functions and to test them out (please give us some test code!).