来自Scratch的2D自上而下Java(1.8)游戏(无)

时间:2014-10-19 20:23:59

标签: java intellij-idea error-handling nullpointerexception topdown

所以,首先这是我的第一次发帖,我正在尝试使用java(1.8)和IntelliJ进行自上而下的游戏,没有别的。我的所有代码都做得很好(为了让sprite显示出来),我测试它并且它一直给我错误消息说某些部分无效。它应该在屏幕右上方显示一个图像(字符),这里是所有代码,请记住,我没有完全完成这个:

Game.java

package main;

import main$entities.Player;
import main$gfx.ImageLoader;
import main$gfx.SpriteSheet;

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.lang.*;

public class Game extends Canvas implements Runnable {
    private static final long serialVersionUID = 1L;
    public static final int WIDTH = 700, HEIGHT = 400, SCALE = 1;
    public static boolean running = false;
    public Thread gameThread;

    private BufferedImage spriteSheet;

    private Player player;

    public void init(){
        ImageLoader loader = new ImageLoader();
        spriteSheet = loader.load("./spritesheet.png");

        SpriteSheet ss = new SpriteSheet(spriteSheet);

        player = new Player(0, 0, ss);
    }

    public synchronized void start(){
        if(running)return;
        running = true;
        gameThread = new Thread(this);
        gameThread.start();
    }
    public synchronized void stop(){
        if(!running)return;
        running = false;
        try {
            gameThread.join();
        } catch (InterruptedException e) {e.printStackTrace();}
    }

    public void run(){
        long lastTime = System.nanoTime();
        final double amountOfTicks = 60D;
        double ns = 1000000000 / amountOfTicks;
        double delta = 0;

        while(running){
            long now = System.nanoTime();
            delta += (now - lastTime) / ns;
            lastTime = now;
            if(delta >= 1){
                tick();
                delta--;
            }
            render();
        }
        stop();
    }
    public void tick(){
        player.tick();
    }
    public void render(){
        BufferStrategy bs = this.getBufferStrategy();
        if(bs == null){
            createBufferStrategy(3);
            return;
        }
        Graphics g = bs.getDrawGraphics();
        // Render Here

        g.fillRect(0, 0, WIDTH * SCALE, HEIGHT * SCALE);

        player.render(g);

        // End Render
        g.dispose();
        bs.show();
    }

    public static void main(String[] args){
        Game game = new Game();
        game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
        game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));

        JFrame frame = new JFrame("Tile RPG");
        frame.setSize(WIDTH *SCALE, HEIGHT * SCALE);
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setResizable(false);
        frame.add(game);
        frame.setVisible(true);

        game.start();
        }
    }

ImageLoader.java

package main$gfx;

import javax.imageio.ImageIO;

import java.awt.image.BufferedImage;
import java.io.IOException;

public class ImageLoader {

    public BufferedImage load(String path){
        try {
            return ImageIO.read(getClass().getResource(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}

SpriteSheet.java

package main$gfx;

import java.awt.image.BufferedImage;

public class SpriteSheet {

    private BufferedImage sheet;

    public SpriteSheet(BufferedImage sheet){
        this.sheet = sheet;
    }

    public BufferedImage crop(int col, int row, int w, int h){
        return sheet.getSubimage(col * 16, row * 16, w, h);
    }

}

Player.java

package main$entities;

import main.Game;
import main$gfx.SpriteSheet;

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

public class Player implements KeyListener{

    private int x, y;
    private SpriteSheet ss;
    private boolean up = false, dn = false, lt = false, rt = false;
    private final int SPEED = 3;

    public Player(int x, int y, SpriteSheet ss){
        this.x = x;
        this.y = y;
        this.ss = ss;
    }

    public void tick(){
        if(up){
            y -= SPEED;
        }
        if(dn){
            y += SPEED;
        }
        if(lt){
            x -= SPEED;
        }
        if(rt){
            x += SPEED;
        }
    }

    public void render(Graphics g){
        g.drawImage(ss.crop(0 ,0, 16, 16), x, y, 16 * Game.SCALE, 16 * Game.SCALE, null);
    }

    public void keyTyped(KeyEvent e) {}

    public void keyPressed(KeyEvent e) {

    }

    public void keyReleased(KeyEvent e) {

    }
}

错误消息(它给了我多条消息,每次都不同// =该行上的内容,所以你不必通过计数,欢迎来找到它):

我第一次运行Game.java:

Exception in thread "Thread-2" java.lang.NullPointerException
    at main.Game.tick(Game.java:64)    // player.tick();
    at main.Game.run(Game.java:56)    // tick();
    at java.lang.Thread.run(Thread.java:745)    // this is in the JDK itself

Process finished with exit code 0

第二次(以及所有这些)我运行Game.java的时间:

Exception in thread "Thread-2" java.lang.NullPointerException
    at main.Game.render(Game.java:77)    // player.render(g);
    at main.Game.run(Game.java:59)    // render();
    at java.lang.Thread.run(Thread.java:745)    // this is in the JDK itself

Process finished with exit code 0

2 个答案:

答案 0 :(得分:2)

game.start();承担全部责任。您的Game类没有扩展线程,线程本身将在您实例化game's类后立即自动启动,因为线程是在游戏类中创建的。 所以删除:

game.start();

顺便说一句,你陷入陷阱:

public static final int WIDTH = 700, HEIGHT = 400;

无效,因为这些字段会隐藏其他字段,为什么?因为

WIDTH& HEIGHT

的保留参数
.fillRect(...);

答案 1 :(得分:1)

这是因为你从不调用init()方法,因此玩家和精灵表永远不会被创建

您可以像这样在Game类中添加构造函数:

public Game() {
    init();
}

或者您可以在main方法中添加以下行:

public static void main(String[] args){
    Game game = new Game();
    game.setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
    game.setMaximumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
    game.setMinimumSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));

    JFrame frame = new JFrame("Tile RPG");
    frame.setSize(WIDTH *SCALE, HEIGHT * SCALE);
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.setResizable(false);
    frame.add(game);
    frame.setVisible(true);

    // Add this line
    game.init();        

    game.start();
    }
} 

但我更喜欢第一种方式