MovingBall.java

import objectdraw.*;
import java.awt.*;

public class MovingBall extends ActiveObject
{
    private static final int BALLSIZE = 30;        
    private static final int SCREENGAP = 130;
    
    // Constants to determine ball speeds
    private static final int MINSPEED = 2;
    private static final int SPEEDRANGE = 10;
    private static final int PAUSETIME = 40;
    
    private FilledOval ball;                
    
    // components of speed vector
    private double xSpeed, ySpeed, initYspeed;
    
    // boundaries of playing area
    private double bLeft, bRight, bTop, offScreen;
    
    // the paddle
    private FilledRect paddle;
    
    private RandomIntGenerator speedGen;
    private DrawingCanvas canvas;
    
    public MovingBall(DrawingCanvas canvas, FilledRect paddle, 
                      FramedRect boundary)
    {
        this.canvas = canvas;
        this.paddle = paddle;
        
        ball = new FilledOval(boundary.getLocation() ,
                              BALLSIZE, BALLSIZE, canvas);
        ball.move(1,1);
        
        // pick random pixel/pause speeds
        speedGen = new RandomIntGenerator(1, SPEEDRANGE);
        xSpeed = speedGen.nextValue()-SPEEDRANGE/2;
        if (xSpeed > 0)
            xSpeed = xSpeed + MINSPEED;
        else
            xSpeed = xSpeed - MINSPEED;
        
        ySpeed = speedGen.nextValue() + MINSPEED;
        
        // compute pixel/millisecond speeds
        xSpeed = xSpeed / PAUSETIME;
        ySpeed = ySpeed / PAUSETIME;
        initYspeed = ySpeed;
        
        // give names to boundary values
        bLeft = boundary.getX();
        bTop = boundary.getY();
        bRight = bLeft + boundary.getWidth() - BALLSIZE;
        
        offScreen = bTop + boundary.getHeight() + SCREENGAP;
        
        start();
    }
    
    public void run()
    {
        // used to record times and compute time between moves
        double lastTime, elapsedTime;
        
        lastTime = getTime();
        
        while (ball.getY() < offScreen) {
            
            elapsedTime = getTime() - lastTime;
            
            ball.move(xSpeed*elapsedTime, ySpeed*elapsedTime);
            
            if ( ball.getX() < bLeft  || ball.getX() > bRight )
                xSpeed = -xSpeed;
            if ( ball.getY() < bTop )
                ySpeed = -ySpeed;
            else if ( ball.overlaps(paddle) )
                ySpeed = -initYspeed;
            
            lastTime = getTime();
            pause(PAUSETIME);
        }
        ball.hide();
    }
}

Pong.java

import objectdraw.*;
import java.awt.*;

public class Pong extends WindowController {

    // position and dimensions of the court
    private static final int COURT_LEFT = 50,
        COURT_TOP = 50,
        COURT_HEIGHT = 300,
        COURT_WIDTH = 250;
    // dimensions of the paddle
    private static final int PADDLE_WIDTH = 50,
        PADDLE_HEIGHT = 20;
    
    private FilledRect paddle;
    private FramedRect boundary;  // the boundary of the playing area.
    
    public void begin()
    {        
        // make the playing area
        boundary = new FramedRect(COURT_LEFT, COURT_TOP,
                                  COURT_WIDTH, COURT_HEIGHT,
                                  canvas);
        
        // make the paddle
        paddle = new FilledRect(COURT_LEFT + (COURT_WIDTH-PADDLE_WIDTH)/2,
                                COURT_TOP + COURT_HEIGHT - PADDLE_HEIGHT -1,
                                PADDLE_WIDTH, PADDLE_HEIGHT,
                                canvas);
    }
    
    public void onMouseClick(Location point)
    {
        // make a new ball when the player clicks
        new MovingBall(canvas, paddle, boundary);
    }
    
    public void onMouseMove(Location point)
    {
        if ( point.getX() < COURT_LEFT ) {
            // place paddle at left edge of the court
            paddle.moveTo( COURT_LEFT,
                           COURT_TOP + COURT_HEIGHT - PADDLE_HEIGHT -1);
        }
        else if ( point.getX() > COURT_LEFT + COURT_WIDTH - PADDLE_WIDTH) {
            // place paddle at right edge of the court
            paddle.moveTo( COURT_LEFT + COURT_WIDTH - PADDLE_WIDTH,
                           COURT_TOP + COURT_HEIGHT - PADDLE_HEIGHT -1);
        }
        else {
            // keep the edge of the paddle lined up with the mouse
            paddle.moveTo( point.getX(),
                           COURT_TOP + COURT_HEIGHT - PADDLE_HEIGHT -1);
        }
    }
}