Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

[java] 2D tilemap array animation problems

Started by Caol Oct 19, 2008 at 5:31 AM 4 replies 2.2k views
Original Post
Caol
Caol
The setup: I am trying to render an updating tilemap to the screen as part of an animation loop. The tilemap is a 2D array of Tile class objects ( Tile[][] tilemap = ...). The animation loop takes places in the run() method of a main class that implements Runnable and extends JPanel. Inside the run() method there are 3 methods, in the following order: update(), render(), paintScreen() The update() method updates the tilemap 2D array by shifting all tiles in the array left, right, up or down and adding new tiles, depending on the characters direction of movement. The render() method draws all game elements to an offscreen Graphics object, including the drawing of the complete tilemap object. The paintScreen() method actively renders the buffered image to the screen. It does this by getting a fresh reference to the panel's graphics context each time (this.getGraphics()) and also ensures that the display is properly sync'ed (Toolkit.getDefaultToolkit().sync()), which is necessary because I am developing on Linux, which doesn't automatically flush it's display buffer. The problem: As the player character (locked in the centre of the screen) walks around, the tilemap moves under them and correctly updates itself as the player crosses a tile boundary, as you would expect. The problem being that every-so-often (at seemingly irregular intervals) when the player crosses a tile boundary the tilemap seems to "jump" back by one tile and the forward again very rapidly. I have thoroughly and repeatedly examined and debugged both the update and the render code for the tilemap and am convinced it is correct. It is almost as if the render code is accessing an old version of the tilemap data structure - but how can this be if the update and the render are two discrete steps, one that follows another, both coming from the same thread and there are no other methods that access the tilemap array??? I can only think that maybe the JVM "schedules" the update of the 2D array and this sometimes get queued behind the next render call. If anyone has any insight into this problem at all then I'd be most grateful to hear it...
Addictman
Addictman
This looks like a problem we might be able to help with if you post some code :)
Development blog, The Omega Sector -- http://www.omegasector.org
Caol
Caol
I guess you're probably right. The problem with that is that the code is long and complex and spread over several classes. I thought it might be simpler to just give a written description of the problem. I will try to extract some simplified code that contains the problem succinctly. Who knows - that may even help me to solve my problem myself. I'll post back here when I've done that - but don't hold your breath!
Addictman
Addictman
I understand. These problems are rarely located in "easy" code, which is usually the reason for the bug in the first place ;)

Since only the update and render methods access the array, why not post those two methods, - perhaps we spot something you missed?
Development blog, The Omega Sector -- http://www.omegasector.org
Caol
Caol
Here is a simplified extract of the relevant code as promised:

public class mainPanel extends JPanel implements Runnable {    private Graphics doubleBufferedGraphics;     private Image doubleBufferedImage = null;    ....    public void run() {        ... // timing code        running = true;        while(running) {            gameUpdate();            gameRender();            paintScreen();	    ... // timing code	}        System.exit(0);    }    private void gameUpdate() {         world.update();    }    private void gameRender() {        if (doubleBufferedImage == null) {            doubleBufferedImage = createImage(PANEL_WIDTH, PANEL_HEIGHT);            doubleBufferedGraphics = doubleBufferedImage.getGraphics();        }        world.draw(doubleBufferedGraphics);    }    private void paintScreen() {        Graphics g;        try {            g = this.getGraphics();            if ((g != null) && (doubleBufferedImage != null)) {                g.drawImage(doubleBufferedImage, 0, 0, null);            }            Toolkit.getDefaultToolkit().sync();            g.dispose();        }        catch (Exception e)        { System.out.println("Graphics context error: " + e); }    }}public class World {    private Tile[][] currentTilemap;    ...    public void update() {        if(...) { // player is moving left            shiftTilemapRight();        }	...        // similar checks for player moving in other directions    }    private void shiftTilemapRight() {        for(int i=currentTilemap.length-1; i>=0; i--) {            for( int j=0; j<currentTilemap[0].length; j++) {                if(i==0) {                    currentTilemap[0][j] = getNextTile();                }                else {                    currentTilemap[j] = currentTilemap[i-1][j];                }            }        }    }    public void draw(Graphics g) {        for(int i=0; i<currentTilemap.length; i++) {            for(int j=0; j<currentTilemap[0].length; j++) {                int xDraw = ... // calculated from player's current position                int yDraw = ...                currentTilemap[j].display(g,xDraw,yDraw);            }        }    }}
Caol
Caol
I found the problem. It was in some code that I didn't include above that I thought was correct. Specifically in the update() method of the World class the following conditional statement:

public void update() {
if(...) { // player is moving left
shiftTilemapRight();
}

the conditional test was incorrect. I would go into details of exactly what was incorrect but the explanation relies on the detailed intricacies of the Player class and the mistake was just a simple oversight, so I don't think there is much to be learned from it other than read your code more carefully before pestering people on gamedev.net!

Thanks to anyone who had a look at this problem.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.