package gvps.gui;
import java.awt.*;
import javax.swing.*;
import java.util.*;
/**
* <p>The VehicleAnimator class provides an automatically updating canvas on
* which to display moving vehicles.</p>
* <p>In order to animate the vehicles "nicely" (without flickering) it uses
* a concept called "double buffering" to render the display off-screen (thus
* in memory) before transferring it over to the screen. This results in
* potentially larger memory usage... however, this should be negligable.</p>
*/
public class VehicleAnimator extends Component implements Runnable {
/* for additional functionality (e.g. collisions, etc), extend the Vector
* class with a "VehicleManager", which checks for additional vehicle
* placement parameters and use it in place of 'vehicles' */
private Vector<MappedVehicle> vehicles;
private int state;
private Image carImage;
private int animationSpeed = 83; // animation speed: ~12fps
private Graphics offScreenGraphics;
private Image offScreenImage;
/** Creates an animated canvas that displays movements of various vehicles
* based on their position and speed */
public VehicleAnimator(){
carImage = Toolkit.getDefaultToolkit().getImage("car_icon.png");
vehicles = new Vector<MappedVehicle>();
}
public void addVehicle(String vehicleId, Vector<Point> path, int speed){
MappedVehicle vehicle = new MappedVehicle(vehicleId, path, speed);
vehicles.add(vehicle);
Thread vehicleThread = new Thread(vehicle);
vehicleThread.start();
}
/**
* Forces the current location of a vehicle with the specified vehicleID
* @param vehicleId the unique identifier of the desired vehicle
* @param location the new location of the vehicle
*/
public void forceVehicleLocation(String vehicleId, Point location){
try {
getMappedVehicle(vehicleId).setLocation(location);
}
catch (VehicleNotFoundException e) {
System.out.println(e);
}
}
/**
* Changes the predictive speed of a vehicle with the specified vehicleID.
* Warning: No mutexes are used to validate the size of vehicles Vector,
* resulting in possibly incorrect vehicle counts.
* @param vehicleID the id of the vehicle
* @param speed the new speed of the chosen vehicle
*/
public void setVehicleSpeed(String vehicleId, int speed) {
try {
getMappedVehicle(vehicleId).setSpeed(speed);
}
catch (VehicleNotFoundException e) {
System.out.println(e);
}
}
/**
* Pauses a selected vehicles movements.
*/
public void pauseVehicle(String vehicleId){
/**
* Gets a MappedVehicle object based on it's vehicleId.
* @param id the unique identifier of a vehicle
* @throws VehicleNotFoundException if a vehicle does not exist with this id
*/
public MappedVehicle getMappedVehicle(String id) throws VehicleNotFoundException {
boolean vehicleFound = false;
int totalVehicles = vehicles.size();
int count = 0;
// loop through each vehicle looking for one with the right ID
while ( !vehicleFound || count < totalVehicles ){
if ( vehicles.get(count).getId().equals(id) ){
vehicleFound = true;
}
else {
count++;
}
}
if ( !vehicleFound ){
throw new VehicleNotFoundException("A vehicle does not exist "+
"with the id \"" + id + "\"" );
}
else {
return vehicles.get(count);
}
}
public void run(){
while (true){
repaint();
try {
Thread.sleep(animationSpeed);
}
catch (InterruptedException e){
System.out.println("This thread has been broken... "+
"I have NO idea what that means");
}
}
}
/**
* Redraws the positions of the vehicles on screen.
*/
public void update(Graphics g){
// clears the offscreen graphics image, places a "car" image at every point
// on the map where a car is supposed to be
// then draws that to the component
int totalVehicles = vehicles.size();
if (offScreenGraphics == null) {
//System.out.println("Creating buffer");
offScreenImage = createImage(getWidth(), getHeight());
offScreenGraphics = offScreenImage.getGraphics();
}
// clear the screen
offScreenGraphics.clearRect(0,0, this.getWidth(),this.getHeight());
// if we have vehicles, loop through them, get their position, and draw them
if ( totalVehicles > 0 ){
for ( int i = 0; i < totalVehicles; i++ ){
MappedVehicle currentVehicle = vehicles.get(i);
// check if the current vehicle hasn't actually reached its
// destination, if it hasn't, draw it
if ( !currentVehicle.isFinished() ){
//System.out.println("Drawing to buffer");
offScreenGraphics.drawImage(
carImage,
(int)currentVehicle.getLocation().getX(),
(int)currentVehicle.getLocation().getY(),
this);
}
// else, remove it from the list of vehicles
else {
vehicles.remove(i);
// compensate for removed vehicle
i--;
totalVehicles = vehicles.size();
}
}
if ( offScreenGraphics != null ) {
//System.out.println("Drawing to screen");
g.drawImage(offScreenImage, 0, 0, this);
}
}
}
public void paint(Graphics g){
}
}