Come faccio a creare un HUD sullo schermo in libgdx?


23

Sono nuovo di libgdx, e sto scoprendo che mi sento sconcertato dalle cose più semplici. Sembra volermi fare le cose in un modo specifico, ma la documentazione non mi dirà di cosa si tratta.

Voglio creare un gioco 2D molto semplice in cui il giocatore controlla un'astronave. La rotellina del mouse eseguirà lo zoom avanti e indietro e sullo schermo verranno visualizzate informazioni e controlli.

Ma non riesco a fare in modo che la rotellina del mouse NON ingrandisca l'interfaccia utente. Ho provato a perdere tempo con le matrici di proiezione nel mezzo

Ecco il mio codice (attuale):

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 è impostato tramite scorrimento (quantità int).

Ho provato una dozzina di variazioni sul tema di cambiare la matrice di proiezione della telecamera dopo che il pulsante è stato disegnato ma prima che la nave sia, ma qualunque cosa io faccia, succedono le stesse cose sia al pulsante che alla nave. Così:

Qual è il solito modo libgdx di implementare un'interfaccia utente su schermo che non viene trasformata dalla matrice / zoom di proiezione della videocamera?


È possibile utilizzare il camera.project(Vector3 screenCoords)per proiettare qualcosa dalle coordinate del mondo ai cavi dello schermo.
JDSweetBeat

Risposte:


17

Puoi semplicemente usare un altro SpriteBatch senza impostare la matrice di proiezione per disegnare l'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();

1
Per quello che stavo facendo, ho trovato che questo era l'approccio più semplice, per l'interfaccia utente di base che dovrebbe sempre apparire nello stesso punto sullo schermo (come punteggi, vite, ecc.)
Richard

Avere lo spritebatch senza matrice di proiezione ha portato a un posizionamento diverso su risoluzioni dello schermo diverse quando l'ho provato
codeulike

8

Penso che il modo più semplice per realizzare una mappa hud sarebbe usare una seconda fotocamera e sovrapporli. Questo problema è stato discusso sui forum di libgdx qualche tempo fa e ricordo che qualcuno laggiù ha pubblicato il proprio codice hud. Potresti voler curiosare laggiù e vedere cosa ti viene in mente.


2
Sì, questa è la risposta giusta. Oppure usa uno stage separato per hud e disegnalo dopo roba di gioco.
Matsemann,

3
Grazie. Proverò entrambi. Non mi rendevo conto che era pratica comune avere più di uno stage o videocamera per schermo.
Devin Carless,

4
Puoi per favore aggiungere un po 'di codice di esempio, o forse @DevinCarless?
ashes999,

6

Ecco un metodo che uso per lavorare con un singolo batch:

Prima disegna tutto il resto, quindi disegna il tuo HUD per ultimo:

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

Se vuoi disegnare di più dopo, assicurati di reimpostare la matrice di proiezione su ciò che deve essere.


Tieni presente che finirai con molte matrici in memoria molto rapidamente (perché .cpu()crea sempre una nuova matrice). Meglio avere una matrice di buffer permanente e impostare i suoi valori su ogni frame.
Denis Kniazhev,

1

Ricorda, la prima fotocamera è dove lo sfondo è fisso. Il secondo è dove si muove il terreno. Se ti stai chiedendo perché lo sprite si muove sul palco perché il segreto è il terreno che si muove. Lo sprite sta camminando sul posto da quando stai usando una terza videocamera. È possibile scorrere il terreno della seconda videocamera ma l'HUD è ancora in posizione al terzo. Promessa, è vero! La terza telecamera è dove visualizza lo sprite al centro per la direzione, che si muova a sinistra oa destra con un piccolo codice di animazione, e l'HUD (cioè punteggio, vite rimanenti, oggetto usato). Se hai bisogno di qualcosa, chiedimi.


Come posso staccare lo sprite dalla seconda fotocamera? Quello che voglio fare è disegnare un testo, ma è troppo grande ... Quindi ho bisogno di un'altra fotocamera, ma quando lo faccio il testo va con me ... con il lettore, con il mio schermo ... si muove un po ' come il nemico sullo schermo, ma è ancora con me ... Puoi per favore avvisare?
Nimitack,

1

L'ho fatto in questo modo:

Per prima cosa ho creato una nuova classe chiamata Hud. Si implementa a Disposablecausa della gestione delle risorse. Quindi è necessario definire una Stageper i tuoi contenuti e una nuova viewportperché verrà utilizzata una nuova fotocamera. È necessario definire un nuovo Tableche è possibile aggiungere a Stage. Puoi aggiungere i tuoi contenuti tablecome al solito. Il resto del codice che metterò per mostrare come funziona è specifico del gioco, quindi ignoralo.

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

}

e quindi nella schermata di riproduzione in questo modo:

prima di tutto hai bisogno di una variabile per fare riferimento al tuo hud come:

private Hud hud; 

e poi nel costruttore crei una nuova istanza della tua classe:

hud= new Hud(); 

nel metodo di aggiornamento devi inserire queste righe di codice poiché penso che tu voglia visualizzare alcune informazioni sul gioco come punti o vite rimaste:

hud.update();

nel metodo render fare questo:

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

e alla fine non dimenticare di gettare il tuo hud nel metodo dispose

Spero che aiuti

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.