今回はカメラの使い方について簡単に見ていきます。これは前回までのチュートリアルではまだ扱っていない内容になります。 カメラを使うといくつかのメリットがあります。 LibGDX が端末の解像度に合わせてサイズの変更を行うので、端末の解像度への対処が簡単になります。 また、シーンが一つの画面に収まらないくらい大きい場合、視点の移動が簡単にできます。 後述するサンプルコードでは、まさしくそういった処理を行っています。
ここで取得した 大きめの( 2048x1024 ) 画像を使用しています。
それでは、今回のコードです:
package com.gamefromscratch;
import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.math.Vector2;
public class CameraDemo implements ApplicationListener, GestureListener {
private OrthographicCamera camera;
private SpriteBatch batch;
private Texture texture;
private Sprite sprite;
@Override
public void create() {
camera = new OrthographicCamera(1280, 720);
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("data/Toronto2048wide.jpg"));
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
sprite = new Sprite(texture);
sprite.setOrigin(0,0);
sprite.setPosition(-sprite.getWidth()/2,-sprite.getHeight()/2);
Gdx.input.setInputProcessor(new GestureDetector(this));
}
@Override
public void dispose() {
batch.dispose();
texture.dispose();
}
@Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
sprite.draw(batch);
batch.end();
}
@Override
public void resize(int width, int height) {
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public boolean touchDown(float x, float y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean tap(float x, float y, int count, int button) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean longPress(float x, float y) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean fling(float velocityX, float velocityY, int button) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean pan(float x, float y, float deltaX, float deltaY) {
// TODO Auto-generated method stub
camera.translate(deltaX,0);
camera.update();
return false;
}
@Override
public boolean zoom(float initialDistance, float distance) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2,
Vector2 pointer1, Vector2 pointer2) {
// TODO Auto-generated method stub
return false;
}
}
さらに、Main.java 内で以下のように、解像度を 720p へ変更しました:
package com.gamefromscratch;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "camera";
cfg.useGL20 = false;
cfg.width = 1280;
cfg.height = 720;
new LwjglApplication(new CameraDemo(), cfg);
}
}
このコードを実行すると、以下が表示されます:
都市の夜景画像が表示されるだけでなく、パン操作も可能です。左右にスワイプすることで画像のパン操作ができます。
このコードのほとんどはこれまで見たことがある内容ですが、新たに追加された重要な行は以下です:
camera = new OrthographicCamera(1280, 720);
ここではカメラを作成しています。LibGDXには、 Orthographic と Perspectiveの二種類のカメラがあります。 基本的には、orthographic カメラはシーン内のものをそのままのサイズで描写します。 一方でperspective カメラは、離れた位置にあるオブジェクトを少し小さく描写することで、人間の目と同じ様な見え方を再現します。 以下にBlender チュートリアルの連載記事で作成した例があります。
Perspective:
Orthographic:
perspective の描写では、遠くの翼が近くの翼よりも小さくなっていることに気づきましたか? perspective があなたの代わりにそうした描写をしています。 しかし、2D描写の場合99%はOrthographicを使用したほうが良いです。
コンストラクタに引数として渡している値は、カメラの解像度(横幅と高さ)です。 今回の場合、1280x720のピクセルサイズで描写したいので、解像度にはピクセルを使用しています。 しかし、これは強制ではありません… 例えば、あなたが物理演算を使用していて現実世界の単位を使いたい場合は、メートルなどの好きな単位を使用できます。 重要なのは、アスペクト比を正しく設定することです。 create()内の残りのコードでは、画像を読み込んでゲーム内世界での原点と位置を設定しています。 最後にジェスチャーハンドラーを登録すると、画像上での左右へのパン/スワイプができるようになります。
render()内で次に重要な呼び出しは以下です:
batch.setProjectionMatrix(camera.combined);
これはLibGDX のcamera オブジェクトとOpenGL レンダラーを結びつけています。 OpenGL の描写処理にかかる時間は、描写する際にシーンやゲーム内世界から画面へ座標変換するマトリックスの数によって変わります。 camera.combined は、 cameraの view と projection matrixes の組み合わせを戻り値として返します。 内部行われている計算についての詳細を知りたい場合は、 ここで読むことができます。 もちろん、Camera クラスの良いところはそういった難しい部分をあなたが気にする必要がないということです。 そのため、ややこしいと思っても気にすることはありません。LibGDX があなたに代わって計算してくれます。
最後に、 pan ハンドラー ( huh? )内に以下のコードがあります:
camera.translate(deltaX,0);
camera.update();
translate メソッドを使ってカメラを動かすことができます。 ここではユーザーがスワイプした距離の分、X軸方向にカメラを動かしています。 これにより、ユーザーが画面をスワイプしたりマウスをパンしたりすると画像の視点が移動します。 cameraを編集が完了したら、update を行う必要があります。 update()を呼び出さないと、 camera は決して移動しないでしょう。
ここでは使用していませんが、camera には他にも役立つ機能がいくつかあります。 There are functions to look at a point in space, to rotate or even rotate around ( orbit ) a vector. また、画面からゲーム内世界へ投射する機能だけでなく、シーンにレイキャストする機能もあります。 簡単な 2D ゲームの場合は、一般的にこんなに多くの機能を使うことはありませんが。 後ほど3Dゲームについての説明をする際に、camera クラスについてさらに詳しく見ていきます。