import objectdraw.*; import java.awt.*; // Name: // Description: public class BouncyBall extends ActiveObject { // Time to pause animation private static final int PAUSETIME = 10; // Depiction of the ball private FilledOval ball; // Rectangle that the ball bounces inside of private FramedRect boundary; // Horizontal and vertical speeds. private double xSpeed, ySpeed; // The size of the ball in pixels private int ballSize; // Boundaries of playing area. These are adjusted to account for the ball's width so that we // do not need to add the ball's width in each time that we check the right or bottom of the boundary. private double bLeft, bRight, bTop, bBottom; // dimensions to bounce within private double bWidth, bHeight; // Create a bouncing ball and start it moving. // Parameters: // verticalSpeed - the number of pixels to move vertically per millisecond // horizontalSpeed - the number of pixels to move horizontally per millisecond // theColor - color of the ball // theSize - the diameter of the ball // canvas - the surface to draw the ball on // theBoundary - the box to bounce inside of public BouncyBall(double verticalSpeed, double horizontalSpeed, Color theColor, int theSize, DrawingCanvas canvas, FramedRect theBoundary) { boundary = theBoundary; ballSize = theSize; // Create the ball ball = new FilledOval(boundary.getLocation() , theSize, theSize, canvas); ball.setColor (theColor); // scale the speed to convert from pixels/second to pixels/millisecond. xSpeed = horizontalSpeed/1000.0; ySpeed = verticalSpeed/1000.0; // record the boundary values bWidth = boundary.getWidth() - theSize; bHeight = boundary.getHeight() - theSize; bLeft = boundary.getX(); bTop = boundary.getY(); bRight = bLeft + bWidth; bBottom = bTop + bHeight; // Start the ball bouncing start(); } // end BouncyBall constructor // Values to record the direction. Opposite directions take negated values to make switching directions // simple private static final int UP = 1; private static final int DOWN = -UP; private static final int LEFT = 2; private static final int RIGHT = -LEFT; // Continuously bounces the ball within a boundary public void run() { // used to record times and compute time between moves double lastTime, elapsedTime; // Distance the ball should move based on its speed and actual pause time. double distToMoveRight, distToMoveDown; lastTime = getTime(); while (true) { elapsedTime = getTime() - lastTime; // Compute the length the ball should move. If the pause is very long, it could be more than an // entire lap. We remove those extra laps by modding out the length of a lap. We also // compute the distance to the edge that the ball is heading towards. Both the distance to // move and the distance to the edge are positive numbers. if (xSpeed > 0) { distToMoveRight = (xSpeed*elapsedTime) % (2 * bWidth); move (distToMoveRight, bRight - ball.getX(), RIGHT); } else { distToMoveRight = (-xSpeed*elapsedTime) % (2 * bWidth); move (distToMoveRight, ball.getX() - bLeft, LEFT); } if (ySpeed > 0) { distToMoveDown = (ySpeed*elapsedTime) % (2 * bHeight); move (distToMoveDown, bBottom - ball.getY(), DOWN); } else { distToMoveDown = (-ySpeed*elapsedTime) % (2 * bHeight); move (distToMoveDown, ball.getY() - bTop, UP); } // end if // Pause to make the new location visible lastTime = getTime(); pause(PAUSETIME); } // end while } // end run // Move the ball. If the movement would go past the wall, the ball will bounce // Parameters: // distanceToMove - the number of pixels to move. A positive value moves right or down. A negative // value moves left or up // distanceToEdge - the distance in pixels to the edge the ball is bouncing toward. If the ball is going // right or down, this should have a positive value. If it is going left or up, it // should have a negative value. // direction - the direction the ball is moving private void move (double distanceToMove, double distanceToEdge, int direction) { // If we can complete without bouncing, just move the given distance. if (distanceToMove < distanceToEdge) { moveNoBounce (distanceToMove, direction); } else // The ball has to bounce { // Move to the edge we are heading towards. moveNoBounce (distanceToEdge, direction); // Reduce the amount that is remaining to move. distanceToMove = distanceToMove - distanceToEdge; // Negate the speed so we will know which direction we are heading in for the next animation step. // Note how far the ball now needs to go to reach the opposite wall. if (direction == UP || direction == DOWN) { ySpeed = -ySpeed; distanceToEdge = bHeight; } else { xSpeed = -xSpeed; distanceToEdge = bWidth; } // end if // Bounce and move toward the opposite edge. move (distanceToMove, distanceToEdge, -direction); } // end if // System.out.println ("Exiting move."); } // end move // Move the ball. This method does not handle bouncing. It should only be called when we know that the // wall is too far to bounce off of it. // Parameers: // distance - the distance to move the ball. A positive distance results in a right or down motion. // A negative distance results in a left or up motion. // direction - the direction the ball is traveling. private void moveNoBounce (double distance, int direction) { if (direction == DOWN) { ball.move (0, distance); } else if (direction == UP) { ball.move (0, -distance); } else if (direction == RIGHT) { ball.move (distance, 0); } else { ball.move (-distance, 0); } // end if } // end moveNoBounce } // end BouncyBall class