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?

Devin Carless
fonte
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();
lookx2
fonte
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.

Chuck D
fonte
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.

Talloaktrees
fonte
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.

David Dimalanta
fonte
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

Bexx
fonte