简体   繁体   中英

2D Top-Down Java (1.8) Game from Scratch(nothing)

So, first of all this is my first time posting and I am trying to make a top-down game with java(1.8) and IntelliJ, nothing else. I have all of my code good and done(for making the sprite show up), I test it and it keeps giving me error messages saying that certain parts are invalid. It is supposed to display an image (character) on the screen in the top right here is all code and please keep in mind that I do not have this fully finished:

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

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

}

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

}

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) {

    }
}

The error messages(It gives me multiple messages, each time is different // = what is on that line, so you don't have to find it by counting, your welcome):

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

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

That game.start(); takes all the responsibility. Your Game class is not extending a Thread , the thread itself will start automatically right after you instantiate your game's class, since the thread is created inside the game class. So remove :

game.start();

Btw you fall on trap :

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

won't work, because those fields hide another fields, why ? because

WIDTH & HEIGHT is preserved arguments for

.fillRect(...);

It's because you never call the init() method and, therefore the player and the spriteheet never gets created

You can add a constructor to the Game class like this:

public Game() {
    init();
}

Or you can add the following line in the main method:

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

But I prefer the first way

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM