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;}
}
这里有什么问题?
您确定 skin
和 coat
在绘制时应用了纹理吗?
您的错误消息表明问题出在这里:
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);
我在绘制主角时遇到异常,但最后我发现我忘记将纹理分配给背景区域。
所以早些时候当我测试我的游戏时一切顺利,然后我添加了一些代码。在我的游戏中,我有像 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;}
}
这里有什么问题?
您确定 skin
和 coat
在绘制时应用了纹理吗?
您的错误消息表明问题出在这里:
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);
我在绘制主角时遇到异常,但最后我发现我忘记将纹理分配给背景区域。