在2D游戏线程中获取NPE

时间:2013-12-12 04:54:12

标签: java nullpointerexception

当我运行这个非常基本的2D游戏时,我不断获得NPE。它与关键事件有关,但我不知道如何解决这个问题。有人能帮我吗?它说NPE就在这一行if (_input.up.isPressed()) {

这是InputHandler类

public class InputHandler implements KeyListener {

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

    public class Key {
        private boolean pressed = false;

        public void toggle(boolean isPressed) {
            pressed = isPressed;
        }

        public boolean isPressed() {
            return pressed;
        }
    }

    // public List<Key> keys = new ArrayList<Key>();
    public Key up = new Key();
    public Key down = new Key();
    public Key left = new Key();
    public Key right = new Key();

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

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

    public void keyTyped(KeyEvent e) {

    }

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

这是播放器类

public class Player extends Mob {

    private InputHandler _input;
    private int _speed;
    private int _r = 10;
    private int _x, _y;

    public Player(int x, int y, int speed, InputHandler input) {
        super("Player", x, y, 1);
        _input = input;
        _speed = speed;
        _x = x;
        _y = y;
    }

    public boolean hasCollided(int dx, int dy) {
        return false;
    }

    public void update() {
        int dx = 0;
        int dy = 0;

        if (_input.up.isPressed()) {
            dy--;
        } else if (_input.down.isPressed()) {
            dy++;
        } else if (_input.left.isPressed()) {
            dx--;
        } else if (_input.right.isPressed()) {
            dx++;
        }

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

        if (_x < _r)
            _x = _r;
        if (_y < _r)
            _y = _r;
        if (_x > Game.WIDTH - _r)
            _x = Game.WIDTH - _r;
        if (_y > Game.HEIGHT - _r)
            _y = Game.HEIGHT - _r;
    }

    public void render(Graphics2D g) {
        g.setColor(Color.BLACK);
        g.fillOval(x - _r, y - _r, 2 * _r, 2 * _r);

        g.setStroke(new BasicStroke(3));
        g.setColor(Color.GRAY);
        g.drawOval(x - _r, y - _r, 2 * _r, 2 * _r);
        g.setStroke(new BasicStroke(1));
    }
}

这是创建播放器的游戏类

public class Game extends Canvas implements Runnable {

    private static Game _instance;
    private static final String TITLE = "ProjectG";
    public static final int WIDTH = 960;
    public static final int HEIGHT = WIDTH * 3 / 4;
    private static final int SCALE = 1;
    // to make it have a higher resolution double the width and height but half
    // the scale. You are doubling the width and height but keeping the same
    // window size by reducing the scale
    public static final Dimension SIZE = new Dimension(WIDTH * SCALE, HEIGHT * SCALE);

    private static final int UPDATE_RATE = 60;
    private static final int RENDER_RATE = 60;

    private JFrame _frame;
    private Thread _thread;
    private boolean _running = false;

    private int _tps = 0;
    private int _fps = 0;
    private int _totalTicks = 0;

    private BufferedImage image;
    private Graphics2D g;
    public InputHandler input;

    private Player player;

    public Game() {
        _instance = this;

        setPreferredSize(SIZE);
        setMinimumSize(SIZE);
        setMaximumSize(SIZE);

        _frame = new JFrame(TITLE);
        _frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        _frame.setLayout(new BorderLayout());
        _frame.add(_instance, BorderLayout.CENTER);
        _frame.pack();

        _frame.setResizable(false);
        _frame.setLocationRelativeTo(null);
        _frame.setVisible(true);

        player = new Player(Game.WIDTH / 2, Game.HEIGHT / 2, 1, input);
    }

    public synchronized void start() {
        _running = true;
        _thread = new Thread(this, TITLE + "_main");
        _thread.start();
    }

    public synchronized void stop() {
        _running = false;

        if (_thread != null) {
            try {
                _thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void run() {
        double lastUpdateTime = System.nanoTime();
        double lastRenderTime = System.nanoTime();

        final int ns = 1000000000;
        final double nsPerUpdate = (double) ns / UPDATE_RATE;
        final double nsPerRender = (double) ns / RENDER_RATE;
        final int maxUpdatesBeforeRender = 1;

        int lastSecond = (int) lastUpdateTime / ns;
        int tickCount = 0;
        int renderCount = 0;

        image = new BufferedImage(WIDTH * SCALE, HEIGHT * SCALE, BufferedImage.TYPE_INT_RGB);
        g = (Graphics2D) image.getGraphics();

        while (_running) {
            long currTime = System.nanoTime();
            int tps = 0;

            while ((currTime - lastUpdateTime) > nsPerUpdate && tps < maxUpdatesBeforeRender) {
                update();
                tickCount++;
                _totalTicks++;
                tps++;
                lastUpdateTime += nsPerUpdate;
            }

            if (currTime - lastUpdateTime > nsPerUpdate) {
                lastUpdateTime = currTime - nsPerUpdate;
            }

            float interpolation = Math.min(1.0F, (float) ((currTime - lastUpdateTime) / nsPerUpdate));
            render(interpolation);
            draw();
            renderCount++;
            lastRenderTime = currTime;

            int currSecond = (int) (lastUpdateTime / ns);
            if (currSecond > lastSecond) {
                _tps = tickCount;
                _fps = renderCount;
                tickCount = 0;
                renderCount = 0;
                lastSecond = currSecond;
                System.out.println(_tps + " TPS " + _fps + " FPS");
            }

            while (currTime - lastRenderTime < nsPerRender && currTime - lastUpdateTime < nsPerUpdate) {
                Thread.yield();
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                currTime = System.nanoTime();
            }
        }
    }

    public void update() {
        player.update();
    }

    public void render(float interpolation) {
        BufferStrategy bs = getBufferStrategy();
        if (bs == null) {
            createBufferStrategy(3);
        }

        g.setColor(Color.WHITE);
        g.fillRect(0, 0, WIDTH * SCALE, HEIGHT * SCALE);
        g.setColor(Color.BLACK);
        g.drawString("TPS: " + _fps + " FPS: " + _fps, 10, 20);

        player.render(g);
    }

    public void draw() {
        Graphics g2 = this.getGraphics();
        g2.drawImage(image, 0, 0, null);
        g2.dispose();
    }

    public Game getGame() {
        return this;
    }
}

1 个答案:

答案 0 :(得分:0)

您尚未初始化input,因此您传递给

player = new Player(Game.WIDTH / 2, Game.HEIGHT / 2, 1, input);

null。你需要在

之前初始化它
input = new InputHandler(this);