无法识别NullPointerException的来源

时间:2018-06-29 22:25:15

标签: nullpointerexception

所以我遇到以下错误:

Exception in thread "Thread-0" java.lang.NullPointerException
at dev.tamir.firstgame.entities.creatures.Player.getInput(Player.java:19)
at dev.tamir.firstgame.entities.creatures.Player.tick(Player.java:31)
at dev.tamir.firstgame.states.GameState.tick(GameState.java:25)
at dev.tamir.firstgame.Game.tick(Game.java:65)
at dev.tamir.firstgame.Game.run(Game.java:110)
at java.lang.Thread.run(Unknown Source)

我已经检查了Java标记过我的所有行,但找不到导致null的原因。

玩家:

    package dev.tamir.firstgame.entities.creatures;

import java.awt.Graphics;

import dev.tamir.firstgame.Game;
import dev.tamir.firstgame.gfx.Assets;

public class Player extends Creature {

    private Game game;
    public Player(Game game, float x, float y) {
        super(game, x, y, Creature.DEFAULT_CREATURE_WIDTH, Creature.DEFAULT_CREATURE_HEIGHT);
    }

    @Override
    public void tick() {
        getInput();
        move();
        game.getGameCamera().centerOnEntity(this);
    }

        private void getInput() {
        xMove = 0;
        yMove = 0;

        if(game.getKeyManager().up)
            yMove = -speed;
        if(game.getKeyManager().down)
            yMove = speed;
        if(game.getKeyManager().left)
            xMove = -speed;
        if(game.getKeyManager().right)
            xMove = speed;
    }

    @Override
    public void render(Graphics g) {
        g.drawImage(Assets.robro[7], (int) (x - game.getGameCamera().getxOffset()), (int) (y - game.getGameCamera().getyOffset()), width, height, null);
    }

}

游戏状态:

   package dev.tamir.firstgame.states;

import java.awt.Graphics;

import dev.tamir.firstgame.Game;
import dev.tamir.firstgame.entities.creatures.Player;
import dev.tamir.firstgame.tiles.Tile;
import dev.tamir.firstgame.worlds.World;

public class GameState extends State {

    private Player player;
    private World world;

    public GameState(Game game) {
        super(game);
        player = new Player(game, 0, 0);
        world = new World(game, "res/worlds/world1.txt");

    }

    @Override
    public void tick() {
        world.tick();
        player.tick();
    }

    @Override
    public void render(Graphics g) {
        world.render(g);
        player.render(g);
    }

}

游戏:

package dev.tamir.firstgame;

import java.awt.Graphics;
import java.awt.image.BufferStrategy;

import dev.tamir.firstgame.Display.Display;
import dev.tamir.firstgame.gfx.Assets;
import dev.tamir.firstgame.gfx.GameCamera;
import dev.tamir.firstgame.input.KeyManager;
import dev.tamir.firstgame.states.GameState;
import dev.tamir.firstgame.states.MenuState;
import dev.tamir.firstgame.states.State;

public class Game implements Runnable {

    private Display display;
    private Thread thread;


    private BufferStrategy bs;
    private Graphics g;

    //States
    private State gameState;
    private State menuState;

    //Input
    private KeyManager keyManager;

    //Camera
    private GameCamera gameCamera;

    private boolean running = false;

    private int width, height;
    public String title;



    public Game(String title, int width, int height) {
        this.width = width;
        this.height = height;
        this.title = title;
        keyManager = new KeyManager();
    }

    private void init() {
        display = new Display(title, width, height);
        display.getFrame().addKeyListener(keyManager);
        Assets.init();

        gameCamera = new GameCamera(this, 0,0);

        gameState = new GameState(this);
        menuState = new MenuState(this);
        State.setState(gameState);
    }



    private void tick() {
        keyManager.tick();

        if(State.getState() != null)
            State.getState().tick();
    }

    private void render() {
        bs = display.getCanvas().getBufferStrategy();
        if(bs == null) {
            display.getCanvas().createBufferStrategy(3);
            return;
        }
        g = bs.getDrawGraphics();
        //Clear
        g.clearRect(0, 0, width, height);
        //Draw

        if(State.getState() != null)
            State.getState().render(g);

        //End of Draw

        bs.show();
        g.dispose();


    }

    public void run() {

        init();

        int fps = 60;
        double timePerTick = 1000000000 / fps;
        double delta = 0;
        long now;
        long lastTime = System.nanoTime();
        long timer = 0;
        int ticks = 0;

        while (running) {

            now = System.nanoTime();
            delta +=  (now - lastTime) / timePerTick;
            timer += now - lastTime;
            lastTime = now;

            if(delta >= 1) {
            tick();
            render();
            ticks++;
            delta--;
            }
            if(timer >= 1000000000) {
                System.out.println("FPS: " + ticks );
                ticks = 0;
                timer = 0; 
            }
        }

        stop();

    }

    public KeyManager getKeyManager() {
        return keyManager;
    }

    public GameCamera getGameCamera() {
        return gameCamera;
    }

    public int getWidth() {
        return width;
    }

    public int getHeight() {
        return height;
    }

    public synchronized void start() {
        if (running)
            return;
        running = true;
        thread = new Thread(this);
        thread.start();

    }

    public synchronized void stop() {
        if (!running)
            return;
        running = false;
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

我们将非常感谢您的帮助,因为我已经花了几个小时了,而且我不知道是什么原因导致了null,而且我怀疑错误日志甚至可能会误导我。

1 个答案:

答案 0 :(得分:0)

我的猜测是,您的生物类别中有一个私人游戏。当您在Player中调用super()时,会将Game对象传递给Creature。 Creature构造函数很可能具有this.game = game;

这样的行

当然,我不能肯定地说,因为您的帖子中未包含Creature类,但这是最有可能的代码设置。因为游戏将对Creature专有,所以Player无法看到它。这意味着您在Player中声明的private Game game从未设置。

呼叫超级之后,执行this.game = game;

这几乎可以肯定会解决您的问题。

仅供参考,您将在错误产生时得到的消息是调用堆栈;基本上,它告诉您什么方法称为什么,最近的是最上面的。错误发生在Player.getInput()的第19行,该错误由tick()在同一类中调用。 您在getInput()中使用的唯一对象是game,因此该对象必须是空指针的源。从那里开始,快速检查一下gamePlayer的私有字段,由于它为null,这是巨大的线索,表明它从未初始化(尽管并非总是如此)。私有字段通常是在类构造函数中初始化的(但是它们不必一定是...您的Player类是稀疏的,因此如果您绝对拥有,则无需花太多时间浏览所有私有字段)观察Player构造函数,我们看到传入了名为游戏的Game对象,这表明该对象旨在用于初始化game,但从未如此。我们发现了问题!

很遗憾,如果最后一段觉得有点赞成;这本来不是。我只是想向您介绍如何找到您的问题。希望知道我是如何找到它的,可以帮助您自己以后发现错误。