如何在libgdx中制作屏幕HUD?


23

我是libgdx的新手,我发现自己被最简单的事情所困扰。似乎希望我以特定方式进行操作,但是文档不会告诉我那是什么。

我想制作一个非常简单的2D游戏,玩家可以控制飞船。鼠标滚轮将放大和缩小,并且信息和控件将显示在屏幕上。

但我似乎无法使鼠标滚轮无法缩放UI。我已经尝试过介于两者之间的投影矩阵

这是我的(当前)代码:

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通过滚动(int量)设置。

我已经尝试了十多种变体,主题是在绘制按钮之后但在飞船之前更改相机的投影矩阵,但是无论我做什么,按钮和飞船都会发生相同的事情。所以:

实现不由相机的投影矩阵/缩放转换的屏幕UI的通常libgdx方法是什么?


您可以使用camera.project(Vector3 screenCoords)投影从世界坐标到屏幕线的物体。
JDSweetBeat 2015年

Answers:


17

您可以直接使用另一个SpriteBatch,而无需设置投影矩阵来绘制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
对于我正在做的事情,我发现这是最简单的方法,因为基本UI应该始终出现在屏幕上的同一位置(例如乐谱,生活等)
理查德(Richard

当我尝试此操作时,没有投影矩阵的spritebatch会导致在不同屏幕分辨率上的定位不同
Codeulike

8

我认为完成平视地图的最简单方法是使用第二个摄像头并将其覆盖。这个问题已经在libgdx论坛上讨论过了,我记得那边有人在发布他们的hud代码。您可能想在那儿戳一戳,看看自己想出什么。


2
是的,这是正确的答案。或使用单独的舞台作为hud,并在游戏结束后进行绘制。
Matsemann 2012年

3
谢谢。我会尝试的。我不知道每个屏幕有一个以上的舞台或摄像机是一种常见的做法。
Devin Carless 2012年

4
您能添加一些示例代码,还是@DevinCarless?
ashes999 2014年

6

这是我用于单批处理的方法:

首先绘制其他所有内容,然后最后绘制HUD:

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

如果要在以后绘制更多图形,请确保将投影矩阵重置为所需的大小。


请注意,您很快就会在内存中得到很多矩阵(因为.cpu()每次都会创建一个新矩阵)。最好有一个永久的缓冲区矩阵,并在每帧设置其值。
丹尼斯·克尼亚热夫'17

1

请记住,第一台相机是固定背景的位置。第二个是地面移动的地方。如果您想知道为什么精灵会在舞台中移动,是因为它秘密地移动了地面。由于您正在使用第三个相机,因此精灵仅在原地行走。您可以滚动第二台摄像机的地面,但HUD仍在第三台上。答应,是真的!第三个摄像头是它在中心显示小精灵的方向,无论他是靠一点动画代码向左还是向右走,以及HUD(即得分,剩余寿命,使用的物品)。如果您需要什么,请问我。


如何从第二个相机上卸下精灵?我想做的是绘制文本,但是要很大...所以我需要另一个摄像头,但是当我这样做时,文本随我一起去..随播放器一起,随着我的屏幕...它确实移动了一点像屏幕上的敌人一样,但它仍然陪伴着我...能请您指教吗?
Nimitack

1

我这样做是这样的:

首先,我创建了一个名为Hud的新类。它Disposable是由于资源管理而实现的。然后,您需要Stage为您的内容定义一个和一个新的,viewport因为将使用一个新的相机。您需要定义一个Table可以添加到中的新内容Stage。您可以table像往常一样添加内容。我将要展示的其余代码是特定于游戏的,因此只需忽略它即可。

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

}

然后在Playscreen中像这样:

首先,您需要一个变量来引用您的hud,例如:

private Hud hud; 

然后在构造函数中创建类的新实例:

hud= new Hud(); 

在update-方法中,您需要放置以下代码行,因为我认为您想显示一些游戏信息,例如积分或剩余生命:

hud.update();

在render-方法中执行以下操作:

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

最后,别忘了使用dispose-方法处理您的平视显示器

我希望有帮助

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.