I have a java program which is basically a game. It has a class named 'World'. The "World" class has a method 'levelChanger()', and another method 'makeColorArray()'.
public class World {
private BufferedImage map, map1, map2, map3;
private Color[][] colorArray;
public World(int scrWd, int scrHi) {
try {
map1 = ImageIO.read(new File("map1.png"));
map2 = ImageIO.read(new File("map2.png"));
map3 = ImageIO.read(new File("map3.png"));
} catch (IOException e) {
e.printStackTrace();
}
map = map1;
makeColorArray();
}
private void makeColorArray() {
colorArray = new Color[mapHi][mapWd]; // resetting the color-array
for(int i = 0; i < mapHi; i++) {
for(int j = 0; j < mapWd; j++) {
colorArray[i][j] = new Color(map.getRGB(j, i));
}
}
}
//color-array used by paint to paint the world
public void paint(Graphics2D g2d, float camX, float camY) {
for(int i = 0; i < mapHi; i++) {
for(int j = 0; j < mapWd; j++) {
if(colorArray[i][j].getRed() == 38 && colorArray[i][j].getGreen() == 127 && colorArray[i][j].getBlue() == 0) {
//draw Image 1
}
else if(colorArray[i][j].getRed() == 255 && colorArray[i][j].getGreen() == 0 && colorArray[i][j].getBlue() == 0) {
//draw Image 2
}
}
}
}
public void levelChanger(Player player, Enemies enemies) {
if(player.getRec().intersects(checkPoint[0])) {
map = map2;
//calls the color-array maker
makeColorArray();
}
else if(player.getRec().intersects(checkPoint[1])) {
map = map3;
makeColorArray();
}
}
public void update(Player player, Enemies enemies) {
levelChanger(player, enemies);
}
}
The makeColorArray() method makes a 2d array of type 'Color'. This array stores Color-objects from a PNG image. This array is used by the paint() method of the JPanel to paint the world on the screen.
The levelChanger() method is used to change the levels (stages) of the game when certain codition is true. It is the method which calls the makeColorArray() method to re-make the color-array while changing game-level.
The problem is that I have a game-loop which runs on a Thread. Now, the painting of swing components like JPanel is done on a different background thread by java. When the game-level is being changed, the color-array object is re-made. Now, like I previously said, the color-array object is used by the paint() method to paint the world on the screen. Sometimes, the color-array object is still being used by the background Thread (not finished painting) when, according to game logic, color-array object is re-made and its members set to null. This is causing a null-pointer exception, only sometimes. Clearly a race condition.
I want to know how can i stop my game thread from resetting the color-array until the background swing thread has finished painting.
Suggestions:
paintComponent(...)
method, not its paint(...)
method, and that you call the super method.paintComponent(...)
method for efficiency.repaint()
calls, are called on the Swing event thread.One way with minimal changes is to synchronize access to the color array.
I personally would have the shared data abstracted out to an individual class which is completely thread-safe, that way you wouldn't have to make sure two separate parts of the code base both have to know what to synchronize on (it seems like your class here does more than just handle the map at first glance, perhaps it is such a class that I am describing though).
private void makeColorArray() {
Color[][] colorArrayTemp = new Color[mapHi][mapWd]; // resetting the color-array
for(int i = 0; i < mapHi; i++) {
for(int j = 0; j < mapWd; j++) {
colorArrayTemp [i][j] = new Color(map.getRGB(j, i));
}
}
synchronized(colorArray)
{
colorArray = colorArrayTemp;
}
}
//color-array used by paint to paint the world
public void paint(Graphics2D g2d, float camX, float camY) {
synchronized(colorArray)
{
for(int i = 0; i < mapHi; i++) {
for(int j = 0; j < mapWd; j++) {
if(colorArray[i][j].getRed() == 38 && colorArray[i][j].getGreen() == 127 && colorArray[i][j].getBlue() == 0) {
//draw Image 1
}
else if(colorArray[i][j].getRed() == 255 && colorArray[i][j].getGreen() == 0 && colorArray[i][j].getBlue() == 0) {
//draw Image 2
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With