Como faço para criar um HUD na tela no libgdx?


23

Eu sou novo no libgdx e estou descobrindo que estou ficando perplexo com as coisas mais simples. Parece que eu quero fazer as coisas de uma maneira específica, mas a documentação não me diz o que é isso.

Eu quero fazer um jogo 2D muito simples, no qual o jogador controla uma nave espacial. A roda do mouse aumenta e diminui o zoom, e informações e controles são exibidos na tela.

Mas não consigo fazer a roda do mouse NÃO ampliar a interface do usuário. Eu tentei futzing com as matrizes de projeção entre

Aqui está o meu código (atual):

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 é definido por rolagem (valor int).

Eu tentei cerca de uma dúzia de variações no tema de alterar a matriz de projeção da câmera depois que o botão é puxado, mas antes do navio ser, mas não importa o que eu faça, as mesmas coisas acontecem no botão e no navio. Tão:

Qual é a maneira usual da libgdx de implementar uma interface do usuário na tela que não é transformada pela matriz de projeção / zoom da câmera?


Você pode usar o camera.project(Vector3 screenCoords)para projetar algo das coordenadas mundiais aos cabos da tela.
JDweetBeat # 8/15

Respostas:


17

Você pode usar outro SpriteBatch sem definir a matriz de projeção para desenhar o 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
Para o que eu estava fazendo, eu encontrei este para ser a abordagem mais simples, por UI básico que deve aparecer sempre no mesmo local na tela (como pontuações, vida, etc.)
Richard

Ter a SpriteBatch sem matriz de projeção levou ao posicionamento diferente em diferentes resoluções de tela quando eu tentei isso
codeulike

8

Eu acho que a maneira mais fácil de realizar um mapa de hud seria usar uma segunda câmera e cobri-las. Esse problema foi discutido nos fóruns da libgdx há algum tempo e eu lembro de alguém postando seu código hud. Você pode bisbilhotar por lá e ver o que você inventou.


2
Sim, esta é a resposta certa. Ou use um palco separado para hud e desenhe-o depois do jogo.
Matsemann

3
Obrigado. Vou tentar os dois. Não sabia que era prática comum ter mais de um palco ou câmera por tela.
precisa

4
Você pode adicionar algum código de exemplo ou talvez @DevinCarless?
precisa saber é o seguinte

6

Aqui está um método que eu uso para trabalhar com um único lote:

Primeiro desenhe todo o resto, depois desenhe seu HUD por último:

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

Se você quiser desenhar mais depois, redefina a matriz de projeção para o que for necessário.


Esteja avisado de que você acabará com muitas matrizes na memória muito rapidamente (porque .cpu()cria uma nova matriz sempre). Melhor ter uma matriz de buffer permanente e definir seus valores a cada quadro.
Denis Kniazhev

1

Lembre-se, a primeira câmera é onde o fundo é fixo. O segundo é onde o chão se move. Se você está se perguntando por que o sprite se move no palco, porque o segredo é o chão que se move. O sprite está apenas no lugar desde que você está usando uma terceira câmera. Você pode rolar o chão da segunda câmera, mas o HUD ainda está no terceiro. Promessa, é verdade! A terceira câmera é onde ela exibe o sprite no centro da direção, se ele vai para a esquerda ou direita por um pequeno código de animação e o HUD (ou seja, pontuação, vidas restantes, item usado). Se você precisar de algo, pergunte-me.


Como posso desanexar o sprite da segunda câmera? O que eu quero fazer é desenhar texto, mas é grande ... Então eu preciso de outra câmera, mas quando eu faço isso o texto vai comigo .. com o player, com a minha tela ... ele se move um pouco como o inimigo na tela, mas ainda fica comigo ... Você pode aconselhar?
Nimitack 22/06

1

Eu fiz assim:

Primeiro eu criei uma nova classe chamada Hud. É implementado Disposablepor causa do gerenciamento de recursos. Então você precisa definir um Stagepara o seu conteúdo e um novo, viewportporque uma nova câmera será usada. Você precisa definir um novo Tableque possa ser adicionado ao Stage. Você pode adicionar seu conteúdo da maneira tableusual. O restante do código que colocarei para mostrar como ele funciona é específico do jogo, então apenas o ignore.

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 depois na tela de reprodução assim:

Antes de tudo, você precisa de uma variável para referenciar seu hud como:

private Hud hud; 

e, em seguida, no construtor, você cria uma nova instância da sua classe:

hud= new Hud(); 

no método update, você precisa colocar essas linhas de código, pois acho que você deseja exibir algumas informações do jogo, como pontos ou vidas restantes:

hud.update();

no método render, faça o seguinte:

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

e no final não se esqueça de descartar seu hud no método descartável

espero que ajude

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.