1

Whenever I run my program I get this error:

Exception in thread "Thread-2" java.lang.NullPointerException
    at ca.wamlab.game.entities.Player.tick(Player.java:20)
    at ca.wamlab.game.level.Level.tick(Level.java:38)
    at ca.wamlab.game.Game.tick(Game.java:169)
    at ca.wamlab.game.Game.run(Game.java:112)
    at java.lang.Thread.run(Thread.java:744)

Ignore all but the first at because all of them are because of that one.

I get that error in the following code:

package ca.wamlab.game.entities;

import ca.wamlab.game.InputHandler;
import ca.wamlab.game.gfx.Colors;
import ca.wamlab.game.gfx.Screen;
import ca.wamlab.game.level.Level;

public class Player extends Mob{

private InputHandler input;
private int color = Colors.get(-1, 111, 145, 543);

public Player(Level level, int x, int y, InputHandler input) {
    super(level, "Player", x, y, 1);
}

    public void tick() {
        int xa = 0;
        int ya = 0;
        if(input.up.isPressed()){
            ya--;
        }
        if(input.down.isPressed()){
            ya++;
        }
        if(input.right.isPressed()){
            xa++;
        }
        if(input.left.isPressed()){
            xa--;
        }


        if (xa != 0 || ya != 0){
            move(xa, ya);
            isMoving = true;
        }else{
            isMoving = false;
        }
    }

    public void render(Screen screen) {
        int xTile = 0;
        int yTile = 28;

        int modifier =  8*scale;
        int xOffset = x - modifier/2;
        int yOffset = y - modifier /2-4;

        screen.render(xOffset, yOffset, xTile + yTile * 32, color);
        screen.render(xOffset + modifier, yOffset, (xTile + 1) + yTile * 32, color);

        screen.render(xOffset, yOffset + modifier, xTile + (yTile + 1) * 32, color);
        screen.render(xOffset + modifier, yOffset + modifier, (xTile + 1) + (yTile + 1) *      32, color);


    }

    public boolean hasCollided(int xa, int ya) {
        return false;
    }

}

And the input class is:

package ca.wamlab.game;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class InputHandler implements KeyListener{

    public InputHandler(Game game) {
        game.addKeyListener(this);
    }

    public class Key {
        private int numTimesPressed;
        private boolean pressed = false;

        public int getNumTimesPressed(){
            return numTimesPressed;
        }

        public boolean isPressed(){
            return pressed;
        }
        public void toggle(boolean isPressed){
            pressed = isPressed;
            if(isPressed)numTimesPressed++;
        }
    }

    public Key up = new Key();
    public Key down = new Key();
    public Key right = new Key();
    public Key left = new Key();

    public void keyTyped(KeyEvent e) {
    }

    public void keyPressed(KeyEvent e) {
        toggleKey(e.getKeyCode(), true);
    }

    public void keyReleased(KeyEvent e) {
        toggleKey(e.getKeyCode(), false);
    }

    public void toggleKey(int keyCode, boolean isPressed){
        if(keyCode == KeyEvent.VK_W  || keyCode == KeyEvent.VK_UP){ up.toggle(isPressed);}
        if(keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN){ down.toggle(isPressed);}
        if(keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT){ right.toggle(isPressed);}
        if(keyCode == KeyEvent.VK_A || keyCode == KeyEvent.VK_LEFT){left.toggle(isPressed);}




    }
}

I know I get this because of the fact that something in the code is set to null (I think it is the ispressed()) but I can't figure out a way to fix it...

Wamlab
  • 23
  • 7
  • 2
    Where exactly is line 20? – BitNinja Jul 01 '14 at 23:23
  • I think you are having a thread race. What do you think about that? It would explain the null from anyone of your values that are not declared before the race condition started. – RedRumming Jul 01 '14 at 23:30
  • 1
    Sorry line 20 is if(input.up.isPressed()){ – Wamlab Jul 01 '14 at 23:43
  • Could you see in debug if it is `input` or `input.up` that is `null`? Could you provide the entire `Player` class implementation, so we can track the `input` assignments? Are you using any not mentioned engines? – falsarella Jul 02 '14 at 00:02
  • In that case it means that `input` is null. – BitNinja Jul 02 '14 at 00:02
  • @BitNinja Oh input refers to InputHandler Input = new InputHander; I think that IsPressed is null but i cant figure out how to fix that. All that i can think is that When you press a key, it runs IsPressed it returns pressed meaning the button is pressed down. i cant seem to see an error in there. – Wamlab Jul 02 '14 at 00:08
  • 1
    @Wamlab isPressed is a method that returns boolean. It can never return null, if that is what you mean by 'isPressed is null'. – madhav-turangi Jul 02 '14 at 00:12
  • Please read this Answer on how to debug a NullPointerException: http://stackoverflow.com/a/24347569/139985 – Stephen C Jul 02 '14 at 00:13
  • @Wamlab - And even if `isPressed()` could return `null`, that would not result in a NPE ... in this context. In order to debug this you need to understand what *causes* the JVM to throw an NPE, and use that to *reason* about what is / could be happening in your code. Pulling random diagnoses out of the air will not help. You need to *think* about it. – Stephen C Jul 02 '14 at 00:20
  • There is another recent post that contains almost the same code, though different question. http://stackoverflow.com/questions/16802805/my-simple-key-listener-isnt-working-it-doesnt-seem-to-toggle-the-pressed-bool?rq=1 . Have a look if that helps. – madhav-turangi Jul 02 '14 at 00:45
  • 1
    @Wamlab - That was not intended to be snarky. It was meant to point out that your approach to debugging is flawed. I didn't just mean "think about" in the sense of "try hard". I meant "think about it" in the sense of "use sound logical deduction". Clearly, stuff like *"I think that IsPressed is null ..."* is not logical. It is a purely intuitive statement that is not supported by any facts or (sound) logical reasoning / inference. (In fact, it is contradicted by at least two facts that we do know to be true.) – Stephen C Jul 02 '14 at 00:52
  • @StephenC Im sorry if i was rude also... I really am trying to figure this out. – Wamlab Jul 02 '14 at 00:58
  • @Wamlab - Now, you could ignore me and continue with your current "intuitive" approach. But you won't end up as a productive programmer ... – Stephen C Jul 02 '14 at 01:02
  • @Wamlab - Oh ... and read the link I posted above. It is intended to be helpful. – Stephen C Jul 02 '14 at 01:03

1 Answers1

2

The instance variables up, down, right, left in InputHandler class are initialized with

public Key up = new Key();
public Key down = new Key();
public Key right = new Key();
public Key left = new Key();

If input is a reference variable of InputHandler and an object of InputHandler is assinged to it, then the up, down, right and left can never be null based on above code. Therefore based on confirming the line 20 is if(input.up.isPressed()){ most possibly input is null.

It will help us help you, if you can provide code where InputHander input is assigned an object if anywhere done so. Where in the code the key listener registered using addKeyListenter() method? And also the provided tick() method belongs to which class?

From stacktrace it is evident that all three Player, Level and Game classes have method with same name tick()

at ca.wamlab.game.entities.Player.tick(Player.java:20)
    at ca.wamlab.game.level.Level.tick(Level.java:38)
    at ca.wamlab.game.Game.tick(Game.java:169)

Many important details are unknown to help with this. More details would be helpful.

madhav-turangi
  • 341
  • 2
  • 13
  • The Game Tick Method Calls to the Level Tick MEthod Which calls to the player tick method where the NPE is occuring – Wamlab Jul 02 '14 at 00:49
  • The Main (game) Tick Method public void tick(){ tickCount++; level.tick(); } – Wamlab Jul 02 '14 at 00:52
  • @Wamlab then the `input` is possibly null. Where is the `input` assigned with `InputHandler` object? – madhav-turangi Jul 02 '14 at 00:53
  • The Level Tick Method: public void tick(){ for (Entity e : entities){ e.tick(); } } – Wamlab Jul 02 '14 at 00:53
  • 1
    In the constructor `public Player(Level level, int x, int y, InputHandler input) {` the `input` argument is not assigned to the instance variable input. You need to add `this.input = input;` after `super(level, "Player", x, y, 1);` inside constructor. – madhav-turangi Jul 02 '14 at 00:58
  • well while that fixed that it led to a whole other problem – Wamlab Jul 02 '14 at 01:05
  • Exception in thread "Thread-2" java.lang.StackOverflowError at ca.wamlab.game.gfx.Screen.render(Screen.java:30) x 50 – Wamlab Jul 02 '14 at 01:06
  • That possibly means the Screen render method has gone into infinite recursion. What does Screen render method do? – madhav-turangi Jul 02 '14 at 01:12
  • 1
    @Wamlab - Do this logically. Read the stacktrace. Read the source code. what is calling what? How does this get the stacktrace you are seeing? Why is that wrong with your code that would cause that? You need to learn to do this yourself ... – Stephen C Jul 02 '14 at 01:14
  • @StephenC Okay! I fixed it! thanks for the help you too madhav – Wamlab Jul 02 '14 at 01:36