JavaFX Series - exit application and animated harvesting


Posted by Steven

This week, I got around to adding some animation into the game and fixing a (again) thread-related bug.

Exiting the application

After playing around with the application, I noticed a problem: After a couple of executions from within eclipse, my computer got pretty slow. It turned out that after closing the application, one Java thread always stayed alive. The reason for this is my architecture. In my starting class, I called the JavaFX application as follows:

  1. public class Start {
  2.  
  3. public static void main(String[] args) {
  4.  
  5. // If there were other user interfaces, here would be the decision which
  6. // of them to start. Right now, there is only JavaFX.
  7. JavaFxApplication.main(new String[0]);
  8. }
  9. }

The JavaFxApplication was as follows:

  1. public class JavaFxApplication extends Application implements UserInterface {
  2.  
  3. // ...
  4.  
  5. public static void main(String[] args) {
  6. launch(args);
  7. }
  8.  
  9. // ...
  10. }

As you can see, the JavaFX application started in a new thread. When the user closes the (JavaFX) window, this thread stopped. But because the first thread that called the FX-thread never did something else as to start its counterpart, it was never exited. This way, it went on and on. To make it stop after the user closed the JavaFX window, I changed it as follows:

  1. public class Start {
  2.  
  3. public static void main(String[] args) throws InterruptedException {
  4.  
  5. // If there were other user interfaces, here would be the decision which
  6. // of them to start. Right now, there is only JavaFX.
  7. Thread t = new Thread() {
  8. @Override
  9. public void run() {
  10. System.out.println("Starting JavaFX ...");
  11. JavaFxApplication.main(new String[0]);
  12. System.out.println("JavaFX ended");
  13. }
  14. };
  15.  
  16. t.start();
  17. t.join();
  18. System.out.println("terminating or closing java program");
  19. System.exit(1);
  20. }
  21. }

Now, the first (purely Java) thread starts the JavaFX thread and joins it. This means that only after the JavaFX thread finishes, the originaly thread continues. This gives me the chance to stop it in a proper way.

Animations!

I know that animations are a huge topic in JavaFX and there are many tutorials out there which show pretty impressing stuff. However, I programmed my own little animation for the harvesting colonies. Oh right: There are colonies in the game now! I'm not sure what they will do, but they sure will need some resources to do anything. Hence, I made them harvest existing resources:

The ultimate resource-gathering red laser beam is made as follows:

  1. Colony c = (Colony) harvester;
  2. Resource r = (Resource) harvest;
  3.  
  4. final Line line = new Line(c.getPosition().getX(), c
  5. .getPosition().getY(), r.getPosition().getX(),
  6. r.getPosition().getY());
  7. line.setFill(null);
  8.  
  9. line.setStroke(Color.RED);
  10.  
  11. line.setStrokeWidth(2);
  12.  
  13. rootGroup.getChildren().add(line);
  14.  
  15. FadeTransition ft = new FadeTransition(Duration
  16. .millis(1300), line);
  17. ft.setFromValue(1.0);
  18. ft.setToValue(0);
  19. ft.play();
  20.  
  21. // remove the line after the animation
  22. ft.setOnFinished(new EventHandler<ActionEvent>() {
  23. @Override
  24. public void handle(ActionEvent event) {
  25. rootGroup.getChildren().remove(line);
  26. }
  27. });

There are a few articles out there that describe how to remove a node from the group after its animation went through. However, the most articles I've seen didn't work for JavaFX 2.2.

Get the code

As always, I pushed the code in my repository on github. The codebase for this article is tagged as Codebase_ExitApplicationAndAnimation.

Next steps

Because only having one colony is not very awesome, colonies will be able to expand soon. Most likely, they will be able to spawn a new colony if they have enough energy.

Category: