CS51 - Spring 2010 - Lecture 7

  • http://www.xkcd.com/781/

  • Exercise 9.10.1

    public class SlidingBox extends ActiveObject{
       // Constant declarations omitted

       private FilledRect box;
       private DrawingCanvas canvas;

       public SlidingBox( Location boxLocation, DrawingCanvas aCanvas){
          canvas = aCanvas;
          box = new FilledRect(boxLocation, BOXSIZE, BOXSIZE, canvas);
          run();
       }

       public void run(){
          if( box.getX() < canvas.getWidth() ){
             box.move( X_SPEED, 0);
             pause(DELAY_TIME);
          }
          
          box.removeFromCanvas();
       }

  • Active objects
       - class that extends ActiveObject
       - last line in your constructor should be a call to the start() method
       - run() method specifies what the animation should do
          - will often have a while loop in your run method
          - make sure to put in a pause statement

  • this is a critical point in the course
       - you need to make sure you understand the concepts we've covered so far:
          - classes
          - variables
          - methods
          - parameters
          - conditionals
          - loops
       - if not, come talk to me soon!
       - a lot of what will look at from here on is further applications of these concepts (although I do have a few tricks to teach you still)
          - often, like active objects, it's less conceptual and more about notation, which you can look up

  • review PatheticPong code
       - what will happen if I forget to create the new FramedOval?
          - I'll get a null pointer exception
          - why?
       - when a variable is declared, it is given a default value
          - int: 0
          - double: 0.0
          - boolean: false
          - any object: null
       - null is a special name for nothing
       - when you get a null pointer exception, it's because you've tried to do something to a variable that doesn't reference anything (it references null)

  • show PongPaddleBounded demo
       - what changes need to be made to our pathetic pong?
          - our ball moves in all directions (instead of just down)
          - bounces off of the ceiling and walls
          - bounces off of the paddle
       - ball physics
          - how do we get it to move in any direction?
             - rather than just a y-speed, also an x-speed
          - what happens when we bounce, for example, off the right wall?
             - our y speed stays the same, but set out x-speed to negative
          - what about bouncing off the left side? top? bottom?
       - bouncing off the walls
          - check if the ball.getX() < courtLeft
             - positive x movement
          - check if the ball.getX() > courtRight
             - negative x movement
             - make sure to account for the ball width somewhere. In this example, we did it when defining courtRight
       - bouncing off the ceiling
          - similary, check if the ball.getY() < courtTop
             - positive y movement
       - to get the ball to bounce off of the walls, we need to communicate information to the ball class. What information is that?
          - left and right wall, and the ceiling
          - how do we communicate this information?
             - need to pass it through the constructor and save it
             - in this case, we'll pass the FramedRect for the boundary
             - from that, we calculate private instance variables that keep track of the court boundaries
       - bouncing off the paddle
          - there are a few different ways we could do this
          - one way: check two things
             - ball overlaps with part of the paddle
             - the upper half of the ball is above the paddle
          - again, we need information about the position of the paddle? How can we communicate this information?
             - in this case, we need the actual FramedRect representing the rectangle (i.e. positional information won't work)
             - the ball and the paddle are operating "concurrently", i.e. running at the same time

  • look at MovingBall class in PongPaddleBounded code
       - constructor
          - takes the canvas, paddle and the court
             - what are the "formal" parameters vs. the "actual parameters"?
             - notice that we can specify the formal parameters in any order we like
                - we could have put canvas last
                - when the constructor is called (i.e. new MovingBall) the formal parameters specify what order we must specify the actual parameters
          - pick a random x and y speed
             - what is the unit of the speeds?
                - pixels/millisecond
          - save the various boundaries of the court from the FramedRect
             - make sure to account for the width of the ball when calculating the right side

       - ball movement (run method)
          - each time through the loop, move the ball some distance along x and y
          - what is this elapsed time business?
             - System.currentTimeMillis() gives us a notion of time in ms
                - it is a "static" method associated with the System class
                - notice that we didn't instantiate any System class object
                - what other static things have we seen?
                   - constants
                   - Color.RED
                - a static variable or method is associated with a class, but not any particular object! More on this as we go.
             - we can get how long we were actually paused for
             - and adjust how far we'll actually move based on how long we were paused for
             - our xSpeed and ySpeed represent how far we need to move every ms
             - the challenge is that the pause method is imprecise. It doesn't pause for exactly the time we want, so the motion can look jerky sometimes. To get smooth motion, we want to take into account how long we actually paused for.

       - what changes need to be made to our WindowController class?
          - the only thing we need to change is to construct a new MovingBall instead of new FallingBall
             - notice the order that the actual parameters are specified in... it matches how we defined the formal parameters

  • including images in your program
       - declare an Image variable
       private Image trainPic;

       - load the image into the program (i.e. read it in)
          - often done in the begin method
          - only load the image once (this is slow!)
             - if you need it in multiple places, save the Image away and pass the image as a parameter
          - MUST be done in the class that extends WindowController

          trainPic = getImage("train.gif")
       - to actual display it, create a new VisibleImage object, which tells it where to go, etc
          new VisibleImage(trainPic, x, y, canvas);
       

  • show FallingLeaves demo
       - there may be more than one way to do this, but we'll talk about one straightforward approach
       - let's look at the overall behavior
          - when I click, we get multiple leaves to fall (in this case, 10)
          - each time I click I get 10 more leaves
          - the leaves have:
             - different pictures
             - fall at different speeds
             - fall at different locations
             - and don't all fall together at the same time
       - what's going on here?
          - one class (Fall) that extends WindowController
             - draws, sky, sun, grass
             - how do we draw the individual blades of grass?
                - while loop (similar to WhileRailroad demo)
             - onMouseClick method
                - generate a bunch of leaves
          - leaf class (FallingLeaf) that extends ActiveObject
             - should look somewhat similar to FallingBall class (from PatheticPong code)
             - to create a new FallingLeaf, what information do we need to know?
                - first, what characteristics/differences do the leaves have?
                   - different pictures/sizes
                   - fall at different speeds
                   - fall at different x locations
                - information required
                   - canvas (as always)
                   - which image to use
                   - x location
                   - falling speed
                   - screen height (so we know when they're done falling)
                - how do we provide it this information?
                   - constructor!!!
          - look at FallingLeaf class in FallingLeaves code
          - so, now we can create leaves. how are the leaves created?
             - they fall with random images (selected from 2)
             - they fall at random speeds (which someone needs to create)
             - they fall at different x's (which someone needs to create)
             - they don't all fall at the same time
          - we're going to do this with a third class, the Tree class that also extends ActiveObject
             - how could we do this with another class?
                - generate a "random" leaf
                - pause
                - generate another "random" leaf, etc.
             - what information does it need to know?
                - needs to be given some different leaf images
                   - loading images via getImage is slow!
                   - creating new VisibleImages is fast
                   - only call getImage once, and then pass that Image as a parameter to be shown when creating a new VisibleImage
                - needs the screen width
                - needs the screen height
             - what's going to be in the run() method?
                - pick a random leaf picture
                - pick a random x
                - pick a random speed
                - create the FallingLeaf
                - do this sum fixed number of times
          - look at Tree class in FallingLeaves code
          - look at Fall class in FallingLeaves code
             - very simple!