
Creating Moving Components in Java Games with Timers
Learn how to implement moving components in Java games using Timers to generate ActionEvents and update object locations within a Graphics object. This comprehensive guide covers the steps to set up Timers, implement ActionListener, and handle action events effectively for smooth animations in your projects.
Download Presentation

Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.
E N D
Presentation Transcript
Animation Most games have moving components, how do we make things move? So far, we ve been using a for-loop to delay the program this is not a good idea, instead we want to use a built-in class called a Timer The Timer generates an ActionEvent every few milliseconds The ActionEvent calls the actionPerformed method In actionPerformed, we change some aspect of our game the location within the Graphics object and then do repaint() This requires adding to our program ActionListener and actionPerformed method Timer object paintComponent method class variables that store the location of the object(s) to be moved
Timer class A Timer object is instantiated by: Timer t = new Timer(duration, handler); duration is the time (in milliseconds) that elapses between Timer- generated events, such as 20 or 50 ms handler is the object that handles the Timer-generated events we will use this meaning that this class must include an actionPerformed method The steps are to add import java.awt.event.*; implements ActionListener to our class header declare the Timer as a class variable: private Timer t; instantiate the Timer: t = new Timer(10, this); 10 or 20 would be adequate for most applications, 50 would be slower start the timer: t.start( ); if we need to stop the timer: t.stop( ); That s about all there is to it!
import javax.swing.*; import java.awt.event.*; public class TimerSkeleton implements ActionListener { private Timer t; // other instance data go here as needed public TimerSkeleton( ) { t = new Timer(10, this); t.start( ); // other initialization operations go here as needed } // other methods go here as needed Timer Skeleton } public void actionPerformed(ActionEvent e) { // action for when the Timer generates an event }
What Should actionPerformed Do? This depends on why you are using a Timer To move an object in a Graphics panel (e.g., a ball) alter the x and y coordinates of the ball and call repaint( ) For a Game calculate where game objects (say a spacecraft or a missile) have moved and redraw them you might have multiple objects to move, move them all if you have a variable number of objects, use an array (or two arrays, x[] and y[]) For Animation if our item being drawn is represented by an array of different figures then just increment the array index and repaint( ) you might pre-load an array of Images for drawImage where each image is slightly different from the previous one In any case, in actionPerformed, also make sure the object has not been moved off the screen
Moving an Image to Create Motion Imagine that your class draws on a JPanel an ImageIcon (say of a spaceship) currently, the spaceship is located at coordinates x, y the following actionPerformed method will randomly move the spaceship on the screen public void actionPerformed(ActionEvent e) { int dx = generator.nextInt(3)-1; // generate a # from -1 to +1 int dy = generator.nextInt(3)-1; // generate a # from -1 to +1 x += dx; // move the piece in a random x direction y += dy; // move the piece in a random y direction repaint( ); // assume repaint does drawImage at x, y } x and y should be class variables so that you could do g.drawImage(image, x, y, this); in your paintComponent method
Full Example Code public TimerExample( ) { t = new Timer(10, this); t.start( ); x = 150; y = 150; repaint( ); } public void actionPerformed(ActionEvent ev) { int distanceX = generator.nextInt(2)); int distanceY = generator.nextInt(2)); x += distanceX; y += distanceY; repaint( ); } public void paintComponent(Graphics g) { super.paintComponent(g); g.setColor(Color.red); g.fillOval(x, y, 5, 5); } At each Timer Event, randomly move the object (a red circle) up/down/left/right by 0 or 1 unit Note: we could make it more realistic by generating a random int from 1-9 and move it in one of 8 directions or leave it stationary (1 = upper left, or subtract 1 from x and y, 2 = straight up, etc)
Better Motion The random motion from the previous example would make the object on the screen look like a bee, buzzing around What if we wanted a more purposeful movement? For instance in a straight line? Lets add 2 more variables, dx and dy (delta x means change in x , delta y means change in y , we use d because we don t have the Greek letter delta) For actionPerformed, just do x=x+dx; y=y+dy; If dx=1 and dy=2, then our object will move in a straight line to the right 1 pixel and down 2 pixels at each movement, or a diagonal downward line If dx=0 and dy=-1, then the object moves straight up We do not want dx=0 and dy=0, why not?
Dealing With Edges/Borders Imagine we start our object at x=0, y=0 and use dx=1, dy=1 The animation will move the object steadily down to the right but eventually (quickly) the object will move right off the screen this does not cause an error, but it removes the object from our graphics panel We want to deal with borders, how? Wrap-around: if(x>=X_SIZE-20) x=20; if(x<=20) x=X_SIZE-20; Stop: if(x>=X_SIZE-20||x<=20) dx=0; Bounce: if(x>=X_SIZE||x<=20) dx*=-1; Random bounce: if(x>=X_SIZE||x<=20) dx=gen.nextInt(5)-2; we would similarly handle y and dy we might change dx and dy whenever the object hits any edge
Handling Multiple ActionEvents private static class ExamplePanel extends JPanel implements ActionListener { private Timer t; private JButton b; public ExamplePanel( ) { t = new Timer(1000, this); t.start(); b = new JButton("Button"); b.addActionListener(this); add(b); } public void actionPerformed(ActionEvent e) { if(e.getSource( )==t) System.out.println("Timer pulsed"); else if(e.getSource( )==b) System.out.println("Button pressed"); } }
Moving Multiple Items How would a game like Asteroids work? we need to keep track of the <x, y> coordinates of multiple values, just like we did with our paint program so we create an array of x, y, dx and dy int values private int[ ] x, y, dx, dy; private int num; // number of items in the arrays actionPerformed now manipulates all items in the array and paintComponent draws them all // dx, dy velocity of x, y public void actionPerformed(ActionEvent e) { for(int i=0;i<num;i++) { x[i]+=dx[i]; y[i]+=dy[i]; } } If x[i] or y[i] reaches a boundary (0 or max X/Y) then change dx or dy to be the opposite (multiply by -1)
Determining Collisions For a shooting game, we want to see if we actually successfully shot the object, how? We will have two x,y values, we will call them mx, my (for me) and ex, ey (for enemy) We can t just see if mx==ex&&my==ey because those compare individual pixels and our objects will be larger Assume that the enemy is a circle whose bounding box starts at ex,ey and is 10x10 the center of the enemy is actually ex+5,ey+5 our missile , mx, my needs to touch some part of that circle, which means that Math.abs(mx-(ex+5))<=5&&Math.abs(my- (ey+5))<=5 that is, our object is somewhere within the radius of the enemy If our object is something different from a small missile/bullet or the enemy is different from a round shape, it becomes a bit more challenging
Bouncing Balls Today we will work with a ball class and make several of them bounce around the screen A ball will comprise its current location (x, y), its velocity (dx, dy), a size and a color The ball will be able to move itself x+=dx; y+=dy; but also check to see if it is at a border The ball will be able to change direction or rebound change dx and dy, either multiply them by -1, or change them randomly The ball will be able to draw itself on a Graphics object The ball will be able to determine if it has collided with another ball (passed as a parameter) The ball will be able to change its own size The ball will have to be able to return its own x value, y value and size (to be used later)
Bouncing Balls Program We will start with an array of balls We can either randomly generate their initial locations or we can use the MouseListener so that the user can place them on the Graphics Panel by clicking The timer starts and in actionPerformed, we use a for loop to iterate through each ball and do b[i].move(); (assuming our balls are stored in an array b) If we want to handle collisions In actionPerformed, each time we move a ball, we use another (nested) for loop to iterate through the other balls and text b[i].collide(b[j]) this is true if b[i] and b[j] overlap at all If true, we want to change one or both balls directions by doing b[i].bounce(); b[j].bounce();
Ball Game The game for today is similar to the BouncingBalls program The user, using the mouse, places several balls in the graphics area As a ball collides with another, one ball disappears and the other grows in size if(b[i].collide(b[j])) { b[i].grow(b[j].size/2); b[j]=null;) notice that with each collision, there is 1 fewer balls but the other ball remaining has grown, so what we get as time goes on are fewer and fewer but larger and larger balls The game goes until there is only 1 ball left on the screen We can output the amount of time that has elapsed, the idea is to see how long you can go before you are down to 1 ball