Simple animation
October 16, 2009by Lee Spector (lspector)
Once you have defined the better-draw stuff (see this post) you can do some simple animation by first doing some drawing, then erasing, then drawing again, etc. You should call sleep/yield between each draw and the next erase, both to allow the OS to actually draw the image and to make it stay visible for a bit before you erase it and redraw it elsewhere. Something like (sleep/yield 0.001) might be a good first stab (that’s supposed to sleep for 1/1000 of a second). There are of course fancier ways to make animations that will be smoother, etc., but this is simple and can be fun.
As an example, let’s first define a procedure that draws a guy:
(define draw-guy (lambda (x y) (ellipse x y 50 50 88 156 174 1.0) (ellipse (+ x 15) (+ y 10) 10 10 20 50 150 1.0) (ellipse (+ x 30) (+ y 10) 10 10 20 50 150 1.0) (ellipse (+ x 12) (+ y 25) 30 15 220 50 50 1.0)))
To run this you first want to show the window — (show-window) — and if you’ve previously drawn in it clear it — (clear). Then call (draw-guy).
Now let’s write a procedure to erase the guy. Notice that I make this circle a little bigger, because the “smoothing” in the drawing code, which gets rid of jaggies around circles, etc., “leaks” a little bit of color into adjacent pixels:
(define erase-guy (lambda (x y) (ellipse (- x 5) (- y 5) 60 60 255 255 255 1.0)))
Now I can make a guy move in a diagonal line using a “for” loop like this:
(define move-guy (lambda () (for ((n (in-range 0 100))) (draw-guy (* n 2) (* n 3)) (sleep/yield 0.01) (unless (>= n 99) (erase-guy (* n 2) (* n 3))))))
Again, you should show and clear the window, and then call (move-guy).
Of course we can move him in fancier ways too, by doing something like this:
(define wavy-guy (lambda () (for ((x (in-range 0 500))) (let ((y (+ 200 (* 200 (sin (/ x 50.0)))))) (draw-guy x y) (sleep/yield 0.0005) (unless (>= x 499) (erase-guy x y))))))