0

好的,我正在构建一个 Java 游戏 (RPG),并且我正在使用一个图块集。现在我想让我的角色一个接一个地行走并构建一个代码,只有当我按下行走按钮时它会返回一个 Thread 3 NullPointerException ..

这是它给我的错误:”

Exception in thread "Thread-3" java.lang.NullPointerException
    at net.chosensentinel.dvdv.EntityPlayer.canMove(EntityPlayer.java:152)
    at net.chosensentinel.dvdv.EntityPlayer.move(EntityPlayer.java:48)
    at net.chosensentinel.dvdv.Core.tick(Core.java:70)
    at net.chosensentinel.dvdv.Core.run(Core.java:141)
    at java.lang.Thread.run(Unknown Source)

每个类和方法(据我所知)都以良好的方式被调用。

代码构建:

核:

package net.chosensentinel.dvdv;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;


public class Core extends Applet implements Runnable{

    private static final long serialVersionUID = 1L;

    private static JFrame frame;

    public static final int res = 1;

    public final int TARGET_FPS = 60;
    public final long OPTIMAL_TIME = 1000000000/TARGET_FPS;
    public static long lastFpsTime = 0;
    public static int fps = 0;
    public static int renderFps = 0;

    public static double oY = 0, oX = 0;
    public static int dir = 0;

    public static boolean moving = false;
    public static boolean run = false;

    private Image screen;

    private ArrayList<Entity> entities = new ArrayList<Entity>();
    private ArrayList<Entity> removeList = new ArrayList<Entity>();

    public static EntityPlayer player;

    public static boolean bW, bS, bA, bD, bE, bSpace, bP;

    public static boolean inGame = true;

    public Level level;

    public static Core core;

    public static Dimension screenSize = new Dimension(700, 560);
    public static Dimension pixel = new Dimension(screenSize.width, screenSize.height);
    public static Dimension Size;

    public static String name = "Dawn - The Chosen Sentinel";

    public Core(){
        setPreferredSize(screenSize);
        addKeyListener(new InputManager());

        initEntities();
    }

    public void tick(double delta){

        frame.pack();

        if(inGame){

            for(int i = 0; i < entities.size(); i++) {
                 Entity entity = (Entity)entities.get(i);
                 entity.move(delta);
            }

            for(int i = 0; i < entities.size(); i++) {
                for(int j = i + 1; j < entities.size(); j++){
                    Entity me = (Entity)entities.get(i);
                    Entity him = (Entity)entities.get(j);
                    if(me.collidesWith(him)){
                        me.collidedWith(him);
                        him.collidedWith(me);
                    }
                }
            }

            entities.remove(removeList);
                removeList.clear();
        }
    }

    public void render(){

        Graphics g = screen.getGraphics();
        g.setColor(Color.black);
        g.drawRect(0, 0, 800, 800);

        level.render(g, (int)oX, (int)oY, (pixel.width / Tile.size) + 2, (pixel.height / Tile.size) +2);

        for(int i = 0; i < entities.size(); i++) {
             Entity entity = (Entity)entities.get(i);
             entity.render(g);
        }

        g.setColor(Color.red);
        g.drawString("FPS: " + renderFps, 600, 530);

        g = this.getGraphics();
        g.drawImage(screen, 0, 0, screenSize.width, screenSize.height, 0, 0, pixel.width, pixel.height, null);
        g.dispose();

    }

    public void removeEntity(Entity entity){
        removeList.add(entity);
    }

    public void initEntities(){
        player = new EntityPlayer(core, (pixel.width / 2) - (Tile.size / 2) + oX, (pixel.height / 2) - (Tile.size / 2) + oY, 32, 32);
        entities.add(player);       
    }

    public void run() {
        screen = createVolatileImage(pixel.width, pixel.height);

        long lastLoopTime = System.nanoTime();

        while(run){

            long now = System. nanoTime();
            long updateLength = now - lastLoopTime;
            lastLoopTime = now;

            double delta = updateLength / (double)OPTIMAL_TIME;
            lastFpsTime += updateLength;
            fps++;

            if(lastFpsTime >= 1000000000){
                renderFps = fps;
                fps = 0;
                lastFpsTime = 0;
            }

            tick(delta);

            render();

            try{
                Thread.sleep((lastLoopTime - System.nanoTime() + OPTIMAL_TIME) / 1000000);
            }catch(Exception e){}
        }
    }

    public void start(){
        requestFocus();

        //define classes
        level = new Level(1);
        new Tile();

        run = true;
        new Thread(this).start();
    }

    public void stop(){
        run = false;
    }

    public static void main(String[] args){
        core = new Core();

        frame = new JFrame();
        frame.add(core);
        frame.pack();

        Size = new Dimension(frame.getWidth(), frame.getHeight());

        frame.setTitle(name);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        core.start();
    }

}

实体播放器:

package net.chosensentinel.dvdv;

import java.awt.Graphics;
import java.awt.Rectangle;

public class EntityPlayer extends Entity{

    public double moveSpeed = 2;

    private static int Rx, Ry;
    public static int tX, tY;

    public static boolean isMoving = false;
    private static int moveDelta = 0;

    private Core CS;

    public int aniFrame = 0;
    public int aniTime = 10;
    public int aniDelta = 0;

    public EntityPlayer(Core cS, double x, double y, int width, int height){
        super(new int[] {0,0}, x, y, width, height);

        Rx = (int)(x - CS.oX);
        Ry = (int)(y - CS.oY);
        CS = cS;
        moveSpeed = 32;
        health = 110;
    }

    @Override
    public void move(double delta){

        aniDelta ++;

        if(aniDelta >= aniTime){
            aniFrame ++;
            aniDelta = 0;
            if(aniFrame > 2){
                aniFrame = 1;
            }
        }

        //up
        if(CS.bW){

            if(canMove(tX, tY - 1)&& !isMoving){
                isMoving = true;
                tY -= 1;
            }
            if(!isMoving){
                CS.bW = false;
            }

            if(isMoving){
                CS.oY += moveSpeed;
                moveDelta += moveSpeed;

                if(moveDelta >= 32){
                    isMoving = false;
                    moveDelta = 0;
                    aniFrame = 0;
                }
            }

        }

        //down
        if(CS.bS){

            if(canMove(tX, tY + 1)&& !isMoving){
                isMoving = true;
                tY += 1;
            }
            if(!isMoving){
                CS.bS = false;
            }

            if(isMoving){
                CS.oY -= moveSpeed;
                moveDelta += moveSpeed;

                if(moveDelta >= 32){
                    isMoving = false;
                    moveDelta = 0;
                    aniFrame = 0;
                }
            }

        }

        //left
        if(CS.bA){

            if(canMove(tX - 1, tY)&& !isMoving){
                isMoving = true;
                tX -= 1;
            }
            if(!isMoving){
                CS.bA = false;
            }

            if(isMoving){
                CS.oX -= moveSpeed;
                moveDelta += moveSpeed;

                if(moveDelta >= 32){
                    isMoving = false;
                    moveDelta = 0;
                    aniFrame = 0;
                }
            }

        }

        //right
        if(CS.bD){

            if(canMove(tX + 1, tY)&& !isMoving){
                isMoving = true;
                tX += 1;
            }
            if(!isMoving){
                CS.bD = false;
            }

            if(isMoving){
                CS.oX += moveSpeed;
                moveDelta += moveSpeed;

                if(moveDelta >= 32){
                    isMoving = false;
                    moveDelta = 0;
                    aniFrame = 0;
                }
            }

        }

    }

    @Override
    public void render(Graphics g){
        super.setImage(new int[]{0,0});

        g.drawImage(image, Rx, Ry, null);
    }

    public boolean canMove(int i, int j){

        if(CS.level.solid[i][j].id == Tile.blank){
            return true;
        }

        return false;

    }

    public void collidedWith(Entity entity) {

    }

}

等级:

package net.chosensentinel.dvdv;

import java.awt.Graphics;
import java.awt.Rectangle;

import org.newdawn.slick.SlickException;
import org.newdawn.slick.tiled.TiledMap;

public class Level {

    public int width = 100, height = 100;

    public Background[][] bg = new Background[width][height];
    public Solid[][] solid = new Solid[width][height];
    public Item[][] item = new Item[width][height];

    public final String Dpath = "Res/World/Level_";
    public String path = Dpath;

    public TiledMap map = null;

    public Level(int id){
        path = Dpath + Integer.toString(id) + ".tmx";
        System.out.println(path);

        try{
            map = new TiledMap(path, false);
            }catch(SlickException e){
                System.out.println("Error Loading Map!");
            }

        for(int x = 0; x < bg.length; x++){
            for(int y = 0; y < bg[0].length; y++){
                bg[x][y] = new Background(new Rectangle(x * Tile.size, y * Tile.size, Tile.size, Tile.size), Tile.blank);
                solid[x][y] = new Solid(new Rectangle(x * Tile.size, y * Tile.size, Tile.size, Tile.size), Tile.blank);
                item[x][y] = new Item(new Rectangle(x * Tile.size, y * Tile.size, Tile.size, Tile.size), Tile.blank);
            }
        }

        loadWorld();


    }

    public void loadWorld(){
        int background = map.getLayerIndex("background");
        int solids = map.getLayerIndex("collision");
        int items = map.getLayerIndex("object");

        for(int x = 0; x < bg.length; x++){
            for(int y = 0; y < bg[0].length; y++){

                //Background
                if(map.getTileId(x, y, background) == 1){
                    bg[x][y].id = Tile.grass;
                }
                if(map.getTileId(x, y, background) == 2){
                    bg[x][y].id = Tile.road;
                }
                if(map.getTileId(x, y, background) == 3){
                    bg[x][y].id = Tile.leaves;
                }

                //Solids
                if(map.getTileId(x, y, solids) == 64){
                    solid[x][y].id = Tile.grass;
                }

                //Items
                if(map.getTileId(x, y, items) == 129){
                    item[x][y].id = Tile.grass;
                }

            } 
        }
    }


    public void tick(double delta){

    }

    public void render(Graphics g, int camX, int camY, int renX, int renY){
        for (int x = (camX / Tile.size); x < (camX / Tile.size) + renX; x++){
            for (int y = (camY / Tile.size); y < (camY / Tile.size)+ renY; y++){
                if(x >= 0 && y >= 0 && x < width && y < height){
                    bg[x][y].render(g);
                }
            }
        }
    }


}

这些是我正在使用的每个课程等。

我希望有人可以帮助我,让我的角色移动(只有移动,我会自己尝试动画:))

4

2 回答 2

0

我刚刚发现问题出在构造函数中的初始化上。

当代码如下时,核心返回 null:

public Core(){
        setPreferredSize(screenSize);
        addKeyListener(new InputManager());

        initEntities();
    }

如果你出命令 initEntities(); 比核心正常运行(不显示角色或动作)但也没有返回null ..我的想法真的被吹到这里了..

编辑

好的,所以我将它添加到我的主类中:

public static void main(String[] args){
        core = new Core();
        core.initEntities();
...//More Code

现在构造函数是这样的:

public Core(){
        setPreferredSize(screenSize);
        addKeyListener(new InputManager());
    }

更新

我现在实际上可以移动一个瓷砖,然后出现此错误:

net.chosensentinel.dvdv.Core[panel0,0,0,0x0,invalid,layout=java.awt.FlowLayout]
    Res/World/Level_1.tmx
    Exception in thread "Thread-3" java.lang.ArrayIndexOutOfBoundsException: -1
        at net.chosensentinel.dvdv.EntityPlayer.canMove(EntityPlayer.java:148)
        at net.chosensentinel.dvdv.EntityPlayer.move(EntityPlayer.java:119)
        at net.chosensentinel.dvdv.Core.tick(Core.java:67)
        at net.chosensentinel.dvdv.Core.run(Core.java:138)
        at java.lang.Thread.run(Unknown Source)

这是我改变的:

@Override
public void move(double delta){

    aniDelta ++;

    if(aniDelta >= aniTime){
        aniFrame ++;
        aniDelta = 0;
        if(aniFrame > 2){
            aniFrame = 1;
        }
    }

    //up
    if(Core.bW){

        if(canMove(tX, tY + 1)&& !isMoving){
            isMoving = true;
            tY -= 1;
        }
        if(!isMoving){
            Core.bW = false;
        }

        if(isMoving){
            Core.oY -= moveSpeed;
            moveDelta += moveSpeed;

            if(moveDelta >= 32){
                isMoving = false;
                moveDelta = 0;
                aniFrame = 0;
            }
        }

    }

    //down
    if(Core.bS){

        if(canMove(tX, tY + 1)&& !isMoving){
            isMoving = true;
            tY -= 1;
        }
        if(!isMoving){
            Core.bS = false;
        }

        if(isMoving){
            Core.oY += moveSpeed;
            moveDelta += moveSpeed;

            if(moveDelta >= 32){
                isMoving = false;
                moveDelta = 0;
                aniFrame = 0;
            }
        }

    }

    //left
    if(Core.bA){

        if(canMove(tX + 1, tY)&& !isMoving){
            isMoving = true;
            tX -= 1;
        }
        if(!isMoving){
            Core.bA = false;
        }

        if(isMoving){
            Core.oX -= moveSpeed;
            moveDelta += moveSpeed;

            if(moveDelta >= 32){
                isMoving = false;
                moveDelta = 0;
                aniFrame = 0;
            }
        }

    }

    //right
    if(Core.bD){

        if(canMove(tX + 1, tY)&& !isMoving){
            isMoving = true;
            tX -= 1;
        }
        if(!isMoving){
            Core.bD = false;
        }

        if(isMoving){
            Core.oX += moveSpeed;
            moveDelta += moveSpeed;

            if(moveDelta >= 32){
                isMoving = false;
                moveDelta = 0;
                aniFrame = 0;
            }
        }

    }

}
于 2013-09-05T07:39:41.057 回答
0

这应该足以告诉您异常来自哪里

在 net.chosensentinel.dvdv.EntityPlayer.canMove(EntityPlayer.java:152)

所以很明显这行代码导致你的方法出现问题EntityPlayer.canMove()

if(CS.level.solid[i][j].id == Tile.blank)

这表明CS、或 数组中该点处的元素之一为空levelsolid

使用 IDE 在代码中的该点设置断点或添加此断点以查找(粗略,但如果您不熟悉 IDE 调试会有所帮助)

if(CS == null)
    System.err.println("CS Is null");
else if (CS.level == null)
    System.err.println("CS.level Is null");
else if (CS.level.solid[i][j] == null)
    System.err.println("CS.level.solid["+i+"]["+j+"] Is null");
else if (CS.level.solid[i][j].id == null)
    System.err.println("CS.level.solid["+i+"]["+j+"].id Is null");
else if(CS.level.solid[i][j].id == Tile.blank)
     // your code

然后回溯到这些应该被初始化的地方

编辑

好的,从您的评论和帖子中,我可以看到:

在你的课堂Core上,你有

public static Core core;

在您的主要方法中,您正在创建一个new Core()并将其分配给变量core

但是,在您的构造函数中Core(),您正在引用尚未完成初始化的此变量core(在您的方法中)。initEntities()

所以主要这样做

core = new Core();
core.initEntities();
于 2013-09-04T22:22:09.570 回答