60

I make game. In //ERROR ZONE is called Exception. I don't understand it. Class game has List recrangles.

void spawnt(){
var rnd = new Random();
var rnd2 = new Random();
rnd = rnd.nextInt(100);
if(rnd2.nextBool())
  rnd2 = rnd2.nextInt(100);
else
  rnd2 = -rnd2.nextInt(100);
var x = flappy.position["x"]+lastx+sw+rnd;
var y = rnd2*pomer-100-1800*pomer-168*pomer;
Rectangle vrch = new Rectangle("img/tube1.png", sw, sh, {"x":x, "y":y, "z":0});
Rectangle spodek = new Rectangle("img/tube2.png", sw, sh, {"x":x, "y":sh+mezeray*pomer+y, "z":0});

vrch.onCollision((_){
  checkover();
});

spodek.onCollision((_){
  checkover();
});
game.addObject(spodek);
game.addObject(vrch);
var cp = new Checkpoint(sw, mezeray, {"x":x+sw, "y":y+sh, "z":0});
cp.onCollision((e){
  scoore++;
  querySelector("#scoore").text="SCOORE: ${scoore}";
  sounds[1].play();
  //THIS IS ERROR ZONE
  spawnt();
});
game.addObject(cp);

rnd = new Random();
rnd = rnd.nextInt(300);
rnd2 = new Random();
rnd2 = rnd2.nextInt(300);
var rnd3 = new Random();
rnd3 = new Random();
rnd3 = rnd3.nextInt(10);
Grab w;
if(rnd3 == 0 || rnd3 == 1 || rnd3 == 2){
  w = new Grab("img/cigarette.png", 600*pomer, 418*pomer, {"x":x+sw+rnd,"y":sh+mezeray*pomer+y-mezeray*pomer+rnd2-168*pomer, "z":0});
  w.scale(0.2);
  w.onCollision((c){
    smokescreen = true;
    smoketimer.cancel();
    smoketimer = new Timer(const Duration(milliseconds: 10000), (){
      smokescreen = false;
    });
    kucky.play();
    if(csong)
      cig.play();
    csong = false;
  });
  game.addObject(w);
}
else if(rnd3 == 3 || rnd3 == 4){
  w = new Grab("img/whiskey.png", 162*pomer, 398*pomer, {"x":x+sw+rnd,"y":sh+mezeray*pomer+y-mezeray*pomer+rnd2-168*pomer, "z":0});
  w.scale(0.2);
  w.onCollision((c){
    AudioElement pr = new AudioElement("sounds/yes.${koncovka}");
    pr.play();
    whiskey++;
    if(whiskey>=10 && whiskey<20){
      speedotoceni = 30;
      zhoupni();
    }
    else if(whiskey>=20 && whiskey<30){
      speedotoceni = 25;
      zhoupni();
    }
    else if(whiskey>=30 && whiskey<40){
      speedotoceni = 20;
      zhoupni();
    }
    else if(whiskey>=40 && whiskey<50){
      speedotoceni = 15;
      zhoupni();
    }
    else if(whiskey>=50 && whiskey<60){
     speedotoceni = 10;
      zhoupni();
    }
    else if(whiskey>=60 && whiskey<70){
      speedotoceni = 5;
      zhoupni();
    }
    else if(whiskey>=70 && whiskey<80){
      speedotoceni = 1;
      zhoupni();
    }
    querySelector("#scoore").text="SCOORE: ${scoore}";
  });
  game.addObject(w);
}
else if(rnd3 == 9){
  w = new Grab("img/jatra.png", 539*pomer, 521*pomer, {"x":x+sw+rnd,"y":sh+mezeray*pomer+y-mezeray*pomer+rnd2-168*pomer, "z":0});
  w.scale(0.1);
  w.onCollision((c){
    AudioElement pr = new AudioElement("sounds/yes.${koncovka}");
    pr.play();
    jatra++;
    document.cookie = "jatra=${jatra}; expires=Thu, 24 Dec 4000 00:00:00 GMT; path=/";
    querySelector("#jatracount").text = jatra.toString();
  });
  game.addObject(w);
 }
lastx = lastx+300*pomer+rnd;
}

class Game.dart

  import 'dart:html';
  import 'dart:math';
  import 'dart:async';
  import 'Entity.dart';
  import 'Gravity.dart';
  import 'Rectangle.dart';
  import 'Camera.dart';
  import 'Checkpoint.dart';

  class Game {
    CanvasElement canvas;
    Gravity gravity;
    List<Entity> entities = new List();
    List<Rectangle> rectangles = new List();
    Camera camera;
    var leftSpace = 0;
    var topSpace = 0;
    var _onCollision;
    var _over = (_){};
    var _render = (_){};
    num _lastFrame = 0;
    bool isOver = false;


Game(this.canvas, this.gravity){
  window.animationFrame.then((e){this.render(e);});
}

void addEntity(Entity entita){
  this.entities.add(entita);
}

void addObject(Rectangle rectangle){
  this.rectangles.add(rectangle);
}

void render(num delta){
  num fps = 1000/(delta-this._lastFrame);
  this._lastFrame = delta;
  CanvasRenderingContext2D ctx = this.canvas.context2D;
  ctx.clearRect(0, 0, this.canvas.width+this.leftSpace.abs(), this.canvas.height+this.topSpace.abs());
  this._render(true);
  this.rectangles.forEach((s){
    ctx.fillStyle=s.color;
    if(s.hasColor()){
      ctx.fillStyle=s.color;
      ctx.fillRect(s.position["x"]-this.leftSpace,s.position["y"]-this.topSpace,s.width,s.height);
    }
    else{
      ctx.drawImageScaled(s.texture, s.position["x"]-this.leftSpace,s.position["y"]-this.topSpace,s.width,s.height);
    }
  });
  this.entities.forEach((e){
    e.move(fps);
    e.power["y"] += this.gravity.operate(e)*(60/fps);
    ctx.save(); 
    ctx.translate(e.position["x"]-this.leftSpace+e.width/2, e.position["y"]-this.topSpace+e.height/2);
    ctx.rotate(e.rotation* PI/180);
    ctx.drawImageScaled(e.img, -(e.width/2), -(e.height/2), e.width, e.height);
    ctx.restore(); 
  });
  collisionResponse();
  checkCollisions();
  if(!this.camera.fixed["x"])
    this.leftSpace = this.camera.target.position["x"]-this.canvas.width/2+this.camera.target.width/2;
  else
    this.leftSpace = this.camera.fixedPos["x"];

  if(!this.camera.fixed["y"])
    this.topSpace = this.camera.target.position["y"]-this.canvas.height/2+this.camera.target.height/2;
  else
    this.topSpace = this.camera.fixedPos["y"];
  this._render(false);
  ctx.closePath();
  window.animationFrame.then((e){this.render(e);});
}

void onCollision(e){
  this._onCollision = e;
}

void collisionResponse(){
  this.rectangles.forEach((s){
    num x1 = s.position["x"];
    num y1 = s.position["y"];
    num z1 = s.position["z"];
    num w1 = s.width;
    num h1 = s.height;

    this.entities.forEach((e){
      num rot = e.rotation * (PI / 180);
      num x2 = e.position["x"];
      num y2 = e.position["y"];
      num z2 = e.position["z"];
      num w2 = e.width;
      num h2 = e.height;
      if(x2>=x1-w2 && x2<=x1+w1 && y2>y1-h2 && y2<y1+h1 && z1==z2){
        s.collisionResponse(e);
        e.collision(s);
        s.collision(e);
      }
    });
  });
}

void checkCollisions(){
  List<Entity> kolize = new List();
  for(Entity e1 in this.entities){
    num x1 = e1.position["x"];
    num y1 = e1.position["y"];
    num z1 = e1.position["z"];
    num w1 = e1.width;
    num h1 = e1.height;

    for(Entity e2 in this.entities){
      if(e1 == e2 || (kolize.indexOf(e1) != -1 && kolize.indexOf(e2) != -1)) continue;
      num x2 = e2.position["x"];
      num y2 = e2.position["y"];
      num z2 = e2.position["z"];
      num w2 = e2.width;
      num h2 = e2.height;
      if(x2>=x1-w2 && x2<=x1+w1 && y2>y1-h2 && y2<y1+h1 && z1==z2){
        kolize.add(e1);
        kolize.add(e2);
      }
    }
  }
}

void over(){
  if(!this.isOver)
    this._over();
  this.isOver = true;
}

void onOver(e){
  this._over = e;
}

void onRender(f){
  this._render = f;
}
}

Uncaught Error: Concurrent modification during iteration: Instance(length:17) of '_GrowableList'. Stack Trace: #0 List.forEach (dart:core-patch/growable_array.dart:241)

#1 Game.collisionResponse (FlappyBird/web/classes/Game.dart:83:28)

#2 Game.render (FlappyBird/web/classes/Game.dart:62:22)

#3 Game.render. (FlappyBird/web/classes/Game.dart:75:47)

#4 _rootRunUnary (dart:async/zone.dart:717)

#5 _RootZone.runUnary (dart:async/zone.dart:854)

#6 _Future._propagateToListeners.handleValueCallback (dart:async/future_impl.dart:439)

#7 _Future._propagateToListeners (dart:async/future_impl.dart:522)

#8 _Future._complete (dart:async/future_impl.dart:303)

#9 _SyncCompleter.complete (dart:async/future_impl.dart:44)

#10 Window.animationFrame. (file:///E:/b/build/slave/dartium-win-full-stable/build/src/build/Release/obj/global_intermediate/blink/bindings/dart/dart/html/Window.dart:62)

Exception: Concurrent modification during iteration: Instance(length:17) of '_GrowableList'. undefined (undefined:0:0)

Is it enough? Does somebody know how to repair it? Thanks for answer. :)

Filip Pyrek
  • 730
  • 1
  • 5
  • 8

5 Answers5

128

This error means that you are adding or removing objects from a collection during iteration. This is not allowed since adding or removing items will change the collection size and mess up subsequent iteration.

The error is likely from one of these lines which you haven't posted the source for:

 s.collisionResponse(e);
 e.collision(s);
 s.collision(e);

I assume one of these calls is removing an item from either the entities list or the rectangles list, during the forEach, which is not allowed. Instead you must restructure the code to remove the items outside of the list iteration, perhaps using the removeWhere method.

Consider the following attempt to remove odd numbers from a list:

var list = [1, 2, 3, 4, 5];
list.forEach( (e) {
 if(e % 2 == 1) 
   list.remove(e);
});

This will fail with a concurrent modification exception since we attempt to remove the items during the list iteration.

However, during the list iteration we can mark items for removal and then remove them in a bulk operation with removeWhere:

var list = [1, 2, 3, 4, 5];
var toRemove = [];

list.forEach( (e) {
 if(e % 2 == 1) 
   toRemove.add(e);
});

list.removeWhere( (e) => toRemove.contains(e));
Pixel Elephant
  • 20,649
  • 9
  • 66
  • 83
16

New documentation on latest Dart release 2.1.0 from https://api.dartlang.org/stable/2.1.0/dart-core/Map/removeWhere.html

Implementation

Map.removeWhere((key, value) => toRemove.contains(key));
fritz-playmaker
  • 693
  • 1
  • 10
  • 15
12

try to avoid loop List too much. Using this:

list.removeWhere((element) => element % 2 == 1;
ANDYNVT
  • 531
  • 4
  • 19
4

This way you can remove object from dynamic list and you won't face exception concurrent modification during iteration as looping is done by removeWhere it self !

List data = [
    {
      "name":"stack"
    },
    {
      "name":"overflow"
    }
  ];
  
  data.removeWhere((item) => item["name"]=="stack");
  
  print(data);

Output

[{name: overflow}]
Ankit Parmar
  • 449
  • 5
  • 8
1

create a copy of list and modify I have a stockQty list but I want to modify also there will be break on some conditions so I can't use the about answers.so I make a copy of the list and loop on it and modify on the difference.

  var stockQty = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
  var purchaseQty = 15;
  var stockQrtCp = stockQty.toList();

  for (int sq in stockQrtCp) {
    if (purchaseQty >= sq) {
      print('Purchase Qty is greater than Stock Qty');

      stockQty.removeWhere((element) => element == sq);
      purchaseQty = purchaseQty - sq;
    } else {
      print('Purchase Qty is less than Stock Qty');
      sq = sq - purchaseQty;
      if (sq == 0) {
        stockQty.removeWhere((element) => element == sq);
      }
      break;
    }
  }