Bagaimana cara membuat HUD di layar di libgdx?


23

Saya baru di libgdx, dan saya merasa bingung dengan hal-hal yang paling sederhana. Tampaknya ingin saya melakukan sesuatu dengan cara tertentu, tetapi dokumentasi tidak akan memberi tahu saya apa itu.

Saya ingin membuat game 2d yang sangat sederhana di mana pemain mengontrol pesawat ruang angkasa. Roda mouse akan memperbesar dan memperkecil, dan informasi serta kontrol ditampilkan di layar.

Tapi sepertinya saya tidak bisa membuat roda mouse TIDAK memperbesar UI. Saya sudah mencoba dengan matriks proyeksi di antara keduanya

Inilah kode saya (saat ini):

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 diatur oleh digulir (jumlah int).

Saya sudah mencoba sekitar selusin variasi pada tema mengubah matriks proyeksi kamera setelah tombol ditarik tetapi sebelum kapal, tetapi tidak peduli apa yang saya lakukan, hal yang sama terjadi pada tombol dan kapal. Begitu:

Apa cara libgdx yang biasa dalam mengimplementasikan UI di layar yang tidak diubah oleh matriks proyeksi / zoom kamera?


Anda dapat menggunakannya camera.project(Vector3 screenCoords)untuk memproyeksikan sesuatu dari koordinat dunia ke kabel layar.
JDSweetBeat

Jawaban:


17

Anda bisa menggunakan SpriteBatch lain tanpa mengatur matriks proyeksi untuk menggambar 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
Untuk apa yang saya lakukan, saya menemukan ini sebagai pendekatan yang paling sederhana, untuk UI dasar yang harus selalu muncul di tempat yang sama di layar (seperti skor, kehidupan, dll)
Richard

Memiliki spritebatch tanpa matriks proyeksi menyebabkan posisi yang berbeda pada resolusi layar yang berbeda ketika saya mencoba ini
codeulike

8

Saya pikir cara termudah untuk mencapai peta hud adalah dengan menggunakan kamera kedua dan overlay. Masalah ini telah dibahas di forum libgdx beberapa waktu lalu dan saya ingat seseorang di sana memposting kode hud mereka. Anda mungkin ingin melihat-lihat di sana dan melihat apa yang Anda hasilkan.


2
Ya, ini jawaban yang tepat. Atau gunakan Panggung terpisah untuk menggambar dan menggambar setelah barang-barang game.
Matsemann

3
Terima kasih. Saya akan mencoba keduanya. Saya tidak menyadari itu adalah praktik umum untuk memiliki lebih dari satu Panggung atau Kamera per Layar.
Devin Carless

4
Bisakah Anda menambahkan beberapa kode sampel, atau mungkin @DevinCarless?
ashes999

6

Berikut adalah metode yang saya gunakan untuk bekerja dengan satu batch:

Pertama menggambar segalanya, lalu menggambar HUD Anda terakhir:

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

Jika Anda ingin menggambar lebih banyak setelahnya, pastikan Anda mereset matriks proyeksi ke apa pun yang diperlukan.


Berhati-hatilah karena Anda akan mendapatkan banyak matriks dalam memori dengan sangat cepat (karena .cpu()membuat matriks baru setiap saat). Lebih baik memiliki matriks buffer permanen dan mengatur nilainya setiap frame.
Denis Kniazhev

1

Ingat, kamera pertama adalah tempat latar belakang diperbaiki. Yang kedua adalah di mana tanah bergerak. Jika Anda bertanya-tanya mengapa sprite bergerak di atas panggung karena rahasia itu tanah yang bergerak. Sprite hanya berjalan di tempat karena Anda menggunakan kamera ketiga. Anda mungkin menggulir ground kamera kedua tetapi HUD masih di tempat ketiga. Janji, itu benar! Kamera ketiga adalah tempat itu menampilkan sprite di tengah untuk arah, apakah dia pergi ke kiri atau ke kanan dengan kode animasi kecil, dan HUD (yaitu skor, sisa hidup, item yang digunakan). Jika Anda butuh sesuatu, tanya saya.


Bagaimana saya bisa melepaskan sprite dari kamera kedua? Apa yang ingin saya lakukan adalah menggambar teks, tetapi ini terlalu besar ... Jadi saya perlu kamera lain, tetapi ketika saya melakukannya, teks tersebut ikut dengan saya .. dengan pemain, dengan layar saya ... itu bergerak sedikit seperti musuh di layar tetapi masih ada di tangan saya ... Bisakah Anda memberi saran?
Nimitack

1

Saya telah melakukannya seperti ini:

Pertama saya telah membuat Kelas baru yang disebut Hud. Ini diterapkan Disposablekarena manajemen sumber daya. Maka Anda perlu mendefinisikan Stageuntuk konten Anda dan yang baru viewportkarena kamera baru akan digunakan. Anda perlu menentukan yang baru Tableyang dapat Anda tambahkan ke Stage. Anda dapat menambahkan konten Anda tableseperti biasa. Sisa kode yang akan saya tunjukkan untuk menunjukkan cara kerjanya adalah game spesifik jadi abaikan saja.

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

}

dan kemudian di Playscreen seperti ini:

pertama-tama Anda memerlukan variabel untuk referensi hud Anda seperti:

private Hud hud; 

dan kemudian di konstruktor Anda membuat instance baru dari kelas Anda:

hud= new Hud(); 

dalam metode pembaruan- Anda perlu meletakkan baris kode ini karena saya pikir Anda ingin menampilkan beberapa informasi permainan seperti poin atau sisa nyawa:

hud.update();

dalam metode render- lakukan ini:

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

dan pada akhirnya jangan lupa membuang hud Anda dalam metode pembuangan

saya harap itu membantu

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.