Analysis of BouncyBall

Chapter: Ball World
...Section: Analysis of BouncyBall

There are many important features to observe in the file BouncyBall.java

  1. First of all, notice that BouncyBall extends ActiveObject. You can read about ActiveObject and its importance for animation in Chapter 9 of the text book. But you don't need to read the whole chapter yet (don't let me stop you if you're interested, though). For now, take a look at the Documentation for the objectdraw library and look up ActiveObject. The important method for us is pause(int millis). This is used to control the speed with which the ball appears to be moving across the screen. Without it, Java would execute the move() and moveTo() instructions just as soon as it could. It would no longer look like a convincing simulation of a ball's movements.

  2. Next notice the static final int declarations:
        protected static final int BALLSIZE = 30;
        // Constants to determine ball speeds    
        protected static final int MINSPEED = 2;
        protected static final int MAXSPEED = 7;
        protected static final int PAUSETIME = 30;
    

    Those constants are used throughout the program. If you change any of them in this one location near the top, you can be sure that you will consistently change the entire program. For example, change the BALLSIZE to 10 and you will have a program that still works just fine, but has smaller balls. Try it. It's important that we used the constant BALLSIZE because otherwise, ensuring consistent changes would be close to impossible. Look at places where BALLSIZE is used such as

            right = left + boundary.getWidth() - BALLSIZE;
    
    This makes sure the ball appears to bounce correctly off the right wall. If we had simply put the number "30" to specify the size of the ball, and used "30" throughout the program when we needed to refer to it, we would have a nightmare task changing the ball's size if we wanted to be sure that everything remained consistent.

  3. Next notice how almost all the instance variables are declared protected.
        protected static final int BALLSIZE = 30;
        // Constants to determine ball speeds    
        protected static final int MINSPEED = 2;
        protected static final int MAXSPEED = 7;
        protected static final int PAUSETIME = 30;
        
        protected FilledOval ball;
        
        // components of speed vector
        protected double xSpeed, ySpeed;
        
        // boundaries of playing area
        protected double left, right, top, bottom;
        private RandomIntGenerator speedGen = 
                new RandomIntGenerator(MINSPEED, MAXSPEED); 
        private RandomIntGenerator colorGen = 
                new RandomIntGenerator(0,255); 
        protected DrawingCanvas mycanvas;
    

    protected data is visible in and usable by classes that extend this class. It is our intention to make balls that are "smarter" than this kind of ball. They will, for example, know how to behave if they encounter a paddle. We will program the smarter balls, not from scratch, but by extending this class. We have something that works. We need some extra functionality. That's what inheritance is all about.

    Q. 2
    But what about the variable colorGen. It is declared private?


  4. Look at the constructor for BouncyBall. It needs to know about the frame in which it is bouncing around. It needs a filled oval to portray the ball. It sets a color. It sets an initial speed in the horizontal direction (xSpeed) and the vertical direction (ySpeed). Fianlly note the last line of the constructor: start();. As explained on page 228, start(); should be the last line of every constructor for an ActiveObject. It makes the run() method start. Look at the code to be sure you understand each line. Ask your lab instructor if you are in any doubt.

  5. Now look at the run() method. Most of the code is enclosed in an infinite loop:
      while (true) {
       ...
       ...
      }
    
    This is not unusual in animations. You create objects that will run until the user turns off the system! Our BouncyBalls will keep bouncing as long as you let them. An infinite loop is the right construct.

    Outside of the infinite loop are a declaration

            double lastTime, elapsedTime;
    
    These are used to keep track of how much time has elapsed since we last drew this object. We use that to figure out how far to move the object. We need an initialization for lastTime, and that's provided by:
           lastTime = System.currentTimeMillis();
    
    Look at the Java API documentation to see how this call works to give us the current time in milliseconds.

    Q. 3
    Why milliseconds?


  6. In the infinite loop we:
    1. pause(PAUSETIME) so we don't move on to the next scene too quickly,
    2. calculate how many milliseconds have passed since se last drew the ball. This is not necessarily PAUSETIME seconds, because our computer is doing more than just executing our pause() command!
    3. Moving the ball xSpeed*elapsedTime horizontally and ySpeed*elapsedTime vertically. Notice how larger values of the speed variables will cause the ball to move a greater distance in the same time interval. That's what speed means!
    4. Check to see if the ball has moved out of the boundary. If so, we move it back pronto, and reverse the direction of motion by changing xSpeed or ySpeed appropriately to the negative of its previous value.
    5. Go back to the top of the loop and repeat forever!
So now you know all about computer animation!


Exercise 1

Run the BallFrame as an applet. Change some of the constants in interesting ways and report your observations in your lab notebook. For example, what happens when you increase PAUSETIME? What happens when you decrease it? What happens when you increase MINSPEED? etc. Design some experiments and report your results.

This next exercise may require tools besides a computer. Maybe a watch with a seconds hand or ...?


Exercise 2

If you change BALLSIZE but leave all the other constants unchanged, does the speed of the animation change? Design and run an experiment, and report your findings. To do this question well, you will need to modify the code to remove some of the sources of randomness. Otherwise you will be comparing apples with oranges, as it were.


rhyspj@gwu.edu