2011年5月17日火曜日

Android 数字画像を使って簡単なデジタル時計を作る。

数字画像を用意してデジタル時計を作ってみる。
今回作成した物は、数字画像を使って、時刻の表示のみ、余計な設定は入れていない。

拡張子がpngの画像(数字)が9枚、それから、コロン画像1枚の計10枚。

画像を読み込むための準備
まず、変数で、配列の初期化を行う。
private Bitmap digits[]=new Bitmap[11];

これを使って、コンストラクタの中で画像を読み込む。
Resources r=context.getResources();
dgits[0]=BitmapFactory.decodeResource(r,R.drawable.a0);
dgits[1]=BitmapFactory.decodeResource(r,R.drawable.a1);
dgits[2]=BitmapFactory.decodeResource(r,R.drawable.a2);
dgits[3]=BitmapFactory.decodeResource(r,R.drawable.a3);
dgits[4]=BitmapFactory.decodeResource(r,R.drawable.a4);
dgits[5]=BitmapFactory.decodeResource(r,R.drawable.a5);
dgits[6]=BitmapFactory.decodeResource(r,R.drawable.a6);
dgits[7]=BitmapFactory.decodeResource(r,R.drawable.a7);
dgits[8]=BitmapFactory.decodeResource(r,R.drawable.a8);
dgits[9]=BitmapFactory.decodeResource(r,R.drawable.a9);

コロン画像も読み込む
dgits[10]=BitmapFactory.decodeResource(r,R.drawable.c);

画像の読み込みは終了。

次に、時刻の設定について
Javaで時刻を使うには、Calendarクラスを使って設定を行う。
このCalendarクラスは、デフォルトのタイムゾーンに基づいて
設定されている。

Calendarクラスは、abstractクラスなので、new演算子でオブジェクトを作成することが出来ないので、
次の設定を行って、オブジェクトを作成する。
Calendar calendar=Calendar.getInstance();

これで、Calendarクラスが使えるようになる。
ちなみに、import文は、
import java.util.Calendar;

今回は、変数を設定して使ってみる。
private Calendar currentTime;

そして、描画を設定しているメソッドで時刻の設定情報を呼び出して設定する。
こんな感じ
//時間
canvas.drawBitmap(dgits[currentTime.get(Calendar.HOUR_OF_DAY)/10],1*imageWidth,0,null);
canvas.drawBitmap(dgits[currentTime.get(Calendar.HOUR_OF_DAY)%10],2*imageWidth,0,null);
canvas.drawBitmap(dgits[10],3*imageWidth,0,null);

//分
canvas.drawBitmap(dgits[currentTime.get(Calendar.MINUTE)/10],4*imageWidth,0,null);
canvas.drawBitmap(dgits[currentTime.get(Calendar.MINUTE)%10],5*imageWidth,0,null);
canvas.drawBitmap(dgits[10],6*imageWidth,0,null);

//秒
canvas.drawBitmap(dgits[currentTime.get(Calendar.SECOND)/10],7*imageWidth,0,null);
canvas.drawBitmap(dgits[currentTime.get(Calendar.SECOND)%10],8*imageWidth,0,null);
canvas.drawBitmap(dgits[10],9*imageWidth,0,null);

//ミリ秒
canvas.drawBitmap(dgits[currentTime.get(Calendar.MILLISECOND)/100],10*imageWidth,0,null);
canvas.drawBitmap(dgits[currentTime.get(Calendar.MILLISECOND)%10],11*imageWidth,0,null);
canvas.drawBitmap(dgits[currentTime.get(Calendar.MILLISECOND)%1],12*imageWidth,0,null);

時分秒ミリ秒などを取得する為のものがCalendarクラスのget()メソッドを使って、その引数の中に
Calendarクラスの各フィールドを呼び出して使用する。

※imageWidthについて・・・
この変数には、画像の幅を取得した値が代入されている。
Androidの画像の幅を取得するには、BitmapクラスのgetWidth()メソッドを使用して取得。

今回、SurfaceViewを使用して作っているので、run()メソッドの中でも設定を入れてあげないと
動作しない。
あと、コンストラクタの中にも、currentTime=Calendar.getInstance();
を設定をする。

run()メソッドの中身はこんな感じ
/**
 * スレッドの処理
 */
public void run() {

Canvas canvas;

while(thread!=null) {

//動作させる為にCalendarクラスのgetInstance()メソッドを
//呼び出している。
currentTime=Calendar.getInstance();

//ダブルバッファリングのロック処理
canvas=holder.lockCanvas();

//背景処理
canvas.drawColor(Color.BLACK);

//描画設定のメソッドの呼び出し
draw(canvas);

//ダブルバッファリングのアンロック処理
holder.unlockCanvasAndPost(canvas);

try {
Thread.sleep(30);

}catch(InterruptedException e) {
e.printStackTrace();

}

}
}

これで完成。
完成動画



Java Calendarクラス
Android reference Calendarクラス

その他、数字画像を使用したもの関連
Androidでゲーム ブロック崩し編   9回目:数字画像を使って点数の表示
Androidでゲーム ブロック崩し編 12回目:数字画像を使って機数の表示と設定

2011年5月14日土曜日

Androidでゲーム シューティングゲームっぽい物。      その5:敵の攻撃設定

敵の攻撃を設定する。
敵は、1体のみの設定で、画面右端から移動してきて、座標値X=300付近で
敵の移動を停止し、弾を発射する。

専用のクラスファイルを作り、その中で設定したこと。
変数の設定
座標値x,y
移動値move_x,move_y;
画像サイズsize
画像イメージの変数img
保管場所の設定
(定数)
private static final PointF point=new PointF(画面に描画されない場所);

コンストラクタの中身
画像の読み込み
保管場所から敵弾を呼び出してセットする。

移動設定メソッド
ここでは、弾を移動させるだけの設定と、画面左端に弾が到達したら
保管場所に移動するメソッドの呼び出しを行う。

描画メソッド
画像の描画のみ

その他
SurfaceViewを設定しているクラスファイルで呼び出すために作ったメソッドと、
同じクラスファイルの中で使用するメソッドの設定

敵の弾の位置を返す
public PointF getPos() {
return new PointF((int)x,(int y));
}

敵の弾の位置をセットする
public void setPos(float x,float y) {
this.x=x;
this.y=y;
}

敵の弾を保管場所に移動させるメソッド
保管場所にあるかどうかのチェックをするメソッド

次にSurfaceViewを設定しているクラスファイルでの設定。
設定する事は、複数処理を施すこと、連射機能をつける事。
この2つに絞って作って見る。

①複数処理について
変数の設定
複数処理は、配列の要素に複数処理用の変数を入れるので、その為の定数を作る。
private static final int NUM_ATTACKS2=5;

敵の弾を作ったクラスファイルの呼び出し
ファイルの名前は、E2_Shot.java
private E2_Shot[] attack2;

コンストラクタでは、配列の初期化を行う
attack2=new E2_Shot[NUM_ATTACKS2];
for(int i=0;i<NUM_ATTACKS2;i++)
attack2[i]=new E2_Shot(this);

描画メソッドの呼び出し
for(int i=0;i<NUM_ATTACKS2;i++)
attack2[i].draw(canvas);

敵弾の移動専用のメソッドを作成して、その中で移動メソッドを呼び出した
public void attack_Move() {
for(int i=0;i<NUM_ATTACKS2;i++)
attack2[i].move();
}

②連射機能について
連射機能は、時間を取得し、最初に発射した弾と次に発射した弾の時間を比較し、
比較した結果で次の弾を発射できるようにする設定を行う。
変数の設定
//次の発射までの時間
private static int attack2_interval=500;
//最後に発射した時間
private long attack2_lastTime;

③敵の弾の発射制御メソッドの作成
このメソッドの中身では、敵の弾が保管場所にある場合、弾をセットして1発発射したら
抜けるという仕組みのメソッド。

こんな感じ
public void tryToAttack() {
// 前との発射間隔がshot_interval以下だったら発射できない
//発射できるかどうかチェックする
//発射できない場合・・・return
if(System.currentTimeMillis()-shot_lastTime<shot_interval)
return;

//最後に発射された時間を取得する
//shot_lastTimeに入れる
shot_lastTime=System.currentTimeMillis();

for(int j=0;j<NUM_ATTACK2;j++) {
if(attack2[j].isInStorage()) {
//弾が保管庫にあれば発射できる
//弾の座標を敵の座標にセットすれば発射される
if(enemy2.flg2==true) {
//敵の位置の取得
PointF enemy2_Pos=enemy2.getPos();
//取得した敵の位置を弾の位置にセットする
attack2[j].setPos(enemy2_Pos.x+16, enemy2_Pos.y+16);
//一発発射した抜ける
break;
}
}
}
}

④runメソッドで呼び出す
①で作った、attack_Move()メソッドと、③で作ったtryToAttack()メソッドをrun()メソッドで呼び出す。

その他、シューティングゲーム関連



2011年5月12日木曜日

Androidのタッチイベントを使ってアニメーションを動作させる

画面をタッチしたらアニメーションを動作させる。

アニメーションは、前回爆発エフェクトを作ったので、今回は、タッチしたら雷エフェクトを
表示させてみようと思う。

雷画像は、拡張子がpngの画像で、ゲームとかで使えそうな画像を用意して、動作させた。

作る時に注意することは、タッチしてアニメーションを動作させてる最中にもう一回タッチしても、
前回タッチした分のアニメーションが消えないようにすること。
(動作を維持させる)
それから、タッチイベントにはスライドさせる動作もあるので、その時に連続して表示させる
仕組みを作り、且つ、動作を維持させる。

①アニメーションを維持させる
アニメーションを維持させる仕組みとして、今回試してみた方法は、タッチしたときにフラグを
trueにしてフラグがtrueの時に変数に1代入する。変数に1が入っている時に、
画像を枚数分だけカウントをインクリメントし、そして、描画用のフラグ変数をtrueにして、
カウントの値と画像の枚数が一致(最後の枚数まで回った時)した場合、描画用の
フラグ変数をfalseにする。

これによって、最初にタッチして表示されたアニメーションが、次にタッチして時に消えることなく
最後まで、表示し続けることになる。

設定したコードは
変数の設定
//動作維持用のカウント変数
private int count0
//画像出力用のカウント変数
private int count1
//描画用のフラグ変数
private boolean flg1
//タッチしたときのフラグ変数
private boolean flg2
//カウントをリセットするためのフラグ変数
private boolean flg3;

コンストラクタの中身
/*動作維持用カウント変数*/
//初期状態は0
count0=0;

/*一応count変数の初期化*/
count1=NUM_IMAGES;

/*画像出力用のフラグ変数*/
flg1=false;

/*フラグの初期化*/
flg2=false;
flg3=false;

描画用メソッドの中身
/**
 * 描画
 * @param canvas
 */
public void draw(Canvas canvas) {
/*画像の出力*/
//flg1がtrueの場合
//カウントしたぶんだけ出力する
if(flg1==true) {
canvas.drawBitmap(img[count1],x,y,null);
}

動作を維持させる為のメソッドとアニメーションで表示させる画像をカウントするためのメソッド
/**
 * カウントをするメソッド
 */
public void count_Up() {
//タッチしている時
if(flg2==true) {

//動作維持用のカウント変数に
//1を代入
count0=1;
}

//動作維持用カウント変数に1が入っていたら
if(count0==1) {
//アニメーションカウント変数を回す
count1++;
//描画フラグをtrueにする
flg1=true;
}

//count1とNUM_IMAGESが同じになったら
if(count1==NUM_IMAGES) {
//flg1をfalse
//flg1をfalseにして、countのインクリメントを止める
flg1=false;
//flg3をtrue
//flg3をtrueにして、リセットの準備態勢に入る
flg3=true;
}

}

カウントをリセットするのとフラグを初期化するメソッド
/**
 * カウントをリセットする
 */
public void reset_Count() {
//flg3がtrueの時に
if(flg3==true) {
//count1に0を代入
//カウント開始時の状態に戻る
count1=0;
//動作維持用のカウント変数に0を入れる
count0=0;

//フラグを初期状態にする
flg1=false;
flg3=false;
}
}

②連続して表示させる
タッチイベントで画面をスライドしたらアニメーション画像が連続して表示させる。
大まかな流れは
画像を保管する場所を作る

画面がタッチされたら

保管場所からタッチした座標値にセットする

アニメーションが表示される

画像の枚数分表示される

保管場所に戻る

と、言う流れになる。

保管場所の作成
保管場所はPointクラスを使用する
こんな感じ
private static final Point point=new Point(-100,-100);
ポイントの位置はは画面から見えない座標値に設定

コンストラクタの中身
タッチした場所にセットする
こんな感じ
x=point.x;
y=point.y;

描画メソッドの中身
保管している場所に有る場合は抜けるように設定しておく
/**
 * 描画
 * @param canvas
 */
public void draw(Canvas canvas) {
if(isStorage())
return;
/*画像の出力*/
//flg1がtrueの場合
//カウントしたぶんだけ出力する
if(flg1==true) {
canvas.drawBitmap(img[count1],x,y,null);
}

アニメーション画像の枚数分まで行ったら、保管している場所に移動させる
/**
 * カウントをするメソッド
 */
public void count_Up() {
//タッチしている時
if(flg2==true) {

//動作維持用のカウント変数に
//1を代入
count0=1;
}

//動作維持用カウント変数に1が入っていたら
if(count0==1) {
//アニメーションカウント変数を回す
count1++;
//描画フラグをtrueにする
flg1=true;
}

//count1とNUM_IMAGESが同じになったら
if(count1==NUM_IMAGES) {
//flg1をfalse
//flg1をfalseにして、countのインクリメントを止める
flg1=false;
//flg3をtrue
//flg3をtrueにして、リセットの準備態勢に入る
flg3=true;
//保管場所に移動
point();
}

}

これらで使用する為に作ったメソッド
/**
 * アニメーションが終了したら
 * 保管庫に移動
 */
public void point() {
x=point.x;
y=point.y;
}

/**
 * 保管庫の有無
 *
 * 有る場合
 * @return true
 *
 * 無い場合
 * @return false
 */
public boolean isStorage() {
if(x==point.x&&y==point.y) {
return true;
}
return false;
}

連続して表示されるためには、これだけでは出来ない。
SurfaceViewを設定しているクラスファイルで、配列にして呼び出し設定をすると完成する。

その他、タッチイベント関連

完成品



2011年5月11日水曜日

ランダムクラスを使って色の変更を行う

ランダム処理を使って色の変更を行う。

ただ色の変更を行っても面白くないので、画面にタッチしながら色の変更をする仕組みを作る。

色の変更について。
ランダムクラスを使って色の変更をする仕組み。

Androidの色の描画は、PaintクラスのsetColor()メソッドで指定する。
このsetColor()メソッドの引数の中身にColorクラスを入れて、Colorクラスの
色の定義がされているメソッドやrgb()メソッド、又はargb()メソッドで数字を指定して
使用する方法があるが今回の場合は、rgb()メソッドを使用して作る。

rgb(int red,int green,int blue)メソッドの引数は、int型の数字を使用して色を設定する。
Androidの色の数字は、赤、緑、青ともに0~255の数字が当てられている。

この数字をランダムクラスに使用する。

ランダムクラスの設定
上記の色の数字を入れるのではなく、0~255なので、0番~255番の色が
あるという考え方になるので、256個あるということになる。

ランダムクラスのnextInt(int n)メソッドを使用し、この引数に256と言う数字を
入れることによって、ランダムに0番~255番の色が出力される。

作り方
まず、色の変更のみの場合

int型の変数
nextInt()メソッドで得た値を代入し、rgb()メソッドで使用する
private int red,green,blue;

ランダムクラスのインスタンス変数
private Random random;

コンストラクタの中身
ランダムのインスタンスの作成
random=new Random();

色を変更させるメソッドの作成
public void changeColor() {
この中でnextInt()メソッドを使う
//red
red=random.nextInt(256);
//green
green=random.nextInt(256);
//blue
blue=nextInt(256);
}

描画設定
public void draw(Canvas canvas) {
//色の設定
//changeColor()メソッドで記述したコードのred,green,blueを
//rgb()メソッドの引数に当てる
Paint paint=new Paint();
paint.setColor(Color.rgb(rec,green,blue));

//画面の色を変えるだけ
paint.setStyle(Paint.Style.Fill);
Rect rect=new Rect(0,0,getWidth(),getHeight);
canvas.drawRect(rect,paint);
}

SurfaceViewを使用しているので、
runメソッドの中身に上記で記述したdrwa()メソッドを呼び出す。
public void run() {
Canvas canvas;
while(thread!=null) {
//ダブルバッファリングのロック処理
canvas=holder.lockCanvas();
//色番号の変更
changeColor();
//描画
draw(canvas);
//ダブルバッファリングのアンロック処理
holder.unlockCanvasAndPost(canvas);
try {
Thread.sleep(30);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}

これで、取り合えず、画面全部の色がランダムに変わる。

タッチイベントを使って作る
今度は、タッチして何か落書きをしながら色をランダムに変える仕組みを作る。

タッチイベントで文字を書いたり絵を描いたりする設定については割愛する。
変更するのは、changeColor()メソッドをタッチイベントのメソッドの中に記述すること、それから、
Paint paint=new Paint();
paint.setColor(Color.rgb(rec,green,blue));
をfor(int i=0;i<draw.size();i++) {}
のブロック内に記述する事の2つ。
※上記で作った画面全体を使って色の変更を設定したRectクラスと、
drawRect()は削除しておく。
(タッチイベントで描画する方法はタッチイベントで文字を書いたり絵を描いたりするを参照)

これで、描画している最中に色が変化するようになる。
が、今回の設定だと描画している最中に前に描画した色まで変化する。

Android reference クラス:Color・・・メソッド:rgb(int red, int green, int blue)
Android reference クラス:Random・・・メソッド:nextInt(int n)
Android reference クラス:Paint・・・メソッド:setColor(int color)

その他、ランダム設定関連
Androidでゲーム シューティングゲームっぽい物。その2:敵1体をランダムに出現させる

その他、タッチイベント関連
タッチイベントで文字を書いたり絵を描く
タッチした方向に描画した円を発射する
タッチした方向に描画した円を発射する。その2
Androidでゲーム ブロック崩し編 3回目:板画像のタッチ操作
Androidでゲーム ブロック崩し編 4回目:タッチ操作が出来る範囲と出来ない範囲を作る
タッチイベントを使って、画像を回転させる
Androidのタッチイベントを使ってアニメーションを動作させる
完成品

2011年5月10日火曜日

Androidでゲーム シューティングゲームっぽい物。      その4:弾と敵が衝突したら、爆発エフェクトを動作させる

爆発エフェクトを付けてみる。

androidのアニメーション処理に関するAPIとかを使わないで、配列とカウント変数、
それからフラグ変数を使用しての作成。

参考になるのが、サンプルコードのJetBoy。
でも、JetBoyのサンプルコードよりはシンプルに考えて見たいと思って作った。

問題は画像で、JetBoyを見ると、動作ごとに画像が1枚ずつ存在していて、1枚の画像に複数の
画像を個別に読み出す仕組みにはなっていない。
どちらかと言うと、そっちの方が楽。でも、Androidでそれが出来るのかどうかわからない。

なので、画像は各動作ごとに1枚ずつ用意した。
全部で16枚。
爆発エフェクトを作成するフリーのソフト発色弾を使用し、そこから出力された物を
ペイントソフトで全て手作業で分割。
※ペイントソフトは、背景の透過処理がきちんと行えるものであれば何でもOK。
因みに使ったソフトはGIMP2です。
なにか、いい方法があればなって考えてみたけれども、思いつきません。

最初に、エフェクト用のクラスファイルを作る。
配列を作り、その配列をカウント変数で呼び出す仕組み。
フラグ変数は、敵画像に弾画像が当たったらtrueにするフラグ変数で、これは、カウント変数を
動かす為の変数、もう1つは、
画像の枚数文呼び出したら、countの値を0(この場合、配列のインデックス番号を0番)
にするフラグ変数で、このフラグはリセットを行う。

属性で必要な物は
画像を読み込む為の変数、
複数処理用に変数を定数で設定、
こんな感じ
//爆発イメージ枚数
private static final int NUM_IMAGES=16;

爆発する位置を決める為の座標値、
画像のサイズの変数、
画像を出力する為に必要な枚数を数えるカウント変数、
カウント変数を動かす為のフラグ変数、
リセットを行う為のフラグ変数。

コンストラクタでは、
配列の初期設定を行い、配列に画像ファイルを読み込む設定、
こんな感じ
/**
 * コンストラクタ
 */
public Explosion(MainPanel panel) {

/*イメージ関連の読み込み*/
//イメージファイルの数分だけ配列に入れる
img=new Bitmap[NUM_IMAGES];

Resources r=panel.getResources();

/*読み込む画像*/
img[0]=BitmapFactory.decodeResource(r,R.drawable.e1_0);
img[1]=BitmapFactory.decodeResource(r,R.drawable.e2_0);
img[2]=BitmapFactory.decodeResource(r,R.drawable.e3_0);
img[3]=BitmapFactory.decodeResource(r,R.drawable.e4_0);
img[4]=BitmapFactory.decodeResource(r,R.drawable.e5_0);
img[5]=BitmapFactory.decodeResource(r,R.drawable.e6_0);
img[6]=BitmapFactory.decodeResource(r,R.drawable.e7_0);
img[7]=BitmapFactory.decodeResource(r,R.drawable.e8_0);
img[8]=BitmapFactory.decodeResource(r,R.drawable.e9_0);
img[9]=BitmapFactory.decodeResource(r,R.drawable.e10_0);
img[10]=BitmapFactory.decodeResource(r,R.drawable.e11_0);
img[11]=BitmapFactory.decodeResource(r,R.drawable.e12_0);
img[12]=BitmapFactory.decodeResource(r,R.drawable.e13_0);
img[13]=BitmapFactory.decodeResource(r,R.drawable.e14_0);
img[14]=BitmapFactory.decodeResource(r,R.drawable.e15_0);
img[15]=BitmapFactory.decodeResource(r,R.drawable.e16_0);

画像サイズの指定、
フラグ変数の初期状態の設定、
一応、カウント値の初期状態の設定。

描画メソッドでは、
カウント変数を動かす為のフラグ変数がtrueの場合に、
画像を呼び出す設定をする。
こんな感じ
/**
* 描画
*/
public void draw(Canvas canvas) {
/*画像の出力*/
//カウント変数を動かす為のフラグ変数がtrueの場合
//カウントしたぶんだけ出力する
if(flg1==true) 
canvas.drawBitmap(img[count], x,y,null);
}

弾画像が敵画像に当たって爆発エフェクトが表示される場所の設定を行うメソッドを作る
ここで、設定する事は、敵画像の中心に爆発画像が来るように設定する。
こんな感じ
/**
* 爆発場所の設定
* 敵の中央になるように設定する
*/
public void play(float x,float y) {
/*爆発する場所を中央になるように設定*/
//x
this.x=x-size/2;
//y
this.y=y-size/2;
//カウント変数を動かす為のフラグ変数をtrueにする
flg1=true;
}

カウントを回すメソッドの作成。
ここで設定する事は、
カウント変数を動かす為のフラグ変数がtrueの場合に、カウント変数をインクリメントし、
そして、カウント変数と複数処理用に変数を定数で設定した枚数(今回読み込む画像枚数は16枚)と、
カウント変数の値が同じになったら、カウント変数を動かす為のフラグ変数をfalseにして、
リセットを行う為のフラグ変数をtrueにする。
こんな感じ
/**
* カウントをするメソッド
*/
public void count_Up() {
//カウント変数を動かす為のフラグ変数がtrueの時
if(flg1==true) {
//countをインクリメント
count++;
}

//カウント変数の値と枚数が一致した場合
if(count==NUM_IMAGES) {
//カウント変数を動かす為のフラグ変数をfalse
//カウント変数を動かす為のフラグ変数をfalseにして、countのインクリメントを止める
flg1=false;
//flg2をtrue
//flg2をtrueにして、リセットの準備態勢に入る
flg2=true;
}
}

カウントをリセットする為のメソッドの作成。
この中で設定する事は、
リセットを行う為のフラグ変数をtrueの場合、カウント変数の値を0にして、
各フラグ変数を初期状態のfalseにする。
/**
* カウントをリセットする
*/
public void reset_Count() {
//リセットを行う為のフラグ変数がtrueの時に
if(flg2==true) {
//countに0を代入
//カウント開始時の状態に戻る
count=0;
//フラグを初期状態にする
flg1=false;
flg2=false;
}
}

そして、これらを弾と敵が衝突した時に動作をするように設定をする。
弾と敵の交差を検出した時のメソッド内に、
敵の位置を取得する設定と、弾画像が敵画像に当たって爆発エフェクトが表示される場所の
設定を行うメソッドを呼び出す。
こんな感じ
//敵の位置取得
PointF enemy1_Pos=enemy1.getPos();
//爆発アニメーション
explosion.play(enemy1_Pos.x+16, enemy1_Pos.y+16);

その他、シューティングゲーム関連


2011年5月9日月曜日

Androidでゲーム シューティングゲームっぽい物。      その3:弾と敵の衝突判定

発射された弾が敵にぶつかった時の処理について
前回、前々回とタッチしたときにdrawCircle()メソッドを使って描画した円を
使っていたが、今回から弾画像を用意して、その画像を使って
処理することにした。

弾の画像はこれ


弾画像と敵画像がぶつかった時の処理は
①画面の端に来た場合、弾画像を消す処理
②敵とぶつかった時、弾画像を消す処理
③弾画像とぶつかった時、敵画像を消す処理
④弾画像とぶつかった時、敵画像をもう一度画面右端に戻す処理
の4つを行った。

①について
弾画像を消すにはフラグを使って消すと考えることになるが、それだと、
目に見える部分が消えているが実際は、弾画像と敵画像がぶつかった
ポイントに弾画像の座標値が残ってしまい、次に出てくる敵画像がその座標値に
来た時、弾画像が無いのに敵画像が消えるという不思議なことが起きてしまうので、
これも考慮した考えで行う。
タッチしたときに弾画像を、弾が発射されるスタート位置にセットする。
弾画像を設定しているクラスファイルのコンストラクタにて、設定しておく。
こんな感じ
属性を決める
private static final PointF point=new PointF(-100,-100);
コンストラクタでは
public Ball(MainPanel panel) {
//弾画像の読み込み
Resources r=panel.getResources();
img=BitmapFactory.decodeResource(r,R.drawble.弾画像の名前);
//タッチしたときに弾画像をセットする
x=point.x;
y=point.y;
//弾が発射されるスタート位置
x=-10;
y=-10;
//画面に弾画像があるかどうかのフラグ
//初期状態は無いのでfalse
used=false;
}
次に作るのが、弾画像が敵画像とぶつかった時と弾画像が画面の端に行ってしまった時の処理を施す
public void Store() {
x=point.x;
y=point.y;
}
もう1つが、弾画像がpoint=new PointF(-100,100);の中にあるかどうか
見るための物を作る
public boolean isInStorage() {
//あるかどうかチェックする
if(x==point.x&&y==point.y) {
//ある場合はtrueを返す
return true;
}
//無い場合はfalseを返す
return false;
}
設定したものを今度は、移動を設定しているメソッドで使用する
public void move() {
if(isInStorage())
return;
//画面の端に来た場合
if(x<0||x>panel.getWidth()||y<0||y>panel.getHeight()) {
//画面からなくなるのでfalse
used=false;
//Storeに移動させる
Store();
}
これで、画面の端に来た時の処理は終わり。
②と③について
②と③は、衝突判定処理を設定をして、それぞれの画像についての処理を行う。
弾画像と敵画像の衝突判定処理を設定する。
衝突判定処理はRectクラスを使い、intersectメソッドで設定を行う。
ブロック崩しや矩形同士の交差判定にもintersectメソッドを使用した交差判定処理を記述している。
ブロック崩しの交差判定処理
矩形同士の交差判定処理
敵画像を設定しているクラスファイルにて、衝突を検出したらtrueを返すメソッドを作成する。
こんな感じ
/**
* 自機弾との衝突検出
*/
public boolean collideWith(Ball ball) {
//敵1の矩形
Rect rect_enemy1=new Rect((int)x-size/25,
(int)y-size/25,
(int)x+size,
(int)y+size);
//自機弾の位置の取得
PointF ball_Pos=ball.getPoint();
//自機弾の矩形
Rect rect_ball=new Rect((int)ball_Pos.x-ball.getHeight()/25,
(int)ball_Pos.y-ball.getWidth()/25,
(int)ball_Pos.x+ball.getHeight(),
(int)ball_Pos.y+ball.getWidth());
//交差したらtrueを返す
return rect_enemy1.intersect(rect_ball);
}
衝突を検出する設定を作ったので、今度はSurfaceViewを設定しているクラスファイルで使用する
SurfaceViewを設定しているクラスファイルで設定する事は、弾画像と敵画像が交差したのを検出した時に
どうするか?と言う設定を行う。
設定する事は、弾画像の設定と敵画像が弾画像とぶつかった時に敵画像を画面右端に戻す設定を行う。
こんな感じ
/**
* 弾と敵の交差を検出した時の設定
*/
public void enemy_CollisionDetection() {
/*弾と敵1*/
for(int i=0;i
if(enemy1.collideWith(ball[i])) {
/*弾のフラグをfalse*/
ball[i].used=false;
/*弾画像を移動させる*/
ball[i].Store();
//④の部分
//弾に当たったら初期位置に戻すために
//敵画像のフラグをfalseにする。
enemy1.flg1=false;
//弾が1つぶつかったら抜けるようにする
break;
}
}
}
④について
④は、敵画像のフラグがfalseの時(初期状態)に画面右端に戻された、敵のクラスファイルを設定している
移動メソッドが呼ばれ、その中で、以下のような設定をしている。
if(flg1==false) {
x=533//画面の右端
y=rand.nextInt(250)
}
と、設定している。
enemy_CollisionDetection() メソッドをrun()メソッド内で呼び出したら
使用できるようになる。
その他、シューティングゲーム関連

2011年5月8日日曜日

Androidでゲーム シューティングゲームっぽい物。      その2-2:敵1体をランダムに出現させる。                  setSeed()メソッドを使う

前回のランダムの方法とは別に、今度はsetSeed()メソッドを使った方法を作ってみる。

Javaの説明では、setSeed の一般規約では、シードとして引数 seed を使って作成されたばかりの状態と同じになるように、この乱数ジェネレータオブジェクトの状態を変更します。

と、ある。
与える種(この場合、nextInt()メソッドにある引数)の範囲を出現するたびに初期化するメソッド。

このsetSeed()メソッドの引数にSystem.currentTimeMillis()を入れて、時間的に初期化を行う
用に設定した。

設定方法は簡単。
敵クラスのコンストラクタ内で、Randomクラスのインスタンスを記述した真下に記述。
こんな感じ
rand=new Random();
rand.setSeed(System.currentTimeMillis());

これだけ。


その他、シューティングゲーム関連