Reputation: 63
In my code I have a player class and from that Player
class I want to call in a projectile, but whenever I try calling in the projectile in game, I get this error
Exception in thread "Thread-2" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at ca.runner.level.Level.tick(Level.java:127)
at ca.runner.game.Game.tick(Game.java:149)
at ca.runner.game.Game.run(Game.java:118)
at java.lang.Thread.run(Unknown Source)
I think it has to do maybe with the fact that both Mob and Projectile both call Entity or something like that, but I'm not sure how to fix this. If anyone could help that would be great.
Player Class:
package ca.runner.game.entities;
import ca.runner.game.Game;
import ca.runner.game.InputHandler;
import ca.runner.gfx.Colours;
import ca.runner.gfx.Screen;
import ca.runner.level.Level;
import ca.runner.game.InputHandler;
import ca.runner.gfx.Colours;
import ca.runner.gfx.Screen;
import ca.runner.level.Level;
public class Player extends Mob{
private InputHandler input;
private int colour = Colours.get(-1, 111, 145, 543);
private int scale = 1;
protected boolean isSwimming = false;
private int tickCount = 0;
private int health = 10;
public Player(Level level, int x, int y, InputHandler input) {
super(level, "Player", x, y, 1);
this.input = input;
this.health = health;
}
public void tick() {
int xa = 0;
int ya = 0;
if(input.up.isPressed()) {ya--;}
if(input.down.isPressed()) {ya++;}
if(input.left.isPressed()) {xa--;}
if(input.right.isPressed()) {xa++;}
if(input.space.isPressed()) {
BasicAttack Fireball = new BasicAttack(level, false, "Fireball", 10, 10, 1, 1, 1, getPlayerMoveDir());
level.addEntity(Fireball);
}
if (xa != 0 || ya != 0) {
move(xa, ya);
isMoving = true;
}else {
isMoving = false;
}
if (level.getTile(this.x >> 3, this.y >> 3).getId() == 4) {
isSwimming = true;
}
if (isSwimming && level.getTile(this.x >> 3, this.y >> 3).getId() != 4) {
isSwimming = false;
}
tickCount++;
}
public void render(Screen screen) {
int xTile = 0;
int yTile = 28;
int walkingSpeed = 4;
int flipTop = (numSteps >> walkingSpeed) & 1;
int flipBottom = (numSteps >> walkingSpeed) & 1;;
if (movingDir == 1) {
xTile += 2;
} else if (movingDir > 1) {
xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2;
flipTop = (movingDir - 1) % 2;
}
int modifier = 8 * scale;
int xOffset = x - modifier / 2;
int yOffset = y - modifier / 2 - 4;
if (isSwimming) {
int waterColour = 0;
yOffset += 4;
if (tickCount % 60 < 15) {
waterColour = Colours.get(-1, -1, 225, -1);
} else if (15 <= tickCount % 60 && tickCount % 60 < 30) {
yOffset -= 1;
waterColour = Colours.get(-1, 225, 115, -1);
} else if (30 <= tickCount % 60 && tickCount % 60 < 45) {
waterColour = Colours.get(-1, 115, -1, 225);
} else {
yOffset -= 1;
waterColour = Colours.get(-1, 225, 115, -1);
}
screen.render(xOffset, yOffset+3, 0 + 27 * 32, waterColour, 0x00, 1);
screen.render(xOffset + 8, yOffset+3, 0 + 27 * 32, waterColour, 0x01, 1);
}
//Upper Body
screen.render(xOffset + (modifier * flipTop), yOffset, xTile + yTile * 32, colour, flipTop, scale);
screen.render(xOffset + modifier - (modifier * flipTop), yOffset, (xTile + 1) + yTile * 32, colour, flipTop, scale);
if (!isSwimming) {
//Lower Body
screen.render(xOffset + (modifier * flipBottom), yOffset + modifier, xTile + (yTile+1) * 32, colour, flipBottom, scale);
screen.render(xOffset + modifier - (modifier * flipBottom), yOffset + modifier, (xTile+1) + (yTile+1) * 32, colour, flipBottom, scale);
}
}
public boolean hasCollided(int xa, int ya) {
int xMin = 0;
int xMax = 7;
int yMin = 3;
int yMax = 7;
for (int x = xMin; x < xMax; x++) {
if (isSolidTile(xa, ya, x, yMin)) {
return true;
}
}
for (int x = xMin; x < xMax; x++) {
if (isSolidTile(xa, ya, x, yMax)) {
return true;
}
}
for (int y = yMin; y < yMax; y++) {
if (isSolidTile(xa, ya, xMin, y)) {
return true;
}
}
for (int y = yMin; y < yMax; y++) {
if (isSolidTile(xa, ya, xMax, y)) {
return true;
}
}
return false;
}
public int getPlayerHealth() {
return health;
}
public int getPlayerMoveDir() {
return movingDir;
}
}
Projectile Class:
package ca.runner.game.entities;
import ca.runner.level.Level;
import ca.runner.level.tiles.Tile;
public abstract class Projectile extends Entity{
protected String name;
protected int speed;
protected int numSteps = 0;
protected boolean isMoving;
protected int movingDir = 1;
protected int scale;
protected int damage;
protected boolean emitter;
protected int moveDir;
public Projectile(Level level, boolean isEmitter, String name, int x, int y, int speed, int damage, int scale, int MoveDir) {
super(level);
this.name = name;
this.x = x;
this.y = y;
this.speed = speed;
this.damage = damage;
this.emitter = isEmitter;
this.scale = scale;
this.moveDir = moveDir;
}
public boolean isEmitter() {
return emitter;
}
public void move(int xa, int ya) {
//if(!hasCollided(xa, ya)) {
x+= xa * speed;
y += ya * speed;
//} else {
// level.removeEntity(this);
//}
}
//public abstract boolean hasCollided(int xa, int ya);
protected boolean isSolidTile(int xa, int ya, int x, int y) {
if (level == null) { return false;}
Tile lastTile = level.getTile((this.x + x) >> 3, (this.y + y) >> 3);
Tile newTile = level.getTile((this.x + x + xa) >> 3, (this.y + y + ya) >> 3);
if (!lastTile.equals(newTile) && newTile.isSolid()) {
return true;
}
return false;
}
public String getName() {
return name;
}
}
EDIT: Added the full stacktrace
Upvotes: 1
Views: 97
Reputation: 3274
I would guess that the addEntity method of the Level class adds the Fireball to a collection. The "tick" method in your Player class is probably overriding a tick method in the "Mob" class that is called from something that loops over the same collection that addEntity wants to add to.
Have a look at the documentation for your iterator, it will tell you that it throws the "ConcurrentModificationException" if someone modifies the collection while it is iterating across it.
I can think of several ways to solve the problem.
I hope this helps.
Upvotes: 1