package net.npaka.gl10flightgame; import java.util.Random; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; import net.npaka.gles.GLES; import net.npaka.gles.Graphics; import net.npaka.gles.ObjLoader; import net.npaka.gles.Object3D; import net.npaka.gles.Texture; import android.content.Context; import android.opengl.GLSurfaceView; import android.opengl.GLU; import android.view.MotionEvent; import android.view.View;
//レンダラー public class GLRenderer implements GLSurfaceView.Renderer,View.OnTouchListener { //シーン定数 private final static int S_TITLE =0, S_PLAY =1, S_GAMEOVER=2; private final static int[] MSG_W={56,38,60,86,86}; //システム private float aspect; //アスペクト比 private boolean touchDown;//タッチダウン private float touchX; //タッチX座標 private Graphics g; //2D描画用グラフィックス //シーン private int scene=S_TITLE;//シーン private int init =S_TITLE;//初期化 private int msg =-1; //メッセージ private int score=0; //スコア private int tick=0; //時間経過 //モデル private Object3D jet=new Object3D(); //ジェット private Object3D tree=new Object3D(); //ツリー private Object3D floor=new Object3D();//床 private Texture texture; //2D描画用テクスチャ //位置 private float jetPX; //ジェットの位置のX座標 private float jetRZ; //ジェットの回転のZ座標 private float[] treeX=new float[32];//ツリーのX座標 private float[] treeZ=new float[32];//ツリーのZ座標 //コンストラクタ public GLRenderer(Context context) { GLES.context=context; } //サーフェイス生成時に呼ばれる @Override public void onSurfaceCreated(GL10 gl10,EGLConfig eglConfig) { GLES.gl=(GL11)gl10; //光源の設定 makeLight(gl10); try { //モデルの読み込み jet.figure=ObjLoader.load("jet.obj"); jet.rotate.set(0,180,0); jet.position.set(0,0.5f,0); tree.figure=ObjLoader.load("tree.obj"); tree.scale.set(3.0f,3.0f,3.0f); floor.figure=ObjLoader.load("floor.obj"); floor.scale.set(2.0f,1.0f,2.0f); //2D描画用テクスチャの読み込み texture=Texture.createTextureFromAsset("sprite.png"); } catch (Exception e) { android.util.Log.e("debug",e.toString()); for (StackTraceElement ste:e.getStackTrace()) { android.util.Log.e("debug"," "+ste); } } } //画面サイズ変更時に呼ばれる @Override public void onSurfaceChanged(GL10 gl10,int w,int h) { //ビューポートの指定 gl10.glViewport(0,0,w,h); aspect=(float)w/(float)h; g=new Graphics(w,h); }
//毎フレーム描画時に呼ばれる @Override public void onDrawFrame(GL10 gl10) { //画面のクリア gl10.glClearColor(0.4f,0.8f,1.0f,1.0f); gl10.glClear(GL10.GL_COLOR_BUFFER_BIT| GL10.GL_DEPTH_BUFFER_BIT); //デプステストと光源の有効化 gl10.glEnable(GL10.GL_DEPTH_TEST); gl10.glEnable(GL10.GL_LIGHTING); //射影変換 gl10.glMatrixMode(GL10.GL_PROJECTION); gl10.glLoadIdentity(); GLU.gluPerspective(gl10, 40.0f, //Y方向の画角 aspect, //アスペクト比 0.01f, //ニアクリップ 100.0f);//ファークリップ //ビュー変換 float angle=(float)((90+jetRZ)*Math.PI/180); GLU.gluLookAt(gl10, 0.0f,4.0f,9.0f, //カメラの視点 0.0f,1.0f,0.0f, //カメラの焦点 (float)Math.cos(angle),(float)Math.sin(angle),0.0f);//カメラの上方向
//モデル変換 gl10.glMatrixMode(GL10.GL_MODELVIEW); //モデルの描画 for (int i=0;i<32;i++) { if (treeZ[i]!=-999) { tree.position.set(treeX[i],0.0f,treeZ[i]); tree.draw(); } } jet.draw(); gl10.glDisable(GL10.GL_LIGHTING); gl10.glColor4f(0.3f,0.5f,0.0f,1.0f); floor.draw(); //2D描画 g.loadIdentity(); drawNum(score,8,7,7); drawMsg(msg); } //光源の設定 private void makeLight(GL10 gl10) { gl10.glEnable(GL10.GL_LIGHT0); gl10.glLightfv(GL10.GL_LIGHT0,GL10.GL_AMBIENT,new float[]{0.2f,0.2f,0.2f,1.0f},0); gl10.glLightfv(GL10.GL_LIGHT0,GL10.GL_DIFFUSE,new float[]{0.7f,0.7f,0.7f,1.0f},0); gl10.glLightfv(GL10.GL_LIGHT0,GL10.GL_SPECULAR,new float[]{0.9f,0.9f,0.9f,1.0f},0); gl10.glLightfv(GL10.GL_LIGHT0,GL10.GL_POSITION,new float[]{5.0f,5.0f,5.0f,0.0f},0); } //定期処理 public void onTick() { //初期化 if (init>=0) { scene=init; init=-1; //タイトル if (scene==S_TITLE) { msg=0; score=0; jetPX=0; jetRZ=0; for (int i=0;i<32;i++) treeZ[i]=-999.0f; } //プレイ if (scene==S_PLAY) { msg=-1; score=0; } //ゲームオーバー else if (scene==S_GAMEOVER) { msg=3; tick=0; } } //プレイ時の処理 if (scene==S_PLAY) { //スコア加算 score++;
//ツリーの出現と移動 for (int i=0;i<32;i++) { //木の移動 if (treeZ[i]!=-999) { treeZ[i]+=0.5f; if (treeZ[i]>3) treeZ[i]=-999.0f; if (-1<=treeZ[i] && treeZ[i]<=1 && -2<=treeX[i] && treeX[i]<=2) { init=S_GAMEOVER; } } //木の出現 else if (rand(100)==0) { treeX[i]=rand(20)-10; treeZ[i]=-24.0f; } } //ジェットの移動 if (touchDown) { float dx=0.0f; if (touchX<g.screenW/2) { dx=0.2f; if (jetRZ>=-45) jetRZ-=2; } else { dx=-0.2f; if (jetRZ<=45) jetRZ+=2; } jetPX+=dx; for (int i=0;i<32;i++) { if (treeZ[i]!=999.0f) treeX[i]+=dx; } } else { if (jetRZ<0) jetRZ+=2; if (jetRZ>0) jetRZ-=2; } } tick++; } //タッチイベントの処理 public boolean onTouch(View v,MotionEvent event) { int action=event.getAction(); if (action==MotionEvent.ACTION_DOWN) { if (scene==S_TITLE) { init=S_PLAY; } else if (scene==S_PLAY) { touchDown=true; touchX=event.getX(); } else { if (tick>=20) init=S_TITLE; } } else if (action==MotionEvent.ACTION_MOVE) { if (scene==S_PLAY) touchX=event.getX(); } else if (action==MotionEvent.ACTION_UP) { if (scene==S_PLAY) touchDown=false; } return true; } //数字の描画 private void drawNum(int num,int len,int x,int y) { int v=10; for (int i=2;i<len;i++) v=v*10; for (int i=0;i<len;i++) { g.drawImage(texture,x+i*28,y,28,28, 7*(num/v),0,7,7); num=num%v; v/=10; } } //メッセージの描画 private void drawMsg(int msg) { if (msg<0) return; g.drawImage(texture,(g.screenW-MSG_W[msg]*4)/2,120, MSG_W[msg]*4,16*4,0,7+16*msg,MSG_W[msg],16); } //乱数の取得 private static Random rand=new Random(); private static int rand(int num) { return (rand.nextInt()>>>1)%num; } }
|