タンクを作ってみる(AI目篇)
こんにちはtaroです.
wonderfl flash-gamesの公式コンテンツINFINITY TANK BATTLEはwonderflユーザがゲーム内のキャラクターをActionScriptでカスタマイズできるゲーム・コンテンツです.タンク・ゲームの連載最後に、タンクの作り方AI篇をお送りいたします.
見た目篇同様net.wonderfl.game.infinity_tank.development.TankBaseというクラスを拡張してTankという名前のクラスを作ります。AIを書くにはactionという抽象メソッドを実装します.
まずは、サンプル・コードをご覧になると良いでしょう.
ゲーム内の情報を取得する
基本的には_sceneとうプロパティーを見ることで情報を取得します.
_scene.enemyBulletList | 敵が撃った弾のリスト |
_scne.enemyTankPosition | 敵の位置 |
_scene.myTankPosition | 自分の位置 |
詳細なプロパティーリストについては、リファレンスをご覧下さい.
例えば表にあるリストから、自分からみた敵の位置を計算することが出来ます.計算の詳細については、コチラでもご紹介しています.
// 敵の位置を取得. var enemyPos:WVector2D = _scene.enemyTankPosition; // 自分の位置を敵の位置から引く. // 自分から見た敵の位置を計算 enemyPos.subtract(_scene.myTankPosition); // 敵との距離 var enemyDistance:Number = enemyPos.length; // 自分からみた敵の方向を計算する. var angle:Number = Math.atan2(enemyPos.y, enemyPos.x); // 敵の方向と自分の砲台の向いている方向の差を計算 angle -= (_scene.myTankAngle + _scene.myGunAngle); // 角度を0~2πに丸める angle = WMath.modulo2PI(angle);
角度の丸め込みには、WMath.modulo2PIというメソッドを用意しました.弾のリストは下のようなiteratorの構造となっています.
// enemyBulletListが自分の弾のリスト。このようにfor文で回す for (var enemyBulletList = _scene.myBulletList; i; i = i.next) { // i.position.x 弾のx座標 // i.position.y 弾のx座標 }
AIの行動を決定する
例えば次のようにしてCommandクラスを使ってタンクの次の行動を決定します.AIの行動は1秒間に6回実行されますが、フレーム数は変動しうるので、正確な時間を知るには、実測する必要があります.
var command:Command = new Command(); command.addCommand(Comand.FIRE); command.addCommand(Command.TANK_TURN_LEFT); command.addCommand(Command.TANK_MOVE_FORWARD);
このようにしてコマンドを決定してactionメソッドで最後にcommand.actionをreturnすると、これがタンクの次のターンの行動となります.
制限
大きな制限として、同画面内には弾は3発までしか撃てないというのがあります.これはAI対人間のときのバランス用に設けました.
if (_lastBulletCount < _scene.myBulletCount) { // 前回た弾を撃っている場合は、撃たないようにフラグをセット _gunFlag = false; // 400ms後にフラグを解除 setTimeout(clearGunFlag, 400); } // 現在の画面内にある弾の数を保存する. _lastBulletCount = _scene.myBulletCount; // フラグによって、撃つか撃たないかを判断 if (_gunFlag) command.addCommand(Command.FIRE); function clearGunFlag():void { _gunFlag = true; }
弾切れとなってしまわないようにサンプルのタンクでは弾を連続で撃たないように設定しています.
このような方法を用いなくても、TankBaseにはfire()というメソッドがあるのでここを使って弾が撃たれたかどうかの判定をすることも出来ます.
被弾した時に、hit()というメソッドが実行されますので、ダメージ時のアニメーション等をカスタマイズすることも出来ます.
作ったタンクをエントリーさせるには
infinite-tank-entryというタグをつけます.コチラもご覧下さい.
簡単ではありましたが、一通りご説明いたしました.
サンプル・コードの単純な実装を打ち負かしてしまうような実装、人間相手でもかなり手ごわいAIの実装、お待ちしております!!