[INFINITY TANK BATTLE] ロックマン
ロックマン
* AI未改造。強いの作りたーい。
* 誰かロックバスターの発射時mml作ってー。
*
* BGMはこちらからお借りしました
* http://checksix.s19.xrea.com/?p=134
*
* ドット絵はこちらからお借りしました
* http://www12.atwiki.jp/rockman7/pages/8.html
*
* @author alumican.net<Yukiya Okuda>
*
*********************************************************************************
* このコードを新着タンク一覧http://flash-games.wonderfl.net/tank/list/new
* に表示させるにはinfinite-tank-entry
* というタグをつけてください
/**
* Copyright alumican_net ( http://wonderfl.net/user/alumican_net )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/mThr
*/
//forked from 9re's Wonderfl Tank Game Tank Sample 1
/**
* ロックマン
* AI未改造。強いの作りたーい。
* 誰かロックバスターの発射時mml作ってー。
*
* BGMはこちらからお借りしました
* http://checksix.s19.xrea.com/?p=134
*
* ドット絵はこちらからお借りしました
* http://www12.atwiki.jp/rockman7/pages/8.html
*
* @author alumican.net<Yukiya Okuda>
*
*********************************************************************************
* このコードを新着タンク一覧http://flash-games.wonderfl.net/tank/list/new
* に表示させるにはinfinite-tank-entry
* というタグをつけてください
*/
package
{
import flash.display.Bitmap;
import flash.display.Graphics;
import flash.display.Loader;
import flash.display.Sprite;
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.TimerEvent;
import flash.geom.ColorTransform;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.system.Security;
import flash.text.TextField;
import flash.utils.setTimeout;
import flash.utils.Timer;
import net.wonderfl.game.infinity_tank.development.*;
import net.wonderfl.math.*;
import net.wonderfl.utils.SequentialLoader;
import org.libspark.betweenas3.BetweenAS3;
import org.libspark.betweenas3.tweens.*;
import org.libspark.betweenas3.easing.*;
import org.si.sion.*;
/**
* クラス名は必ずTankにして、TankBaseクラスを拡張して下さい
* http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/tank/TankBase.html
* @author 9re
*/
public class Tank extends TankBase
{
//----------------------------------------
//CLASS CONSTANTS
private const PI:Number = Math.PI;
private const PI2:Number = PI * 2;
private const TO_RADIAN:Number = PI / 180;
private const TO_DEGREE:Number = 180 / PI;
private const MAX_LIFE:uint = 5;
private const COMMANDS:Array =
[
Command.FIRE,
Command.GUN_TURN_LEFT,
Command.GUN_TURN_RIGHT,
Command.TANK_MOVE_BACKWARD,
Command.TANK_MOVE_FORWARD,
Command.TANK_TURN_LEFT,
Command.TANK_TURN_RIGHT
];
private const STATUS_LOADING:uint = 0;
private const STATUS_OPENING:uint = 1;
private const STATUS_MOVE:uint = 2;
private const STATUS_SHOT:uint = 3;
private const STATUS_HIT:uint = 4;
private const STATUS_DEAD:uint = 5;
//----------------------------------------
//VARIABLES
private var _status:uint;
//----------------------------------------
//STAGE INSTANCES
//----------------------------------------
//CONSTRUCTOR
public function Tank():void
{
//Wonderfl.capture_delay(3);
Wonderfl.disable_capture();
// 弾のクラスのurlをセットしてください
// 弾のドキュメントクラスはBulletRendererBaseクラスを拡張したBulletRendererクラスである必要があります
_bulletRenderer = "http://swf.wonderfl.net/swf/usercode/8/88/88da/88daa9c831db6aa1c29b3ba91a9b8a9d9105f5bd.swf";
_status = STATUS_LOADING;
_initView();
_initSound();
_initAction();
}
//----------------------------------------
//VIEW
private var _spTank:Sprite;
private var _spBattery:Sprite;
private var _gunBmp:Bitmap;
private var _clearTransform:ColorTransform;
private var _tankMatrix:Matrix;
private var _loaders:Array;
private var _openingBmds:Array;
private var _openingBmp:Bitmap;
private var _openingAnimationStep:int;
private var _openingAnimationTotal:int;
private var _moveBmds:Array;
private var _moveBmp:Bitmap;
private var _moveAnimationStep:int;
private var _moveAnimationTotal:int;
private var _moveTimer:Timer;
private var _shotBmds:Array;
private var _shotBmp:Bitmap;
private var _hitBmds:Array;
private var _hitBmp:Bitmap;
private function _initView():void
{
_loaders = new Array();
SequentialLoader.loadImages(
[
"http://lab.alumican.net/wonderfl/tank/rockman_tank.png",
"http://lab.alumican.net/wonderfl/tank/rockman_gun.png"
]
, _loaders, _imageLoadComplete);
_spTank = new Sprite();
_spBattery = new Sprite();
_clearTransform = new ColorTransform(1, 1, 1, 0);
_tankMatrix = new Matrix();
}
private function _imageLoadComplete():void
{
//画像の取り出し
var src:Array = _loaders.map(
function ($ldr:Loader, $index:int, $arr:Array):BitmapData
{
var bmd:BitmapData = new BitmapData($ldr.width, $ldr.height, true, 0x0);
bmd.draw($ldr);
return bmd;
}
);
var tankBmds:Array = new Array();
var width:uint = 60;
var height:uint = 60;
var n:uint = src[0].width / width;
for (var i:uint = 0; i < n; ++i)
{
var bmd:BitmapData = new BitmapData(width, height, true, 0x0);
bmd.draw(src[0], new Matrix(1, 0, 0, 1, -i * width, 0));
tankBmds.push(bmd);
}
_openingBmds = [ tankBmds[0], tankBmds[1], tankBmds[2], tankBmds[3] ];
_moveBmds = [ tankBmds[4], tankBmds[5], tankBmds[6], tankBmds[5] ];
_shotBmds = [ tankBmds[7] ];
_hitBmds = [ tankBmds[8] ];
//オープニング
_openingAnimationStep = 0;
_openingAnimationTotal = _openingBmds.length;
_openingBmp = new Bitmap(_openingBmds[_openingAnimationStep]);
_openingBmp.visible = false;
_spTank.addChild(_openingBmp);
//歩行アニメーション
_moveAnimationStep = 0;
_moveAnimationTotal = _moveBmds.length;
_moveBmp = new Bitmap(_moveBmds[_moveAnimationStep]);
_moveBmp.visible = false;
_spTank.addChild(_moveBmp);
//ロックバスター
_shotBmp = new Bitmap(_shotBmds[0]);
_shotBmp.visible = false;
_spTank.addChild(_shotBmp);
//ダメージ
_hitBmp = new Bitmap(_hitBmds[0]);
_hitBmp.visible = false;
_spTank.addChild(_hitBmp);
//照準
_gunBmp = new Bitmap(src[1]);
_gunBmp.x = 20;
_gunBmp.y = -3;
_spBattery.addChild(_gunBmp);
//照準の基準点を本体の中央に合わせる
_spBattery.x = 30;
_spBattery.y = 30;
_spTank.addChild(_spBattery);
//オープニングアニメーションの開始
var timer:Timer = new Timer(500, 1);
timer.addEventListener(TimerEvent.TIMER, _startOpeningAnimation);
timer.start();
}
/**
* オープニングアニメーションの開始
*/
private function _startOpeningAnimation(e:TimerEvent):void
{
e.target.removeEventListener(e.type, arguments.callee);
_status = STATUS_OPENING;
_openingBmp.visible = true;
_openingBmp.y = -500;
var t:ITween = BetweenAS3.tween(_openingBmp, { y:0 }, null, 0.5, Linear.easeNone);
t.onComplete = function():void
{
_spTank.addEventListener(Event.ENTER_FRAME, _openingEnterFrameHandler);
};
t.play();
}
/**
* オープニングアニメーションの更新
*/
private function _openingEnterFrameHandler(e:Event):void
{
if (++_openingAnimationStep >= _openingAnimationTotal)
{
_spTank.removeEventListener(Event.ENTER_FRAME, _openingEnterFrameHandler);
return;
}
_openingBmp.bitmapData = _openingBmds[_openingAnimationStep];
}
/**
* 歩行アニメーションの開始
*/
private function _startMoveAnimation():void
{
_status = STATUS_MOVE;
_openingBmp.visible = false;
_moveBmp.visible = true;
_moveTimer = new Timer(150, 0);
_moveTimer.addEventListener(TimerEvent.TIMER, _moveTimerHandler);
_moveTimer.start();
}
/**
* 歩行アニメーションの更新
*/
private function _moveTimerHandler(e:TimerEvent):void
{
if (++_moveAnimationStep >= _moveAnimationTotal) _moveAnimationStep = 0;
_moveBmp.bitmapData = _moveBmds[_moveAnimationStep];
}
/**
* 通常時の描画
*/
override public function draw(bitmapData:BitmapData):void
{
//照準角度(本体から見た相対角度)の更新
_spBattery.rotation = _scene.myGunAngle * TO_DEGREE;
//前回の描画をクリア
bitmapData.colorTransform(bitmapData.rect, _clearTransform);
//tankの描画位置を合わせる
_tankMatrix.identity();
_tankMatrix.translate(-30, -30);
_tankMatrix.rotate(_scene.myTankAngle);
_tankMatrix.translate(_scene.myTankPosition.x, _scene.myTankPosition.y);
//再描画
bitmapData.draw(_spTank, _tankMatrix, null, null, null, true);
}
/**
* 発射エフェクト
*/
override public function fire():void
{
if (_status != STATUS_MOVE) return;
_status = STATUS_SHOT;
_moveBmp.visible = false;
_shotBmp.visible = true;
var step:uint = 0;
var timer:Timer = new Timer(100, 1);
timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(e:TimerEvent):void
{
e.target.removeEventListener(e.type, arguments.callee);
_moveBmp.visible = true;
_shotBmp.visible = false;
});
timer.start();
}
/**
* 被弾エフェクト
*/
override public function hit():void
{
//オーバーキル防止
if (_life == 0) return;
(--_life == 0) ? _deadEffect() : _hitEffect();
}
private function _hitEffect():void
{
_status = STATUS_HIT;
_moveBmp.visible = false;
_hitBmp.visible = true;
_hitBmp.x = 0;
var step:uint = 0;
var t:ITween = BetweenAS3.tween(_hitBmp, { x:-10 }, null, 0.5, Linear.easeNone);
t.onComplete = function():void
{
_hitBmp.x = 0;
_moveBmp.visible = true;
_hitBmp.visible = false;
};
t.onUpdate = function():void
{
++step;
_hitBmp.visible = (step % 2 == 0);
};
t.play();
}
private function _deadEffect():void
{
_status = STATUS_DEAD;
_openingBmp.visible = false;
_moveBmp.visible = false;
_hitBmp.visible = false;
_spBattery.visible = false;
var n:uint = 8;
var balls:Array = new Array(n);
var tweens:Array = new Array(n);
var container:Sprite = _spTank.addChild( new Sprite() ) as Sprite;
container.x = 30;
container.y = 30;
var ball:Sprite;
var g:Graphics;
var angle:Number;
for (var i:uint = 0; i < n; ++i)
{
balls[i] = ball = container.addChild( new Sprite() ) as Sprite;
g = ball.graphics;
g.lineStyle(2, 0xffffff);
g.drawCircle(0, 0, 5);
angle = PI2 * i / n;
ball.x = 10 * Math.cos(angle);
ball.y = 10 * Math.sin(angle);
tweens[i] = BetweenAS3.tween(ball, {
x : 20 * Math.cos(angle),
y : 20 * Math.sin(angle),
scaleX : 0.5,
scaleY : 0.5,
alpha : 0
}, null, 1.0, Linear.easeNone);
}
var t:ITween = BetweenAS3.parallelTweens(tweens);
t.onComplete = function():void
{
_spTank.removeChild(container);
}
t.play();
_startDeadSE();
}
//----------------------------------------
//SOUND
private var _sionDriver:SiONDriver;
private var _bgmMML:String;
private var _deadMML:String;
private function _initSound():void
{
_bgmMML = "#TITLE{Dr.Wily Stage1 - Rockman2};t180;/*{偽TCP専用}*/#WAV0{(127,-128),32};/*{#WAV 1,<127,127,-127,(127,127),4,(-127,-127),4,(127,127),5,(-127,-127),16>;}*/#WAV5{(-127,-127),9,0,(127,127),9,0,(-127,-127),4,-64,0,64,(127,127),4,0};#A=r;#B=r;#C=r;#D=r;#E=r;#F=r;#G=r;#H=r;#I=r;#J=r;#K=r;#L=r;#M=r;#N=r;#O=r;#P=r;#Q=r;#R=r;#S=r;#T=r;#U=r;#V=r;#W=r;#X=r;#Y=r;#Z=r;#Y=@2;#Z=@4;#A=Y q7r8[l16eee8eee8c+8r8c+c+ e8eee8c+8l8rg+f+g+ l16r8eee8eel8ec+rg+ rf+rerf+r4 l16r8[f+f+f+8]l8d+rg+ rf+rerd+r Z c+4c+g+ba+4. c+4c+g+ba+4|<d+e4>Y];#B=Z b<c+2..>b<e4c+4>b4<c+4. > b2b<c+4. > g+ag+ereg+b < c+2.>b< e4c+4>b4<c+4 >b^2bg+b<c rccd+g+2;#C=>>Y g+2.f+ b4a4g+4a4 g+2..f+ b4a4g+4a4 e^2ef+g+d+1 < Z c+4c+g+ba+4. c+4c+g+ba+4 Y b;#D=<c+^2c+4>b<c+ re4.g+f+ed+ c+2c+4>b<c+ re4.ef+e4 d+2d+c+>b< g+4.f+4e4d+4 d+ed+c+1 r4. >;#E=Z b<c+2..>b<e4c+4>b4<c+4. > b2b<c+4. > g+ag+ereg+b < c+2.>b< e4c+4>b4<c+4 >b^2bg+b<c rccd+g+4.;#F=>Y e reed+e4<c+> b4a4g+4f+4f+ rg+g+rg+rrf+ rg+g+rg+rf+e reed+e4<c+> b4a4g+4f+4r d+ed+c+^2^1;#X=$o5ABCDEF;v10%1l8X;#A=%5@3 [[5r1]r2..c+4c+g+ba+4. c+4c+g+ba+4|<d+e>]b<c+2..>b<e4c+4>b4<c+4. > b2b<c+4. > g+ag+ereg+b < c+2.>b< e4c+4>b4<c+4 >b^2bg+b<c rccd+g+2;#B=>[5r1]r2..c+4c+g+ba+4. c+4c+g+ba+4b<c+^2>r2 [6r1]r2. b<c+2..>b<e4c+4>b4<c+4. > b2b<c+4. > g+ag+ereg+b < c+2.>b< e4c+4>b4<c+4 >b^2bg+b<c rccd+g+4.r[8r1];v6l8r16$AB;v4l8r8$AB;#A=%1@2q7l16r8c+c+c+8c+c+c+8>g+8r8g+g+ < c+8c+c+c+8>g+8<l8red+e l16r8c+c+c+8c+c+l8c+>g+r<e rd+rc+rd+r4;#B=l16r8[d+d+d+8]l8>b<re rd+rc+r>br4< r1r2.b<c+>;#C=l16r8[d+d+d+8]l8>b<re rd+rc+r>br4< r1r2..b ;#D=[8r1][l16r8eee8eee8c+8r8c+c+ e8eee8c+8l8rg+f+g+ l16r8eee8eel8ec+rg+ rf+rerf+r4 l16r8[f+f+f+8]l8d+rg+ rf+rerd+r |r r1r1]c+4c+g+ba+4. c+4c+g+ba+4br;#E=[7r1]r2..c+ rc+c+>b<c+4a g+4f+4e4d+4d+ reerer4d+ reererd+c+ rc+c+>b<c+4a g+4f+4e4d+4r >b<c+>bg+^2^1;#X=$o5ABACDE;v8l8X;#A=%5@3s63q7;#B=l16[[8c+8c+c+]>[8a8aa][8b8bb]<[7c+8c+c+]>b8<c+c+];#C=l16 [[3d8|dd]aaf+8<c+c+ > r8dda8f+f+<c+8>f+f+a8dd |[3c+8|c+c+]g+g+e8bb r8c+c+g+8eeb8eeg+8c+c+]> [b8bb]l8bbb< c4cccc4;#D=r4;#E=l16>r8 [a4[3aaa8]b4|[3bbb8]l8 [c+4<c+>d+<d+>e<e>d+l16]][bbb8]bbb4 l8 b<c+>bg+4.b<c+> rb<c+4>b<cc+4;#X=v7$o5ABCDBCE;k-4l8X;l8r32k-8X;#A=r4cr;%2 v10q0s27$o3l8A;#S=v10%2@4s27o5))))g64)))g64))g64)g64;$l16SrSSrrSS;#H=b;#M=g;#L=c;#A=[54r1]l16r4HHHHMMMMLLLLr1;#X=$o4kt4A;#FM{b8(a)+c4(a)+d1(a)};@ml16v15l8%3 q0k0X;v10l8%3 q0s42k0X;v10l8%3 q0s29,-45k-40X;v10l8%3 q0s29,-60k0X;/*[tab]*/";
_deadMML = "t210l64x63o6c#<a#f#d#c<af#d#c<agec#&c#x59o6c#<a#f#d#c<af#d#c<agec#&c#x51o6c#<a#f#d#c<af#d#c<agec#&c#x42o6c#<a#f#d#c<af#d#c<agec#&c#x34o6c#<a#f#d#c<af#d#c<agec#&c#x25o6c#<a#f#d#c<af#d#c<agec#&c#x17o6c#<a#f#d#c<af#d#c<agec#&c#x8o6c#<a#f#d#c<af#d#c<agec#&c#;";
}
private function _startBGM():void
{
if (_sionDriver != null) _sionDriver.stop();
_sionDriver = new SiONDriver();
_sionDriver.play( _sionDriver.compile(_bgmMML) );
}
private function _startDeadSE():void
{
_sionDriver.stop();
_sionDriver.play( _sionDriver.compile(_deadMML) );
}
//----------------------------------------
//ACTION
private var _commandCount:uint;
private var _life:int;
private var _gunFlag:Boolean = true;
private var _lastBulletCount:int = 0;
private function _initAction():void
{
_commandCount = 0;
_life = MAX_LIFE;
}
// 5フレームに1度呼ばれるcallback
// 現在のゲームの状態を見るには、_sceneオブジェクトのプロパティーを
// 調べます.
// @see http://flash-games.wonderfl.net/static/asdoc/net/wonderfl/game/infinity_tank/development/BattleScene.html
override public function action():int
{
if (_commandCount == 0)
{
//BGMの開始
_startBGM();
//歩行アニメーションの開始
_startMoveAnimation();
}
//**********************************************************************
//AI
// 前回のactionで弾が撃たれたかどうかを調べる.
// 人対AIのゲーム・バランスのために弾は同画面内に最大3発までしか
// 撃てない.
if (_lastBulletCount < _scene.myBulletCount) {
// 前回た弾を撃っている場合は、撃たないようにフラグをセット
_gunFlag = false;
// 400ms後にフラグを解除
setTimeout(clearGunFlag, 400);
}
// 現在の画面内にある弾の数を保存する.
_lastBulletCount = _scene.myBulletCount;
// フラグによって、撃つか撃たないかを判断
var action:int = (_gunFlag) ? Command.FIRE : Command.DO_NOTHING;
// 敵の位置を取得.
var enemyPos:WVector2D = _scene.enemyTankPosition;
// 自分の位置を敵の位置から引く.
// 自分から見た敵の位置を計算
enemyPos.subtract(_scene.myTankPosition);
// 敵との距離
var enemyDistance:Number = enemyPos.length;
// 敵の速度を取得
var enemySpeed:WVector2D = _scene.enemyTankLinearVelocity;
// 0.5秒の位置を線形で予想
enemySpeed.scale(0.5);
enemyPos.add(enemySpeed);
// 自分からみた敵の方向を計算する.
var angle:Number = Math.atan2(enemyPos.y, enemyPos.x);
// 敵の方向をコピー
var direction:Number = angle;
// 敵の方向と自分の砲台の向いている方向の差を計算
angle -= (_scene.myTankAngle + _scene.myGunAngle);
// 敵の方向と自分のタンクの向いている方向の差を計算
direction -= _scene.myTankAngle;
// 角度を0~2πに丸める
angle = WMath.modulo2PI(angle);
direction = WMath.modulo2PI(direction);
// 角度が0~πの場合は敵は砲台より右側にいる.
if (angle <= Math.PI) action |= Command.GUN_TURN_RIGHT;
// 角度がπより大きい場合は敵は砲台の左側にいる.
else action |= Command.GUN_TURN_LEFT;
// 角度が0~πの場合は敵は自分の向いている方向の右側にいる.
if (direction <= Math.PI) action |= Command.TANK_TURN_RIGHT;
// 角度がπより大きい場合は敵は自分の向いている方向の左側にいる.
else action |= Command.TANK_TURN_LEFT;
// 許容する角度を-π/4~π/4にセットし、
var allow:Number = Math.PI / 4;
// 敵との距離が200ピクセルより離れていて、かつ、
// 敵が許容角度の範囲内に居るなら敵に向かって前進
if ((enemyDistance > 200) && ((direction < allow) || (direction > WMath.DOUBLE_PI - allow)))
action |= Command.TANK_MOVE_FORWARD;
else // そうでないときは、ランダムな確立で後退
action |= (Math.random() < 0.3) ? Command.TANK_MOVE_BACKWARD : Command.DO_NOTHING;
//**********************************************************************
++_commandCount;
return action;
}
private function clearGunFlag():void
{
_gunFlag = true;
}
}
}