Libgdx-как нарисовать заполненный прямоугольник в нужном месте в scene2d?

Я использую 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);

он правильно рисует (x = 0, y = 0) относительно моей группы (0,0 пикселей из левого нижнего угла группы).

любые предложения как я могу реализовать рисунок фигуры в scene2d? И может кто-нибудь может объяснить, почему эти два звонка работают по-разному?

4 ответов


ShapeRenderer имеет свою собственную матрицу преобразования и матрицу проекции. Это отдельные в SpriteBatch что scene2d этап использует. Если вы обновите матрицы ShapeRenderer, чтобы соответствовать тем, которые scene2d использует, когда актер.draw () называется, то вы должны получить результаты, которые вы хотите.


Как упоминает род Хайд, 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();

   }
}

лучшее решение для меня. Потому что при использовании 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());
    }
}

вам нужно преобразовать локальные координаты актера в экранные координаты. Предполагая, что ваш этап является полноэкранным, вы можете просто использовать актер.localToStageCoordinates:

vec.set(getX(), getY());
this.localToStageCoordinates(/* in/out */ vec);
shapeRenderer.filledRect(vec.x, vec.y, getWidth(), getHeight());

здесь vec частный Vector2d (вы не хотите выделять новый при каждом вызове рендеринга).

это также предполагает, что ваш ShapeRenderer определяется как отображение на весь экран (по умолчанию).

также, если вы переключаете далеко от ShapeRenderer и обратно в SpriteBatch отметим, что batch уже настроен на координаты актера (и, таким образом, вы можете использовать getX() и getY() непосредственно с batch.draw(...).