nullpointerexception - 无法识别 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,我怀疑错误日志甚至可能误导我。
解决方案
我的猜测是你的生物类中有一个私人游戏。当你在 Player 中调用 super() 时,你将一个 Game 对象传递给 Creature。Creature 构造函数很可能有这样一行this.game = game;
当然,我不能肯定地说,因为 Creature 类不包含在您的帖子中,但这是最有可能的代码设置。因为游戏将是 Creature 私有的,所以玩家无法看到它。这意味着private Game game
您在 Player 中声明的 永远不会设置。
在你打电话给超级之后,做this.game = game;
这几乎肯定会解决您的问题。
仅供参考,您在错误导致时收到的消息是调用堆栈;基本上它告诉你什么方法叫什么,最近的在顶部。错误发生在第 19 行,在同一个类Player.getInput()
中被调用。tick()
您在其中使用的唯一对象getInput()
是game
,因此它必须是空指针的来源。从那里,可以快速检查它game
是否是 的私有字段Player
,并且由于它为 null,这是一个巨大的线索,表明它从未被初始化(尽管情况并非总是如此)。私有字段通常在类构造函数中初始化(但它们不必是......你的Player
类非常稀少,因此如果您绝对必须查看所有内容,则不会花费那么长时间。查看Player
构造函数,我们看到Game
传入了一个名为 game 的对象,这表明它旨在用于初始化game
,但从来没有。瞧,我们发现了问题!
如果最后一段感觉有点居高临下,我很抱歉;这不是故意的。我只是想告诉你我是如何发现你的问题的。希望知道我是如何找到它的,这将帮助您自己发现以后的错误。