neurona

by flik forked from Wonderfl Tank Game Tank Sample 1 (diff: 271)
♥0 | Line 167 | Modified 2009-12-16 21:07:17 | MIT License | (replaced)
play

ActionScript3 source code

/**
 * Copyright flik ( http://wonderfl.net/user/flik )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/aJw6
 */

package 
{
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.BitmapData;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix;
	import flash.utils.setTimeout;
	import flash.utils.Timer;
	
	import net.wonderfl.game.infinity_tank.development.*;
	import net.wonderfl.math.*;
	import net.wonderfl.utils.SequentialLoader;
	
	public class Tank extends TankBase
	{
		private var _gunFlag:Boolean = true;
		private var _lastBulletCount:int = 0;
		private var _spTank:Sprite;
		private var _spBattery:Sprite;
		private var _ctfm:ColorTransform;
		private var _images:Vector.<Bitmap>;
		private var _gun:Bitmap;
		private var _arr:Array = [];
		private var _i:int = -1;
		private var _j:int = 0;
		private var _mat:Matrix = new Matrix(1, 0, 0, 1, 5, 15);
		private var weight:Number = 0.3;
		private var bias:Number = 0.25;
		
		public function Tank() 
		{           
			_bulletRenderer = "http://swf.wonderfl.net/swf/usercode/0/04/046c/046cee45b4334c4f2dac8dfa7ec9ea2b2b2eb27d.swf";
			
			_spTank = new Sprite;
			_spBattery = new Sprite;
			
			SequentialLoader.loadImages(["http://assets.wonderfl.net/images/tank/tankA_1.png", "http://assets.wonderfl.net/images/tank/tankA_2.png", "http://assets.wonderfl.net/images/tank/tankA_cannon.png"], _arr, onImageLoaded);
			
			_ctfm = new ColorTransform(1, 1, 1, 0);			
			
			super();
		}
		
		private function onImageLoaded():void
		{
			_images = Vector.<Bitmap>(_arr.map(function ($ldr:Loader, $index:int, $arr:Array):Bitmap {
				var mat:Matrix = new Matrix;
				var bd:BitmapData = new BitmapData($ldr.width, $ldr.height, true, 0x00ffffff);
				bd.draw($ldr, mat);
				var bm:Bitmap = new Bitmap(bd);
				bm.x = -bm.width / 2;
				bm.y = -bm.height / 2;
				
				return bm;
			}));
			
			_gun = _images.pop();
			_gun.x = -5;
			
			_gun.y = -5;
			_spBattery.addChild(_gun);
			_i = 0;
			_images.forEach(function ($bm:Bitmap, $index:int, $vec:Vector.<Bitmap>):void {
				_spTank.addChild($bm);
			});
			_spTank.addChild(_spBattery);
		}
		
		
		override public function action():int
		{
			if (_lastBulletCount < _scene.myBulletCount) {
				_gunFlag = false;
				setTimeout(clearGunFlag, 100);
			}
			_lastBulletCount = _scene.myBulletCount;            
			
            var pos:WVector2D = new WVector2D(_scene.myTankPosition.x,_scene.myTankPosition.y);
			var enemyPos:WVector2D = _scene.enemyTankPosition;
			
			//Enemy relative position vetor
            enemyPos.subtract(_scene.myTankPosition);
			
			//enemy relative distance
			var enemyDistance:Number = enemyPos.length;
			
			//enemy velocity vector
			var enemySpeed:WVector2D = _scene.enemyTankLinearVelocity;
			
			//neuron estimates future position according to enemy current velocity and position
			enemySpeed.scale(bias + enemyDistance/100*weight);
			enemyPos.add(enemySpeed);
						
			var enemyDistance2:Number = enemyPos.length;
			
			var enemyPos2:WVector2D = _scene.enemyTankPosition;
			enemyPos2.subtract(_scene.myTankPosition);
			enemyPos2.add(enemySpeed);
			
			var action:int;
			if (_gunFlag) {
				action = Command.FIRE;
				//supply timeout with parameters: old enemyPos & expected enemyPos
				//estimated time to collision is "enemyDistance2 * 6"
				setTimeout(backPropagate , enemyDistance2 * 6, _scene.enemyTankPosition, enemyPos2);
			}
			else {
				action = Command.DO_NOTHING;
			}
			
			//turn gun according to expected position
			var angle:Number = Math.atan2(enemyPos.y, enemyPos.x);
			var direction:Number = angle;
			
			angle -= (_scene.myTankAngle + _scene.myGunAngle);
			direction -= _scene.myTankAngle;
			
			angle = WMath.modulo2PI(angle);
			direction = WMath.modulo2PI(direction);
			
    		if (angle <= Math.PI) action |= Command.GUN_TURN_RIGHT;
			else action |= Command.GUN_TURN_LEFT;

			var centerVec:WVector2D=new WVector2D(600/2,550/2);
            centerVec.subtract(pos);
			
			if(centerVec.length>240)
            {
                if(Math.random()<0.15)
               {
                   action |= Command.TANK_MOVE_BACKWARD;
                   }
    		    else
    		    {
    		        action |= Command.TANK_MOVE_FORWARD;
    		    }
		        action |= Command.TANK_TURN_LEFT;
            }
       		else
       		{
                var dir2:Number=WMath.modulo2PI(direction+Math.PI/2-Math.PI/3*Math.random());
    			if (dir2 <= Math.PI) action |= Command.TANK_TURN_RIGHT;
    			else action |= Command.TANK_TURN_LEFT;
    			
    			if(Math.random()<0.05)
               {
    		        action |= Command.TANK_MOVE_BACKWARD;
    		    }
    		    else
    		    {
        		    action |= Command.TANK_MOVE_FORWARD;
                }
    	    }

			return action;
		}
		
		//training the tank...
		private function backPropagate():void {
			//enemy current distance from old enemy position
			var newEnemyPos:WVector2D = _scene.enemyTankPosition;
			newEnemyPos.subtract(arguments[0]);
			var actualDist:Number = newEnemyPos.length;
			
			//enemy expected distance from old enemy position
			var expectedPos:WVector2D = arguments[1];
			expectedPos.subtract(arguments[0]);
			var expectedDist:Number = expectedPos.length;
			
			//bias += bias * (actualDist - expectedDist) / actualDist;
			//weight += weight * (actualDist - expectedDist) / actualDist;
			
			if (actualDist - expectedDist < -10) {
					bias -= 0.05;
					weight -= 0.05;
			}
			else if (actualDist - expectedDist > 10) {
					bias += 0.05;
					weight += 0.05;
			}
		}
		
		//used to regulate gun shots
		private function clearGunFlag():void
		{
			_gunFlag = true;
		}
		
		//not important... updates the drawing
		override public function draw(bitmapData:BitmapData):void
		{
			_spBattery.rotation = _scene.myGunAngle * 180 / Math.PI;
			
			
			if (_i > -1) {
				_i = (_j & 1) ? 1 : 0;
				var bm:Bitmap = _images[_i];
				bm.visible = true;
				_i = 1 - _i;
				bm = _images[_i];
				bm.visible = false;
				_j++;
				_j &= 3;
			}
			
			_mat.identity();
			_mat.rotate(_scene.myTankAngle);
			_mat.translate(_scene.myTankPosition.x, _scene.myTankPosition.y);
			
			bitmapData.colorTransform(bitmapData.rect, _ctfm);
			bitmapData.draw(_spTank, _mat, null, null, null, true);
		}
		
		// called when a bullet hits this tank
		override public function hit():void {
			
		}
		
		// called when this tank fires
		override public function fire():void {
			
		}
	}
}