Daving
asked on
Need help on Java animation
Hi there, experts.
I was wondering if anyone here can help me out on my "Trucks" program. I set up three files. One java file deals with positioning the truck on the panel, the second have to do with constructing the truck, and the third have to do with actually viewing the program of my truck. Now, i want to move 3 of the 5 trucks, but I'm not to sure how to do this properly. Noticed that I named my files "Car" because I was drawing cars @ first, and then I changed them to trucks, and I'm too lazy to renamed them (lol). The one file that I really need help with is the "CarComponent" file, where I need to modify that file so that the trucks can actually move. I tried, but failed. Before I inserted "public void animateCar()" and "public void playAnimation()", I was able to display 5 trucks. I'm not too familiar with java animation, but if anyone here can help me, that would be great. Thanks.
========================== ========== ========
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.math.BigInteger;
import java.math.BigDecimal;
public class CarComponent extends JComponent
{
public void sleep()
{
try
{
Thread thread;
Thread.sleep(60);
}
catch (Exception e){}
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Car car1 = new Car(0, 0);
int x = getWidth() - Car.WIDTH;
int y = getHeight() - Car.HEIGHT;
Car car2 = new Car(x, y);
Car car3 = new Car(x - 185, y - 150);
Car car4 = new Car(x - 50, y - 150);
Car car5 = new Car(x - 380, y - 150);
car1.draw(g2);
car2.draw(g2);
car3.draw(g2);
car4.draw(g2);
car5.draw(g2);
}
public void animateCar(Graphics gr, Car car, int deltaX, int deltaY)
{
car.erase(gr);
car.setX(Car.getX() + deltaX);
car.getY(Car.getY() + deltaY);
car.draw(gr);
}
public void playAnimation()
{
Graphics gr = getGraphics();
for (int i = 0; i < 200; i = i + 3)
{
animateCar(gr, car3, i, 0);
animateCar(gr, car4, i, Math.round(-i * 1.5));
animateCar(gr, car5, 0, i);
sleep();
}
}
}
========================== ========== ===
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
public class Car
{
public Car(int x, int y)
{
xLeft = x;
yTop = y;
}
public void draw(Graphics2D g2)
{
Rectangle body = new Rectangle(xLeft, yTop, 120, 10);
Rectangle window = new Rectangle(xLeft + 30, yTop - 50, 15, 15);
Ellipse2D.Double frontTire = new Ellipse2D.Double(xLeft + 10, yTop + 10, 20, 20);
Ellipse2D.Double rearTire = new Ellipse2D.Double(xLeft + 85, yTop + 10, 20, 20);
Point2D.Double r1 = new Point2D.Double(xLeft, yTop - 35);
Point2D.Double r2 = new Point2D.Double(xLeft, yTop);
Point2D.Double r3 = new Point2D.Double(xLeft + 50, yTop);
Point2D.Double r4 = new Point2D.Double(xLeft + 50, yTop + 10);
Point2D.Double r5 = new Point2D.Double(xLeft + 35, yTop - 60);
Point2D.Double r6 = new Point2D.Double(xLeft + 50, yTop - 60);
Point2D.Double r7 = new Point2D.Double(xLeft + 50, yTop);
Line2D.Double frontWindshield = new Line2D.Double(r1, r2);
Line2D.Double roofTop = new Line2D.Double(r5, r6);
Line2D.Double rearWindshield = new Line2D.Double(r6, r7);
Line2D.Double anotherFront = new Line2D.Double(r1, r5);
g2.draw(body);
g2.draw(window);
g2.draw(frontTire);
g2.draw(rearTire);
g2.draw(frontWindshield);
g2.draw(roofTop);
g2.draw(rearWindshield);
g2.draw(anotherFront);
}
public static int WIDTH = 60;
public static int HEIGHT = 30;
private int xLeft;
private int yTop;
}
========================== ========== =========
import javax.swing.JFrame;
public class CarViewer
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
final int FRAME_WIDTH = 800;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
frame.setTitle("Two Cars");
frame.setDefaultCloseOpera tion(JFram e.EXIT_ON_ CLOSE);
CarComponent component = new CarComponent();
frame.add(component);
frame.setVisible(true);
}
}
========================== ========== =======
I was wondering if anyone here can help me out on my "Trucks" program. I set up three files. One java file deals with positioning the truck on the panel, the second have to do with constructing the truck, and the third have to do with actually viewing the program of my truck. Now, i want to move 3 of the 5 trucks, but I'm not to sure how to do this properly. Noticed that I named my files "Car" because I was drawing cars @ first, and then I changed them to trucks, and I'm too lazy to renamed them (lol). The one file that I really need help with is the "CarComponent" file, where I need to modify that file so that the trucks can actually move. I tried, but failed. Before I inserted "public void animateCar()" and "public void playAnimation()", I was able to display 5 trucks. I'm not too familiar with java animation, but if anyone here can help me, that would be great. Thanks.
==========================
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.math.BigInteger;
import java.math.BigDecimal;
public class CarComponent extends JComponent
{
public void sleep()
{
try
{
Thread thread;
Thread.sleep(60);
}
catch (Exception e){}
}
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Car car1 = new Car(0, 0);
int x = getWidth() - Car.WIDTH;
int y = getHeight() - Car.HEIGHT;
Car car2 = new Car(x, y);
Car car3 = new Car(x - 185, y - 150);
Car car4 = new Car(x - 50, y - 150);
Car car5 = new Car(x - 380, y - 150);
car1.draw(g2);
car2.draw(g2);
car3.draw(g2);
car4.draw(g2);
car5.draw(g2);
}
public void animateCar(Graphics gr, Car car, int deltaX, int deltaY)
{
car.erase(gr);
car.setX(Car.getX() + deltaX);
car.getY(Car.getY() + deltaY);
car.draw(gr);
}
public void playAnimation()
{
Graphics gr = getGraphics();
for (int i = 0; i < 200; i = i + 3)
{
animateCar(gr, car3, i, 0);
animateCar(gr, car4, i, Math.round(-i * 1.5));
animateCar(gr, car5, 0, i);
sleep();
}
}
}
==========================
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
public class Car
{
public Car(int x, int y)
{
xLeft = x;
yTop = y;
}
public void draw(Graphics2D g2)
{
Rectangle body = new Rectangle(xLeft, yTop, 120, 10);
Rectangle window = new Rectangle(xLeft + 30, yTop - 50, 15, 15);
Ellipse2D.Double frontTire = new Ellipse2D.Double(xLeft + 10, yTop + 10, 20, 20);
Ellipse2D.Double rearTire = new Ellipse2D.Double(xLeft + 85, yTop + 10, 20, 20);
Point2D.Double r1 = new Point2D.Double(xLeft, yTop - 35);
Point2D.Double r2 = new Point2D.Double(xLeft, yTop);
Point2D.Double r3 = new Point2D.Double(xLeft + 50, yTop);
Point2D.Double r4 = new Point2D.Double(xLeft + 50, yTop + 10);
Point2D.Double r5 = new Point2D.Double(xLeft + 35, yTop - 60);
Point2D.Double r6 = new Point2D.Double(xLeft + 50, yTop - 60);
Point2D.Double r7 = new Point2D.Double(xLeft + 50, yTop);
Line2D.Double frontWindshield = new Line2D.Double(r1, r2);
Line2D.Double roofTop = new Line2D.Double(r5, r6);
Line2D.Double rearWindshield = new Line2D.Double(r6, r7);
Line2D.Double anotherFront = new Line2D.Double(r1, r5);
g2.draw(body);
g2.draw(window);
g2.draw(frontTire);
g2.draw(rearTire);
g2.draw(frontWindshield);
g2.draw(roofTop);
g2.draw(rearWindshield);
g2.draw(anotherFront);
}
public static int WIDTH = 60;
public static int HEIGHT = 30;
private int xLeft;
private int yTop;
}
==========================
import javax.swing.JFrame;
public class CarViewer
{
public static void main(String[] args)
{
JFrame frame = new JFrame();
final int FRAME_WIDTH = 800;
final int FRAME_HEIGHT = 400;
frame.setSize(FRAME_WIDTH,
frame.setTitle("Two Cars");
frame.setDefaultCloseOpera
CarComponent component = new CarComponent();
frame.add(component);
frame.setVisible(true);
}
}
==========================
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you so much for that, Mark. You deserve my 350 points :)
ASKER
Mark, if you have anything more to add, email me:
Dragon_316ca@yahoo.ca
Dragon_316ca@yahoo.ca
Do you still want the code for the design i suggested?
Mark
Mark
ASKER
Yeah sure.
Here the code:
===CarViewer===
import java.awt.event.ActionEvent ;
import java.awt.event.ActionListe ner;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JFrame;
//Class is the visible frame. For now only
//consisting of a CarComponent and some buttons
//to start and stop animation.
class CarViewer extends JFrame implements ActionListener
{
private final static int FRAME_WIDTH = 800;
private final static int FRAME_HEIGHT = 400;
private CarComponent carComponent;
private JButton butStart;
private JButton butStop;
//Constructor
public CarViewer()
{
//Frame properties
this.setSize(FRAME_WIDTH, FRAME_HEIGHT);
this.setTitle("Cars Example");
this.setLayout(new BorderLayout());
this.setDefaultCloseOperat ion(JFrame .EXIT_ON_C LOSE);
//Add CarComponent
this.carComponent = new CarComponent();
this.add(this.carComponent , BorderLayout.CENTER);
//Add some cars
this.carComponent.addCar(n ew Car(10, 10));
this.carComponent.addCar(n ew Car(10, Car.HEIGHT+20));
this.carComponent.addCar(n ew Car(10, Car.HEIGHT*2+30));
this.carComponent.addCar(n ew Car(10, Car.HEIGHT*3+40));
this.carComponent.addCar(n ew Car(10, Car.HEIGHT*4+50));
this.carComponent.addCar(n ew Car(10, Car.HEIGHT*5+60));
//Add buttons
this.butStart = new JButton("Start");
this.butStart.addActionLis tener(this );
this.butStart.setActionCom mand("star t");
this.butStop = new JButton("Stop");
this.butStop.addActionList ener(this) ;
this.butStop.setActionComm and("stop" );
this.butStop.setEnabled(fa lse);
JPanel pnlButtons = new JPanel();
pnlButtons.add(this.butSta rt);
pnlButtons.add(this.butSto p);
this.add(pnlButtons, BorderLayout.NORTH);
}
//Handle actions
public void actionPerformed(ActionEven t ae)
{
if("start".equals(ae.getAc tionComman d()))
{
this.butStop.setEnabled(tr ue);
this.butStart.setEnabled(f alse);
this.carComponent.startAni mation();
}
else if("stop".equals(ae.getAct ionCommand ()))
{
this.butStart.setEnabled(t rue);
this.butStop.setEnabled(fa lse);
this.carComponent.stopAnim ation();
}
}
//Program entry
public static void main(String[] args)
{
CarViewer carViewer = new CarViewer();
carViewer.setVisible(true) ;
}
}
===CarComponent===
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.util.LinkedList;
//Class for holding a number of cars. All tasks
//are delegated to the objects. This component
//starts and stops the CarThread.
class CarComponent extends JComponent
{
private LinkedList<Car> cars;
private CarThread carThread;
//Constructor
public CarComponent()
{
this.cars = new LinkedList<Car>();
this.carThread = new CarThread(this);
}
//Paint component
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
//Loop cars
for(Car car : this.cars)
car.draw(g2);
}
//Add car to list
public void addCar(Car car)
{
this.cars.add(car);
}
//Remove car from list
public void removeCar(Car car)
{
this.cars.remove(car);
}
//Returns list of cars
public LinkedList<Car> getCars()
{
return this.cars;
}
//Start animation
public void startAnimation()
{
this.carThread.startAnimat ion();
}
//Stop animation
public void stopAnimation()
{
this.carThread.stopAnimati on();
}
}
===CarThread===
import java.util.LinkedList;
//Class is only concerned with moving the cars on
//a specific interval.
class CarThread implements Runnable
{
private final static int INTERVAL = 60;
private CarComponent carComponent;
private boolean running;
//Constructor
public CarThread(CarComponent carComponent)
{
this.carComponent = carComponent;
this.running = false;
}
//Thread loop
public void run()
{
this.running = true;
while(running)
{
try
{
//Move cars
for(Car car : this.carComponent.getCars( ))
{
car.move(5, 0);
}
//Repaint
this.carComponent.repaint( );
//Sleep for INTERVAL ms
Thread.sleep(INTERVAL);
}
catch (InterruptedException ie)
{
System.out.println("Interr upt exception. Animation will stop now.");
this.running = false;
}
}
}
//Start thread
public void startAnimation()
{
if(!this.running)
new Thread(this).start();
}
//Stop thread
public void stopAnimation()
{
this.running = false;
}
}
===Car===
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
//Class is only concerned with drawing the car.
class Car
{
public final static int WIDTH = 120;
public final static int HEIGHT = 70;
private int x;
private int y;
//Constructor
public Car(int x, int y)
{
this.x = x;
this.y = y;
}
//Draw car
public void draw(Graphics2D g2)
{
Rectangle body = new Rectangle(this.x, this.y, 120, 10);
Rectangle window = new Rectangle(this.x + 30, this.y - 50, 15, 15);
Ellipse2D.Double frontTire = new Ellipse2D.Double(this.x + 10, this.y + 10, 20, 20);
Ellipse2D.Double rearTire = new Ellipse2D.Double(this.x + 85, this.y + 10, 20, 20);
Point2D.Double r1 = new Point2D.Double(this.x, this.y - 35);
Point2D.Double r2 = new Point2D.Double(this.x, this.y);
Point2D.Double r3 = new Point2D.Double(this.x + 50, this.y);
Point2D.Double r4 = new Point2D.Double(this.x + 50, this.y + 10);
Point2D.Double r5 = new Point2D.Double(this.x + 35, this.y - 60);
Point2D.Double r6 = new Point2D.Double(this.x + 50, this.y - 60);
Point2D.Double r7 = new Point2D.Double(this.x + 50, this.y);
Line2D.Double frontWindshield = new Line2D.Double(r1, r2);
Line2D.Double roofTop = new Line2D.Double(r5, r6);
Line2D.Double rearWindshield = new Line2D.Double(r6, r7);
Line2D.Double anotherFront = new Line2D.Double(r1, r5);
g2.draw(body);
g2.draw(window);
g2.draw(frontTire);
g2.draw(rearTire);
g2.draw(frontWindshield);
g2.draw(roofTop);
g2.draw(rearWindshield);
g2.draw(anotherFront);
}
//Move car
public void move(int dx, int dy)
{
this.x += dx;
this.y += dy;
}
}
I did not change the drawing of the car, so now they ride backwards, but it shouldn't be difficult to adjust now. This is a pretty flexible design if you ask me. I am pretty proud at this piece of code, if I might say so myself. :-)
Have fun.
Mark
===CarViewer===
import java.awt.event.ActionEvent
import java.awt.event.ActionListe
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JFrame;
//Class is the visible frame. For now only
//consisting of a CarComponent and some buttons
//to start and stop animation.
class CarViewer extends JFrame implements ActionListener
{
private final static int FRAME_WIDTH = 800;
private final static int FRAME_HEIGHT = 400;
private CarComponent carComponent;
private JButton butStart;
private JButton butStop;
//Constructor
public CarViewer()
{
//Frame properties
this.setSize(FRAME_WIDTH, FRAME_HEIGHT);
this.setTitle("Cars Example");
this.setLayout(new BorderLayout());
this.setDefaultCloseOperat
//Add CarComponent
this.carComponent = new CarComponent();
this.add(this.carComponent
//Add some cars
this.carComponent.addCar(n
this.carComponent.addCar(n
this.carComponent.addCar(n
this.carComponent.addCar(n
this.carComponent.addCar(n
this.carComponent.addCar(n
//Add buttons
this.butStart = new JButton("Start");
this.butStart.addActionLis
this.butStart.setActionCom
this.butStop = new JButton("Stop");
this.butStop.addActionList
this.butStop.setActionComm
this.butStop.setEnabled(fa
JPanel pnlButtons = new JPanel();
pnlButtons.add(this.butSta
pnlButtons.add(this.butSto
this.add(pnlButtons, BorderLayout.NORTH);
}
//Handle actions
public void actionPerformed(ActionEven
{
if("start".equals(ae.getAc
{
this.butStop.setEnabled(tr
this.butStart.setEnabled(f
this.carComponent.startAni
}
else if("stop".equals(ae.getAct
{
this.butStart.setEnabled(t
this.butStop.setEnabled(fa
this.carComponent.stopAnim
}
}
//Program entry
public static void main(String[] args)
{
CarViewer carViewer = new CarViewer();
carViewer.setVisible(true)
}
}
===CarComponent===
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import java.util.LinkedList;
//Class for holding a number of cars. All tasks
//are delegated to the objects. This component
//starts and stops the CarThread.
class CarComponent extends JComponent
{
private LinkedList<Car> cars;
private CarThread carThread;
//Constructor
public CarComponent()
{
this.cars = new LinkedList<Car>();
this.carThread = new CarThread(this);
}
//Paint component
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
//Loop cars
for(Car car : this.cars)
car.draw(g2);
}
//Add car to list
public void addCar(Car car)
{
this.cars.add(car);
}
//Remove car from list
public void removeCar(Car car)
{
this.cars.remove(car);
}
//Returns list of cars
public LinkedList<Car> getCars()
{
return this.cars;
}
//Start animation
public void startAnimation()
{
this.carThread.startAnimat
}
//Stop animation
public void stopAnimation()
{
this.carThread.stopAnimati
}
}
===CarThread===
import java.util.LinkedList;
//Class is only concerned with moving the cars on
//a specific interval.
class CarThread implements Runnable
{
private final static int INTERVAL = 60;
private CarComponent carComponent;
private boolean running;
//Constructor
public CarThread(CarComponent carComponent)
{
this.carComponent = carComponent;
this.running = false;
}
//Thread loop
public void run()
{
this.running = true;
while(running)
{
try
{
//Move cars
for(Car car : this.carComponent.getCars(
{
car.move(5, 0);
}
//Repaint
this.carComponent.repaint(
//Sleep for INTERVAL ms
Thread.sleep(INTERVAL);
}
catch (InterruptedException ie)
{
System.out.println("Interr
this.running = false;
}
}
}
//Start thread
public void startAnimation()
{
if(!this.running)
new Thread(this).start();
}
//Stop thread
public void stopAnimation()
{
this.running = false;
}
}
===Car===
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
//Class is only concerned with drawing the car.
class Car
{
public final static int WIDTH = 120;
public final static int HEIGHT = 70;
private int x;
private int y;
//Constructor
public Car(int x, int y)
{
this.x = x;
this.y = y;
}
//Draw car
public void draw(Graphics2D g2)
{
Rectangle body = new Rectangle(this.x, this.y, 120, 10);
Rectangle window = new Rectangle(this.x + 30, this.y - 50, 15, 15);
Ellipse2D.Double frontTire = new Ellipse2D.Double(this.x + 10, this.y + 10, 20, 20);
Ellipse2D.Double rearTire = new Ellipse2D.Double(this.x + 85, this.y + 10, 20, 20);
Point2D.Double r1 = new Point2D.Double(this.x, this.y - 35);
Point2D.Double r2 = new Point2D.Double(this.x, this.y);
Point2D.Double r3 = new Point2D.Double(this.x + 50, this.y);
Point2D.Double r4 = new Point2D.Double(this.x + 50, this.y + 10);
Point2D.Double r5 = new Point2D.Double(this.x + 35, this.y - 60);
Point2D.Double r6 = new Point2D.Double(this.x + 50, this.y - 60);
Point2D.Double r7 = new Point2D.Double(this.x + 50, this.y);
Line2D.Double frontWindshield = new Line2D.Double(r1, r2);
Line2D.Double roofTop = new Line2D.Double(r5, r6);
Line2D.Double rearWindshield = new Line2D.Double(r6, r7);
Line2D.Double anotherFront = new Line2D.Double(r1, r5);
g2.draw(body);
g2.draw(window);
g2.draw(frontTire);
g2.draw(rearTire);
g2.draw(frontWindshield);
g2.draw(roofTop);
g2.draw(rearWindshield);
g2.draw(anotherFront);
}
//Move car
public void move(int dx, int dy)
{
this.x += dx;
this.y += dy;
}
}
I did not change the drawing of the car, so now they ride backwards, but it shouldn't be difficult to adjust now. This is a pretty flexible design if you ask me. I am pretty proud at this piece of code, if I might say so myself. :-)
Have fun.
Mark
ASKER
How can you make the truck to move "in reverse"? Please tell me via email: Dragon_316ca@yahoo.ca
thanks
thanks
Use negative numbers for the move(int dx, int dy) method.
I believe it is not allowed to sent email if the question is posted on this forum.. since you would get questions without answers, being answered. :-)
Mark
I believe it is not allowed to sent email if the question is posted on this forum.. since you would get questions without answers, being answered. :-)
Mark
You have the following classes: Car, CarThread, CarViewer, CarComponent
In the code above (mine and yours), the implementation is a bit inflexible. I might have some better code later, but let me explain first a better idea.
The CarViewer is the main frame. Next is the CarComponent which can be added to a container to show a number of cars. The CarComponent should have an add method which allows the CarViewer to add cars. Thus the CarComponent holds a list of the Cars in it's component. Now you can choose to have every Car in a single thread or every CarComponent in a single thread. I think the later is preferable, since it's more scalable and less intensive. The Car class should only be concerned with drawing itself and keeping the position and the CarThread should only be concerned with the regular interval movement of the cars.
So in Java terms it should look like:
==CarViewer==
public static void main(String[] args);
==CarComponent==
private LinkedList<Car> cars;
private CarThread animation;
public void addCar(Car car);
public void removeCar(Car car);
public void startAnimation();
public void stopAnimation();
==Car==
private int x;
private int y;
private int width;
private int height;
public void move(int dx, int dy);
==CarThread==
public CarThread(LinkedList<Car> cars);
public void run();
Sth. like this.. I will start coding now, let me see if I can make some nice setup.
Mark