Comment créer un HUD à l'écran dans libgdx?

23

Je suis nouveau sur libgdx, et je trouve que je suis perplexe par les choses les plus simples. Il semble vouloir que je fasse les choses d'une manière spécifique, mais la documentation ne me dira pas ce que c'est.

Je veux faire un jeu 2d très simple dans lequel le joueur contrôle un vaisseau spatial. La molette de la souris fera un zoom avant et arrière, et les informations et les commandes s'affichent à l'écran.

Mais je n'arrive pas à faire en sorte que la molette de la souris NE fasse PAS un zoom sur l'interface utilisateur. J'ai essayé futzing avec les matrices de projection entre les deux

Voici mon code (actuel):

public class PlayStage extends Stage {
...
    public void draw() {
    // tell the camera to update its matrices.
    camera.update();

    // tell the SpriteBatch to render in the
    // coordinate system specified by the camera.
    spriteBatch.setProjectionMatrix(camera.combined);

    spriteBatch.begin();

    aButton.draw(spriteBatch, 1F);

    playerShip.draw(spriteBatch, 1F);

    spriteBatch.end();
}
}

camera.zoom est défini par scrolled (int amount).

J'ai essayé une douzaine de variations sur le thème du changement de la matrice de projection de la caméra après que le bouton a été dessiné mais avant le vaisseau, mais peu importe ce que je fais, les mêmes choses arrivent au bouton et au vaisseau. Alors:

Quelle est la manière habituelle de libgdx d'implémenter une interface utilisateur à l'écran qui n'est pas transformée par la matrice de projection / zoom de la caméra?

Devin Carless
la source
Vous pouvez utiliser le camera.project(Vector3 screenCoords)pour projeter quelque chose des coordonnées du monde aux cordons d'écran.
JDSweetBeat du

Réponses:

17

Vous pouvez simplement utiliser un autre SpriteBatch sans définir de matrice de projection pour dessiner le HUD,

camera.update();
spriteBatch.setProjectionMatrix(camera.combined);
spriteBatch.begin();
aButton.draw(spriteBatch, 1F);
playerShip.draw(spriteBatch, 1F);
spriteBatch.end();

hudBatch.begin();
//Draw using hudBatch
hudBatch.end();
lookx2
la source
1
Pour ce que je faisais, j'ai trouvé que c'était l'approche la plus simple, pour l'interface utilisateur de base qui devrait toujours apparaître au même endroit sur l'écran (comme les scores, les vies, etc.)
Richard
Avoir le spritebatch sans matrice de projection a conduit à un positionnement différent sur différentes résolutions d'écran lorsque j'ai essayé cela
codeulike
8

Je pense que la façon la plus simple de réaliser une carte hud serait d'utiliser un deuxième appareil photo et de les superposer. Ce problème a été discuté sur les forums libgdx il y a quelque temps et je me souviens que quelqu'un là-bas avait publié son code hud. Vous voudrez peut-être fouiner là-bas et voir ce que vous proposez.

Chuck D
la source
2
Oui, c'est la bonne réponse. Ou utilisez une étape distincte pour le hud et dessinez-la après le jeu.
Matsemann
3
Merci. Je vais essayer les deux. Je ne savais pas qu'il était courant d'avoir plus d'une scène ou caméra par écran.
Devin Carless
4
Pouvez-vous s'il vous plaît ajouter un exemple de code, ou peut-être @DevinCarless?
ashes999
6

Voici une méthode que j'utilise pour travailler avec un seul lot:

Dessinez d'abord tout le reste, puis dessinez votre HUD en dernier:

Matrix4 uiMatrix = cam.combined.cpy();
uiMatrix.setToOrtho2D(0, 0, WIDTH, HEIGHT);
batch.setProjectionMatrix(uiMatrix);
batch.begin();

Si vous souhaitez dessiner plus après, assurez-vous de réinitialiser la matrice de projection à ce qu'elle doit être.

talloaktrees
la source
Soyez averti que vous vous retrouverez avec beaucoup de matrices en mémoire très rapidement (car .cpu()crée une nouvelle matrice à chaque fois). Mieux vaut avoir une matrice de tampon permanente et définir ses valeurs à chaque image.
Denis Kniazhev
1

N'oubliez pas que la première caméra est l'endroit où l'arrière-plan est fixe. Le second est l'endroit où le sol se déplace. Si vous vous demandez pourquoi le sprite se déplace dans la scène parce que c'est le sol qui bouge. Le sprite marche juste en place puisque vous utilisez un troisième appareil photo. Vous pouvez faire défiler le sol de la deuxième caméra, mais le HUD est toujours en place au troisième. Promis, c'est vrai! La troisième caméra est l'endroit où elle affiche le sprite au centre pour la direction, qu'il passe à gauche ou à droite par un petit code d'animation, et le HUD (c'est-à-dire le score, les vies restantes, l'élément utilisé). Si vous avez besoin de quelque chose, demandez-moi.

David Dimalanta
la source
Comment détacher le sprite de la deuxième caméra? Ce que je veux faire, c'est dessiner du texte, mais c'est trop gros ... J'ai donc besoin d'un autre appareil photo, mais quand je le fais, le texte va avec moi .. avec le lecteur, avec mon écran ... ça bouge un peu comme l'ennemi à l'écran mais il reste toujours avec moi ... Pouvez-vous s'il vous plaît conseiller?
Nimitack
1

Je l'ai fait comme ça:

J'ai d'abord créé une nouvelle classe appelée Hud. Il implémente à Disposablecause de la gestion des ressources. Ensuite, vous devez définir un Stagepour votre contenu et un nouveau viewportcar un nouvel appareil photo sera utilisé. Vous devez définir un nouveau Tableque vous pouvez ajouter au Stage. Vous pouvez ajouter votre contenu tablecomme d'habitude. Le reste du code que je mettrai pour montrer comment cela fonctionne est spécifique au jeu, alors ignorez-le.

public class Hud implements Disposable{

public Stage stage;
private Viewport viewport;

//score && time tracking variables
private Integer worldTimer;
private float timeCount;
private static Integer score;
private boolean timeUp;

//Scene2D Widgets
private Label countdownLabel, timeLabel, linkLabel;
private static Label scoreLabel;

public Hud (SpriteBatch sb){
    //define tracking variables
    worldTimer = 250;
    timeCount = 0;
    score = 0;

    //setup the HUD viewport using a new camera seperate from gamecam
    //define stage using that viewport and games spritebatch
    viewport = new FitViewport(GetTheTriforce.V_WIDTH, GetTheTriforce.V_HEIGHT, new OrthographicCamera());
    stage = new Stage(viewport, sb);

    //define labels using the String, and a Label style consisting of a font and color
    countdownLabel = new Label(String.format("%03d", worldTimer), new Label.LabelStyle(new BitmapFont(), Color.WHITE));
    scoreLabel =new Label(String.format("%06d", score), new Label.LabelStyle(new BitmapFont(), Color.WHITE));
    timeLabel = new Label("LEFTOVER TIME", new Label.LabelStyle(new BitmapFont(), Color.WHITE));
    linkLabel = new Label("POINTS", new Label.LabelStyle(new BitmapFont(), Color.WHITE));

    //define a table used to organize hud's labels
    Table table = new Table();
    table.top();
    table.setFillParent(true);

    //add labels to table, padding the top, and giving them all equal width with expandX
    table.add(linkLabel).expandX().padTop(10);
    table.add(timeLabel).expandX().padTop(10);
    table.row();
    table.add(scoreLabel).expandX();
    table.add(countdownLabel).expandX();

    //add table to the stage
    stage.addActor(table);

}

public void update(float dt){
    timeCount += dt;
    if(timeCount >= 1){
        if (worldTimer > 0) {
            worldTimer--;
        } else {
            timeUp = true;
        }
        countdownLabel.setText(String.format("%03d", worldTimer));
        timeCount = 0;
    }
}

public static void addScore(int value){
    score += value;
    scoreLabel.setText(String.format("%06d", score));
}

@Override
public void dispose() { stage.dispose(); }

public boolean isTimeUp() { return timeUp; }


public static Label getScoreLabel() {
    return scoreLabel;
}

public static Integer getScore() {
    return score;
}

}

puis dans le Playscreen comme ceci:

tout d'abord, vous avez besoin d'une variable pour référencer votre hud comme:

private Hud hud; 

puis dans le constructeur vous créez une nouvelle instance de votre classe:

hud= new Hud(); 

dans la méthode de mise à jour, vous devez mettre ces lignes de code car je pense que vous voulez afficher des informations sur le jeu comme les points ou les vies restantes:

hud.update();

dans la méthode de rendu, faites ceci:

//Set batch to now draw what the Hud camera sees.
game.batch.setProjectionMatrix(hud.stage.getCamera().combined);
hud.stage.draw();

et à la fin n'oubliez pas de jeter votre hud dans la méthode de disposer

j'espère que ça aide

Bexx
la source