2
\$\begingroup\$

In my game there are AI characters that try to either steal your gold or destroy the walls of your castle. Previously I simply updated them all every second, but with a large number of characters on the map there were some noticeable frame skips. This code spreads out the updating of the AIs so they are no longer done all at once.

I believe there are better ways to do this so I am looking for clues as to a better structure.

One nice thing about this approach is that it dynamically adapts to the number of AIs and will increase the speed of updates depending on how many are in game. It's also possible to change the number of AIs that will be updated each tick by changing a single variable.

public void updatePersons(float delta) {
    this.personAccumulator += delta;
    if (this.personAccumulator > this.timeBetweenPersonMoves) {
        this.personAccumulator = 0;

        this.personsToDestroy.clear();

        int numPersons = this.persons.size();
        int currentPerson = this.currentTick * this.numPersonsPerTick;
        int targetPerson = Math.min(numPersons, currentPerson + this.numPersonsPerTick);

        for (int i = currentPerson; i < targetPerson; i++) {
            PersonRoot person = this.persons.get(i);
            person.update(this.buildings);
            if (person.checkForFire(this.gameScreen.fireImages)) {
                person.shouldDestroy = true;

                this.gameScreen.personDied(person);
            }
            if (person.shouldDestroy) {
                this.personsToDestroy.add(person);
            }
        }

        for (PersonRoot person : this.personsToDestroy) {
            person.destroy();
            this.persons.remove(person);
        }

        //this now needs its own update because it will happen faster
        //when there are more persons as a side effect of this new approach
        this.spawnNewPersons();

        numPersons = this.persons.size();
        this.numTicksRequired = (int)Math.floor(numPersons / this.numPersonsPerTick);
        if (this.currentTick < this.numTicksRequired) {
            this.currentTick++;
        } else {
            this.currentTick = 0;
        }
        //adjust speed of ticks depending on how many persons there are
        if (this.numTicksRequired > 0) {
            this.timeBetweenPersonMoves = this.idealTimeBetweenPersonMoves / this.numTicksRequired;
        } else {
            this.timeBetweenPersonMoves = this.idealTimeBetweenPersonMoves;
        }
    }
}

They are not the greatest screenshots in the world, but I have some before and after screenshots from the profiling.

Before: before

After: after

Between the two screenshots I also changed a heavily used HashMap into a libGDX ObjectMap, so that has some effect on the numbers as well. Also, the idea behind the code above was not to necessarily increase overall performance, but rather to improve the user experience and reduce stuttering by spreading the work out over time.

\$\endgroup\$
  • 2
    \$\begingroup\$ I'm guessing... Looking at your screenshots, the highlighted method is indirectly called from the render-thread and my guess would be, that's the main source of the problem. Usually, the rendering works independently from the game mechanics itself and the game itself can run in a separate thread... \$\endgroup\$ – slowy Apr 27 '17 at 17:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.