尝试更新 Sprite 时出现 NullPointerException

NullPointer Exception When Trying to Update Sprite

你好,我目前正在编写一个 LibGDX 基于物理的游戏,球必须留在平台上,我已经为球设置了物理组件,但是当我尝试更新精灵时ball 基于物理 body 的位置,它给了我一个空指针异常。

我花了一整天的时间通过研究和查看其他人的代码来尝试解决问题,但找不到我的错误。感谢您抽出宝贵时间以及您可以提供的任何意见。下面我输入了我的 Render class、Ball GameObject class、Asset class 和 Exception.

的代码

球类游戏对象Class:

public class Ball {

    public static World physicsWorld;

    public static BodyDef ballBodyDef;
    public static Body ballBody;

    public static CircleShape ballShape;

    public static FixtureDef ballFixtureDef;
    public static Fixture ballFixture;

    public Ball() {

        physicsWorld = new World(new Vector2(0, -9.8f), true);

        ballBodyDef = new BodyDef();
        ballBodyDef.position.set(Assets.ballSprite.getX(),
                Assets.ballSprite.getY());
        ballBodyDef.type = BodyDef.BodyType.DynamicBody;

        ballBody = physicsWorld.createBody(ballBodyDef);

        ballShape = new CircleShape();
        ballShape.setRadius(6f);

        ballFixtureDef = new FixtureDef();
        ballFixtureDef.density = 1.0f;
        ballFixtureDef.friction = 0.2f;
        ballFixtureDef.restitution = 0.4f;

        ballFixture = ballBody.createFixture(ballFixtureDef);

    }

    public void dispose() {

        physicsWorld.dispose();
        ballShape.dispose();

    }

    public BodyDef getBallBodyDef() {
        return ballBodyDef;
    }

    public void setBallBodyDef(BodyDef ballBodyDef) {
        this.ballBodyDef = ballBodyDef;
    }

    public Body getBallBody() {
        return ballBody;
    }

    public void setBallBody(Body ballBody) {
        this.ballBody = ballBody;
    }

    public CircleShape getBallShape() {
        return ballShape;
    }

    public void setBallShape(CircleShape ballShape) {
        this.ballShape = ballShape;
    }

    public FixtureDef getBallFixtureDef() {
        return ballFixtureDef;
    }

    public void setBallFixtureDef(FixtureDef ballFixtureDef) {
        this.ballFixtureDef = ballFixtureDef;
    }

    public Fixture getBallFixture() {
        return ballFixture;
    }

    public void setBallFixture(Fixture ballFixture) {
        this.ballFixture = ballFixture;
    }

}

渲染 Class:

public class GameRenderer {

    private GameWorld myWorld;
    private OrthographicCamera cam;

    int width = Gdx.graphics.getWidth();
    int height = Gdx.graphics.getHeight();

    private SpriteBatch batch;

    public GameRenderer(GameWorld world, int gameHeight, int midPointY) {
        myWorld = world;
        cam = new OrthographicCamera();
        cam.setToOrtho(true, width, height);

        batch = new SpriteBatch();
        batch.setProjectionMatrix(cam.combined);

    }

    public void render(float delta) {
        Gdx.app.log("GameRenderer", "render");

        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        Ball.physicsWorld.step(Gdx.graphics.getDeltaTime(), 6, 2);
        Assets.ballSprite.setPosition(Ball.ballBody.getPosition().x,
                Ball.ballBody.getPosition().y);

        batch.begin();

        batch.draw(Assets.skySprite, 0, 0, 1920, 1080);
        batch.draw(Assets.ballSprite, Assets.ballSprite.getX(),
                Assets.ballSprite.getY());
        batch.draw(Assets.platformSprite, Assets.platformSprite.getX(),
                Assets.platformSprite.getY());

        batch.end();

    }

}

最后是我的资产 Class:

public class Assets {

    public static Texture skyTexture;
    public static Sprite skySprite;

    public static Texture ballTexture;
    public static Sprite ballSprite;

    public static Texture platformTexture;
    public static Sprite platformSprite;

    public static Button rightTiltButton;
    public static TextureAtlas rightButtonAtlas;
    public static TextButtonStyle rightButtonStyle;
    public static Skin rightButtonSkin;

    public static void Load() {

        skyTexture = new Texture(Gdx.files.internal("Assets/skybackground.png"));
        skyTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
        skySprite = new Sprite(skyTexture);
        skySprite.flip(false, true);

        ballTexture = new Texture(
                Gdx.files.internal("Assets/ballcharacter.png"));
        ballTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
        ballSprite = new Sprite(ballTexture);
        ballSprite.flip(false, true);
        ballSprite.setPosition(
                Gdx.graphics.getWidth() / 2 - ballSprite.getWidth()/2,
                Gdx.graphics.getHeight() / 2 - ballSprite.getHeight()-4);

        platformTexture = new Texture(Gdx.files.internal("Assets/platform.png"));
        platformTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
        platformSprite = new Sprite(platformTexture);
        platformSprite.flip(false, true);
        platformSprite.setPosition(
                Gdx.graphics.getWidth() / 2 - platformSprite.getWidth()/2,
                Gdx.graphics.getHeight() / 2 - platformSprite.getHeight()/2);

        rightButtonSkin = new Skin();
        rightButtonAtlas = new TextureAtlas(
                Gdx.files.internal("Assets/right_tilt_button.pack"));
        rightButtonSkin.addRegions(rightButtonAtlas);
        rightButtonStyle = new TextButtonStyle();
        rightButtonStyle.up = rightButtonSkin.getDrawable("right_tilt_button");
        rightButtonStyle.up = rightButtonSkin
                .getDrawable("right_tilt_button_pressed");
        rightButtonStyle.up = rightButtonSkin.getDrawable("right_tilt_button");
        rightButtonStyle.over = rightButtonSkin
                .getDrawable("right_tilt_button_pressed");
        rightButtonStyle.down = rightButtonSkin
                .getDrawable("right_tilt_button_pressed");

        rightTiltButton = new Button(rightButtonStyle);

    }

    public static void dispose() {

        skyTexture.dispose();
        rightButtonAtlas.dispose();
        rightButtonSkin.dispose();
        ballTexture.dispose();

    }

}

空指针异常:

Exception in thread "LWJGL Application" java.lang.NullPointerException
at com.manumade.tiltr.tiltrhelpers.GameRenderer.render         (GameRenderer.java:36)
at com.manumade.tiltr.screens.GameScreen.render(GameScreen.java:39)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:208)
at com.badlogic.gdx.backends.lwjgl.LwjglApplication.run(LwjglApplication.java:114)

绘制您的一个 sprite 似乎有问题(根据异常行号)。尝试用其他精灵替换您使用过的精灵(显然它看起来很傻),看看它们是否有效。

一旦您知道哪些 sprite 有效,哪些无效,您就可以尝试缩小它们的不同之处。例如,我遇到过使用两个纹理的非幂引起的类似问题。

查看您的代码和堆栈跟踪,其中一行似乎有问题:

 batch.draw(Assets.skySprite, 0, 0, 1920, 1080);
 batch.draw(Assets.ballSprite, Assets.ballSprite.getX(),
            Assets.ballSprite.getY());
 batch.draw(Assets.platformSprite, Assets.platformSprite.getX(),
            Assets.platformSprite.getY());

从您提供的堆栈跟踪中我们可以看到错误发生在第 36 行:

at com.manumade.tiltr.tiltrhelpers.GameRenderer.render         (GameRenderer.java:36)

查看您的 GameRenderer class 并查看在该行调用的对象。当您收到 NullPointerException 时,这意味着您正在尝试调用一个方法或访问一个不指向任何对象的变量(该对象可能永远不会被创建。)

我会假设:

  • SpriteBatch 为 NULL
  • Assets.skySprite 为 NULL
  • Assets.ballSprite 为 NULL
  • Assets.platformerSprite 为 NULL

所以看看这些对象的实例化方式。还要确保在对这些对象执行任何操作之前实际初始化它们。您的 render() 方法可能会在您实际初始化资产 class.

中的 Sprite 对象之前被调用

我看到你打电话:

Assets.ballSprite.setPosition(Ball.ballBody.getPosition().x,
                              Ball.ballBody.getPosition().y);

batch.begin();

batch.draw(Assets.skySprite, 0, 0, 1920, 1080);

batch.draw(Assets.ballSprite,
           Assets.ballSprite.getX(),
           Assets.ballSprite.getY());

batch.draw(Assets.platformSprite, 
           Assets.platformSprite.getX(),
           Assets.platformSprite.getY());

batch.end();

Assets.skySprite,
Assets.ballSprite,
Assets.platformSprite

但是我看不到你打电话给Assets.load ();

在使用上面为什么是null之前,因为它们没有初始化只是声明或者我认为这是错误的。

尝试在渲染方法中使用之前调用 Assets.Load ();,例如在您的 public GameRenderer(...); 方法内部。

可以尝试阅读它 AssetsManager :

https://github.com/libgdx/libgdx/wiki/Managing-your-assets 并在进入游戏区之前创建资产加载。(但这只是一个想法)。

可以看看,www 一些教程关于它 AssetManager.

P.S: 这是行: (GameRenderer.java:36), 确保例如在 Ball 中使用的 staticas 变量在渲染中使用之前已初始化。