【Android】アンドロイドでOpenGLを使ってみる(2Dアニメーション編)


概ねタイトルとおりです。
今回は複数の画像を順番に読み込んでパラパラアニメのようなものを作ってみます。
こういうのも2Dアニメーションと呼んでもいい…はず。



前回と前々回で、OpenGL使って画像を一枚表示する方法を紹介しました。
・【Android】アンドロイドでOpenGLを使ってみる(準備編)
・【Android】アンドロイドでOpenGLを使ってみる(2Dテクスチャ描画編)

パラパラアニメ用の画像を用意する


パラパラアニメということで、徐々にポーズが変わっていく画像を順番に表示するだけです(^ω^)
今回は複数の画像を一つにまとめた画像を用意して、テクスチャの表示領域を変化させていく方式を紹介してみます。

まずは画像です。
適当なペイントソフトを使いドロイド君を描いてみました。
アンドロ君
若干コレジャナイ感がしますが…(;^ω^)
これを元にポーズが変わっていく画像を作り、つなげて一つの画像にします。

パラパラアニメ用ドロイド君

一つあたりのサイズは128x128です。10枚あるので全体のサイズは128x1280になります。


テクスチャの表示領域を指定する


テクスチャの表示には前回の記事で使ったSampleSpriteクラスを使いまわします。

//テクスチャの座標と幅と高さを指定
int rect[] = { texX,  texY,  texWidth, texHeight};
//テクスチャ画像のどの部分を使うかを指定
((GL11) gl).glTexParameteriv(GL10.GL_TEXTURE_2D,GL11Ext.GL_TEXTURE_CROP_RECT_OES, rect, 0);
//描画
((GL11Ext) gl).glDrawTexfOES( pos_x, pos_y, pos_z, width, height);



glTexParameteriv関数の引数で表示領域を指定しています。
前回作成したSampleSpriteでテクスチャをセットしてそのまま表示すると、
読み込んだ画像サイズの横幅が1280でそのまま表示されてしまいます。

今回の画像では一枚あたりのサイズが横幅が128なので
テクスチャを読み込んだ後にtexWidthに指定します。
また、描画処理のglDrawTexfOESで実際に描画するサイズを指定していますので、
同じようにwidthに横幅が128を指定します。

・SampleRenderer.java
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
	//背景色をクリア
	gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
	//ディザを無効化
	gl.glDisable(GL10.GL_DITHER);
	//深度テストを有効化
	gl.glEnable(GL10.GL_DEPTH_TEST);
	//テクスチャ機能ON
	gl.glEnable(GL10.GL_TEXTURE_2D);
	//透明可能に
	gl.glEnable(GL10.GL_ALPHA_TEST);
	//ブレンド可能に
	gl.glEnable(GL10.GL_BLEND);
	gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

	droid_img.setTexture(gl,context.getResources(),R.drawable.droid);
	droid_img.texWidth  = 128;
	droid_img.width     = 128;
}



実行すると、読み込んだ画像の一番左のドロイド君が表示されます。

テクスチャの表示領域を切り替える



順番に表示領域を切り替える処理を追加します。
毎フレームごとに一回ずつ切り替えると流石に早すぎますね。
描画のために毎フレーム呼び出されるonDrawFrameで数字をカウントして、
カウントが一定数増えた時に表示位置を切り替えるようなプログラムを用意します。

今回は5フレーム毎に画像が切り替わるようしてみます。
@Override
public void onDrawFrame(GL10 gl) {
    // 描画用バッファをクリア
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    droid_img.texX = 128 * (int)count;
    count += 0.2f;
    if( count >= 10 ){
    	count = 0;
    }
    droid_img.draw(gl);
}



テクスチャ内の座標はtexXで指定しています。
そこに、0,128,256,384,...と一枚あたりの横幅の倍数を設定すれば、うまく一枚毎の画像が表示されますね(^ω^)


サンプルプログラム

(前回の記事からの修正箇所のみ)

・SampleRenderer
public class SampleRenderer implements Renderer{

	private Context context;
	private float count;


	//2次元スプライト
	SampleSprite droid_img = new SampleSprite();

	public SampleRenderer(Context _context){
		context = _context;
	}

	@Override
	public void onDrawFrame(GL10 gl) {
	    // 描画用バッファをクリア
	    gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
	    droid_img.texX = 128 * (int)count;
	    count += 0.2f;
	    if( count >= 10 ){
	    	count = 0;
	    }
	    droid_img.draw(gl);
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		gl.glViewport(0, 0, width, height);
		gl.glMatrixMode(GL10.GL_PROJECTION);//プロジェクションモードに設定
		GLU.gluOrtho2D(gl, 0.0f, width, 0.0f, height);//平行投影用のパラメータをセット
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		//背景色をクリア
		gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
		//ディザを無効化
		gl.glDisable(GL10.GL_DITHER);
		//深度テストを有効化
		gl.glEnable(GL10.GL_DEPTH_TEST);
		//テクスチャ機能ON
		gl.glEnable(GL10.GL_TEXTURE_2D);
		//透明可能に
		gl.glEnable(GL10.GL_ALPHA_TEST);
		//ブレンド可能に
		gl.glEnable(GL10.GL_BLEND);
		gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
		//128x128のサイズが10枚横に並んだ画像を読込み
		droid_img.setTexture(gl,context.getResources(),R.drawable.droid);
		droid_img.texWidth  = 128;
		droid_img.width     = 128;
	}
}



アンドロイドでOpenGLを使ってみる(2Dアニメーション)03
上手くいけばこんな風に表示されます。なんか怖い。


関連記事

【Android】アンドロイドでOpenGLを使ってみる(2Dアニメーション編)” への1件のコメント

  1. ピンバック: 【Androidアプリ開発】オープンソースゲームエンジン「AndEngine」を導入してみる | 桜花満開/テンシホタル