libGDX에서 다양한 종횡비를 처리하는 방법은 무엇입니까?


81

ScreenlibGDX 프레임 워크에서 제공 하는 클래스를 분명히 사용하는 libGDX를 사용하여 일부 화면을 구현했습니다 . 그러나 이러한 화면에 대한 구현은 사전 정의 된 화면 크기에서만 작동합니다. 예를 들어 스프라이트가 640 x 480 크기 화면 (4 : 3 가로 세로 비율) 용인 경우 스프라이트가 화면 경계를 따르고 화면 크기에 맞게 조정되지 않기 때문에 다른 화면 크기에서는 의도 한대로 작동하지 않습니다. 조금도. 또한 libGDX에서 간단한 확장을 제공했다면 게임 화면의 종횡비가 변경 될 수 있기 때문에 제가 직면 한 문제는 여전히 존재했을 것입니다.

인터넷에서 조사한 후 같은 문제를 논의한 블로그 / 포럼 을 발견했습니다. 나는 그것을 구현했고 지금까지 잘 작동하고 있습니다. 그러나 이것이 이것을 달성하는 최선의 선택인지 또는 더 나은 대안이 있는지 확인하고 싶습니다. 다음은이 합법적 인 문제를 어떻게 처리하고 있는지 보여주는 코드입니다.

포럼 링크 : http://www.java-gaming.org/index.php?topic=25685.new

public class SplashScreen implements Screen {

    // Aspect Ratio maintenance
    private static final int VIRTUAL_WIDTH = 640;
    private static final int VIRTUAL_HEIGHT = 480;
    private static final float ASPECT_RATIO = (float) VIRTUAL_WIDTH / (float) VIRTUAL_HEIGHT;

    private Camera camera;
    private Rectangle viewport;
    // ------end------

    MainGame TempMainGame;

    public Texture splashScreen;
    public TextureRegion splashScreenRegion;
    public SpriteBatch splashScreenSprite;

    public SplashScreen(MainGame maingame) {
        TempMainGame = maingame;
    }

    @Override
    public void dispose() {
        splashScreenSprite.dispose();
        splashScreen.dispose();
    }

    @Override
    public void render(float arg0) {
        //----Aspect Ratio maintenance

        // update camera
        camera.update();
        camera.apply(Gdx.gl10);

        // set viewport
        Gdx.gl.glViewport((int) viewport.x, (int) viewport.y,
        (int) viewport.width, (int) viewport.height);

        // clear previous frame
        Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

        // DRAW EVERYTHING
        //--maintenance end--

        splashScreenSprite.begin();
        splashScreenSprite.disableBlending();
        splashScreenSprite.draw(splashScreenRegion, 0, 0);
        splashScreenSprite.end();
    }

    @Override
    public void resize(int width, int height) {
        //--Aspect Ratio Maintenance--
        // calculate new viewport
        float aspectRatio = (float)width/(float)height;
        float scale = 1f;
        Vector2 crop = new Vector2(0f, 0f);

        if(aspectRatio > ASPECT_RATIO) {
            scale = (float) height / (float) VIRTUAL_HEIGHT;
            crop.x = (width - VIRTUAL_WIDTH * scale) / 2f;
        } else if(aspectRatio < ASPECT_RATIO) {
            scale = (float) width / (float) VIRTUAL_WIDTH;
            crop.y = (height - VIRTUAL_HEIGHT * scale) / 2f;
        } else {
            scale = (float) width / (float) VIRTUAL_WIDTH;
        }

        float w = (float) VIRTUAL_WIDTH * scale;
        float h = (float) VIRTUAL_HEIGHT * scale;
        viewport = new Rectangle(crop.x, crop.y, w, h);
        //Maintenance ends here--
    }

    @Override
    public void show() {
        camera = new OrthographicCamera(VIRTUAL_WIDTH, VIRTUAL_HEIGHT); //Aspect Ratio Maintenance

        splashScreen = new Texture(Gdx.files.internal("images/splashScreen.png"));
        splashScreenRegion = new TextureRegion(splashScreen, 0, 0, 640, 480);
        splashScreenSprite = new SpriteBatch();

        if(Assets.load()) {
            this.dispose();
            TempMainGame.setScreen(TempMainGame.mainmenu);
        }
    }
}

업데이트 : 최근에 libGDX가 여기에서 논의하고 싶은 종횡비를 유지하는 자체 기능이 있다는 것을 알게되었습니다. 인터넷에서 종횡비 문제를 검색하는 동안 "다른 화면 크기에서 종횡비를 유지하는 방법"이라는 문제가있는 여러 포럼 / 개발자를 발견했습니다. 저에게 실제로 효과가 있었던 솔루션 중 하나가 위에 게시되었습니다.

나중에 touchDown()화면에 대한 메서드 구현을 진행했을 때 크기 조정에 대한 크기 조정으로 인해 구현 한 좌표 touchDown()가 크게 변경된다는 것을 알았습니다 . 화면 크기 조정에 따라 좌표를 변환하는 코드로 작업 한 후이 양을 크게 줄 였지만 정확한 위치를 유지하는 데 성공하지 못했습니다. 예를 들어, touchDown()텍스처를 구현 한 경우 화면 크기를 조정하면 크기 조정에 따라 텍스처 영역의 touchListener가 약간의 픽셀을 오른쪽 또는 왼쪽으로 이동하며 이것은 분명히 바람직하지 않습니다.

나중에 스테이지 클래스에 종횡비 ( boolean stretch = false) 를 유지하기위한 고유 한 기능이 있다는 것을 알게되었습니다 . 이제 스테이지 클래스를 사용하여 화면을 구현 했으므로 화면 비율이 잘 유지됩니다. 그러나 크기가 조정되거나 다른 화면 크기에서 생성되는 검은 색 영역은 항상 화면 오른쪽에 나타납니다. 즉, 화면이 중앙에 있지 않기 때문에 검정색 영역이 상당히 크면보기가 매우보기 흉합니다.

커뮤니티 회원이이 문제를 해결하도록 도와 줄 수 있습니까?


같은 문제가있는 블로그 나 포럼에 링크 할 수 있습니까?
Steve Blackwell 2012

@SteveBlackwell은 여기 링크입니다 : java-gaming.org/index.php?topic=25685.new
Rafay

@SteveBlackwell 업데이트 된 질문을보고 이에 대해 도움이 될 수 있는지 확인하십시오.
Rafay 2012

1
스테이지에 대해 잘 모르지만 여기 를 보면이 문제가 해결되어야하는 것 같습니다. 워드 프로세서 를 중심으로 너무 많이 도움이되지 않습니다. 카메라를 약간 이동하거나 뷰포트를 조정할 수 있습니다.
Steve Blackwell

1
내 문제는 실제로 해결되었습니다. 나는 그것을 대답으로 게시하고 있습니다.
Rafay 2012

답변:


51

요즘하는 방법 :

이것은 여기서 libgdx에 대한 가장 유명한 질문 중 하나이므로 약간의 업데이트를 제공하겠습니다 .

Viewport이 문제를 처리하기 위해 LibGDX v1.0이 도입 되었습니다. 사용하기가 훨씬 쉽고 확장 전략이 플러그 가능합니다. 즉, 한 줄로 동작을 변경할 수 있으며 게임에 가장 적합한 것을 확인할 수 있습니다.

그것에 대해 알아야 할 모든 것은 여기 에서 찾을 수 있습니다 .


나는 그것을 시도했지만 여전히 내 TextureRegionStreches. 휴가하면 reszie(int width, int height)기능을 비 웁니다. 그것은 TextureRegionstrectch하지 않습니다.
Muhammad Babar

하지만 뷰포트를 사용할 때에도 서로 다른 종횡비에 대해 별도의 텍스처를 사용해야합니다. 그렇지 않습니까? 그 방법을 단순화하는 논리가 있습니까? 아니면 해상도와 무관하게 그래픽 디자인을해야합니까?
WeirdElfB0y

뷰포트 사용에 대한 좋은 튜토리얼 : gamefromscratch.com/post/2014/12/09/…
ubzack

이 답변에 추가하고 댓글의 질문에 답하면 16 : 9로 세계를 그리고 4 : 3으로로드 할 수 있도록 텍스처에 더 많은 높이를 줄 수 있습니다. 그런 다음 뷰포트를 인스턴스화 할 때 화면의 실제 종횡비를 확인할 수 있으며 너비 표준을 유지하면서 실행중인 종횡비에 맞는 높이를 뷰포트에 지정할 수 있습니다. 단점은 4 : 3 해상도에서 "빈"공간이 많이 있다는 것입니다.하지만 텍스처가이를 처리 할 수 ​​있다면 모든 것이 그려지고
늘어나지

24

편집 : libGDX가 진화했습니다. 우수 답변은 지금 이 하나의 사용자 아무도에 의해. Viewport문서 링크를 확인하십시오 . .

SteveBlack이 무대 수업에서보고 된 문제의 링크를 게시했을 때 나는 그 문제 (실제로 내 문제가 아님)가 최근 야간에서 해결되었음을 발견하기 위해 그곳에갔습니다.

내가 겪고있는 문제에 대해 인터넷에서 여기 저기 조사한 후 해결책을 찾을 수 없어서 버그를 신고 한 사람에게 직접 연락하기로 결정했습니다. 그 후, 그는 libgdx 포럼에서 저에게 답장을했고 저를 도와 준 것에 대해 빚을지고 있습니다. 여기 링크가 있습니다

한 줄의 코드 였고 다음과 같이하면됩니다.

resize () 방식에서 :

stage.setViewport(640, 480, false);
stage.getCamera().position.set(640/2, 480/2, 0);

여기서 640 X 480은 의도 한 종횡비를 설명하는 TextureRegion의 해상도입니다. TextureRegion 크기가 320 X 240이면 두 인수를 모두 새로운 해상도로 변경해야합니다.

실제로 내 문제를 해결 한 원래 사람의 프로필 링크


6
libGDX 0.9.6에서 stage.setViewport (640, 480, false)는 stage.getCamera (). position.set (640/2, 480/2, 0)에 대한 호출을 이미 포함하고 있으므로 충분합니다.
Alexis Pautrot 2012-08-25

1
setViewport3 개의 매개 변수로 지금은 사용할 수 없습니다!
Muhammad Babar 2014

나는 그것이 최신이고 올바른 것 같아서 Steve Blackwell이 지적한 것처럼 사용자 noone이 게시 한 답변에 대한 수락 된 답변을 변경했습니다.
Rafay 2014

7

화면에 맞게 전체 장면을 왜곡하는 것보다 왼쪽 / 오른쪽 또는 위쪽 / 아래쪽의 검은 색 막대가 더 잘 보입니다. 가능한 범위의 중간에있는 종횡비 (4 : 3은 아마도 로우 엔드, 16 : 9는 하이 엔드)를 타겟팅하는 경우 막대는 대부분의 장치에서 작게 유지되어야합니다. 이것은 또한 더 큰 화면에서도 대부분 의 화면 을 사용할 수있게 해주 며, 이미 그 사람의 코드를 가지고 있으므로 매우 쉽습니다. 이것이 libgdx에 내장 된 옵션이라면 더 좋을 것입니다.

하지만 가장 좋은 방법은 전체 화면을 사용하는 것입니다. 아직이 작업을 수행하지 않았지만 다음 프로젝트를 위해 취하는 접근 방식이 될 것입니다. 아이디어는 누군가가 더 넓은 화면을 가지고 있다면 측면에서 더 많이 볼 수 있어야한다는 것입니다. Chris Pruett는 자신의 강연 중 하나에서이를 수행하는 방법에 대해 이야기합니다 (대화 에서 스팟 링크- 실제로 모든 것이 실제로 꽤 좋습니다). 아이디어는 높이에 맞게 크기를 조정 한 다음 화면에 맞게 뷰포트를 넓게 설정하는 것입니다. OpenGL은 나머지를 표시합니다. 그가하는 방식은 여기에 있습니다 .

libgdx의 경우 카메라를 무대 위로 이동하여 scene2d로 쉽게 수행 할 수있는 방법이있을 수 있지만 실제로 scene2d로 작업 한 적이 없습니다. 어쨌든 앱을 크기 조정이 가능한 기본 창으로 실행하는 것이 AVD 묶음을 만드는 것보다 여러 화면 크기를 테스트하는 훨씬 쉬운 방법입니다.


"어쨌든 앱을 크기 조정이 가능한 기본 창으로 실행하는 것이 AVD를 만드는 것보다 여러 화면 크기를 테스트하는 훨씬 쉬운 방법입니다." 잘했다. 실제로 저는 텍스처 크기가 다른 다양한 화면 크기를 대상으로하는 대신 최대 호환성을 보장하기 위해이 현상에 대한 작업을 시도하고 있습니다.
Rafay 2012.02.22


3

ResolutionFileResolver의 클래스는 최고의 해상도로 파일 이름을 확인 할 수 있습니다. 해당 종횡비에 대한 스프라이트를 만든 경우 다른 종횡비에서도 작동한다고 생각합니다. AssetManagerTest에 사용 예제가 있습니다 .


0

나는 http://blog.acamara.es/2012/02/05/keep-screen-aspect-ratio-with-different-resolutions-using-libgdx/ 에서 그 방법을 사용하고 있습니다.

터치 한 화면의 포인트를 원하는 게임 위치로 축소하는 기능을 만들었습니다.

public Vector2 getScaledPos(float x, float y) {
    float yR = viewport.height / (y - viewport.y);
    y = CAMERA_HEIGHT / yR;

    float xR = viewport.width / (x - viewport.x);
    x = CAMERA_WIDTH / xR;

    return new Vector2(x, CAMERA_HEIGHT - y);
}

터치 다운 / 위 / 드래그에서 이것을 사용하고 게임에서 터치를 확인할 수 있습니다.


이것은 카메라의 unproject 방법과 비슷해 보입니다. 같은 일을합니까?
milosmns

@milosmns이 내가 1 년 전에 같은 일을 한 방법입니다, 내가 unproject 것을 발견 좋은 .. 카메라가 같은 위치에 항상있을 때 좋은 ...
Boldijar 폴

0

이 코드는 최신 업데이트에서 저에게 적합합니다. * OrthographicCamera는 캠입니다. 자르지 않고 뷰포트 만 변경하여 너비가 실제 창 / 장치보다 "그만큼"배 더 큽니다.

public void resize(int width, int height) {
    int newW = width, newH = height;
    if (cam.viewportWidth > width) {
        float scale = (float) cam.viewportWidth / (float) width;
        newW *= scale;
        newH *= scale;
    }

    // true here to flip the Y-axis
    cam.setToOrtho(true, newW, newH);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.