In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

[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;
		}
	}
}