Libgdx 如何在一个屏幕上使用SpriteBatch和ShaperEnder?

Libgdx 如何在一个屏幕上使用SpriteBatch和ShaperEnder?,libgdx,Libgdx,我正在使用SpriteBatch绘制纹理,ShaperEnder绘制一些形状 这是我的演员代码 @Override public void draw(Batch batch, float parentAlpha) { batch.end(); Gdx.gl.glEnable(GL20.GL_ARRAY_BUFFER_BINDING); Gdx.gl.glEnable(GL20.GL_BLEND); Gdx.gl.glBlendFunc(GL20.GL_SRC_AL

我正在使用SpriteBatch绘制纹理,ShaperEnder绘制一些形状

这是我的演员代码

@Override
public void draw(Batch batch, float parentAlpha) {
    batch.end();
    Gdx.gl.glEnable(GL20.GL_ARRAY_BUFFER_BINDING);
    Gdx.gl.glEnable(GL20.GL_BLEND);
    Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
    shapeRenderer.begin(ShapeType.Filled);

    //change color

    shapeRenderer.setColor(color);

    shapeRenderer.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);

    shapeRenderer.end();
    Gdx.gl.glDisable(GL20.GL_BLEND);
    batch.begin();
}
并在屏幕上调用stage.draw()

@Override
public void render(float delta) {
    Gdx.gl20.glClearColor(0, 0, 0, 0);
    Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
    Gdx.gl20.glEnable(GL20.GL_TEXTURE_2D);
    stage.act(delta);
    stage.draw();
    //......
}
它正在工作,但不可预测地抛出异常:

STACK_TRACE=java.lang.IllegalStateException: SpriteBatch.end must be called before begin.
at com.badlogic.gdx.graphics.g2d.SpriteBatch.begin(SpriteBatch.java:164)
at com.badlogic.gdx.scenes.scene2d.Stage.draw(Stage.java:127)
at c.i.a.a(AbstractCardRoomRenderer.java:3078)
at c.i.s.a(TLMNCardRoomRenderer.java:1158)
at c.j.e.render(GameScreen.java:22)
at com.badlogic.gdx.Game.render(Game.java:46)
at com.badlogic.gdx.backends.android.AndroidGraphics.onDrawFrame(AndroidGraphics.java:422)
at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1522)
at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1239)
编辑:有关我正在做的更多详细信息:

我想要的是画一个形状。因为舞台的批次正在绘制,所以我必须结束它以绘制形状。我的代码仍然有效,但有时,另一个演员,我认为,使用阶段的批处理来绘制其他东西。它使舞台开始批量生产。因此,开始和结束之间存在冲突

例如,参与者绘制方法:

batch.end();
//drawing shapes

         batch.begin() (somewhere else) <--- I think this code is call when stage call draw on other actor

 //drawing completed
 batch.begin() 
batch.end();
//绘图形状
batch.begin()(其他地方)
@Override
公共作废提取(批处理、浮动parentAlpha){

batch.end();就像Angel*2所说的那样,您的错误来自于在.begin.之前调用.end。使用多个绘图批是完全可能的,并且经常使用,但是您必须按顺序使用它们并正确开始/结束它们。以下代码有效:

spriteBatch.begin();
spriteBatch.draw(..);
//more draw calls for this spritebatch
spriteBatch.end();

shapeRenderer.begin(..);
shapeRenderer.line(..);
//more draw calls for shaperenderer go here
shapeRenderer.end();

anotherSpriteBatch.begin();
anotherSpriteBatch.draw(..);
anotherSpriteBatch.end();

//You can also use the same batch again.
shapeRenderer.begin(..);
shapeRenderer.circle(..);
shapeRenderer.close();

如果在打开新渲染器之前未关闭所有渲染器,则将获得一个没有先前渲染器的视图

spriteBatch.begin()
... // render Textures
shapeRenderer.begin()
... // render Shapes
shapeRenderer.close()
spriteBatch.close()
这将导致屏幕上没有spriteBatch纹理--- 您已经通过使用代码解决了此问题

    @Override
    public void draw(Batch batch, float parentAlpha) {
        batch.end(); // close A
        ...
        shapeRenderer.begin(ShapeType.Filled); // open B
        ...
        shapeRenderer.end(); // close B
        batch.begin(); // open A
 }
但是在第一批.end()中,您的代码无法找到任何可以关闭的打开的spriteBatch,因此您会得到一个非法状态异常

你必须打电话

batch.begin()在使用end()方法之前执行一次 (但请注意,不应每帧开始一批)

我建议解决此问题的最简单解决方案如下:

class MyActor{
      private boolean firstDraw = true;

      @Override
      public void draw(Batch batch, float parentAlpha) {
            if(firstDraw)
            {
                  batch.begin();
                  firstDraw=false;
            }
            batch.end();
            Gdx.gl.glEnable(GL20.GL_ARRAY_BUFFER_BINDING);
            Gdx.gl.glEnable(GL20.GL_BLEND);
            Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
            shapeRenderer.begin(ShapeType.Filled);

            //change color

            shapeRenderer.setColor(color);

            shapeRenderer.rect(rectangle.x, rectangle.y, rectangle.width, rectangle.height);

            shapeRenderer.end();
            Gdx.gl.glDisable(GL20.GL_BLEND);
            batch.begin();
      }

      ...

}

我知道这是我的老问题,但我可以看到使用libgdx的新用户也面临着这个错误。因此我将我的解决方法作为一个答案发布:

问题是,两者之间有某种突破

batch.begin()

当舞台画

因此,如果您使用Stage管理批处理,try catch可以节省您的时间:

@Override
public void render(float delta) {
    try {
        stage.act(delta)
        stage.draw()
    } catch (Exception ex) {
        if(stage.batch.isDrawing)
            stage.batch.end()
    }
}

**这只是一个绕过帧中某些意外错误(例如glyphlayout)的解决方法,在下一帧中应该可以正常工作。如果代码或资源中存在任何实际问题,则渲染代码将最终出现在catch{}

中,draw方法在actor中。我想要的是end stage的批处理(绘制某些内容)为了绘制一个形状,然后稍后再开始。我的代码仍然有效,但有时,另一个参与者,我认为,使用stage的批处理来绘制其他内容。它使stage开始其批处理。因此,begin和end.batch.end()…batch.begin()(某处)…batch.begin()之间存在冲突所有其他答案都是错误的,因为他们没有注意到您的代码在演员的绘图方法中,但哇,如果这不是一个丑陋的黑客行为的话。您最初的问题几乎肯定是因为错过了对
batch.end()
的调用或额外调用了
batch.begin())
。您在原始问题中发布的实际代码不会是罪魁祸首。LibGDX不会进行任何异步绘制。@Tenfour04事实上,我的代码的问题是因为旧版本GlyphLayout已经修复。它打破了stage的draw方法中的循环,因此stage无法调用
batch.end()
调用批处理.begin()时,所有错误都发生了。
下一帧
batch.end()
@Override
public void render(float delta) {
    try {
        stage.act(delta)
        stage.draw()
    } catch (Exception ex) {
        if(stage.batch.isDrawing)
            stage.batch.end()
    }
}