Practical Exercise 16 – Timers

This prac demonstrates how a timer can be used to create a simple animation or game involving a ball moving around the screen.

C Standard Copy the following code into a Java applet and run it. You should see a green ball bouncing around inside a rectangle – but something is wrong! Examine the code carefully and make the following changes:  fix the program so that the ball bounces off all the walls correctly  double the size of the bouncing ball  change the colour of the ball to blue  start the ball in the bottom right corner of the square  change the speed of the ball

import java.awt.*; import java.applet.*; import java.util.Timer; import java.util.TimerTask;

public class Prac16_Timers_C extends Applet { Timer timer; int refreshRate = 25; // in milliseconds int [] rectangle = {5,5,300,200}; // left, top, right, bottom int [] position = {10,10}; // ball position x,y int [] velocity = {1, 3}; // ball velocity x,y int ballSize = 20;

public void init() { setSize(310,210); timer = new Timer(); timer.schedule(new TimerTask() { public void run() // the code that you want to run repeatedly { ballBounce(); repaint(); }

}, 0, refreshRate); // first number is initial delay, second is refresh rate }

public void paint(Graphics g) { g.setColor(Color.black); g.drawRect(rectangle[0], rectangle[1], rectangle[2]-rectangle[0], rectangle[3]-rectangle[1]);

g.setColor(Color.green); g.fillOval(position[0], position[1], ballSize, ballSize); }

public void ballBounce() { //move the ball according to its velocity position[0] += velocity[0]; position[1] += velocity[1];

Claremont College 2014, adapted from Rosny College 2009 Page 1 of 8 //if the ball hits any side of the rectangle, change its direction if(position[0]<=rectangle[0] || position[0]>=rectangle[2]) { velocity[0]= -velocity[0]; } if(position[1]<=rectangle[1] || position[1]>=rectangle[3]) { velocity[1]= -velocity[1]; } }

}

B Standard The following example should do the same as the first example but the mouseListener and mouseMotionListener methods have been added. Copy this code then follow the steps below to to add a swatter controlled by the mouse that can swat the bouncing ball.

import java.awt.*; import java.applet.*; import java.util.Timer; import java.util.TimerTask; import java.awt.event.*;

public class Prac16_Timers_B extends Applet implements MouseListener, MouseMotionListener { Timer timer; int refreshRate = 25; // in milliseconds int [] rectangle = {5,5,300,200}; // left, top, right, bottom int [] position = {10,10}; // ball position x,y int [] velocity = {1, 3}; // ball velocity x,y int ballSize = 20; int paddleSize = 15;

int [] mouse={0,0}; boolean hit=false;

public void init() { setSize(310,210); addMouseListener(this); addMouseMotionListener(this);

timer = new Timer(); timer.schedule(new TimerTask() { public void run() //the code that you want to run repeatedly { ballBounce(); repaint(); }

}, 0, refreshRate); // first number is initial delay, second is refresh rate }

public void paint(Graphics g) { //Draw the rectangle/game frame g.setColor(Color.black); g.drawRect(rectangle[0], rectangle[1], rectangle[2]-rectangle[0], rectangle[3]-rectangle[1]);

//Draw the bouncing ball g.setColor(Color.green);

Claremont College 2014, adapted from Rosny College 2009 Page 2 of 8 g.fillOval(position[0], position[1], ballSize, ballSize);

//Draw the paddle g.setColor(Color.red); g.fillRect(mouse[0], mouse[1], paddleSize, paddleSize); }

public void ballBounce() { //move the ball according to its velocity position[0] += velocity[0]; position[1] += velocity[1];

//If the ball hits any sides of the rectangle, change its direction if(position[0]<=rectangle[0] || position[0]>=rectangle[2]-ballSize) { velocity[0]= -velocity[0]; } if(position[1]<=rectangle[1] || position[1]>=rectangle[3]-ballSize) { velocity[1]= -velocity[1]; } }

public boolean checkHit() { Boolean result = false;

//Write method body here

return result; }

public void mouseDragged(MouseEvent e) {

}

public void mouseMoved(MouseEvent e) {

}

public void mouseClicked(MouseEvent e) {

}

public void mouseEntered(MouseEvent e) {

}

public void mouseExited(MouseEvent e) {

}

public void mousePressed(MouseEvent e) {

}

public void mouseReleased(MouseEvent e) {

}

}

Claremont College 2014, adapted from Rosny College 2009 Page 3 of 8 To make the swatter move, add the following code to the mouseMoved method:

mouse[0]=e.getX(); mouse[1]=e.getY(); repaint();

Add the following code to the mouseClicked method:

mouse[0]=e.getX(); mouse[1]=e.getY(); if (checkHit()) { timer.cancel(); } repaint();

Edit the checkHit method to set the variable result to true when the swatter has ‘hit’ the bouncing ball. This should now allow you to swat the ball (i.e. freeze it). Run the applet and check.

B+ Standard How close do you have to be to swat it? How could this be adjusted? The mouse has to be still when you click on it. Why? How would you fix this?

A Standard Copy and paste the following object code into a new class called Ball in the same project folder. public class Ball { int x, y, x_velocity, y_velocity, size;

public Ball(int x, int y, int x_velocity, int y_velocity, int size) { this.x=x; this.y=y; this.x_velocity = x_velocity; this.x_velocity = x_velocity; this.size=size; }

public int getX() { return x; }

public void setX(int x) { this.x = x; }

public int getY() { return y; }

public void setY(int y)

Claremont College 2014, adapted from Rosny College 2009 Page 4 of 8 { this.y = y; }

public int getX_velocity() { return x_velocity; }

public void setX_velocity(int x_velocity) { this.x_velocity = x_velocity; }

public int getY_velocity() { return y_velocity; }

public void setY_velocity(int y_velocity) { this.y_velocity = y_velocity; }

public int getSize() { return size; }

public void setSize(int size) { this.size = size; }

public void move() { //move the ball according to its velocity x += x_velocity; y += y_velocity; }

public void x_reverse() { x_velocity = -x_velocity; }

public void y_reverse() { y_velocity = -y_velocity; } }

Copy your code from Prac16_Timers_B and copy it into a new class called Prac16_Timers_A. Edit this code to use the Ball object, rather than using the position and velocity variables. Create a second timer and a second ball object – use these to enable two balls to bounce around the frame and be independently stopped with the one swatter

Claremont College 2014, adapted from Rosny College 2009 Page 5 of 8 Extension Task 1 Create a version of pong. You will need to incorporate your knowledge of the keyboard listener to get this working.

1. Create an applet and draw the pong board:  a rectangle  two ‘gutters’  a centre line 2. Make sure the left and right gutters are stored as variables. 3. Incorporate your bouncing ball code, make sure it bounces off the gutters, not the rectangle. 4. Draw two paddles – left and right.  Make sure their x- and y-values and their height are stored in variables.  You may choose to create a Paddle object OR code them into the main class – it is your choice. 5. Incorporate the KeyListener.  Control the left paddles up movement with the ‘w’ key and down movement with the ‘s’ key.  Control the right paddle with the up and down arrow keys. 6. Make sure that the paddles do not go past the top or bottom edges of the rectangle. 7. Write code to allow the ball to bounce off the paddle, but stop if it hits the gutter.  Get collisions happening for the left paddle first, before moving on to the right paddle.  See diagram.  You need to test if the ball is between the top of the paddle and the bottom of the paddle, but you cannot test against the Y co-ordinate of the ball, you must test against the middle of the ball.  Eg.

if (ball_y + (ball_size/2) >= paddle_y) // the ball hit below the top edge of // the paddle

8. Once the ball correctly stops when it hits either gutter, comment out the line that stops the ball, and add in a line that incorporates scoring and re-spawns the ball from the centre of the game.

Claremont College 2014, adapted from Rosny College 2009 Page 6 of 8 9. If the ball hits the right gutter, the left player should win a point and the ball should spawn in a way that will make it move upwards and to the left. If the ball hits the left gutter, the right player should win a point and the ball should spawn in a way that will make it move upwards and to the right. 10. Write code to display these scores on the applet (see image). 11. If you want to add in an additional level of difficulty, add code to increase the ball speed with each hit of the paddle.

Claremont College 2014, adapted from Rosny College 2009 Page 7 of 8 Extension Task 2 To avoid a possible problem with flickering, you can use something called Double Buffering. In the top of the class, paste the follow lines of code:

private Image dbImage; //double buffering private Graphics dbg; //double buffering

After the init() method, paste in the following method:

//Double Buffering Method public void update (Graphics g) { if (dbImage == null) { dbImage = createImage (this.getSize().width, this.getSize().height); dbg = dbImage.getGraphics(); } dbg.setColor (getBackground ()); dbg.fillRect (0, 0, this.getSize().width, this.getSize().height); dbg.setColor (getForeground()); paint(dbg); g.drawImage(dbImage, 0, 0, this); }

Claremont College 2014, adapted from Rosny College 2009 Page 8 of 8