I am currently creating a quite simple JavaFX program, simulating planes and ships transporting passengers between cities. So far I've been able to make the planes perform short flights through a few cities but the problem is that when I add more than 3 or 4 planes, the animation is terribly slow.
What I'm doing is using the Timeline class as my main game loop and clearing and then redrawing the plane images on the Canvas every frame at 60 FPS. Here is the timeline part:
Timeline gameLoop = new Timeline();
gameLoop.setCycleCount( Timeline.INDEFINITE );
KeyFrame keyFrame = new KeyFrame(
Duration.seconds(0.017),
new EventHandler<ActionEvent>()
{
public void handle(ActionEvent ae)
{
dynamicGC.clearRect(0, 0, 1280, 800);
for (Plane plane : Spawner.planeList)
{
if(plane.isInFlight()) plane.Draw(dynamicGC);
}
}
});
gameLoop.getKeyFrames().add(keyFrame);
gameLoop.play();
Here is how I create new threads for the planes:
//plane initalization
Thread t = new Thread(plane);
t.setDaemon(true);
t.start();
Here is the run() method defined in the Plane class:
public void run() {
int routeCounter = 0;
int direction = 1;
boolean active = true;
double recordedTime = 0.0;
double aParameter = 0.0;
while(active) {
if (inFlight) {
double tmpTime = System.currentTimeMillis();
double timeDifference = tmpTime - recordedTime;
recordedTime = tmpTime;
double change = planeVelocity * (timeDifference) * direction;
xCoordinate += change;
yCoordinate += change * aParameter;
if ( Math.abs(xCoordinate - Spawner.airportList.get(nextAirport).getXCoordinate()) < Spawner.airportList.get(nextAirport).getDetectionPrecision()
&& Math.abs(yCoordinate - Spawner.airportList.get(nextAirport).getYCoordinate()) < Spawner.airportList.get(nextAirport).getDetectionPrecision()) {
inFlight = false;
routeCounter++;
}
} else {
if(routeCounter < plannedRoute.size() ) {
nextAirport = plannedRoute.get(routeCounter);
aParameter = (Spawner.airportList.get(nextAirport).getYCoordinate() - this.yCoordinate)/
(Spawner.airportList.get(nextAirport).getXCoordinate() - this.xCoordinate);
if (Spawner.airportList.get(nextAirport).getXCoordinate() < this.xCoordinate) {
direction = -1;
} else direction = 1;
recordedTime = System.currentTimeMillis();
inFlight = true;
}
else active = false;
}
}
}
I'm aware that the code is pretty messy, but right now I want to know why do animations slow down so dramatically. I'm unsure if I'm using threads correctly. Also I've tried some solutions like caching the Canvas and Group nodes like in an answer to this question and it did nothing.
EDIT: It seems that it's the threads that slow down the execution of the program.
I create a new plane (and a new thread for it) every time a certain button is pressed with this handler in the JavaFX Application Thread:
@FXML
private void handleNewPassengerPlaneCreated(ActionEvent event) {
ArrayList<Integer> route = new ArrayList<>();
int startingAirport = Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
for(int i = 0; i < 3; i++) {
int addedAirport = Spawner.randomNumberGenerator.nextInt(Spawner.airportList.size());
if ( addedAirport != startingAirport)
route.add(addedAirport);
}
System.out.println(Spawner.airportList.get(startingAirport).xCoordinate + " " + Spawner.airportList.get(startingAirport).yCoordinate );
PassengerPlane plane = new PassengerPlane(Spawner.airportList.get(startingAirport).xCoordinate,
Spawner.airportList.get(startingAirport).yCoordinate, "ID", 10, 1000, route, 300);
Spawner.planeList.add(plane);
new Thread(plane).start();
}