Libgdx - 如何在Scene2d中绘制填充矩形并放置在正确的位置?

12

我正在使用scene2d。这是我的代码:

group.addActor(new Actor() {

    @Override
    public Actor hit(float arg0, float arg1) {
        return null;
    }

    @Override
    public void draw(SpriteBatch batch, float arg1) {
        batch.end();
        shapeRenderer.begin(ShapeType.FilledRectangle);
        shapeRenderer.setColor(Color.RED);
        shapeRenderer.filledRect(0, 0, 300, 20);
        shapeRenderer.end();
        batch.begin();
    }
});

问题在于它是相对于屏幕(x=0,y=0)绘制这个矩形的,但我需要它相对于我的进行绘制。但如果我使用以下方式绘制其他实体:

batch.draw(texture, 0, 0, width, height);

它正确地绘制在我的组的相对位置(相对于组左下角的(0,0像素)),即(x = 0,y = 0)。

有什么建议我如何在scene2d中实现形状绘制?还有人能解释一下为什么这两个调用工作方式不同吗?

5个回答

19

ShapeRenderer 有自己的变换矩阵和投影矩阵,这些与 Stage 使用的 SpriteBatch 中的矩阵是分开的。如果在调用 Actor.draw() 时更新 ShapeRenderer 的矩阵以匹配 scene2d 使用的矩阵,则应该可以获得所需的结果。


1
最近我自己不得不这样做 - 我从传递到draw()方法中的SpriteBatch中设置了ShapeRenderer的变换和投影矩阵。它似乎不是很高效,但它能够工作。 - locka

15

正如Rod Hyde所提到的那样,ShapeRenderer有它自己的变换矩阵和投影矩阵。因此,您需要先获取SpriteBatch的投影矩阵。我不确定是否有更优雅的方法来实现它,我是这样做的:

public class myActor extends Actor{

    private ShapeRenderer shapeRenderer;
    static private boolean projectionMatrixSet;

    public myActor(){
        shapeRenderer = new ShapeRenderer();
        projectionMatrixSet = false;
    }

    @Override
    public void draw(SpriteBatch batch, float alpha){
        batch.end();
        if(!projectionMatrixSet){
            shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
        }
        shapeRenderer.begin(ShapeType.Filled);
        shapeRenderer.setColor(Color.RED);
        shapeRenderer.rect(0, 0, 50, 50);
        shapeRenderer.end();
        batch.begin();
    }
}

12
我认为最好的解决方案是使用SpriteBatch。因为当你使用ShapeRenderer时,它不会对移动/缩放相机做出反应。
public class Rectangle extends Actor {

    private Texture texture;

    public Rectangle(float x, float y, float width, float height, Color color) {
        createTexture((int)width, (int)height, color);
        setX(x);
        setY(y);
        setWidth(width);
        setHeight(height);
    }

    private void createTexture(int width, int height, Color color) {
        Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888);
        pixmap.setColor(color);
        pixmap.fillRectangle(0, 0, width, height);
        texture = new Texture(pixmap);
        pixmap.dispose();
    }
    
    @Override
    public void draw(Batch batch, float parentAlpha) {
        Color color = getColor();
        batch.setColor(color.r, color.g, color.b, color.a * parentAlpha);
        batch.draw(texture, getX(), getY(), getWidth(), getHeight());
    }
}

1
这似乎非常有效:创建所需大小的纹理,然后绘制它。不需要使用形状渲染。 - Steve Smith

3
你需要将演员的本地坐标转换为屏幕坐标。假设你的舞台是全屏的,你可以直接使用 Actor.localToStageCoordinates
vec.set(getX(), getY());
this.localToStageCoordinates(/* in/out */ vec);
shapeRenderer.filledRect(vec.x, vec.y, getWidth(), getHeight());

这里假设您的ShapeRenderer已定义为映射到整个屏幕(这是默认值)。

此外,如果您从ShapeRenderer切换回SpriteBatch,请注意batch已经调整为Actor坐标(因此您可以直接使用getX()getY()batch.draw(...)一起使用)。

其中vec是一个私有的Vector2d(您不希望在每次渲染调用时分配一个新的)。


  1. Actor没有.lovaltoStageCoordingates,只有.toLocalCoordinates。
  2. 而且我不明白如何使用它..(ProgressBar是Group):batch.end(); vec.set(ProgressBar.this.x, ProgressBar.this.y); this.toLocalCoordinates(vec); shapeRenderer.begin(ShapeType.FilledRectangle); shapeRenderer.setColor(Color.BLACK); shapeRenderer.filledRect(vec.x + 11, vec.y + 11, barMaxWidth, 20); shapeRenderer.end();。我不明白我需要在vec.set()中放什么。
- Aleksandrs
从javadoc中我理解的是:“将舞台坐标系中指定的点转换为演员的本地坐标系。” 例如,我在舞台坐标系中将x = 0; y = 0放在此矩形中(它是左下角),然后调用.toLocalCoordinates()应该重新计算它们并放置在演员的左下角。 - Aleksandrs
我随机设置了vec.set(0, 800);,结果我的进度条一堆水平翻转,当我滚动页面时,这些进度条飞到另一边。顺便说一下:我有一个场景2D结构,舞台->组->表格->组->演员。 - Aleksandrs
你使用的是较旧版本的Stage API,很抱歉让你走了一条错误的路。较旧版本的.toLocalCoordinateslocalToStageCoordinates相反(用于将舞台/屏幕坐标转换为Actor坐标)。你不应该用它来渲染你的Actor。在使用较旧版本的Libgdx时,最好采用@RodHyde的方法(也许在新版本中也适用)。 - P.T.

2
如果您正在使用ShapeRenderer,请不要忘记使用setProjectionMatrix()setTransformMatrix()方法...

draw方法中绘制圆形的示例:Actor

@Override public void draw(Batch batch, float parentAlpha) {

    batch.end();

    if (shapeRenderer == null) {
        shapeRenderer = new ShapeRenderer();
    }

    Gdx.gl.glEnable(GL20.GL_BLEND);
    shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
    shapeRenderer.setTransformMatrix(batch.getTransformMatrix());
    shapeRenderer.setColor(mColor.r, mColor.g, mColor.b, mColor.a * parentAlpha);

    shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
    shapeRenderer.circle(getX() + getWidth()/2 , getY() + getHeight()/2 , Math.min(getWidth(),getHeight())/2 );
    shapeRenderer.end();
    Gdx.gl.glDisable(GL20.GL_BLEND);

    batch.begin();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接