1

I'm making a maze game using tiles. The maze changes shape in regular intervals. At this time the tilearray gets empty before the maze recreates. I'm getting NPE errors after different intervals and after a while the game stops. Probably because some methods tries to access before it is actually recreated. I tried to put if(... !=null) in some places and even tried to synchronize some part (which I'm not really familiar with).

Edit: Thank you for Arvind for pointing out the problem. I managed to fix it but I would still appriciate some more help as it is not the best and most neat fix I think. Tile t was equal to null at some cases. I simply just checked it and put a continue; into the for loop to avoid the error.

Thank you very much for any help and advice in advance!

With this error the game still runs:

Exception in thread "AWT-EventQueue-1" java.lang.NullPointerException
at shiftingmaze.Game.paintTiles(Game.java:161)
at shiftingmaze.Game.paint(Game.java:115)
at shiftingmaze.Game.update(Game.java:107)
at sun.awt.RepaintArea.updateComponent(Unknown Source)
at sun.awt.RepaintArea.paint(Unknown Source)
at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$400(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

And after a while it freezes with this error:

Exception in thread "Thread-4" java.lang.NullPointerException
at shiftingmaze.Game.updateTiles(Game.java:153)
at shiftingmaze.Game.run(Game.java:86)
at java.lang.Thread.run(Unknown Source)

Here is some parts of the code:

@Override
public void start() {

    hero = new Hero();

    Timer t = new Timer();

    t.scheduleAtFixedRate(new TimerTask() {
        public void run() {
            tilearray.clear();
            shiftMaze();
        }
    }, 0, 1000);

    Thread thread = new Thread(this);
    thread.start();
}

@Override
public void stop() {

}

@Override
public void destroy() {

}

@Override
public void run() {

    while (true) {
        hero.update();
        updateTiles();
        repaint();
        try {
            Thread.sleep(17);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

@Override
public void update(Graphics g) {

    if (image == null) {
        image = createImage(this.getWidth(), this.getHeight());
        second = image.getGraphics();
    }

    second.setColor(getBackground());
    second.fillRect(0, 0, getWidth(), getHeight());
    second.setColor(getForeground());
    paint(second);
    g.drawImage(image, 0, 0, this);
}

@Override
public void paint(Graphics g) {

    g.drawImage(background, 0, 0, this);
    paintTiles(g);
    // g.drawRect((int)Hero.rect.getX(), (int)Hero.rect.getY(),
    // (int)Hero.rect.getWidth(), (int)Hero.rect.getHeight());
    // g.drawRect((int)Hero.bigRect.getX(), (int)Hero.bigRect.getY(),
    // (int)Hero.bigRect.getWidth(), (int)Hero.bigRect.getHeight());
    g.drawImage(character, hero.getHeroX(), hero.getHeroY(), this);
}

public void shiftMaze() {

    final int MAZEROW = 24;
    final int MAZECOL = 40;

    for (int i = 0; i < MAZEROW * MAZECOL / 2; i++) {
        int n = rand.nextInt(MAZECOL - 2) + 1;
        int m = rand.nextInt(MAZEROW - 2) + 1;
        if (!(n == 1 && m == 1) && !(n == MAZECOL - 2 && m == MAZEROW - 2)) {
            Tile t = new Tile(n, m);
            tilearray.add(t);
        }
    }

    for (int i = 0; i < MAZECOL; i++) {
        for (int j = 0; j < MAZEROW; j++) {
            if (i == 0 || i == MAZECOL - 1 || j == 0 || j == MAZEROW - 1)
                if (!(i == 1 && j == 0)
                        && !(i == MAZECOL - 2 && j == MAZEROW - 1)) {
                    Tile t = new Tile(i, j);
                    tilearray.add(t);
                }
        }
    }
}

public void updateTiles() {

    for (int i = 0; i < tilearray.size(); i++) {
        Tile t = (Tile) tilearray.get(i);
        t.update();
    }
}

public void paintTiles(Graphics g) {

    for (int i = 0; i < tilearray.size(); i++) {
        Tile t = (Tile) tilearray.get(i);
        g.drawImage(t.getTileImage(), t.getTileX(), t.getTileY(), this);
    }
}

This is from the Tile class:

public Tile(int x, int y) {

    tileX = x * 20;
    tileY = y * 20;
    tileImage = Game.getWall();

    r = new Rectangle();
}

public void update() {

    r.setBounds(tileX, tileY, 20, 20);
    if (r.intersects(Hero.bigRect))
        checkCollision(Hero.rect);
}
Kokufuu
  • 29
  • 6
  • please check if Tile is null here: `Tile t = (Tile) tilearray.get(i);` inside the method updateTiles() –  Aug 30 '14 at 06:48
  • Where is `tilearray` declared and initialized? Maybe this is null. Try to debug your code. – Jens Aug 30 '14 at 06:51
  • @Arvind: I checked and yes, it is null when it throws AWT-EventQueue-1 – Kokufuu Aug 30 '14 at 08:00
  • @Jens: At the very beginning, before init() private ArrayList tilearray = new ArrayList(); – Kokufuu Aug 30 '14 at 08:04
  • @Kokufuu where do you call `shiftMaze´? – Jens Aug 30 '14 at 08:05
  • @Jens: as you can see above at start() after tilearray.clear(); inside the Task timer – Kokufuu Aug 30 '14 at 08:24
  • possible duplicate of [What is a Null Pointer Exception, and how do I fix it?](http://stackoverflow.com/questions/218384/what-is-a-null-pointer-exception-and-how-do-i-fix-it) – DavidPostill Aug 30 '14 at 08:33
  • @Arvind: Thank you for pointing out the problem. I fixed it with a continue; but I know it is not the neatest way. Any other suggestion to fix it in the right way? – Kokufuu Aug 30 '14 at 15:08

2 Answers2

0

The problem is here:

public void updateTiles() {
    for (int i = 0; i < tilearray.size(); i++) {
        Tile t = (Tile) tilearray.get(i);//<-- tile is null in some cases
        t.update();
    }
}

There are many options to avoid this:

Option 1: Sub-class ArrayList and override the method add() and addAll() with null check.

Option 2: After populating the tilearray, remove the null values by using this line

    tilearray.removeAll(Collections.singleton(null));

EDIT

If you are looking for second option then you should try this:

public void shiftMaze() {
    //<-- to do here
    tilearray.removeAll(Collections.singleton(null));//<-- at the end
}
  • where should I actually insert it? I tried it but still receiving errors... after the shiftMaze() method? this is where it is getting populated after clearing it. – Kokufuu Aug 31 '14 at 06:51
  • Thank you! I'm still getting errors but at least I know where to search it. I checked the number of elements removed with removeAll after populating the array and it is always 0. So the problem is somewhere after this. With my solution below the game can still run, calling shiftMaze hundreds of times before it freezes. – Kokufuu Sep 01 '14 at 06:30
  • I have found the solution. I called the updateTiles inside run() and paintTiles() inside paint() so they interfered with each other randomly. Now both are called inside paint() after eachother. I made a test, called shiftMaze() 500000 times and only got 28 NPE which were solved with the checking posted in the 2nd answer. – Kokufuu Sep 02 '14 at 08:38
0

Thank you for your help, I tried that one but it still gets some nulls. In the meanwhile I made the following to get rid of the error. It works ALMOST all the time but very rarely I still get NPE or Index out of bounds error... I speeded up the game to 100 millisec recreation to get the error check in a long term.

for (int i = 0; i < tilearray.size(); i++) {
    Tile t = (Tile) tilearray.get(i);
    if (t == null && i < tilearray.size() - 1) {
        System.out.println("t = null @ updateTiles(), moving to next element");
        continue;
    }
    if (t == null && i >= tilearray.size()) {
        System.out.println("t = null @ updateTiles(), no elements left");
        break;
    }
    t.update();
Kokufuu
  • 29
  • 6