2D自上而下Java(1.8)从头开始的游戏(无)



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

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

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

game.start();

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

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

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

WIDTH&HEIGHT是的保留自变量

.fillRect(...);

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

你可以向Game类添加一个构造函数,如下所示:

public Game() {
    init();
}

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

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();
    }
} 

但我更喜欢的第一种方式

最新更新