A runnable Pong.jar. Here is one that I implemented PongL.jar.
In this lab we are going to go back to the start of the video game era and implement a game called Pong. In Pong there are paddles and balls and your job is not to let the ball get past your paddle. For this lab we will concentrate on a simple single paddle, single ball game. If you write nice general code you should easily be able to scale it up to more advanced versions of the game (like Breakout--- which may well be our next lab). The file Pong.jar contains a running program (it is minimal and should not be considered the standard to shoot for) that should give you a good idea of what we are shooting for in this lab.
Some useful links:
Your program should be fairly similar in structure to the Magnet example and will consist of three classes. We will discuss them in turn. The first class is the Pong class itself. It is basically the game controller.
The code for the Pong class is relatively simple. The constructor just makes a new window (like you did in the last lab), adds the appropriate listeners and makes a ball, a paddle and starts the Timer.
public void paint(Graphics g)method. This is already defined for the JFrame class, but for this program you will want to over-ride it and provide your own version of the method. In Java the paint method is called every time Java thinks that the screen needs refreshing (for example when you minimize the window). For this program your paint method will be very short, it will simply blank the window, then draw a rectangle to outline the game, then draw the paddle and finally the ball. It should get the information for the paddle and the ball from the appropriate instances. E.g.
g.fillOval(ball.getX(), ball.getY(), ball.getSize(), ball.getSize());would draw the ball assuming you have written the ball class correctly. You'll have similar code for the paddle.
One counter-intuitive thing about using paint in Java is how to call it. You don't force the program to paint by directly calling paint (in fact it is a bad idea). You do it by calling the method repaint(). Repaint is actually a Java directive which tells the Java Virtual machine to please call paint as soon as it is convenient. You do not write your own repaint method!
Drawing in this program is fundamentally different than in earlier programs. Since the paint method is doing the drawing, it needs to get its information from the other objects (e.g. the Ball and the Paddle). So it will get that information by calling their "setters."
private Timer timer;You actually need to be slightly careful about the Timer declaration as there are three different Timer classes in Java. To be on the safe side you might declare it this way:
private javax.swing.Timer timer;
Setting up a timer involves creating a Timer object, registering one or more action listeners on it, and starting the timer using the start method. For example, the following code creates and starts a timer that fires an action event once per MOVE milliseconds (as specified by the first argument to the Timer constructor). The second argument to the Timer constructor specifies a listener to receive the timer's action events.
//timer set to go off every MOVE milliseconds; //the timer events are sent to actionListenerObject---this object must be //an instance of a class that implements ActionListenerInterface timer = new Timer(MOVE, actionListenerObject); timer.setInitialDelay(1000); // Waits a 1000 milliseconds before starting timer.setCoalesce(true); timer.start();The timer in the example will go off every 25 milliseconds and create an event that your program listens for. You'll need an
public void actionPerformed(ActionEvent newEvent)method. Remember that your program is implementing the ActionListener interface, so this is the method you need to fulfill that contract. The action that you are listening for in this case is the Timer going off. The action that you want to occur when the Timer goes off is that the ball should move. So your method will tell the ball object to move.
One thing you will need to figure out here is how to trigger the timer to repaint (in addition to moving the ball).
You might find it useful in implementing the Paddle class to use the Java Rectangle class, or the Rectangle2D.Double class. These classes would be useful for implementing contains, as well as for tracking where the paddle is (using the setLocation(x, y)) method.
The contains method (or alternatively an intersect method) is probably the key part of the program and almost certainly the most difficult. The idea is that other objects should never pierce your paddle, instead they should bounce off it. Among other things this means you need to be able to tell if two objects intersect each other. If you really want to do a nice job with it, it is also useful to figure out where they would hit. There are many strategies for doing this. One thing to think about is that hitting the side of the paddle might be quite different from hitting the top of the paddle. What this suggests is that instead of thinking of your paddle as a single rectangle, you might think of several smaller rectangles (perhaps including Rectangles within the class instead of simply extending the Rectangle class).
Ideally the speed of the ball should be initially set somewhat randomly (e.g. give each dimension a value between 2 and 5). For starters I would just fix them at some constant (I used 3 in each dimension).
One thing to be careful about---when the Ball runs into a paddle (or a wall) it should not literally go into the paddle (its movement should end on the paddle boundary). I have seen (and accidentally programmed myself) Balls get stuck inside paddles. In fact it is a very common error. You must have logic to prevent this, every program I've ever tested that doesn't has this bug.
The ball speed changes that I outline above are merely guidelines. It is reasonable to make the behaviors more interesting. For example the actual part of the paddle you hit might affect the directional change. Or a moving paddle might add velocity, you might change the velocity the longer the program runs, etc. It isn't necessary to do any of this, but I always encourage you to have fun with your programs.
//position and dimensions of the court private static final int COURT_LEFT = 100; private static final int COURT_TOP = 50; private static final int COURT_HEIGHT = 300; private static final int COURT_WIDTH = 250; // location and dimensions of the paddle private static final int PADDLE_WIDTH = 50; private static final int PADDLE_HEIGHT = 20; private static final int PADDLE_TOP = COURT_TOP + COURT_HEIGHT - PADDLE_HEIGHT -1; private static final int BALLSIZE = 30; private static final int MOVE = 25;