ฉันจะสร้าง HUD บนหน้าจอใน libgdx ได้อย่างไร


23

ฉันใหม่สำหรับ libgdx และฉันพบว่าฉันกำลังถูกทำให้งงโดยสิ่งที่ง่ายที่สุด ดูเหมือนว่าต้องการให้ฉันทำสิ่งต่าง ๆ ด้วยวิธีเฉพาะ แต่เอกสารไม่ได้บอกฉันว่ามันคืออะไร

ฉันต้องการสร้างเกม 2d ที่เรียบง่ายซึ่งผู้เล่นควบคุมยานอวกาศ ล้อเมาส์จะซูมเข้าหรือออกและข้อมูลและการควบคุมจะปรากฏขึ้นบนหน้าจอ

แต่ฉันไม่สามารถทำให้ล้อเมาส์ไม่ซูม UI ได้ ฉันลอง futzing กับเมทริกซ์การฉายในระหว่าง

นี่คือรหัส (ปัจจุบัน) ของฉัน:

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)

ฉันได้ลองเกี่ยวกับรูปแบบโหลในรูปแบบของการเปลี่ยนเมทริกซ์การฉายของกล้องหลังจากปุ่มถูกวาดขึ้น แต่ก่อนที่เรือจะออกมา แต่ไม่ว่าฉันจะทำอะไรสิ่งเดียวกันก็เกิดขึ้นกับทั้งปุ่มและเรือ ดังนั้น:

อะไรคือวิธีการใช้ libgdx ปกติบนการใช้ UI บนหน้าจอที่ไม่ได้ถูกแปลงโดยเมทริกซ์ / การฉายภาพของกล้อง?


คุณสามารถใช้camera.project(Vector3 screenCoords)เพื่อโปรเจ็กต์บางอย่างตั้งแต่พิกัดโลกไปจนถึงสายสกรีน
JDSweetBeat

คำตอบ:


17

คุณสามารถใช้ SpriteBatch อื่นได้โดยไม่ต้องตั้งค่า matrix matrix เพื่อวาด 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 ในขณะที่ย้อนกลับไปและฉันจำได้ว่ามีคนโพสต์รหัสของฮัด คุณอาจต้องการแหย่ที่นั่นและดูว่าคุณเกิดอะไรขึ้น


2
ใช่นี่คือคำตอบที่ถูก หรือใช้สเตจแยกต่างหากสำหรับฮัดและวาดมันหลังจากสิ่งต่างๆในเกม
Matsemann

3
ขอขอบคุณ. ฉันจะลองทั้งสองอย่าง ฉันไม่ทราบว่ามันเป็นเรื่องธรรมดาที่จะมีมากกว่าหนึ่ง Stage หรือ Camera ต่อ Screen
Devin Carless

4
คุณช่วยเพิ่มรหัสตัวอย่างหรือ @DevinCarless ได้ไหม?
ashes999

6

นี่คือวิธีที่ฉันใช้สำหรับทำงานกับแบทช์เดียว:

ก่อนอื่นให้ดึงสิ่งอื่นจากนั้นดึง HUD ของคุณออกมา

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

หากคุณต้องการวาดเพิ่มเติมหลังจากนั้นให้แน่ใจว่าคุณรีเซ็ตเมทริกซ์การฉายเป็นสิ่งที่จำเป็นต้องมี


ถูกเตือนว่าคุณจะพบกับ.cpu()เมทริกซ์จำนวนมากในหน่วยความจำอย่างรวดเร็ว (เพราะสร้างเมทริกซ์ใหม่ทุกครั้ง) มีเมทริกซ์บัฟเฟอร์ถาวรที่ดีกว่าและตั้งค่าทุกเฟรม
เดนิส Kniazhev

1

โปรดจำไว้ว่ากล้องตัวแรกเป็นที่ที่พื้นหลังได้รับการแก้ไข ส่วนที่สองคือตำแหน่งที่พื้นดินเคลื่อนที่ หากคุณสงสัยว่าทำไมผีสางเคลื่อนที่ในเวทีเพราะความลับนั้นเป็นพื้นที่เคลื่อนที่ สไปรท์กำลังเดินเข้ามาเพราะคุณใช้กล้องตัวที่สาม คุณอาจเลื่อนพื้นของกล้องตัวที่สอง แต่ HUD ยังคงอยู่ในตำแหน่งที่สาม สัญญามันเป็นเรื่องจริง! กล้องตัวที่สามคือที่ที่มันจะแสดงผีสางตรงกลางสำหรับทิศทางไม่ว่าเขาจะไปทางซ้ายหรือขวาด้วยรหัสภาพเคลื่อนไหวเล็กน้อยและ HUD (เช่นคะแนนชีวิตที่เหลืออยู่รายการที่ใช้) หากคุณต้องการอะไรซักอย่างถามฉัน


ฉันจะแยกเทพดาออกจากกล้องที่สองได้อย่างไร สิ่งที่ฉันต้องการจะทำคือการวาดข้อความ แต่มันใหญ่ ... ดังนั้นฉันต้องการกล้องอีกตัว แต่เมื่อฉันทำอย่างนั้นข้อความจะไปกับฉัน .. ด้วยผู้เล่นพร้อมกับหน้าจอของฉัน ... มันขยับเล็กน้อย เหมือนศัตรูบนหน้าจอ แต่ยังอยู่กับฉัน ... คุณช่วยแนะนำได้ไหม?
Nimitack

1

ฉันทำแบบนี้แล้ว:

ก่อนอื่นฉันได้สร้าง Class ใหม่ที่ชื่อว่า 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 เช่นนี้:

ก่อนอื่นคุณต้องมีตัวแปรเพื่ออ้างอิงฮัดของคุณเช่น:

private Hud hud; 

จากนั้นใน Constructor คุณสร้างอินสแตนซ์ใหม่ของคลาส:

hud= new Hud(); 

ในวิธีการอัพเดทคุณต้องใส่โค้ดเหล่านี้เนื่องจากฉันคิดว่าคุณต้องการแสดงข้อมูลเกมบางอย่างเช่นคะแนนหรือชีวิตที่เหลือ:

hud.update();

ในโหมด render- ทำสิ่งนี้:

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

และท้ายที่สุดอย่าลืมทิ้งฮัดของคุณในวิธีการกำจัด

ฉันหวังว่าจะช่วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.