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はscrolled(int amount)によって設定されます。

ボタンが描かれた後、船が出る前にカメラの投影行列を変更するというテーマについて、10種類のバリエーションを試してみましたが、何をしても、ボタンと船の両方に同じことが起こります。そう:

カメラの投影マトリックス/ズームによって変換されないオンスクリーンUIを実装する通常のlibgdxの方法は何ですか?


を使用しcamera.project(Vector3 screenCoords)て、世界座標からスクリーンコードに何かを投影できます。
JDSweetBeat

回答:


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

HUDマップを作成する最も簡単な方法は、2台目のカメラを使用してオーバーレイすることだと思います。この問題はしばらく前にlibgdxフォーラムで議論されてきました。あなたはあちこち突っついて、あなたが思いついたものを見たいかもしれません。


2
はい、これは正しい答えです。または、ハド用に別のステージを使用し、ゲームの後にそれを描画します。
マツマン

3
ありがとうございました。両方試してみます。スクリーンごとに複数のステージまたはカメラを設置するのが一般的だとは思いませんでした。
デビンカーレス

4
サンプルコードを追加してもらえますか、それとも@DevinCarlessを追加してください。
ashes999 14年

6

単一のバッチで作業するために使用する方法は次のとおりです。

最初に他のすべてを描画し、次にHUDを最後に描画します。

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

さらに描画したい場合は、投影マトリックスを必要なものにリセットしてください。


.cpu()毎回新しいマトリックスが作成されるため、非常に高速にメモリ内に多数のマトリックスが作成されることに注意してください。永続的なバッファーマトリックスを用意し、その値をフレームごとに設定する方が良いでしょう。
デニスクニアジェフ

1

最初のカメラは背景が固定されている場所であることを忘れないでください。2つ目は、地面が動く場所です。なぜスプライトがステージで動くのか疑問に思っているなら、秘密は動く地面だからです。3番目のカメラを使用しているので、スプライトはちょうどその場所を歩いています。2番目のカメラの地面をスクロールしたかもしれませんが、HUDは3番目の場所にまだあります。約束、それは本当です!3番目のカメラは、少しのアニメーションコードで左または右に移動するかどうか、およびHUD(つまり、スコア、残りのライフ、使用アイテム)の方向の中央にスプライトを表示する場所です。何か必要な場合は、私に尋ねてください。


2番目のカメラからスプライトをデタッチするにはどうすればよいですか?私がやりたいのはテキストを描くことですが、それは大きすぎます...だから私は別のカメラが必要ですが、それを行うとテキストが私と一緒になります..プレーヤー、私の画面で...それは少し動きます画面上の敵のようですが、それはまだ私と一緒にいる...あなたはアドバイスしてもらえますか?
ニミタック

1

私はこのようにしました:

最初に、Hudという新しいクラスを作成しました。Disposableリソース管理のために実装します。次に、新しいカメラが使用されるため、Stageコンテンツと新しいを定義する必要がありますviewport。にTable追加できる新しいものを定義する必要がありますStagetable通常のようにコンテンツを追加できます。それがどのように機能するかを示すために私が置くコードの残りは、ゲーム固有のものなので、無視してください。

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

}

そして、次のようなプレイ画面で:

まず、次のような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-メソッドでhudを破棄することを忘れないでください

それがお役に立てば幸いです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.