LibGDX SpriteBatch 渲染错误

LibGDX SpriteBatch rendering error

所以早些时候当我测试我的游戏时一切顺利,然后我添加了一些代码。在我的游戏中,我有像 PlayState 或 MenuState 这样的状态,现在一切顺利,但是当我尝试在游戏中切换状态时,出现以下错误:

Exception in thread "LWJGL Application" java.lang.NullPointerException
    at com.badlogic.gdx.graphics.g2d.SpriteBatch.flush(SpriteBatch.java:955)
    at com.badlogic.gdx.graphics.g2d.SpriteBatch.end(SpriteBatch.java:176)
    at com.platformer.Entities.Player.draw(Player.java:191)
    at com.platformer.gamestates.PlayState.draw(PlayState.java:102)
    at com.platformer.managers.GameStateManager.draw(GameStateManager.java:44)
    at com.platformer.game.Game.render(Game.java:55)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.mainLoop(LwjglApplication.java:214)
    at com.badlogic.gdx.backends.lwjgl.LwjglApplication.run(LwjglApplication.java:120)

它说我的播放器有问题class,所以这是代码:

package com.platformer.Entities;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import static com.platformer.managers.B2DVars.PPM;

import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasRegion;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.platformer.game.Game;
import com.platformer.managers.Animation;
import com.platformer.managers.B2DVars;
import com.platformer.managers.GameContacts;

import java.util.Random;

/**
 * Created by Oliverss on 23/04/2015.
 */
public class Player extends Entities{

    public static boolean DebugOn=false;
    public boolean shouldPlay=false;
    public boolean shouldMenu=false;

    public static final int LEFT = 0;
    public static final int RIGHT = 1;
    public int direction=1;

    float BPF=255f;
    int canJump=0;
    float weaponY;

    public static int shade=100;
    public static int coatColor;

    Controller controller;
    Weapons weapon;

    Random random=new Random();

    float[][] skinShades={
            {210/BPF,180/BPF,140/BPF},  //tan
            {139/BPF,69/BPF,19/BPF},    //saddle-brown
            {160/BPF,82/BPF,45/BPF},    //sienna
            {255/BPF,235/BPF,205/BPF},  //blanched almond
            {255/BPF,228/BPF,196/BPF},  //bisque
    };

    float[][] coatColors={
            {64/BPF,64/BPF,64/BPF},  //dark-gray
            {102/BPF,102/BPF,0/BPF},  //dark-green
            {47/BPF,79/BPF,79/BPF},   //dark-slate-gray
            {165/BPF,42/BPF,42/BPF},    //brown
    };

    public Player(World world,float x,float y){

        this.x=x;
        this.y=y;
        speed=1.5f;

        if(shade==100){
            shade=random.nextInt(skinShades.length);
            coatColor=random.nextInt(coatColors.length);
            System.out.println("*Generating*");
            System.out.println("shade "+shade);
            System.out.println("coat "+coatColor);
        }

        controller=new Controller();
        weapon=new Weapons("pistol");

        AtlasRegion region=Game.atlas.findRegion("playerskin");
        TextureRegion[] sprites=region.split(32,32)[0];
        skinAnimation=new Animation(sprites,1/12f);

        region=Game.atlas.findRegion("playercoat");
        sprites=region.split(32,32)[0];
        coatAnimation=new Animation(sprites,1/12f);

        region=Game.atlas.findRegion("playerskinjump");
        sprites=region.split(32,32)[0];
        skinJumpAnimation=new Animation(sprites,1/12f);

        region=Game.atlas.findRegion("playercoatjump");
        sprites=region.split(32,32)[0];
        coatJumpAnimation=new Animation(sprites,1/12f);

        skin=new Sprite();
        skin.setSize(32/PPM,32/PPM);

        coat=new Sprite();
        coat.setSize(32/PPM,32/PPM);

        bdef=new BodyDef();
        bdef.position.set(x/PPM,y/PPM);
        bdef.type=BodyType.DynamicBody;
        body=world.createBody(bdef);

        PolygonShape shape=new PolygonShape();
        shape.setAsBox(9/PPM,15/PPM);

        fdef=new FixtureDef();
        fdef.shape=shape;
        fdef.filter.categoryBits=B2DVars.BIT_PLAYER;
        fdef.filter.maskBits=B2DVars.BIT_BLOCK|B2DVars.BIT_HOUSE;
        body.createFixture(fdef).setUserData("player");

        //create sensor
        shape.setAsBox(7/PPM,6/PPM,new Vector2(0,-16/PPM),0);
        fdef.shape=shape;
        fdef.filter.categoryBits=B2DVars.BIT_PLAYER;
        fdef.filter.maskBits=B2DVars.BIT_BLOCK;
        fdef.isSensor=true;
        body.createFixture(fdef).setUserData("player_sensor");

    }

    public void update(float dt,GameContacts gameContacts){

        handleInput(dt,gameContacts);

        skin.setPosition(body.getPosition().x-(16/PPM),body.getPosition().y-(17/PPM));
        coat.setPosition(body.getPosition().x-(16/PPM),body.getPosition().y-(17/PPM));

        switch (movementState){
            case 0:{
                coatAnimation.setCurrentFrame(0);
                skinAnimation.setCurrentFrame(0);
                coatJumpAnimation.setCurrentFrame(0);
                skinJumpAnimation.setCurrentFrame(0);
                coat.setRegion(coatAnimation.getFrame());
                skin.setRegion(skinAnimation.getFrame());
                break;
            }
            case 1:{
                coatAnimation.update(dt);
                skinAnimation.update(dt);
                coat.setRegion(coatAnimation.getFrame());
                skin.setRegion(skinAnimation.getFrame());
                break;
            }
            case 2:{
                coatAnimation.update(dt);
                skinAnimation.update(dt);
                coat.setRegion(coatAnimation.getFrame());
                skin.setRegion(skinAnimation.getFrame());
                break;
            }
            case 3:{
                coatAnimation.setCurrentFrame(0);
                skinAnimation.setCurrentFrame(0);
                coat.setRegion(coatJumpAnimation.getFrame());
                skin.setRegion(skinJumpAnimation.getFrame());
                break;
            }

        }

        y=coat.getY();
        x=coat.getX();
        weaponY=y;

        if(!gameContacts.isPlayerOnGround()){
            coatJumpAnimation.setCurrentFrame(1);
            skinJumpAnimation.setCurrentFrame(1);
            coat.setRegion(coatJumpAnimation.getFrame());
            skin.setRegion(skinJumpAnimation.getFrame());
            weaponY+=4/PPM;
        }

        weapon.update(x,weaponY,direction,coatAnimation.getCurrentFrame());

    }

    public void draw(SpriteBatch batch){

        if(direction==LEFT)flip();

        batch.begin();
        skin.draw(batch);
        coat.draw(batch);
        batch.end();

        weapon.draw(batch);

        controller.debug(DebugOn);
        controller.draw();

    }

    public void flip(){

        skin.flip(true,false);
        coat.flip(true,false);

    }

    public void handleInput(float dt,GameContacts gameContacts){

        //movement
        if(controller.leftDown||Gdx.input.isKeyPressed(Input.Keys.LEFT))movementState=1;
        if(controller.rightDown||Gdx.input.isKeyPressed(Input.Keys.RIGHT))movementState=2;
        if(!controller.leftDown&&!controller.rightDown&&!Gdx.input.isKeyPressed(Input.Keys.LEFT)&&!Gdx.input.isKeyPressed(Input.Keys.RIGHT))movementState=0;

        Vector2 vec=body.getLinearVelocity();
        force=0;

        switch (movementState){
            case 1:if(vec.x>-speed)force=-50;direction=LEFT;break;
            case 2:if(vec.x<speed)force=50;direction=RIGHT;break;
            case 0:force=vec.x*-10;break;
        }

        body.applyForceToCenter(new Vector2(force,0),true);

        if((controller.jumpDown||Gdx.input.isKeyPressed(Input.Keys.UP))&&gameContacts.isPlayerOnGround()&&canJump>50){
            body.applyForceToCenter(0,300,true);
            canJump=0;
        }
        if(canJump>51)canJump=51;
        canJump++;
        if(canJump<52)movementState=3;

        if(controller.attackdown&&gameContacts.isOnHouse()){
            shouldPlay=true;
        }

        if(Gdx.input.isKeyJustPressed(Input.Keys.C)){
            shade=random.nextInt(skinShades.length);
            coatColor=random.nextInt(coatColors.length);
            System.out.println("shade "+shade);
            System.out.println("coat "+coatColor);
        }

        skin.setColor(skinShades[shade][0],skinShades[shade][1],skinShades[shade][2],1);
        coat.setColor(coatColors[coatColor][0],coatColors[coatColor][1],coatColors[coatColor][2],1);

        //debug
        if(controller.attackdown&&(Gdx.input.isKeyJustPressed(Input.Keys.VOLUME_DOWN)||Gdx.input.isKeyJustPressed(Input.Keys.VOLUME_UP)||Gdx.input.isKeyJustPressed(Input.Keys.CONTROL_LEFT))){if(DebugOn){DebugOn=false;System.out.println("off");}else{DebugOn=true;System.out.println("on");}}
        //debug
        if(controller.jumpDown&&(Gdx.input.isKeyJustPressed(Input.Keys.VOLUME_DOWN)||Gdx.input.isKeyJustPressed(Input.Keys.VOLUME_UP)||Gdx.input.isKeyJustPressed(Input.Keys.CONTROL_LEFT))){shouldMenu=true;}
    }

    @Override
    public void dispose(){
        skin.getTexture().dispose();
        coat.getTexture().dispose();
        weapon.dispose();
    }

    public float getx(){return x;}
    public float gety(){return y;}

}

这里有什么问题?

您确定 skincoat 在绘制时应用了纹理吗?

您的错误消息表明问题出在这里:

batch.begin();
skin.draw(batch);
coat.draw(batch);
batch.end();

我唯一能想到的就是如果状态搞砸了,他们没有纹理可以绘制。

您使用的 libgdx 是什么版本?

如果和我的一样(1.5.4),那么问题出在这一行...

lastTexture.bind();

看起来您在状态更改期间丢失了一些纹理。

如果有人仍然面临这个问题,这可能会有所帮助。实际上,当批处理要用新纹理替换最后绘制的纹理时,会发生此错误。所以,实际上,纹理是在最后一个绘制语句中丢失的,而不是真正发生异常的语句。

例如,我在 render 方法中有这两行:

  batch.draw(backgroundImage, 0, 0,width, height);
  batch.draw(mainCharacter, 0, 0,width, height);

我在绘制主角时遇到异常,但最后我发现我忘记将纹理分配给背景区域。