Reputation: 118
I am programming a basic java game, but I am having an issue.
Everytime that I try it out, if I wait just for 10 seconds, the program stops working correctly. I've made a class called Drawable
, which has a paint
function. This paint
function paints a rectangle on a certain area(given on the constructor).
And I have a thread that iterates over all drawables in an arraylist(added randomly, with another thread), and just substracts 1 to their x
. When it stops working correctly, the character can jump and does all animations, but the drawables stop moving. At first I thought this might have given a ConcurrentModificationException
error, but it didn't print it on the console.
So right now I don't really know what to do.
Here I add the Drawables
:
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while (Game.isPlayingGame) {
try {
Thread.sleep((long) (Math.random()*2000));
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
obstacles.add(new Drawable(
Constants.WIDTH,
(int) (Constants.HEIGHT / 2),
Constants.WIDTH - 100,
(int) (Constants.HEIGHT / 2) - 100,
Color.BLUE));
}
}
});
t2.start();
Here I move the Drawables
:
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (Game.isPlayingGame) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (Drawable d : obstacles) {
d.x -= 1;
d.x2 -= 1;
if (d.x2 < 0) {
obstacles.remove(d);
}
}
}
}
});
t.start();
paint method:
@Override
public void paint(Graphics g) {
super.paint(g);
floor.paint(g);
Graphics2D g2d = (Graphics2D) g;
AffineTransform ant = g2d.getTransform();
g2d.rotate(Math.toRadians(rotation),
character.x - Constants.characterSize / 2,
character.y - Constants.characterSize / 2);
character.paint(g);
g2d.setTransform(ant);
for (Drawable d : obstacles) {
d.paint(g);
System.out.println(rotation_down);
if (!rotation_down) {
if (!character.onCollision(floor)) {
character.y += (int) gravityAccel; // gravity
character.y2 += (int) gravityAccel; // gravity
gravityAccel += 0.1;
} else {
Screen.canJump = true;
gravityAccel = 0;
}
}
}
repaint();
}
Thanks in advance.
Upvotes: 1
Views: 138
Reputation: 312
The proper synchronization depends on the exact internals of your Drawable. Also use CopyOnWriteArrayList. For the Drawable class, decrement of x and x2 should be atomic and synchronized with at least paint() method:
synchronized moveToLeft() {
x-=1;
x2-=1;
}
However, it does not make sense to have an object with x2 < 0 but this is a separate discussion.
You would also want to have
synchronized getX2() {
return x2;
}
and in your second thread do something like this:
if (d.getX2 == 0) {
obstacles.remove(d);
}
else {
d.moveToLeft();
}
The reason to do the check first is that if you do it other way around, you can and up in a situation when x2 is already -1, obstacles.remove(d)
has not been called yet, and d.paint()
is called. This could cause issues unless your paint() method can handle negative coordinates.
Upvotes: 1