Title: Lecture 11: More Repetition
1Lecture 11 More Repetition Talking to
ActiveObjects
2Finally -- Pong!
- Recall the Pong game from last time
- The balls move around, but whats the big deal?
- Their motion is tracked in 2 directions
- X direction
- Y direction
- We take time into account when moving the balls
- Constant motion with respect to time
3From last time run() in MovingBall
public void run() // used to record times
and compute time between moves double
elapsedTime double lastTime
System.currentTimeMillis() while
(ball.getY() lt offScreen) elapsedTime
System.currentTimeMillis() - lastTime
ball.move(xspeedelapsedTime,yspeedelapsedTime)
if ( ball.getX() lt bleft ball.getX()
gt bright ) xspeed -xspeed
if ( ball.getY() lt btop )
yspeed initYspeed else if (
ball.overlaps(paddle) ) yspeed
-initYspeed lastTime
System.currentTimeMillis()
pause(PAUSETIME) ball.removeFromCanvas()
- Well go through this loop one more time
- Note use of System.currentTimeMillis() to get the
time - pause() takes at least as many milliseconds as
you give it - So we have to ask the system how many ms really
elapsed - We move the ball as far as it would have moved in
that much time
4One more thing
- Remember the constructor for MovingBall?
- Notice that we passed the paddle to the Ball
- Why does the Ball know about the paddle and not
vice versa?
public MovingBall(DrawingCanvas aCanvas,
Filled Rect thePaddle, FramedRect boundary)
paddle thePaddle //etc
start()
5One more thing
- Why does the MovingBall know about the paddle and
not vice versa? - The MovingBall is the active object
- Its constantly running a while loop, and can
check whether it overlaps the paddle all the time - Paddle is just a FramedRect
- Even if we tried to check for overlap in
onMouseMove(), what if the user doesnt move the
mouse? - Passive object might not check frequently enough
for a game like this!
public MovingBall(DrawingCanvas aCanvas,
Filled Rect thePaddle, FramedRect boundary)
paddle thePaddle //etc
start()
6More on loops Nested while loops
- Take a look at the example program to draw
American Flags - Only draws with 48 stars
- Todays flag is harder, so we stuck with this one
- Uses two loops to draw the stars
- Look at the drawStars method in the Flag class
- 2 nested loops
7More on loops Nested while loops
- Look at the drawStars method in the Flag class
- 2 nested loops
- Outer loop iterates over rows
- Inner loop iterates over columns
while (row lt NUM_ROWS_STARS) col 0
x point.getX()OFFSET while (col lt
NUM_COLS_STARS) new FilledOval(
x, y, STAR_DIAM, STAR_DIAM,canvas
).setColor(Color.white) col
x x STAR_JUMP y y
STAR_JUMP row
8Some other new things
- operator
- We can use to increment a numbers value by
one - This is the same as just saying
- Its shorter, so programmers like it.
- You can use whichever you want, but this is more
common.
col
col col 1
9Some other new things
- Private methods
- Here are their headers
- These arent designed to be used outside of the
Flag class, so theyre private - These are only called inside of Flag
- They just let us break the work up into easy to
manage pieces - drawStripes is particularly useful b/c it lets us
draw different kinds of stripes - We can set the width and the number of stripes on
each call
private void drawStars(Location point) private
void drawStripes( double x, double y, double
width, int numStripes )
10More loops drawing a basket
// top of the basket new Line(x, y,
xBASKET_SIZE, y, canvas) // bottom of
the basket new Line(xINSET,
yBASKET_HEIGHT, xBASKET_SIZE-INSET,
yBASKET_HEIGHT, canvas) topLineX x
botLineX xINSET while ( topLineX lt
xBASKET_SIZE) new Line(topLineX, y,
botLineX, yBASKET_HEIGHT, canvas)
topLineX topLineX LINESEP botLineX
botLineX LINESEP(BASKET_SIZE-2.0INSET)/BASKET_
SIZE
- Look at Laundry Basket example program
- Draws (sort of) a laundry basket
- Draws almost-vertical lines from left to right
- Top x coord is changing faster than bottom x
11More loops drawing a scarf
- This will be a lot like drawing the American Flag
- Draws a bunch of circles, as shown, but theyre
interlocking - Well put this together piece by piece.
12First draw one row
- Well start by drawing one row of the scarf
- This is pretty easy -- just one loop!
// draws a scarf with upper left at point of
click public void onMouseClick( Location
point ) double x point.getX()
double y point.getY() // x and y
positions of the next "stitch"
int numCols 0 while (numCols
lt SCARF_WIDTH) new FramedOval(x, y,
DIAMETER, DIAMETER,
canvas).setColor(Color.green) x x
X_DISP numCols numCols 1
13First draw one row
// draws a scarf with upper left at point of
click public void onMouseClick( Location
point ) double x point.getX()
double y point.getY() // x and y
positions of the next "stitch"
int numCols 0 while (numCols
lt SCARF_WIDTH) new FramedOval(x, y,
DIAMETER, DIAMETER,
canvas).setColor(Color.green) x x
X_DISP numCols numCols 1
- Each time through
- Increase the value of x
- increase numCols
14Now draw more than one
// draws a scarf with upper left at point of
click public void onMouseClick( Location
point ) double x point.getX()
double y point.getY() // x and y
positions of the next "stitch"
int numCols 0 while (numCols
lt SCARF_WIDTH) new FramedOval(x, y,
DIAMETER, DIAMETER,
canvas).setColor(Color.green) x x
X_DISP numCols numCols 1
- Want to change this so it draws multiple rows
- Each time we start a row, we need to
- Reset value of x so that we draw starting at the
beginning of the row - Increase the value of y so that we dont draw
rows on top of each other - Reset numCols so that it keeps the correct count
- Increment numRows each time through
15Final version
- New code is labeled with //new!
- Recall the 4 things we needed to do
- Reset value of x so that we draw starting at the
beginning of the row - Increase the value of y so that we dont draw
rows on top of each other - Reset numCols so that it keeps the correct count
- Increment numRows each time through
// draws a scarf with upper left at point of
click public void onMouseClick( Location
point ) // x and y positions of the
next "stitch" double x point.getX()
double y point.getY()
int numRows 0 // new!
int numCols 0 while (numRows
lt SCARF_T) // new! while
(numCols lt SCARF_WIDTH) new
FramedOval( x, y, DIAMETER,
DIAMETER, canvas
).setColor(Color.green) x x
X_DISP numCols numCols 1
x point.getX()
// new! y y Y_DISP
// new! numCols 0
// new! numRows numRows 1 //
new!
16Now try this
- Modify the code so that
- First row only has one circle
- Second row has two circles
- Third row has three circles
- Etc
- Well do this in class
// draws a scarf with upper left at point of
click public void onMouseClick( Location
point ) // x and y positions of the
next "stitch" double x point.getX()
double y point.getY()
int numRows 0 // new!
int numCols 0 while (numRows
lt SCARF_T) // new! while
(numCols lt SCARF_WIDTH) new
FramedOval( x, y, DIAMETER,
DIAMETER, canvas
).setColor(Color.green) x x
X_DISP numCols numCols 1
x point.getX()
// new! y y Y_DISP
// new! numCols 0
// new! numRows numRows 1 //
new!
17New topic Talking to Active Objects
- Active Objects can have methods just like other
objects - Recall last time when I was saying you could make
a wind class that moved clouds around in our
snow program - Well revisit our basketball program, but this
time the balls will dribble - Well have a Dribbler class that moves them up
and down
18Dribbling
- How would you describe dribbling?
- We could use a loop like in Pong
- Move the ball by some amount
- Use a positive value sometimes
- Use a negative value other times
- Switch the value to switch directions
- Seems a little complicated how about something
more natural?
19Dribbling
- If we were to say this in English, we might say
something like - Hey, thats more natural (hopefully)
- Theres an outer loop (for while carrying)
- And two nested loops for the slowly move parts
while were carrying the ball Slowly move
the ball up a few times Slowly move the
ball down a few times
20Dribbling
- Heres the actual code to dribble the ball
- This is in the run() method of our ActiveObject
Dribbler - Notice that theres a boolean variable called
moving that controls the loop - We could make the ball stop if we could change
the value of that boolean
while ( moving ) int moveCount
// make ball bounce down moveCount
0 while ( moveCount lt MOVES moving)
ball.move(0, MOVESIZE)
pause( DELAY ) moveCount
bounce.play()
// make ball bounce up moveCount 0
while ( moveCount lt MOVES moving)
ball.move(0,-MOVESIZE)
pause( DELAY ) moveCount
21Stopping the dribbling
- We can add another method to the Dribbler class
- This will change the value of moving to false
- If its called while the run() method is going
on, then the run method will stop executing when
it checks its condition - The dribblers run method will then finish, and
the dribbler thread will die
public void stopDribbling() moving false
22Calling our new method
- We can call stopDribbling() from the Basketball
class (the game, not the ball) - When the user clicks the mouse, well do this
public void onMousePress(Location point)
lastMouse point if ( ballInPlay null
) if ( leftBall.contains( point ) )
ballInPlay leftBall else
if ( rightBall.contains( point ) )
ballInPlay rightBall else
player.stopDribbling()
player null ballInPlay.moveTo(
point.getX() - BALLSIZE/2,
point.getY() - BALLSIZE/2)