CSE 341, Assignment 2 -- Smalltalk/Pinball Project

April 6, 1998
Due in sections, Thursday, April 23, 1998

For this project, you may work by yourself, or in groups of two or three. If you work in a group, just hand in one completed assignment with everyone's name on it. Your assignment should include the code for all the methods you wrote, and give a brief summary of your design, justifying your design decisions (a partial class hierarchy diagram may be especially useful).

On Monday (April 27) each group will give a 5 minute demo to Alan or Greg (and anyone else who wants to watch) of their pinball game in the NT lab. We will post a sign-up sheet in the lab several days before for you to select a time. (More details on this later).

Write a pinball game in Smalltalk using Smalltalk/Express. Your game should include flippers and a scoring device. It should be written in good object-oriented style. For extra credit, you can add other gadgets and features (see the end of this assignment).

Start by considering what the objects are, how they can be arranged in class hierarchies, and how they interact. Smalltalk/Express includes several classes which will prove very useful if you take the time to learn how they work. In particular, you should read Chapter 9 and Chapter 14 (especially the part on "Window Classes") of the Smalltalk/Express online documentation.

One obvious class is class Ball. You will probably want to make class Ball a subclass of AnimatedObject since it is-a AnimatedObject. Be sure to first learn about the functionality of AnimatedObject before you start adding features to your new Ball class.

For a pinball game, there are also various kinds of things that balls can bump into: walls, the flippers, a scoring thing, and a black hole into which the ball drops ending a turn. There should be a class for each of these. Some of these classes will have several instances (e.g. two flippers). You should make a superclass Bumper of all of these, that holds behavior common to all of the things that you can bump into.

To make all of these AnimatedObjects animate (i.e. change frames and move around), you should add them all into a PinballAnimationPane class that you subclass from the built-in AnimationPane.

Finally, you will want a class PinballGame. An instance of PinballGame should hold all the state of the game (such as the animation frame which is displaying the game -- the animation frame will likely hold all of the state of the game that is relevant to displaying the game, so your PinballGame class may only be a thin layer over the pinball animation frame instance).

For input, the left and right mouse buttons could control the left and right flippers. In addition, you can add some menu items or put some buttons at the bottom of the game for any additional commands you need, such as "launch a ball" and "quit". Part of the assignment is for you to design the exact interface.

Note that using the AnimationPane as a superclass means that your program will be event-driven. You do not need to write the main loop to perform the animation -- it has already been written for you. For example, you can make the flippers flip by just overriding the nextFrame method of an AnimatedObject (after creating appropriate frame bitmaps, of course), and you can respond to button presses simply by overriding the button1Down: and button1Up: methods inherited by PinballAnimationPane from AnimationPane. The flipper should remain up as long as the button is pressed, and return to its resting position when the mouse button is released.

To update the ball's velocity (as set by methods speed: and direction:), use the normal laws of physics: the velocity should increase by the acceleration due to gravity. Your physics should be plausible, but need not be entirely accurate.

If the ball has hit a bumper, different things will occur depending on what kind of bumper it is. Walls should make the ball reflect off (remember, angle of reflectance equals the angle of incidence). Flippers should make the ball reflect off also -- plus if the flipper is moving it should increase the ball's velocity in the appropriate direction. Hitting a scoring bumper should increment the score. Hitting the gutter at the bottom should make the ball disappear. A good object-oriented design for this is to send a message to the bumper, with the ball as an argument, and let each bumper affect the ball and do whatever processing is needed (e.g., incrementing the score). For example,

   aBumper bumpBall: ball
If the ball is not colliding with a bumper object, its bumpBall: method will not change the path of the ball for that message invocation. You might have an array of bumper objects, each of which would get an opportunity to bump the ball at each step.

Finally, your game doesn't have to be especially fast -- it's ok to have an underwater version of a pinball game. Using a smaller pane may help speed things up, and ultimately you may want to optimize the step method of AnimationPane to not redraw objects that have not changed (e.g., flippers, though you should keep them continuously animating, need not be redrawn except when they are changing their appearance or have been hidden by another window and later exposed). Also, do not worry about how your game looks in the beginning. After you get the game working you can improve its esthetics if you have time.

Extra Credit

Lots of possibilities:
Greg J. Badros / U Washington Computer Science and Engineering / gjb@cs.washington.edu