0

所以,首先这是我第一次发帖,我正在尝试用 java(1.8) 和 IntelliJ 制作一个自上而下的游戏,仅此而已。我的所有代码都已做好并已完成(用于显示精灵),我对其进行了测试,但它不断给我错误消息,指出某些部分无效。它应该在右上角的屏幕上显示一个图像(字符),这里是所有代码,请记住,我还没有完全完成:

游戏.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);
    }

}

播放器.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
4

2 回答 2

2

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

game.start();

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

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

不起作用,因为这些字段隐藏了另一个字段,为什么?因为

WIDTH&HEIGHT是保留的参数

.fillRect(...);
于 2014-10-19T21:08:15.873 回答
1

这是因为您从不调用 init() 方法,因此永远不会创建播放器和 spriteheet

您可以像这样向 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();
    }
} 

但我更喜欢第一种方式

于 2014-10-19T20:54:12.867 回答