Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GdxRuntimeException: #iterator() cannot be used nested

I'm working on this game which has a World. In this World there are many Units.

The problem stems from the fact that World serves (among other things) two main tasks:

  1. Iterate through each Unit so that they can update their properties based on time passed an so forth.
  2. Find potential targets for each Unit.

In World, this happens:

for (Actor a : stage.getActors())
{
    a.draw(batch, 1);
    a.act(10);
    findTargets((Unit)a);
}

findTargets() is defined as such:

public ArrayList<Unit> findTargets(Unit source) {
    double sight = source.SIGHT;
    ArrayList<Unit> targets = new ArrayList<Unit>();
    for (Actor a : stage.getActors()) {
        Unit target = (Unit)a;
        if (!(target instanceof Unit))
            continue;

        if (target.equals(source)) continue;
        if (((Unit)target).getPos().dst(source.getPos()) < sight) {
            targets.add((Unit)target);
        }
    }
    return targets;
}

The problem is obvious: findTargets() also iterates over every unit, resulting in a nested iteration. However, I'm unsure as to how I should proceed to "un-nest" this, as I'm only seeing a catch 22: Every unit does in effect have to iterate over every other unit to see if they're within their sight-range.

Some fresh eyes on this would be greatly appreciated.

like image 293
Jarmund Avatar asked Jul 24 '16 12:07

Jarmund


1 Answers

There may be ways to refactor your design to avoid the nesting. But the simplest solution might be to just use the old school for loops for both outer and inner, or just the inner. Don't use the iterator, as that is not allowed here for nested loops. getActors returns a libGDX Array, so just traverse that by index

for (int i=0; i < stage.getActors().size; i++) {
  //...etc --> use stage.getActors().items[i] ...
like image 190
Peter R Avatar answered Sep 21 '22 00:09

Peter R