Androidプログラミング日記 (仮)  

シューティング作るぞ!> 第二回 自機の移動

あなたは

人目のプログラマーだよ。

Androidプログラミング日記 (仮).

 

 

 

 

自機の移動

今回は自機の移動をします。スマホの場合、キャラを移動させる方法は制限されますよね。画面を犠牲にしてコントローラーを表示させる。タップで移動させる。傾きセンサーで移動。コントローラがない為に基本細かい動きはなかなかできません。でもそのなかで工夫したりするとおもしろいかもしれませんね。

このシューティングゲームはタップ方式でいきたいと思います。

シリーズものなので、前回と比べて変更した箇所のファイルのみ掲載しようと思います。

 

 

 

 

コード追記場所はMainLoop内onTouchEventメソッドです。

ACTION_MOVE値を取得すると、画面タップしたあとに移動したかどうかがわかります。なのでタップした指にキャラがついてくるような移動方法になります。タップした場所が自機クラスで定めた範囲であれば移動するようにしているため、ワープっぽく移動してしまうようなことを防いでいます。

Objectクラスの追記

OMoveメソッドで移動を実装しています。ただ単にタップしている場所に座標を置き換えているだけです。いまある座標を保存し、移動後に画面外にでるようなら保存している座標に戻しています。

OgetTapRectメソッドは、タップをちょっと早くするとどうしても処理の速さの関係上画像がタップ移動についてこれなくなりタップ位置から画像がはなれてついてこれなくなります。それを画像の範囲よりもちょっと幅広に設定してあげることにより余裕をもたせて、ある程度タップ位置が画像から離れても大丈夫なようにするための処理です。

 

ファイル名「MainLoop.java」


/*
 * SurfaceViewをextendsさせたクラス
 * メインループなどはここにあります
 * 基本的にSurfaceViewを使用した時には決まった変数の使用
 * などがあるので、そういう変数やメソッドの末尾に
 * ”お決まり”と書いておきます
 */
package and.roid.shooting2;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MainLoop extends SurfaceView implements SurfaceHolder.Callback,Runnable{
	private SurfaceHolder holder;//お決まり
	private Thread thread;//お決まり

	//どのActivityを使用しているかのための変数
	private Shooting2Activity s2a;
	private Mesod ms;
	private float disp_w,disp_h;
	private Drawable jikiimg,tamaimg;


	/*
	 * Objectクラスを使用する準備
	 * 今回だけではこれの意味はあまりありません
	 */
	private Object jiki;

	//コンストラクタが二つあるけど気にしないように
	//こちらのコンストラクタは、自前でViewを実装するときに
	//呼ばれるコンストラクタっぽい
	public MainLoop(Context context) {
		super(context);
		init(context);
	}
	//こちらはxml方式でViewを呼び出すときに呼ばれるぽい
	public MainLoop(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public void init(Context context){
		holder = getHolder();//お決まり
		holder.addCallback(this);//お決まり
		holder.setFixedSize(getWidth(), getHeight());//お決まり
		/*
		 * s2a = (Shooting2Activity)context;
		 * よくわからないけども、私的には使用している(今現在
		 * 画面に表示させている)アプリの何か色々なものをcontext
		 * として受け取り、それがいまどのActivityのやつかとか
		 * そんな感じの雰囲気と思います。(キニシテナイ)
		 */
		s2a = (Shooting2Activity)context;
		ms = new Mesod();
		disp_w = s2a.disp_w;
		disp_h = s2a.disp_h;

		Resources resources = context.getResources();//画像登録準備
		//ビットマップ方式で画像取り込み
		//ビットマップで取り込む理由として、使用したい大きさなどに変換できるので
		Bitmap img= BitmapFactory.decodeResource(resources,and.roid.shooting2.R.drawable.jiki);
		//ここで画像分割
		//わざわざ画像の大きさをgetWidthgetHeightを使用するのは
		//確実に大きさを図って分割するため
		Bitmap jikibit = Bitmap.createBitmap(img,0,0,img.getWidth()/2,img.getHeight());
		Bitmap tamabit = Bitmap.createBitmap(img,img.getWidth()/2,0,img.getWidth()/2,img.getHeight());

		/*
		 * Onjectクラスではインスタンス(実装)できないので
		 * ObjectクラスをextendsさせたJikiクラスを実装
		 */
		jiki = new Jiki(disp_w,disp_h);
		jiki.Oint(jikibit, 240, 800, 0, 0, jikibit.getWidth(), jikibit.getHeight());

	}

	//implements Runnableを実装するとこのメソッドが自動追加
	//ここがメインループとなります
	public void run() {//お決まり
		Canvas c;
		Paint p = new Paint();
		p.setAntiAlias(true);

		while(thread != null){
			c = holder.lockCanvas();//お決まり

			c.drawColor(Color.BLACK);
			jiki.ODraw(c);


			holder.unlockCanvasAndPost(c);//お決まり

			try {
				Thread.sleep(50);//お決まり
			} catch (Exception e){}
		}
	}

	public boolean onTouchEvent(MotionEvent event){
		int action = event.getAction();
		int x = (int)event.getX();
		int y = (int)event.getY();
		switch(action){
		case MotionEvent.ACTION_DOWN:
			break;
		case MotionEvent.ACTION_UP:
			break;
		case MotionEvent.ACTION_MOVE:
			/*
			 * タップ範囲にオブジェクトがあると自機の移動処理をします
			 * これがないと、ワープのような動きになる場合があります。
			 */
			if(ms.RectTap(x, y, jiki.OgetTapRect()) == true) jiki.OMove(x, y);
			break;
		}
		return true;
	}


	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}//お決まり

	public void surfaceCreated(SurfaceHolder arg0) {thread = new Thread(this);thread.start();}//お決まり

	public void surfaceDestroyed(SurfaceHolder arg0) {thread = null;}//お決まり

}

						

前回書き忘れたのでちょっと細かく表記しています

ファイル名「Object.java」


/*
 * このクラスは画面に表示させるオブジェクト
 * を作成させるためのクラスです
 * このクラス単体ではインスタンス(オブジェクト化、実体化)
 * はできず、このクラスをextendsさせて使うようにしています
 * 理由としてはこのゲームを作成していくうちにわかってきますが
 * コード表記がラクチンになります
 */
package and.roid.shooting2;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;

public abstract class Object {
	private Mesod ms = new Mesod();
	private float disp_w,disp_h;
	//オブジェクトの画像
	private Drawable img;
	//オブジェクトの中心座標
	private float cx,cy;
	//向かおうとしている座標
	private float vx,vy;
	//オブジェクトの移動スピード
	private float spx,spy;
	//オブジェクトの大きさ
	private int imgw,imgh;

	public Object(){}
	public Object(float dw,float dh){
		disp_w = dw;
		disp_h = dh;
	}
	//初期設定
	public void Oint(Bitmap imgb,float x,float y, float sx,float sy,int w,int h){
		img = new BitmapDrawable(imgb);
		cx = ms.setSizeX(disp_w, x);
		cy = ms.setSizeY(disp_h, y);
		spx = sx;
		spy = sy;
		imgw = w;
		imgh = h;
	}
	//画像表示
	public void ODraw(Canvas c){
		/*
		 * cx,cyは中心座標のため、画像の中心にちゃんとcx,cyがくるように調整
		 */
		img.setBounds((int)(cx-imgw/2),(int)(cy-imgh/2),(int)(cx+imgw/2),(int)(cy+imgh/2));
		img.draw(c);
	}
	/*
	 * タップしたまま指を動かすとオブジェクトを移動するようにします
	 * そのため動かした先の座標におきかえるだけにしています。
	 * しかし、弾などはそういう動きにしないため、のちのちはここは
	 * abstractになる予定です
	 * このままだと弾も敵もタップして動くような書き方になっています
	 * 今回は自機を動かすだけなのでとりあえずこれで
	 */
	public void OMove(int x,int y){
		float cxx = cx;
		float cyy = cy;
		cx = x;
		cy = y;

		if(cx-imgw/2<0 || cx+imgw/2>disp_w) cx = cxx;
		if(cy-imgh/2<0 || cy+imgh/2>disp_h) cy = cyy;
	}
	/*
	 * タップ範囲にオブジェクトがあると移動できるようにしてます。。
	 * しかしタップして動かしてみると、指の動きにオブジェクトが
	 * ついてこれない場合があります。そのためオブジェクトの大きさを
	 * タップ時のみ大きくしてある程度オブジェクトから離れても
	 * ついてこれるようにごまかしています。
	 */
	public Rect OgetTapRect(){
		Rect taprect = new Rect(
				img.getBounds().left-50,img.getBounds().top-50,
				img.getBounds().right+50,img.getBounds().bottom+50);
		return taprect;
		}
}


						
 

無事成功しました!

 

自機の移動はこれで完了です。

こうやって自分で作成するとわかるのですが、既存のスマホゲームなどはちゃんと細かい気配りの工夫などがしてあるんだなと思います。

あーしたいこーしたいっていうのをコードにおこす為に思案するのがプログラミングの醍醐味ですよね!

 

<戻る   次へ>

 

 

 

Androidプログラミング日記 (仮) | サイトマップ | 個人情報保護方針 | 応援メールテヘペロ | ©2012 Japan  相互リンク大募集中です