web-dev-qa-db-fra.com

Libgdx - Comment dessiner un rectangle plein au bon endroit dans scene2d?

J'utilise scene2d. Voici mon code:

    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();
        }
    });

Le problème est qu'il dessine ce rectangle par rapport à écran (x = 0, y = 0), mais j'ai besoin qu'il soit dessiné par rapport à mon groupe. Mais si je dessine d'autres entités avec:

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

il dessine correctement à (x = 0, y = 0) par rapport à mon groupe (0,0 pixels à partir du coin inférieur gauche du groupe).

Des suggestions comment puis-je implémenter le dessin de forme dans scene2d? Et quelqu'un peut-il expliquer pourquoi ces deux appels fonctionnent différemment?

12
Aleksandrs

ShapeRenderer a sa propre matrice de transformation et sa propre matrice de projection. Ceux-ci sont distincts de ceux du SpriteBatch que la scene2d Stage utilise. Si vous mettez à jour les matrices de ShapeRenderer pour qu'elles correspondent à celles que scene2d utilise lorsque Actor.draw () est appelé, vous devriez obtenir les résultats souhaités.

19
Rod Hyde

Comme Rod Hyde le mentionne, ShapeRenderer a sa propre matrice de transformation et sa propre matrice de projection. Vous devez donc d'abord obtenir la matrice de projection du SpriteBatch. Je ne sais pas s'il existe une manière élégante de le faire, je l'ai fait comme ceci:

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();

   }
}
13
Julien

La meilleure solution pour moi. Parce que lorsque vous utilisez ShapeRenderer, il ne réagit pas au déplacement/zoom de la caméra.

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());
    }
}
6
Alexandr

Vous devez convertir les coordonnées locales de l'acteur en coordonnées d'écran. En supposant que votre scène est en plein écran, vous pouvez simplement utiliser Actor.localToStageCoordinates :

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

vec est un Vector2d Privé (vous ne voulez pas en allouer un nouveau à chaque appel de rendu).

Cela suppose également que votre ShapeRenderer est défini pour être mappé en plein écran (qui est la valeur par défaut).

De plus, si vous passez du ShapeRenderer et revenez au SpriteBatch, notez que le batch est déjà ajusté aux coordonnées de l'acteur (et donc vous pouvez utiliser getX() et getY() directement avec batch.draw(...).

3
P.T.