0

I am currently developing a tower defence game for a university project. At higher waves there are hundreds of enemies moving arround. My problem is that it's getting very inperforment at about 300+ enemies moving simultaneously. Every enemy is a children of a Pane which is displayed in my scene.

I've got a method in my EnemyGraphics class which updates the positon by calling the update method:

    public class EnemyGraphics extends ImageView implements EventObserver {

...
    @Override
    public void update() {
            Platform.runLater(() -> {
                    relocate(enemy.getxCoordinate(), enemy.getyCoordinate());
            });
    }
    }

I guess it's getting laggy because every enemy is updating its location on its own every time it moves by calling update().

Is there a way that I can set new coordinates for my ImageView object, without redrawing the scene and in the main FX-Thread creating a timer which redraws the entire scene in a certain interval? Or is there a other solution / method I can call to move images performantly over the pane?

GreenLegend
  • 41
  • 1
  • 4
  • I personally would run the code under a profiler to see where most time is actually spent. Is it thread creation, calculation, garbage collection or just a bit of bad code. You could create a concurrent queue of the moved entities. These should be produced on another thread, and a consumer reads these updates to invoke them on the UI thread. You would need to calculate as much as possible on the other threads, to minimize the work on that is done on the GUI thread. Also, look at whether you are creating a large number of temporary objects that the Garbage collector has to deal with. – Dragonthoughts Dec 03 '18 at 14:19
  • 1
    You could probably get some ideas from [here](https://gist.github.com/james-d/8327842). – SedJ601 Dec 03 '18 at 14:37
  • Did you try using a `Canvas`? – user1803551 Dec 04 '18 at 01:24
  • @user1803551 Yes I tried and I can't notice any difference perfomance wise – GreenLegend Dec 04 '18 at 07:10
  • @Sedrick I looked at your given example, but I couldn't find much difference to the way I move my Objects. In the example the balls are moved by using the setCenterX / Y method from the Circle class. I tryed using the setX / Y method from the ImageView class but I can't notice a difference. I also implemented a method that updates every Objects positon by iterating through a list, which gave me a bit of performance increase but not much. – GreenLegend Dec 04 '18 at 07:38
  • What are the sizes of your Images? Are you reusing the same image? – SedJ601 Dec 04 '18 at 12:28
  • @Sedrick they are arround 2 - 20 kb. And yes I've got a extra class for loading and storing the images so that they can be loaded directly from ram. – GreenLegend Dec 04 '18 at 13:38
  • Given that you have to wrap your relocate method in platform.runlater, I can only assume you do have a true grasp of the Animation class. You need to post a Minimal, Complete, and Verifiable example. – SedJ601 Dec 04 '18 at 13:45

1 Answers1

1

Ok I've found my mistake. Everytime my enemyLogic class compute a new position it called the enemyGraphic object to update its position. During testing I've removed the functionality of the method in the enemyGraphics class but not the call.

To update the postions of all the enemys I've written a method in my GUIcontroller class:

private void startUpdateTicker() {
    final AnimationTimer timer = new AnimationTimer() {
        @Override
        public void handle(long timestamp) {
                updateEnemies();
        }
    };
    timer.start();
}

public synchronized void updateEnemies() {
        for (EnemieGUI enemy : enemyList) {
            enemy.relocate(enemy.getEnemie().getxCoordinate(), enemy.getEnemie().getyCoordinate());
        }
}
GreenLegend
  • 41
  • 1
  • 4