OrthographicCameraで2Dカメラ

OrthographicCameraで2Dカメラ

今回はカメラの処理をやります。2Dです。

ビューポートが絡んでいるみたいなので実機でのどのように表示されているか確認をしたいところですが、 確認できていないので後ほど。

→20150810 add とくに問題なかった!

公式Wikiはここ↓だと思います。

https://github.com/libgdx/libgdx/wiki/Orthographic-camera

以下のソースも上のコードを改変したものです。

/**
 * 2Dカメラ処理のサンプル
 */
public class OrthographicCameraSampleListener extends ApplicationAdapter {

    private Stage stage = null;
    private OrthographicCamera cam;
    private float rotationSpeed;

    @Override
    public void create() {

        rotationSpeed = 0.5f;

        float w = Gdx.graphics.getWidth();
        float h = Gdx.graphics.getHeight();

        stage = new Stage();
        Gdx.input.setInputProcessor(stage);

        cam = (OrthographicCamera) stage.getViewport().getCamera(); //stageが持っているカメラを使う
        cam.setToOrtho(false, w/2, h/2);

        Texture t2 = new Texture("./profile.gif");
        Image image = new Image(t2);
        image.setPosition(0, 0);
        stage.addActor(image);
    }

    @Override
    public void render() {
        Gdx.gl.glClearColor(1, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);   //画面クリア

        handleInput();
        stage.draw();
    }

    private void handleInput() {
        if (Gdx.input.isKeyPressed( Input.Keys.A)) {
            cam.zoom += 0.02;
        }
        if (Gdx.input.isKeyPressed(Input.Keys.Q)) {
            cam.zoom -= 0.02;
        }
        if (Gdx.input.isKeyPressed(Input.Keys.LEFT)) {
            cam.translate(-3, 0, 0);
        }
        if (Gdx.input.isKeyPressed(Input.Keys.RIGHT)) {
            cam.translate(3, 0, 0);
        }
        if (Gdx.input.isKeyPressed(Input.Keys.DOWN)) {
            cam.translate(0, -3, 0);
        }
        if (Gdx.input.isKeyPressed(Input.Keys.UP)) {
            cam.translate(0, 3, 0);
        }
        if (Gdx.input.isKeyPressed(Input.Keys.W)) {
            cam.rotate(-rotationSpeed, 0, 0, 1);
        }
        if (Gdx.input.isKeyPressed(Input.Keys.E)) {
            cam.rotate(rotationSpeed, 0, 0, 1);
        }
    }

    @Override
    public void resize(int width, int height) {
        cam.update();
    }

    @Override
    public void dispose() {
        stage.dispose();
    }
}

以下、自分がつまずいた部分を書いておく。

OrthographicCameraを作るとき

2D用に使えるクラスはOrthographicCameraというクラスらしい。

このインスタンスを作るとき、

OrthographicCamera camera = new OrthographicCamera(w, h);

コンストラクタの引数でカメラのサイズを渡すと、カメラ座標の中心が原点のまま

OrthographicCamera camera = new OrthographicCamera();
camera.setToOrtho(false, w, h);

↑上のようにsetToOrthoメソッドにすると、左下が原点になってくれる。

Scene2dを使っていてカメラを使うとき

//...
SpriteBatch batch = new SpriteBatch();
Sprite sprite = new Sprite(texture);
//...

batch.setProjectionMatrix(camera.combined);
batch.begin();
sprite.draw(batch);

↑のようにSpriteBacth#setProjectionMatrixにカメラオブジェクトを渡してdrawする例はあるのだけど、

自分はScene2d*1を使って描画をしているので、

Stageのメンバがもっているカメラを使います。

Stageをnewするときに引数を指定しなければ、StageクラスでSpriteBatchとViewport(とカメラ)をnewしてくれてます。

cam = (OrthographicCamera) stage.getViewport().getCamera();    //stageが持っているカメラを使う

あと、Stage#drawの中で Sprite#draw(Batch)やCamera#update をやっているので、 Stage#drawをやっていればこれらのメソッドを呼ぶ必要はないみたいです。わかってなかったけどこういうのがあるので、seane2dは便利。

今のとこの理解だと、 描画をするのはSpriteを使うのが基本みたいで、StageのdrawはSpriteをラッピングして便利にしているクラスってこと、っていう認識。

こんなかんじ↓

上記の内容をもとに、今作ってるゲームに取り込んでみた。

画像なのでわかりにくいけど、プレイヤー(棒人間)が動くとプレイヤーも移動していますが、 描画の度にプレイヤーがカメラの中心になるようにカメラ座標を合わせているので、 背景が逆方向に動いているようなかんじになります。

f:id:snoopopo:20150716154935p:plain

今いるところから…(↑)

左に移動するとこんな見た目になります。(↓)

f:id:snoopopo:20150716154936p:plain

昔のポケモン(GBのとか)とかも主人公がずっと画面の中心にいたので、そういうかんじです。

*1:ここらへんのやつをいいたい。https://github.com/libgdx/libgdx/wiki/Scene2d