繁体   English   中英

为什么我在 Libgdx 中更改屏幕并绘制 Sprite 后得到 NPE

[英]Why i get an NPE after changing Screen and Drawing a Sprite in Libgdx

这是我在这里要问的第一个问题,所以我很抱歉我在这里做错了什么。

我目前正在尝试在 libgdx 中开发我自己的第一个游戏。 所以一开始我有4节课。

  1. FlipX 是从 Game 扩展的 class。
  2. StartMenu 是从 Screen 实现的 class。
  3. GameScreen 从 Screen 实现的 class。
  4. 按钮从 Sprite 扩展的 class。

我希望我可以在这里向您展示一些代码,但让我先解释一下。
启动代码 Class FlipX 时,我要在其中绘制 SpriteBatch,将屏幕设置为 StartMenu Class。 在那里我可以单击从 FlipX 绘制到 SpriteBatch 的 2 个按钮。
这些按钮来自按钮 Class,我创建它是为了将多个纹理存储到一个所谓的按钮。 这个按钮 Class 从 Sprite 扩展而来。
当我点击 PlayBtn 时,PlayBtn 会将屏幕设置为 GameScreen class。
当 GameScreen Class 在 Screen 设置为 GameScreen 后在同一批次上绘制另一个 Button 时,就会出现问题。
这是 drawBatch() function 中 GameScreen 的线,我在其中绘制 jumpBtn.draw(game.batch)。 当我这样做时,我收到以下错误。

Exception in thread "LWJGL Application" java.lang.NullPointerException
    at com.badlogic.gdx.graphics.g2d.SpriteBatch.switchTexture(SpriteBatch.java:1067)
    at com.badlogic.gdx.graphics.g2d.SpriteBatch.draw(SpriteBatch.java:558)
    at com.badlogic.gdx.graphics.g2d.Sprite.draw(Sprite.java:580)
    at de.geecogames.flipx.Screens.GameScreen.drawBatch(GameScreen.java:88)
    at de.geecogames.flipx.Screens.GameScreen.render(GameScreen.java:63)
    at com.badlogic.gdx.Game.render(Game.java:46)
    at de.geecogames.flipx.FlipX.render(FlipX.java:26)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:232)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication$1.run(LwjglApplication.java:127)

当我用简单的 Sprite 替换 Button 时,不会发生此错误,这很奇怪,因为 Button Class 只是扩展 Sprite 的 class。 private Sprite jumpBtn = new Sprite(new Texture("game/UpDef.png"));

public class FlipX extends Game {
    public SpriteBatch batch;

//Filemanager to load Assets from an Asset Manager
    public FileManager manager;

    StartMenu startMenu;
    
    @Override
    public void create () {
        manager= new FileManager();
        startMenu=new StartMenu(this);
        batch = new SpriteBatch();
        setScreen(startMenu);
    }

    @Override
    public void render () {
        super.render();
    }
    
    @Override
    public void dispose () {
        batch.dispose();
    }

    public FileManager getFileManager(){
        return manager;
    }
}
public class StartMenu implements Screen {
private final FlipX game;
    private final FileManager fileM;

    private final OrthographicCamera camera;

    private final FitViewport viewport;

    private Sprite img = new Sprite(new Texture("badlogic.jpg"));

    private final Button playBtn, exitBtn;

    private final Sprite backGround;

    private boolean playPressed, exitPressed;
    public StartMenu(FlipX game) {
        this.game = game;

        //Get Manager and load Assets
        this.fileM = game.getFileManager();
        fileM.loadAssetsMenu();

        //Testlabel
        Label testlabel = new Label(String.format("test"), new Label.LabelStyle(new BitmapFont(), Color.BLACK));

        //Get the Assets from Manager
        playBtn = new Button(fileM.getTexture(fileM.playBtnDefault), fileM.getTexture(fileM.playBtnHover), fileM.getTexture(fileM.playBtnClick));

        exitBtn = new Button(fileM.getTexture(fileM.exitBtnDefault), fileM.getTexture(fileM.exitBtnHover), fileM.getTexture(fileM.exitBtnClick));

        backGround = fileM.getSprite(fileM.backgroundMenu);

        camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
        viewport = new FitViewport(Z.V_WIDTH, Z.V_HEIGHT, camera);

        camera.position.set(viewport.getWorldWidth() / 2, viewport.getWorldHeight() / 2, 0);

        //Btn Position
        playBtn.setPosition(Z.V_WIDTH / 2 - playBtn.getWidth() / 2, Z.V_HEIGHT / 2 - playBtn.getHeight() / 2);
        exitBtn.setPosition(Z.V_WIDTH / 2 - exitBtn.getWidth() / 2, Z.V_HEIGHT / 2 - exitBtn.getHeight() / 2 - playBtn.getHeight() - playBtn.getHeight() / 2);

        img.setPosition(0, 0);
    }
    @Override
    public void render(float delta) {
        update(delta);

        clearColor();

        drawBatch();
    }

    private void update(float dt) {
        handleInput();

        cameraUpdates();
    }

    private void clearColor() {
        Gdx.gl.glClearColor(0, 0.5f, 0.9f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    }

    private void drawBatch() {
        game.batch.setProjectionMatrix(camera.combined);
        game.batch.begin();
        backGround.draw(game.batch);
        img.draw(game.batch);

        //Buttons
        playBtn.draw(game.batch);
        exitBtn.draw(game.batch);

        game.batch.end();
    }

    private void handleInput() {
        Vector3 realCoords = viewport.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));

        if (Gdx.input.isKeyPressed(Input.Keys.K)) {
            float addX = 2;
            float addY = 0;
            img.setPosition(img.getX() + addX, img.getY() + addY);
        }

        if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
            camera.position.y = camera.position.y + 1;
        } else if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
            camera.position.y = camera.position.y - 1;
        }

        if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
            camera.position.x = camera.position.x - 1;
        } else if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
            camera.position.x = camera.position.x + 1;
        }

        if (Gdx.input.isKeyPressed(Input.Keys.PAGE_UP)) {
            camera.zoom = camera.zoom + 0.1f;
        } else if (Gdx.input.isKeyPressed(Input.Keys.PAGE_DOWN)) {
            camera.zoom = camera.zoom - 0.1f;
        }

        //btn test
        if (BasicFunctions.isInside(realCoords.x, realCoords.y, playBtn)) {
            if (Gdx.input.justTouched()) {
                playBtn.setClick();
                playPressed = true;
                fileM.playSound(fileM.playBtnSound);
            } else {
                if (playPressed) {
                    game.setScreen(new GameScreen(game));
                }
                playBtn.setHover();
            }
        } else
            playBtn.setNormal();


        if (BasicFunctions.isInside(realCoords.x, realCoords.y, exitBtn)) {
            if (Gdx.input.isTouched()) {
                exitBtn.setClick();
                exitPressed = true;
            } else {
                if (exitPressed)
                    Gdx.app.exit();
                exitBtn.setHover();
            }
        } else
            exitBtn.setNormal();
    }

    private void cameraUpdates() {
        camera.update();
    }
}
public class GameScreen implements Screen {

private final FlipX game;

    private final FileManager fileM;

    private final OrthographicCamera camera;

    private final FitViewport viewport;

    private final Button jumpBtn;

    private final Sprite background;

    public GameScreen(FlipX game){
        this.game=game;
        this.fileM=game.getFileManager();

        fileM.loadAssetsGame();

        camera=new OrthographicCamera(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
        viewport = new FitViewport(Z.V_WIDTH,Z.V_HEIGHT,camera);



        jumpBtn = new Button(new Texture("game/UpDef.png"),new Texture("game/UpHov.png"),new Texture("game/UpClick.png"));
        jumpBtn.setPosition(2,2);

        background = fileM.getSprite(fileM.backgroundMenu);
    }

    @Override
    public void show() {

    }

    @Override
    public void render(float delta) {
        update(delta);

        clearColor();

        drawBatch();
    }

    private void update(float dt){
        handleInput(dt);
    }

    private void clearColor() {
        Gdx.gl.glClearColor(1, 0.5f, 0.9f, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
    }

    private void drawBatch(){
        game.batch.setProjectionMatrix(camera.combined);
        game.batch.begin();

        background.draw(game.batch);

        //Bug here?
        jumpBtn.draw(game.batch);

        game.batch.end();
    }

    private void handleInput(float dt){
        Vector3 realCoords = viewport.unproject(new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0));

        if(Gdx.input.isTouched()){
            if(BasicFunctions.isInside(realCoords.x,realCoords.y,jumpBtn)){
                EzLog.logging("X " + jumpBtn.getX() + " Y " + jumpBtn.getY());
            }
        }
    }
public class Button extends Sprite {
    private final Texture normal, hover, click;

    private float stateTimer;

    public Button(Texture normal, Texture hover, Texture click){
        this.normal=normal;
        this.hover=hover;
        this.click=click;

        stateTimer=0;

        setSize();
    }

    private void setSize(){
        float height,width;

        width=normal.getWidth();
        height=normal.getHeight();

        setBounds(0,0,width*3,height*3);
    }

    public void setNormal(){
        setRegion(normal);
    }
    public void setHover(){
        setRegion(hover);
    }
    public void setClick(){
        setRegion(click);
    }
}

几个小时后,我找到了解决方案。

问题是我的 Class 按钮最多可以保存 3 个纹理。 要绘制其中一个纹理,我们可以使用它的 draw function,因为 Button 是从 Sprite 扩展而来的。 要在 SpriteBatch 上显示它,只需将纹理设置为区域。

setRegion("TextureHere.png")

所以每次我用我的 playBtn.draw(game.batch) 绘制它时,它都会在我之前用 setPosition(x,y) 给他的 position 上显示这个纹理

但我实际上从未在构造函数中执行“setRegion()”,因此它会尝试绘制不存在的东西。 这就是为什么它说 NullPointerException。 由于 SpriteBatch 中的 switchTexture 函数,我只是对错误感到困惑。
在 Class StartMenu 中,它巧合地只是调用了“setRegion()”,因为它总是在“handleInput”中的条件的 else 部分中调用 function“setNormal()”按钮 Z9BD81329FEBF8AFEDE227.

我知道的解决方案如下:

我在构造函数中添加了 setNormal() function,所以第一个纹理将始终设置为区域,如果我可以这样说的话,这很有效。

public class Button extends Sprite {
    private final Texture normal, hover, click;

    public Button(Texture normal, Texture hover, Texture click){
        this.normal=normal;
        this.hover=hover;
        this.click=click;

        setSize();
        setNormal();
    }

    private void setSize(){
        float height,width;

        width=normal.getWidth();
        height=normal.getHeight();

        setBounds(0,0,width*3,height*3);
    }

    public void setNormal(){
        setRegion(normal);
    }
    public void setHover(){
        setRegion(hover);
    }
    public void setClick(){
        setRegion(click);
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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