In Lab 1, you began experimenting with DrRacket's animation features (the moving soccer ball and the goalie). To give you a better perspective on what's happening, here's a brief introduction to the style of programming used in an animation - it's called event-driven programming.
In event-driven programming, the flow of a program is determined by events. An event can be something as simple as the passage of time (i.e. the "tick" of the computer's clock), or it can be an external action such as the pressing of a key on the keyboard. So instead of getting a function to execute by explicity calling it (as we have done with all of our other programs), a function starts executing in response to some event.
Let's look at one of the programs you were asked to write for Lab 1. Here's the code I wrote for the first part of the animation, where the objective was to get the ball to move across the animation window. (In addition to the constants defined below, there would need to be a constant named BALL that represents the image of the soccer ball):
;; dimensions of the animation window (define HEIGHT 200) (define WIDTH 200) ;; the ball's y-coordinate (define Y-COORD 150) ;; place-ball-x: number -> scene ;; consumes the x-coordinate of a window and produces a scene with the image of a ball at that x-coordinate (define (place-ball-x x-coord) (place-image BALL x-coord Y-COORD (empty-scene WIDTH HEIGHT))) ;; update-ball-x: number -> number ;; consumes an x-coordinate and produces a new x-coordinate 3 units to the right (define (update-ball-x x-coord) (+ x-coord 3))We know what we want the program to do - move the ball across the window. If we think about what needs to change as the ball moves, we only come up with one thing - the x-coordinate of the ball in the animation window (the image of the ball itself is not going to change, and the problem description states that the vertical position of the ball is not going to change). We call those things that need to change as the animation progresses the "state" of the program. So the state of our animation can be represented by a single number, the x-coordinate of the ball. We'll want the function that executes in response to an event to be a function that changes the state of the animation. That's what the function
update-ball-x
does.
To run the function, we used the following expression:
(big-bang 0 (on-tick update-ball-x) (to-draw place-ball-x))
big-bang
is a function defined in DrRacket that starts an event-driven program.
The first argument to big-bang
gives an initial value to the state of the program. In this case, the 0 represents the fact that the ball is going to start off
at x-coordinate 0 in the animation window (remember, the state of our program
is the x-coordinate). The remaining arguments to big-bang
provide a way for the animation to respond to various events. The line
(on-tick update-ball-x)
can be interpreted as meaning "run the function update-ball-x every time the
computer's clock ticks". So the ball's x-coordinate will change on every clock tick. But wait - doesn't the contract for update-ball-x require that the
function consume a number? Yes. Any function that is run in response to an
event should be defined such that it consumes and produces the type of data that represents
the state of the program (another way of saying the same thing is that
update-ball-x consumes the state of the animation and produces a new state).
Thus, the argument to update-ball-x does not need to be specified -
big-bang
knows that the function executed in response to "on-tick" needs to consume and
produce a number, because the starting state value that was provided was a number.
Finally,
big-bang
requires that you provide a function that
defines how the animation window will be drawn when an event occurs. So the
last line
(to-draw place-ball-x)will re-draw the ball in the animation window, at its new x-coordinate, giving the illusion of the ball moving across the screen.