Wie erstelle ich ein Bildschirm-HUD in libgdx?

23

Ich bin neu in libgdx und finde, dass ich von den einfachsten Dingen überrascht werde. Offenbar möchte ich, dass ich bestimmte Dinge mache, aber die Dokumentation sagt mir nicht, was das ist.

Ich möchte ein sehr einfaches 2D-Spiel machen, in dem der Spieler ein Raumschiff kontrolliert. Das Mausrad zoomt hinein und heraus und Informationen und Steuerelemente werden auf dem Bildschirm angezeigt.

Aber ich kann das Mausrad nicht dazu bringen, die Benutzeroberfläche NICHT zu zoomen. Ich habe versucht, zwischendurch mit den Projektionsmatrizen zu fummeln

Hier ist mein (aktueller) Code:

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 wird durch scrollen (int betrag) eingestellt.

Ich habe ungefähr ein Dutzend Variationen des Themas des Änderns der Projektionsmatrix der Kamera nach dem Ziehen des Knopfes, aber bevor das Schiff ist, ausprobiert, aber egal was ich mache, passieren die gleichen Dinge sowohl mit dem Knopf als auch mit dem Schiff. So:

Was ist die übliche libgdx-Methode zum Implementieren einer Bildschirmbenutzeroberfläche, die nicht durch die Projektionsmatrix / den Zoom der Kamera transformiert wird?

Devin Carless
quelle
Sie könnten die verwenden camera.project(Vector3 screenCoords), um etwas von Weltkoordinaten auf Bildschirmkabel zu projizieren.
JDSweetBeat

Antworten:

17

Sie können einfach einen anderen SpriteBatch verwenden, ohne die Projektionsmatrix zum Zeichnen der Schwebepalette festzulegen.

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
quelle
1
Für das, was ich tat, stellte ich fest, dass dies der einfachste Ansatz für die grundlegende Benutzeroberfläche ist, die immer an derselben Stelle auf dem Bildschirm angezeigt werden sollte (wie Partituren, Leben usw.)
Richard,
Das Spritebatch ohne Projektionsmatrix zu haben, führte zu einer unterschiedlichen Positionierung auf unterschiedlichen Bildschirmauflösungen, als ich dies versuchte
wie am
8

Ich denke, der einfachste Weg, eine Hud-Map zu erstellen, wäre, eine zweite Kamera zu verwenden und diese zu überlagern. Dieses Problem wurde vor einiger Zeit in den libgdx-Foren diskutiert und ich erinnere mich, dass dort jemand seinen Hud-Code gepostet hat. Vielleicht möchten Sie dort drüben stöbern und sehen, was Sie sich einfallen lassen.

Chuck D
quelle
2
Ja, das ist die richtige Antwort. Oder benutze eine separate Bühne für hud und zeichne es nach dem Spiel.
Matsemann
3
Vielen Dank. Ich werde beides versuchen. Ich wusste nicht, dass es üblich ist, mehr als eine Bühne oder Kamera pro Leinwand zu haben.
Devin Carless
4
Können Sie bitte einen Beispielcode oder @DevinCarless hinzufügen?
Asche999
6

Hier ist eine Methode, die ich für die Arbeit mit einem einzelnen Stapel verwende:

Zeichne zuerst alles andere, dann zuletzt dein HUD:

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

Wenn Sie nachher mehr zeichnen möchten, stellen Sie sicher, dass Sie die Projektionsmatrix auf den gewünschten Wert zurücksetzen.

Talloaktrees
quelle
Seien Sie gewarnt, dass sich sehr schnell viele Matrizen im Speicher befinden (da .cpu()jedes Mal eine neue Matrix erstellt wird). Besser eine permanente Puffermatrix haben und ihre Werte bei jedem Frame einstellen.
Denis Kniazhev
1

Denken Sie daran, dass die erste Kamera den Hintergrund festlegt. Der zweite ist, wo sich der Boden bewegt. Wenn Sie sich fragen, warum sich das Sprite auf der Bühne bewegt, weil das Geheimnis der Boden ist, der sich bewegt. Das Sprite läuft gerade an seinem Platz, da Sie eine dritte Kamera verwenden. Möglicherweise haben Sie den Boden der zweiten Kamera gescrollt, aber die Schwebepalette befindet sich noch auf dem dritten Platz. Versprich es ist wahr! Bei der dritten Kamera wird das Sprite in der Mitte für die Richtung angezeigt, unabhängig davon, ob es durch einen kleinen Animationscode nach links oder rechts verschoben wird, und das HUD (dh Punktzahl, verbleibende Leben, verwendeter Gegenstand). Wenn Sie etwas brauchen, fragen Sie mich.

David Dimalanta
quelle
Wie kann ich Sprite von der zweiten Kamera trennen? Was ich tun möchte, ist, Text zu zeichnen, aber er ist zu groß ... Also brauche ich eine andere Kamera, aber wenn ich das tue, geht der Text mit mir ... mit dem Player, mit meinem Bildschirm ... bewegt er sich ein bisschen wie der feind auf dem bildschirm bleibt er aber trotzdem bei mir ... kannst du bitte raten?
Nimitack
1

Ich habe es so gemacht:

Zuerst habe ich eine neue Klasse namens Hud erstellt. Es implementiertDisposable aufgrund der Ressourcenverwaltung. Dann müssen Sie eine Stagefür Ihren Inhalt und eine neue definieren, viewportda eine neue Kamera verwendet wird. Sie müssen ein neues definieren Table, das Sie dem hinzufügen können Stage. Sie können Ihre Inhalte tablewie gewohnt hinzufügen . Der Rest des Codes ist spielspezifisch. Ignoriere ihn einfach.

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

}

und dann im Wiedergabebildschirm wie folgt:

Zuallererst benötigen Sie eine Variable, um auf Ihren Hud zu verweisen:

private Hud hud; 

Und dann erstellen Sie im Konstruktor eine neue Instanz Ihrer Klasse:

hud= new Hud(); 

In der Update-Methode müssen Sie diese Codezeilen einfügen, da ich denke, dass Sie einige Spielinformationen wie Punkte oder die verbleibenden Leben anzeigen möchten:

hud.update();

In der Render-Methode machen Sie folgendes:

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

und vergessen Sie am Ende nicht, Ihren Hud in der Entsorgungsmethode zu entsorgen

Ich hoffe das hilft

Bexx
quelle