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)에 의해 설정됩니다.

버튼이 그려진 후 배가 오기 전에 카메라의 프로젝션 매트릭스를 변경하는 주제에 대해 수십 가지 변형을 시도했지만, 내가 무엇을하든 버튼과 선박에 동일한 일이 발생합니다. 그래서:

카메라의 투영 매트릭스 / 줌으로 변환되지 않은 온 스크린 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

허드 맵을 달성하는 가장 쉬운 방법은 두 번째 카메라를 사용하여 오버레이하는 것입니다. 이 문제는 얼마 전 libgdx 포럼에서 논의되었으며 허드 코드를 게시하는 누군가를 기억합니다. 당신은 저기 찔러서 당신이 생각 해낸 것을 볼 수 있습니다.


2
네, 정답입니다. 또는 hud에 별도의 스테이지를 사용하고 게임 후에 그립니다.
Matsemann 2016 년

3
고맙습니다. 두 가지 모두 시도합니다. 화면 당 하나 이상의 스테이지 또는 카메라를 갖는 것이 일반적인 관례라는 것을 알지 못했습니다.
Devin Carless 2016 년

4
샘플 코드를 추가하거나 @DevinCarless를 추가 할 수 있습니까?
ashes999

6

단일 배치 작업에 사용하는 방법은 다음과 같습니다.

먼저 다른 모든 것을 그린 다음 마지막으로 HUD를 그립니다.

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

이후에 더 많은 것을 그리려면 영사 매트릭스를 필요한 것으로 재설정하십시오.


.cpu()매번 새로운 행렬을 생성 하기 때문에 메모리에 많은 행렬이 매우 빠르게 생성 된다는 경고를 받으십시오 . 영구 버퍼 매트릭스를 사용하고 매 프레임마다 값을 설정하는 것이 좋습니다.
Denis Kniazhev 2016 년

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

}

그런 다음 재생 화면에서 다음과 같이하십시오.

우선 다음과 같이 hud를 참조하는 변수가 필요합니다.

private Hud hud; 

그런 다음 생성자에서 클래스의 새 인스턴스를 만듭니다.

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.