敵を発生させる部分を作っていきます。
ゲームでは敵が発生するタイミングは乱数によって決めることが多いです。
時間で管理するパターンや、特定の行動を行った時に発生させるパターンもあります。
今回は乱数により決める方法で行います。
プログラムを次のように変更しましょう。
const LINE_MAX = 6; // 宝と敵の段数 var enemyArr:Array = []; var turn:Vector.<int> = new Vector.<int>(LINE_MAX,true); var state:Vector.<int> = new Vector.<int>(LINE_MAX,true); var beamFlg:int = 0; var xSpeed:Number = 0; initFunc(); //---------------------------------------------------- // システム関連の初期化 function initFunc() { trace("initFunc ---"); for( var i=0; i < LINE_MAX; i++ ){ enemyArr[i] = new enemy(); // 敵の作成 disp.addChild(enemyArr[i]); // ステージに表示 } initGame(); // 毎フレームイベントの登録 stage.addEventListener(Event.ENTER_FRAME, mainloop); // マウスイベント 左ボタン押下のイベント登録 stage.addEventListener(MouseEvent.MOUSE_DOWN, m_down); } //---------------------------------------------------- // 毎フレーム処理 function mainloop(event:Event):void { // マウスの座標を取得して自機を動かす player_mc.x += (player_mc.mouseX / 5); if( beamFlg == 0 ){ // 0:未発射 1:発射中 // 未発射なら自機と動きを同期させる beam_mc.x = player_mc.x; } else { // 発射中のとき弾を移動する beam_mc.y -= 10; if( beam_mc.y < -30 ){ // 画面外へ弾が出たとき beamFlg = 0; beam_mc.x = player_mc.x; beam_mc.y = player_mc.y - 25; } } moveEnemy(); // 敵の移動 } //---------------------------------------------------- // 敵の移動 function moveEnemy() { for( var i=0; i < LINE_MAX; i++ ){ // 出現中のみ以下の処理を行う if( !(state[i] == 1) ) continue; // 敵の移動処理 if( turn[i] == 0 ){ enemyArr[i].x -= xSpeed; // 左際まできたら右移動へ変更 if( enemyArr[i].x < 20 ){ turn[i] = 1; } } else { enemyArr[i].x += xSpeed; // 画面外へ出たら待機中にする if( enemyArr[i].x > 530 ){ state[i] = 0; // 0:待機中 } } } if( Math.random() < 0.015 ){ // 敵の出現率 // 出現位置 var rnd:int = Math.floor(Math.random()*LINE_MAX); for( i=0; i < LINE_MAX; i++ ){ var lno = (rnd + i) % LINE_MAX; if( !(state[lno] == 0) ) continue; state[lno] = 1; // 1:出現中 turn[lno] = 0; // 0:左移動 enemyArr[lno].x = 530; break; } } } //---------------------------------------------------- // ゲーム関連の初期化 function initGame() { trace("initGame ---"); beamFlg = 0; // 0:未発射 1:発射中 xSpeed = 2.0; // 敵の初期移動速度 player_mc.y = 360; // 自機のy座標(固定) beam_mc.x = player_mc.x; beam_mc.y = player_mc.y - 25; // 弾の表示(半分 自機と重ねる) for( var i=0; i < LINE_MAX; i++ ){ // 敵の初期設定 enemyArr[i].x = 530; enemyArr[i].y = (i*42) + 60; turn[i] = 0; // 0:左移動 1:右移動 2:右(宝付き) state[i] = 0; // 0:待機中 1:出現中 2:爆発中 } } //---------------------------------------------------- // マウス左ボタン押されたとき function m_down(event:MouseEvent):void { if( beamFlg == 1 ) return; // 0:未発射 1:発射中 beamFlg = 1; // 自機の位置に弾を表示する beam_mc.x = player_mc.x; beam_mc.y = player_mc.y - 25; }
ムービープレビューしてみましょう。
前回、縦一列に動いていたUFOがバラバラに動いてますね。
乱数によって出現タイミングを決めているのでこの様になります。
変更点の説明です。
5行目、敵の状態を管理するための配列変数です。
値が0なら待機中、1なら出現中、2なら爆発中という感じに使います。
62行目、変数 state が1の時のみ、移動処理が行われるようになります。
75、76行目、敵が画面外へ出たら変数 state を0にして待機中にします。
75行目、敵のx座標が 530 以上かどうか判断しています。
敵のサイズは 60 で、座標は絵の中心点をもとに計算されるので
ステージサイズより 30 ほど移動すれば、画面から見えなくなります。
81行目、ランダム関数の値と比較することで出現率を制御しています。
試しに 0.015 を 0.005 としてみて下さい。
出現する間隔が長くなります。
83行目、変数 rnd の中には0から5の数値がランダムに入ります。
今回、LINE_MAXの値は6です。
Math.random() が発生する値は0~0.9999...です。
もし乱数が 0.9 だった場合、0.9×6=5.4 という計算が行われて
Math.floor() で整数値のみ使用されるので5という値になります。
86行目、lno = (rnd + i) % LINE_MAX の % は割った余りを算出します。
rnd の値が3だった場合、for 文による lno は次のように変化します。
(3 + 0) % 6 = 3
(3 + 1) % 6 = 4
(3 + 2) % 6 = 5
(3 + 3) % 6 = 0
(3 + 4) % 6 = 1
(3 + 5) % 6 = 2
87行目、変数 state が0(待機中)以外のとき continue しています。
つまり待機中でなければ for 文の次のカウントへ進めています。
85-93行目、ここで行われている処理は、待機中の敵を探し出し
見つかれば出現中に変更しています。
113行目、敵の出現位置を画面の外に設定しました。
116行目、変数 state を0の待機中にしてます。
今までの説明で理解できましたか?
私自身、今回の説明は上手くできていないと感じています。
なのでもう少し説明したいと思います。
今回、2つの乱数を使っています。
1つ目は、敵を出現させるかどうか
2つ目は、敵をどの位置に出現させるか
この2つです。
1つ目は 81行目になります。
Math.random() を実行すると0~0.9999...の間の数値がランダムに発生します。
この値が 0.015 以下なら出現の処理をしている訳です。
2つ目は 83行目になります。
ここでは変数 rnd に0から5までの数値をランダムに入れてます。
85-87行目の for 文で行っていることは、待機中の敵を探しています。
例えば乱数で3という数字が出たとします。
3番目を調べ、出現中なら4番目を調べます。
4番目も出現中なら5番目を調べます。
というように3、4、5、0、1、2という順番で調べていきます。
その中で待機中の敵がいれば、89行目以降を実行して
出現させる為の設定を行っています。
92行目に break 文があるのは、敵を1つ出現させたら処理をストップし
2つ目の敵を出現させないためです。
次[ 敵の爆発アニメを作る ]へ進む