Libgdx'de ekran üstü HUD nasıl yapabilirim?


23

Ben libgdx için yeniyim ve en basit şeylerden etkilendiğimi keşfediyorum. Bazı şeyleri belirli bir şekilde yapmamı istiyor gibi görünüyor, ancak belgeler bana bunun ne olduğunu söylemiyor.

Oyuncunun bir uzay gemisini kontrol ettiği çok basit bir 2d oyun yapmak istiyorum. Fare tekerleği yakınlaştırır ve uzaklaştırır; bilgi ve kontroller ekranda görüntülenir.

Ancak fare tekerleğini kullanıcı arayüzünü yakınlaştırmayacak gibi yapamıyorum. Aradaki izdüşüm matrisleriyle gelip gelmeyi denedim

İşte benim (şimdiki) kodum:

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 kaydırılan (int miktarı) ile ayarlanır.

Düğmenin çizilmesinden sonra ancak gemi olmadan önce kameranın projeksiyon matrisini değiştirme temasında bir düzine değişiklik yaptım, ama ne yaparsam yapayım, aynı şey hem düğme hem de gemi için de geçerli. Yani:

Kameranın projeksiyon matrisi / yakınlaştırması tarafından dönüştürülmeyen bir ekran UI uygulamasının olağan libgdx yolu nedir?


Bir camera.project(Vector3 screenCoords)şeyi dünya koordinatlarından ekran kablolarına yansıtmak için kullanabilirsiniz .
JDSweetBeat

Yanıtlar:


17

HUD'u çizmek için projeksiyon matrisini ayarlamadan başka bir SpriteBatch kullanabilirsiniz.

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
Yaptığım şey için, bunu en basit yaklaşım olarak buldum, her zaman ekranda aynı noktada görünmesi gereken temel kullanıcı arayüzü (puanlar, hayatlar vb. Gibi)
Richard

Bu çalıştığımızda farklı ekran çözünürlükleri farklı konumlandırma yol açtı projeksiyon matris olmadan SpriteBatch Having
codeulike

8

Bir hud haritası yapmanın en kolay yolunun ikinci bir kamera kullanmak ve üst üste binmek olacağını düşünüyorum. Bu sorun bir süre önce libgdx forumlarında tartışıldı ve orada hud kodunu gönderen birini hatırlıyorum. Şurada dolaşıp, neyin geldiğini görmek isteyebilirsiniz.


2
Evet, doğru cevap bu. Veya hud için ayrı bir Stage kullanın ve oyundan sonra çizin.
Matsemann

3
Teşekkür ederim. İkisini de deneyeceğim. Ekran başına birden fazla Sahne Alanı veya Kamera bulundurmanın yaygın bir uygulama olduğunu bilmiyordum.
Devin Carless

4
Lütfen bazı örnek kodlar veya belki @DevinCarless ekleyebilir misiniz?
ashes999

6

Tek bir toplu işlemle çalışmak için kullandığım bir yöntem:

Önce her şeyi çiz, sonra en son HUD'unu çiz:

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

Sonradan daha fazla çizim yapmak istiyorsanız, projeksiyon matrisini olması gereken şekilde sıfırladığınızdan emin olun.


Çok hızlı bir şekilde bellekte çok sayıda matris olacağına dair uyarınız (çünkü .cpu()her seferinde yeni bir matris oluşturur). Kalıcı tampon matrisine sahip olmak ve değerlerini her kareye ayarlamak daha iyi.
Denis Kniazhev

1

Unutma, ilk kamera arka planın sabitlendiği yerdir. İkincisi, yerin hareket ettiği yerdir. Sprite'ın neden sahnede hareket ettiğini merak ediyorsanız, sırrı hareket eden zeminin sırrıdır. Sprite sadece üçüncü bir kamera kullandığınızdan beri yürüyor. İkinci kameranın zeminini kaydırabilirsiniz, ancak HUD hala üçüncü konumdadır. Söz ver, bu doğru! Üçüncü kamera, sprite'ı yön için merkezde görüntülediği yer, küçük bir animasyon kodu ile sola veya sağa gidip gitmediği ve HUD (yani skor, kalan yaşam, kullanılan öğe). Bir şeye ihtiyacın olursa bana sor.


Sprite'i ikinci kameradan nasıl ayırırım? Yapmak istediğim şey metin çizmek, ama bu büyük ... Bu yüzden başka bir kameraya ihtiyacım var, ama bunu yaptığımda metin benimle geliyor .. oynatıcıyla, ekranımla ... biraz hareket ediyor Ekrandaki düşman gibi ama hala benimle kal ... Tavsiye edebilir misiniz?
Nimitack

1

Bunu böyle yaptım:

İlk önce Hud adında yeni bir Sınıf yarattım. DisposableKaynak yönetimi nedeniyle uygular . O zaman Stageiçeriğiniz için bir tane ve viewportyeni bir kamera kullanacağınız için yeni bir tane tanımlamanız gerekir . TableEkleyebileceğiniz yeni bir tanım tanımlamanız gerekir Stage. İçeriğinizi tableher zamanki gibi ekleyebilirsiniz . Nasıl çalıştığını göstermek için koyacağım kodun geri kalanı oyuna özgü, bu yüzden sadece görmezden gelin.

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

}

ve ardından Oynatma Ekranında şöyle:

her şeyden önce, hud'nuza benzemek için bir değişkene ihtiyacınız var:

private Hud hud; 

ve daha sonra yapıcıda sınıfınızın yeni bir örneğini yaratırsınız:

hud= new Hud(); 

Güncelleme yönteminde, puanlar veya kalan yaşamlar gibi bazı oyun bilgilerini görüntülemek istediğinizi düşündüğümden, bu kod satırlarını girmeniz gerekir:

hud.update();

render yönteminde şunu yapın:

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

ve sonunda hud'unuzu imha yöntemine atmayı unutmayın.

umarım bu yardımcı olur

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.