Làm cách nào để tạo HUD trên màn hình trong libgdx?


23

Tôi mới sử dụng libgdx và tôi thấy mình đang bị cản trở bởi những điều đơn giản nhất. Dường như muốn tôi làm mọi thứ một cách cụ thể, nhưng tài liệu sẽ không cho tôi biết đó là gì.

Tôi muốn tạo một game 2d rất đơn giản trong đó người chơi điều khiển tàu vũ trụ. Bánh xe chuột sẽ phóng to và thu nhỏ, thông tin và điều khiển được hiển thị trên màn hình.

Nhưng tôi dường như không thể làm cho bánh xe chuột KHÔNG phóng to UI. Tôi đã thử làm mờ với các ma trận chiếu ở giữa

Đây là mã (hiện tại) của tôi:

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 được đặt bằng cách cuộn (số lượng int).

Tôi đã thử khoảng một chục biến thể về chủ đề thay đổi ma trận chiếu của máy ảnh sau khi nút được rút ra nhưng trước khi xuất xưởng, nhưng dù tôi có làm gì thì điều tương tự cũng xảy ra với cả nút và tàu. Vì thế:

Cách libgdx thông thường để thực hiện giao diện người dùng trên màn hình không bị biến đổi bởi ma trận chiếu / thu phóng của máy ảnh là gì?


Bạn có thể sử dụng camera.project(Vector3 screenCoords)để chiếu một cái gì đó từ tọa độ thế giới đến dây màn hình.
JDSweetBeat

Câu trả lời:


17

Bạn chỉ có thể sử dụng một SpriteBatch khác mà không cần đặt ma trận chiếu để vẽ 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
Đối với những gì tôi đang làm, tôi thấy đây là cách tiếp cận đơn giản nhất, đối với giao diện người dùng cơ bản luôn xuất hiện tại cùng một vị trí trên màn hình (như điểm số, cuộc sống, v.v.)
Richard

Việc có spritebatch mà không có ma trận chiếu dẫn đến định vị khác nhau trên các độ phân giải màn hình khác nhau khi tôi thử điều này
codeulike

8

Tôi nghĩ cách dễ nhất để thực hiện bản đồ hud sẽ là sử dụng máy ảnh thứ hai và che phủ chúng. Vấn đề này đã được thảo luận trên các diễn đàn libgdx một thời gian trước và tôi nhớ ai đó ở đó đăng mã hud của họ. Bạn có thể muốn chọc quanh đó và xem những gì bạn nghĩ ra.


2
Vâng, đây là câu trả lời đúng. Hoặc sử dụng một Giai đoạn riêng cho hud và vẽ nó sau công cụ trò chơi.
Matsemann

3
Cảm ơn bạn. Tôi sẽ thử cả hai. Tôi đã không nhận ra rằng đó là thông lệ để có nhiều Sân khấu hoặc Máy ảnh trên mỗi Màn hình.
Devin bất cẩn

4
Bạn có thể vui lòng thêm một số mã mẫu, hoặc có thể @DevinCarless không?
tro999

6

Đây là một phương pháp tôi sử dụng để làm việc với một đợt duy nhất:

Đầu tiên vẽ mọi thứ khác, sau đó vẽ HUD cuối cùng của bạn:

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

Nếu bạn muốn vẽ thêm sau đó, hãy đảm bảo bạn đặt lại ma trận chiếu thành bất cứ thứ gì nó cần.


Được cảnh báo rằng bạn sẽ kết thúc với rất nhiều ma trận trong bộ nhớ rất nhanh (vì .cpu()tạo ra một ma trận mới mỗi lần). Tốt hơn là có một ma trận bộ đệm vĩnh viễn và thiết lập các giá trị của nó mỗi khung.
Denis Kniazhev

1

Hãy nhớ rằng, máy ảnh đầu tiên là nơi cố định nền. Cái thứ hai là nơi mặt đất di chuyển. Nếu bạn đang tự hỏi tại sao sprite di chuyển trong giai đoạn bởi vì bí mật đó là mặt đất di chuyển. Sprite chỉ đi bộ tại chỗ vì bạn đang sử dụng máy ảnh thứ ba. Bạn có thể cuộn mặt đất của máy ảnh thứ hai nhưng HUD vẫn ở vị trí thứ ba. Hứa, đó là sự thật! Camera thứ ba là nơi nó hiển thị sprite ở giữa để tìm hướng, cho dù anh ta đi sang trái hay phải bằng một mã hoạt hình nhỏ và HUD (tức là điểm số, thời gian còn lại, vật phẩm được sử dụng). Nếu bạn cần một cái gì đó, hãy hỏi tôi.


Làm thế nào tôi có thể tách sprite từ máy ảnh thứ hai? Những gì tôi muốn làm là vẽ văn bản, nhưng nó rất lớn ... Vì vậy, tôi cần một máy ảnh khác, nhưng khi tôi làm điều đó, văn bản đi với tôi .. với trình phát, với màn hình của tôi ... nó sẽ di chuyển một chút Giống như kẻ thù trên màn hình nhưng nó vẫn ở lại với tôi ... Bạn có thể vui lòng tư vấn?
Nimitack

1

Tôi đã làm nó như thế này:

Đầu tiên tôi đã tạo ra một Class mới gọi là Hud. Nó thực hiện Disposablevì quản lý tài nguyên. Sau đó, bạn cần xác định một Stagecho nội dung của bạn và mới viewportvì một máy ảnh mới sẽ được sử dụng. Bạn cần xác định một cái mới Tablemà bạn có thể thêm vào Stage. Bạn có thể thêm nội dung của bạn vào tablenhư bình thường. Phần còn lại của mã tôi sẽ đưa ra để hiển thị cách thức hoạt động của trò chơi là cụ thể vì vậy hãy bỏ qua nó.

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

}

và sau đó trong Màn hình như thế này:

trước hết bạn cần một biến để tham chiếu hud của bạn như:

private Hud hud; 

và sau đó trong hàm tạo, bạn tạo một thể hiện mới của lớp:

hud= new Hud(); 

trong phương thức cập nhật, bạn cần đặt các dòng mã này vì tôi nghĩ rằng bạn muốn hiển thị một số thông tin trò chơi như điểm hoặc cuộc sống còn lại:

hud.update();

trong phương thức render- làm điều này:

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

và cuối cùng, đừng quên vứt bỏ hud của bạn trong phương pháp xử lý

tôi hy vọng điều đó sẽ giúp

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.