いよいよ本格的にスマートフォン上に画像を動かしてみます。 私のゲームソフトでは5種類の戦闘機セットを考えています。 この戦闘機にはタイマーが刻まれるごとにその位置を変えるためにその x座標とY座標を指示してやることが必要です。それをクラスファイルJplaneとしました。 下記に示しますJconファイルの最後のほうに掲載しています。位置はこのクラスファイルに持たせます。 JconクラスではコンストラクターによりAirFightから引数として戦闘機の画像(Drawable[][] imgs)、位置(int all_i,)、スマートフォンの 画面の幅(float w)、高さ(float h)、スマートフォンの各機器による寸法の修正(dw,dh),爆破画像、音響、 を受け取ります。 init()メソッドで戦闘機位置の初期値をとりあえず15種類(5場面で3機の戦闘機)二次元配列で作成しておきます。 先ほどのJplaneクラスの二次元配列にこの初期値を代入しておきます。同じ次数のブール型変数を用意します。 これがtrueのもののみ戦闘機を表示させ移動させるというロジックです。初期値はfalseにしておきます。 同時にカウンターも作成しておきます。初期値は0にしておきます。。 getX()メソッドは3機の戦闘機の一機の(index 0)位置を捕まえます。その後setX()メソッドで残りの戦闘機の位置を少し離して 配置します。こうして位置を決めdraw()メソッドでjaliveがtrueのときのみ画像を下記という要領です。 package kureishi.example.nationaldefence; import android.graphics.*; import android.graphics.drawable.Drawable; import android.media.MediaPlayer; public class Jcon { public float[][] plane_pos_x; public float[][] plane_pos_y; public float dw,dh,w,h; //private int[][] datas; public Jplane[][] datas; private Drawable[][] imgs; public int all_i, jplane_width,jplane_height; public boolean[][] jalive; public int[][] count; private Drawable bang; private MediaPlayer bon1; public int destroyed_no=0; public int broken_formation=0; public Jcon(Drawable[][] imgs,int all_i,float w,float h,float dw,float dh,Drawable bang,MediaPlayer bon1){ this.imgs=imgs;this.all_i=all_i;this.w=w;this.h=h;this.dw=dw;this.dh=dh;this.bang=bang;this.bon1=bon1; } public void init(){ plane_pos_x=new float[5][3]; plane_pos_y=new float[5][3]; plane_pos_x[0][0]=50; plane_pos_y[0][0]=490; plane_pos_x[0][1]=30; plane_pos_y[0][1]=440; plane_pos_x[0][2]=185; plane_pos_y[0][2]=440; plane_pos_x[1][0]=250; plane_pos_y[1][0]=486; plane_pos_x[1][1]=202; plane_pos_y[1][1]=430; plane_pos_x[1][2]=358; plane_pos_y[1][2]=445; plane_pos_x[2][0]=477; plane_pos_y[2][0]=527; plane_pos_x[2][1]=371; plane_pos_y[2][1]=435; plane_pos_x[2][2]=530; plane_pos_y[2][2]=437; plane_pos_x[3][0]=700; plane_pos_y[3][0]=527; plane_pos_x[3][1]=671; plane_pos_y[3][1]=435; plane_pos_x[3][2]=830; plane_pos_y[3][2]=437; plane_pos_x[4][0]=877; plane_pos_y[4][0]=527; plane_pos_x[4][1]=771; plane_pos_y[4][1]=435; plane_pos_x[4][2]=830; plane_pos_y[4][2]=437; datas=new Jplane[5][3]; for(int i=0;i<5;i++){ for(int j=0;j<3;j++){ plane_pos_x[i][j] *=dw;plane_pos_y[i][j] *=dh; datas[i][j]=new Jplane(i,j,plane_pos_x[i][j],plane_pos_y[i][j]); } } jalive=new boolean[5][3];count=new int[5][3]; for(int i=0;i<5;i++){ for(int j=0;j<3;j++){ jalive[i][j]=false; count[i][j]=0; } } } public void draw(Canvas canvas){ jplane_width=(int)(150*dw);jplane_height=(int)(150*dh); for(int j=0;j<3;j++){ if(jalive[all_i][j]){ if(count[all_i][j]==0 && !(j_new[all_i])){ imgs[all_i][j].setBounds(new Rect((int)datas[all_i][j].x,(int)datas[all_i][j].y,(int)(datas[all_i][j].x+jplane_width),(int)(datas[all_i][j].y+jplane_height))); imgs[all_i][j].draw(canvas); }else if(count[all_i][j]==1){ bang.setBounds(new Rect((int)datas[all_i][j].x,(int)datas[all_i][j].y,(int)(datas[all_i][j].x+jplane_width),(int)(datas[all_i][j].y+jplane_height))); bang.draw(canvas); bon1.start(); count[all_i][j]++;jalive[all_i][j]=false; }else{} } } } public float getX(int ii){ return datas[ii][0].x; } public void setX(int ii,float x){ if(x<=-100*dw){ x=-30*dw; }else if(x>=w){ x=w-100*dw; }else{} datas[ii][0].x=x;datas[ii][1].x=x-50*dw;datas[ii][2].x=x+150*dh; all_i=ii; } public boolean[][] getAlive(){ return jalive; } public boolean getJ_new(int i){ return j_new[i]; } } class Jplane{ public float x,y; public Jplane(float x,float y){ this.x=x; this.y=y; } } 次にAirFightからの指令です。下記にプログラムコードを掲載します。 init()メソッドからsetBoardSize()メソッドに処理が移ります。背景画像を5種類 戦闘機もDrawableで設定しています。音響ファイルは適当に何種類か用意します。 初期画像が表示されゲーム開始ボタンにタップするとonTouchEvent()メソッドのstart()メソッドが実行されます。 このメソッドにはタイマーと位置センサーがセットされています。タイマーによりdraw()メソッドが1.1秒間隔で 実行されます。またスマートフォンを傾けるとその傾きをonSenserChanged()メソッドが捕まえます。 このディジタル値を取ってJconオブジェクトを動かすという仕組みです。 スマートフォンの右端を下げると戦闘機が右に移動していきます。 package kureishi.example.nationaldefence; import java.util.List; import java.util.concurrent.*; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.app.Activity; import android.content.Context; import android.graphics.*; import android.hardware.*; import android.util.AttributeSet; import android.graphics.drawable.Drawable; import android.content.res.Resources; import android.media.MediaPlayer; import android.os.SystemClock; import android.content.Intent; public class AirFight extends SurfaceView implements SensorEventListener,SurfaceHolder.Callback{ private Activity context; private NationalDefenceActivity nationaldefence; private Drawable[] back; private Drawable[][] jplane; private Drawable start,bang; private Point press_loc; private long start_time; public long GAME_TIMES=40000; public Jcon jcon; public Ccon ccon; public Jmcon jmcon; public Cmcon cmcon; private float flick_w=40.0f; private float flick_h=30.0f; public SurfaceHolder holder; private ScheduledExecutorService executor; public float w,h,jplane_x,dw,dh; public float dx=0f; public float dy=0f; private float xperia_width=1280.0f; private float xperia_height=720.0f; public float velocity=1.3f;//2.5f; public float missile_velocity=4.5f;//2.5f;//3.5f;//2.0f; public int jplane_ii=0; public Point[][] ppp; public int jj=0; public int callBack_count=0; public boolean game_end=true; public boolean[][] jalive; public int tap_count=0; public int max_tap_count=100; private MediaPlayer bon0,bon1,bon2,bon3,bon4,bon5; private int cplane_no=20;//10; private int[] jtroop_new; private int ctroop_new=0; public AirFight(Context context){ super(context); init(context); } public AirFight(Context context,AttributeSet attrs){ super(context,attrs); init(context); } public void init(Context context){ this.context=(Activity)context; holder =getHolder(); holder.addCallback(this); setFocusable(true); requestFocus(); nationaldefence=(NationalDefenceActivity) context; setBoardSize(); } public void setBoardSize(){ Resources resources=context.getResources(); back=new Drawable[5]; back[0]=resources.getDrawable(R.drawable.back_0_1); back[1]=resources.getDrawable(R.drawable.back_1_1); back[2]=resources.getDrawable(R.drawable.back_2_1); back[3]=resources.getDrawable(R.drawable.back_3_1); back[4]=resources.getDrawable(R.drawable.back_4_1); jplane=new Drawable[5][3]; jplane[0][0]=resources.getDrawable(R.drawable.jplane_00); jplane[0][1]=resources.getDrawable(R.drawable.jplane_00); jplane[0][2]=resources.getDrawable(R.drawable.jplane_00); jplane[1][0]=resources.getDrawable(R.drawable.jplane_11); jplane[1][1]=resources.getDrawable(R.drawable.jplane_11); jplane[1][2]=resources.getDrawable(R.drawable.jplane_11); jplane[2][0]=resources.getDrawable(R.drawable.jplane_20_1); jplane[2][1]=resources.getDrawable(R.drawable.jplane_20_1); jplane[2][2]=resources.getDrawable(R.drawable.jplane_20_1); jplane[3][0]=resources.getDrawable(R.drawable.jplane_30); jplane[3][1]=resources.getDrawable(R.drawable.jplane_30); jplane[3][2]=resources.getDrawable(R.drawable.jplane_30); jplane[4][0]=resources.getDrawable(R.drawable.jplane_24_1); jplane[4][1]=resources.getDrawable(R.drawable.jplane_24_1); jplane[4][2]=resources.getDrawable(R.drawable.jplane_24_1); bon0=MediaPlayer.create(getContext(),R.raw.launch01); bon1=MediaPlayer.create(getContext(),R.raw.explosion01); bon2=MediaPlayer.create(getContext(),R.raw.pyo1); bon3=MediaPlayer.create(getContext(),R.raw.destruction01); bon4=MediaPlayer.create(getContext(),R.raw.heal01); bon5=MediaPlayer.create(getContext(),R.raw.status06); start=resources.getDrawable(R.drawable.start); bang=resources.getDrawable(R.drawable.bang); w=nationaldefence.disp_w; h=nationaldefence.disp_h; dw=w/xperia_width; dh=h/xperia_height; flick_w *=dw; flick_h *=dh; jcon =new Jcon(jplane,jplane_ii,w,h,dw,dh,bang,bon3); jcon.init(); } public boolean onTouchEvent(MotionEvent event1){ int n=event1.getAction(); float x=event1.getX(); float y=event1.getY(); switch(n){ case MotionEvent.ACTION_DOWN: press_loc=new Point((int)x,(int)y); if(isIn((int) x,(int) y,start.getBounds()) && game_end){ game_end=false; start(); } break; case MotionEvent.ACTION_UP: } return true; } public void start(){ try{executor.shutdown();}catch(Exception e){} SensorManager manager=(SensorManager)context.getSystemService(Activity.SENSOR_SERVICE); List sensors=manager.getSensorList(Sensor.TYPE_ACCELEROMETER); if(sensors.size() >0){ Sensor sensor=sensors.get(0); manager.registerListener(this,sensor,SensorManager.SENSOR_DELAY_FASTEST); } try{executor.shutdown();}catch(Exception e){} start_time=SystemClock.currentThreadTimeMillis(); executor=Executors.newSingleThreadScheduledExecutor(); if(!game_end){ executor.scheduleAtFixedRate(new Runnable(){ @Override public void run(){ if(SystemClock.currentThreadTimeMillis()-start_time >GAME_TIMES || tap_count > max_tap_count){ gameOver(); } draw(); } },1000,100,TimeUnit.MILLISECONDS); } } public void draw(){ Canvas canvas=holder.lockCanvas(); back[jplane_ii].setBounds(new Rect(0,0,(int)w,(int) h)); back[jplane_ii].draw(canvas); jcon.draw(canvas); if(game_end){ start.setBounds(new Rect((int)w/3,0,(int)(2*w/3),(int) h/10)); start.draw(canvas); } holder.unlockCanvasAndPost(canvas); } public boolean isIn(int x,int y,Rect rect){ return x>rect.left && xrect.top && y< rect.bottom; } public void gameOver(){ game_end=true;tap_count=0; try{executor.shutdown();}catch(Exception e){}//click_no++; Intent intent=new Intent(this.getContext(),RecordActivity.class); this.getContext().startActivity(intent); } @Override public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){ } @Override public void surfaceCreated(SurfaceHolder holder){ draw(); } @Override public void surfaceDestroyed(SurfaceHolder holder){ try{ executor.shutdown(); }catch(Exception e){} } @Override public void onAccuracyChanged(Sensor sensor,int accuracy){} @Override public void onSensorChanged(SensorEvent event){ jplane_x=jcon.getX(jplane_ii); float xx=0;float dxx=0.4f; if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){ xx=(event.values[1]/velocity); xx +=dxx; jplane_x +=xx; } if(jplane_x<=156*dw){ jplane_ii=0; }else if(jplane_x<=412*dw){ jplane_ii=1; }else if(jplane_x<=668*dw){ jplane_ii=2; }else if(jplane_x<=924*dw){ jplane_ii=3; }else{ jplane_ii=4; } for(int i=0;i<3;i++){ jcon.jalive[jplane_ii][i]=true; jcon.count[jplane_ii][i]=0; } jcon.setX(jplane_ii,jplane_x); } } 以上が基本的な仕組みです。 これを基本としていろいろな動きのあるゲームを作成していくことができるはずです。