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

某スペルカードをズルしてみた

緑色の弾しか見ないようにして、通常より1段深く探索しています。
uwiさんが改良してくれたのを更に改良しました。
http://wonderfl.net/code/f3e75f89a0423a830d4f1a7e85f4fd0af4a8fbb3
東風谷早苗スペルカード「グレイソーマタージ」風処理
前回とは違い☆のスライド処理も入れ、より本物らしくしました。
かなり目コピなんで計算方法はムリがあるかも
表示レイヤーは考慮していないです。余計なパラメータもあるかと思いますw
クリックすると新たに作成します
/**
 * Copyright uwi ( http://wonderfl.net/user/uwi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/bbUO
 */

// forked from okoi's forked from: forked from: 某スペルカードの一部風 目コピ処理 - より本物らしく
// forked from okoi's forked from: 某スペルカードの一部風 目コピ処理 - より本物らしく
// forked from okoi's 某スペルカードの一部風 目コピ処理
//
// 緑色の弾しか見ないようにして、通常より1段深く探索しています。
//
//	uwiさんが改良してくれたのを更に改良しました。
//	http://wonderfl.net/code/f3e75f89a0423a830d4f1a7e85f4fd0af4a8fbb3
//
//	東風谷早苗スペルカード「グレイソーマタージ」風処理
//	前回とは違い☆のスライド処理も入れ、より本物らしくしました。
//	かなり目コピなんで計算方法はムリがあるかも
//
//	表示レイヤーは考慮していないです。余計なパラメータもあるかと思いますw
//	クリックすると新たに作成します
package 
{
	import flash.display.Sprite;
	import flash.display.Shape;
	import flash.display.BitmapData;
	import flash.display.Bitmap;
	import flash.display.Graphics;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import net.hires.debug.*;
	
	import flash.text.TextField;
	
	[SWF(backgroundColor = "0x000000", frameRate = "60")]

	/**
	 * 
	 * @author okoi
	 */
	public class Main extends Sprite 
	{
		private var patternList:Array = new Array();
		
		private var _bmdBulletRed : BitmapData;
		private var _bmdBulletBlue : BitmapData;
		
		private var _canvas : BitmapData;
		
		private var _d : Dodger2D;
		
		private var _bullets : Array = [];
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
//			MouseDown(null);
			
			var s : Shape = new Shape();
			var g : Graphics = s.graphics;
			g.beginFill(0xff5555);
			g.drawCircle(5, 5, 5);
			g.endFill();
			g.beginFill(0xffffff, 0.5);
			g.drawCircle(5, 5, 3);
			g.endFill();
			_bmdBulletRed = new BitmapData(10, 10, true, 0x00000000);
			_bmdBulletRed.draw(s);
			
			g.clear();
			g.beginFill(0x5555ff);
			g.drawCircle(5, 5, 5);
			g.endFill();
			g.beginFill(0xffffff, 0.5);
			g.drawCircle(5, 5, 3);
			g.endFill();
			_bmdBulletBlue = new BitmapData(10, 10, true, 0x00000000);
			_bmdBulletBlue.draw(s);
		
			_canvas = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
			addChild(new Bitmap(_canvas));
				
			addEventListener(Event.ENTER_FRAME, EnterFrame );
			stage.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);
			
			g.clear();
			g.beginFill(0xffffff);
			g.drawCircle(4, 4, 4);
			g.endFill();
			var self : BitmapData = new BitmapData(8, 8, true, 0x00000000);
			self.draw(s);
		
			_d = new Dodger2D(self, _canvas, VelocityStrokeDodgeAlgorithm2D.run);
			_d.xx = 465 / 2;
			_d.xy = 300;
//			addChild(_tf);
//			_tf.textColor = 0xffffff;

// addChild(new Stats()); 
		}
		
		private var _tf : TextField = new TextField();
		
		private function EnterFrame(event:Event):void 
		{
			var i:int = 0;
			var b : Bullet;

			for ( i = 0; i < patternList.length; i++ )
			{
				b = patternList[i].Run();
				if ( b != null )
				{
					_bullets.push(b);
				}
			}
			
			for ( i = patternList.length - 1; i >= 0; i-- )
			{
				if ( patternList[i].isEnd() )
				{
					//	待機リストから移動リストへ
//					moveBullet = moveBullet.concat(patternList[i].waitBullet);
					for each(b in patternList[i].waitBullet){
						b.t = 0;
					}
					patternList.splice( i, 1 );
				}
			}
			
			//	弾移動
			// やっぱり無理があるなぁ・・Bulletにkind属性とかつければすんなりいけそうな
			for ( i = 0; i < _bullets.length; i++ )
			{
				b = _bullets[i];
				if(b.next != null){
					if(b.t < 50){
						b.step(1 - b.t/50);
						if(b.t >= 50){
							_bullets[i] = b.next;
							_bullets[i].xx = b.xx;
							_bullets[i].xy = b.xy;
						}
					} 
				}else{
					b.step(Math.min(b.t*0.02, 1));
					if ( b.xx < -50 || b.xx > stage.stageWidth + 50 || b.xy < -50 || b.xy > stage.stageHeight + 50 )
					{ 
						if(i == _bullets.length - 1){
							_bullets.pop();
						}else{
							_bullets[i] = _bullets.pop();
							i--;
						}
					}
				}
			}
			
			// 描画
			_canvas.lock();
			_canvas.fillRect(_canvas.rect, 0x000000);
			for each(b in _bullets){
				b.draw(_canvas);
			}
			
			var val : int = _d.run(2, 
				{maxxx : 460, maxxy : 460, minxx : 5, minxy : 5, bullets : _bullets, selfr : 3, basex : 465 / 2, basey : 465 / 2},
				[[0, 0], [-3, 0], [3, 0], [0, -3], [0, 3], [2, 2], [-2, 2], [-2, -2], [2, -2]],
				50);
			_d.step();
			_d.paint();
			
			_canvas.unlock();
		}
		
		private function MouseDown(event:MouseEvent):void
		{
			//	小さい☆
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, false, 50, _bmdBulletRed, (270 + 72 * 0), 3 ) );
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, false, 50, _bmdBulletRed, (270 + 72 * 1), 3 ) );
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, false, 50, _bmdBulletRed, (270 + 72 * 2), 3 ) );
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, false, 50, _bmdBulletRed, (270 + 72 * 3), 3 ) );
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, false, 50, _bmdBulletRed, (270 + 72 * 4), 3 ) );
			//	大きい☆
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, true, 100, _bmdBulletBlue, (270 + 72 * 0) + 180, 5 ) );
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, true, 100, _bmdBulletBlue, (270 + 72 * 1) + 180, 5 ) );
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, true, 100, _bmdBulletBlue, (270 + 72 * 2) + 180, 5 ) );
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, true, 100, _bmdBulletBlue, (270 + 72 * 3) + 180, 5 ) );
			patternList.push( new Pattern(stage.mouseX, stage.mouseY, true, 100, _bmdBulletBlue, (270 + 72 * 4) + 180, 5 ) );
		}
		
	}
	
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
import flash.display.Sprite;
import flash.geom.Point;

//-----------------------------
//	弾幕パターンクラス
class Pattern {
	
	private var reverse:Boolean = false;		//	反転フラグ
	private var starSize:Number = 150;			//	☆サイズ
	private var bmd:BitmapData;
	
	private var slideAngle:Number = 0;			//	弾スライド時に使用
	private var slideSpeed:Number = 0;			//	弾スライド時に使用
	
	private var end:Boolean = false;
	private var count:int = 0;
	private var defX:int = 0;
	private var defY:int = 0;
			
	private var target:Array = new Array();
	
	private static const PATH_OBJ_NUM:int = 20;		//	1辺に出す弾の数
	private static const TARGET_NUM:int = 5;
	private static const TARGET_ANGLE:Array = [ 270 + 72 * 3, 270 + 72 * 1, 270 + 72 * 4, 270 + 72 * 2, 270 ];	//	パスの目標地点の角度
	private static const TARGET_ANGLE2:Array = [ 270 + 72 * 2, 270 + 72 * 4, 270 + 72 * 1, 270 + 72 * 3, 270 ];	//	パスの目標地点の角度

	public var waitBullet:Array = new Array();		//	保持用バッファ
	
	public function Pattern(
		_gx:int = 0, _gy:int = 0,
		_rev:Boolean = false,
		_starSize:Number = 80,
		_bmd:BitmapData = null,
		_slideAngle:Number = 0,
		_slideSpeed:Number = 0 
	) {
		count = 0;
		defX = _gx;
		defY = _gy;
		
		reverse = _rev;
		starSize = _starSize;
		bmd = _bmd;
		slideAngle = _slideAngle;
		slideSpeed = _slideSpeed;
		
		for ( var i:int = 0; i < 5; i++ )
		{
			var angle:Number = TARGET_ANGLE[i];
			if ( reverse ) angle = TARGET_ANGLE2[i] + 180;	//	反転
			else 		   angle = TARGET_ANGLE[i];

			target[i] = new Point( Math.cos( angle * Math.PI / 180 ) * starSize, Math.sin( angle * Math.PI / 180 ) * starSize );
		}
	}
	
	/**
	 * 弾発生処理
	 * @return
	 */
	public function Run() : Bullet {
		
		var targetNo:int = int(count / PATH_OBJ_NUM);
		var targetRate:int = int(count % PATH_OBJ_NUM);
		var p:Point;

		//	弾の座標を出す
		p = Point.interpolate( target[targetNo], target[(targetNo+(TARGET_NUM-1))%TARGET_NUM], targetRate / PATH_OBJ_NUM );		
 
		//    弾の移動角度を出す 
        var moveAngle : Number = (-count / PATH_OBJ_NUM / TARGET_NUM * 720 + 135) * (reverse ? -1 : 1) * Math.PI / 180;
        var bullet : Bullet = new Bullet(
        		bmd,
        		p.x + defX, p.y + defY, 
			Math.cos(slideAngle*Math.PI/180)*slideSpeed, 
			Math.sin(slideAngle*Math.PI/180)*slideSpeed
			);
		bullet.next = new Bullet(
        		bmd,
        		p.x + defX, p.y + defY, 
			Math.cos(moveAngle) * 0.8, 
			Math.sin(moveAngle) * 0.8
			);
		
		bullet.t = 999;
		waitBullet.push( bullet );
		
		count++;
		if ( count == TARGET_NUM * PATH_OBJ_NUM )	end = true;
		
		return	bullet;
	}

	public	function isEnd() : Boolean {	return	end;	}
}

import flash.display.BitmapData;

  class Bullet2D
  {
    public var xx : Number;
    public var xy : Number;
    public var vx : Number;
    public var vy : Number;
    public var r : Number;
  }
 
//-----------------------------
//	弾クラス
class Bullet extends Bullet2D {
	private var bmd:BitmapData;
	private var _t:uint = 0;
	
	public var next:Bullet = null;
	
	public function Bullet(bmd:BitmapData, xx:Number, xy:Number,vx:Number,vy:Number) {
		this.bmd = bmd;
		this.xx = xx;
		this.xy = xy;
		this.vx = vx;
		this.vy = vy;
		this.r = 5;
	}
	
	public function step(c : Number = 1.0):void
	{
		xx += vx * c;
		xy += vy * c;
		_t++;
	}
	
	public function get t() : uint { return _t;}
	public function set t(val:uint) : void { _t = val;}
	
	public function draw(canvas : BitmapData) : void
	{
		canvas.copyPixels(bmd, bmd.rect, new Point(xx - bmd.width / 2, xy - bmd.height / 2));
	}
}

  class RangeUtils
  {
    
    public static function intersection(a : Array, b : Array) : Array
    {
      if (a == null || b == null) return null;
      if (a[1] < b[0] || b[1] < a[0]) return null;
      return [Math.max(a[0], b[0]), Math.min(a[1], b[1])];
    }
  }
  
  import flash.geom.Point;
  import flash.geom.Rectangle;
  
  class Dodger2D extends Bullet2D
  {
    private var _bmd : BitmapData;
    private var _parent : BitmapData;
    private var _algorithm : Function;
    
    public function Dodger2D(bmd : BitmapData, parent : BitmapData, algorithm : Function)
    {
      _bmd = bmd;
      _parent = parent;
      _algorithm = algorithm;
    }
    
    /**
     * devlop tunnel vision
     * @param	w
     * @param	env
     * @return
     */
    private function filter(w : Number, env : Object) : Object
    {
      var d : Number;
      
      var seen : Array = [];
      for each(var b : Bullet2D in env.bullets) {
        var ww : Number = w/2 + b.r;
        var dx0 : Number = b.xx - xx;
        var dy0 : Number = b.xy - xy;
        var tr : Array = [0, 100];
        if (b.vx != 0) {
          var tx0 : Number = (ww - dx0) / b.vx;
          var tx1 : Number = (-ww - dx0) / b.vx;
          if (tx0 > tx1) {
            d = tx0; tx0 = tx1; tx1 = d;
          }
          tr = RangeUtils.intersection(tr, [tx0, tx1]);
        }
        if (b.vy != 0) {
          var ty0 : Number = (ww - dy0) / b.vy;
          var ty1 : Number = (-ww - dy0) / b.vy;
          if (ty0 > ty1) {
            d = ty0; ty0 = ty1; ty1 = d;
          }
          tr = RangeUtils.intersection(tr, [ty0, ty1]);
        }
        if (tr != null) {
          seen.push(b);
          // coloring for debugging
          _parent.fillRect(new Rectangle(b.xx - b.r, b.xy - b.r, 2*b.r, 2*b.r), 0x00ff00);
        }
      }
      
      var ret : * = { };
      for (var key : String in env) ret[key] = env[key];
      ret.bullets = seen;
      
      return ret;
    }
    
    /**
     * 
     * @param	depth
     * @param	env
     * @param	motions {minxx, minxy, maxxx, maxxy, selfr, [bullets], [basex, basey]}
     * @param	width tunnel vision width
     * @return
     */
    public function run(depth : uint, env : Object, motions : Array, width : uint = 0) : Number
    {
      var filtered : Object = width > 0 ? filter(width, env) : env;
      var ret : Object = _algorithm.apply(null, [xx, xy, depth, filtered, motions]);
      vx = ret.motion[0];
      vy = ret.motion[1];
      return ret.time;
    }
    
    public function step() : void
    {
      xx += vx;
      xy += vy;
    }
    
    public function paint() : void
    {
      _parent.copyPixels(_bmd, _bmd.rect, new Point(xx - _bmd.width / 2, xy - _bmd.height / 2));
    }
  }

  class VelocityStrokeDodgeAlgorithm2D
  {
    /**
     * the root of calcSurvivalTime
     * @param	xx
     * @param xy
     * @param	depth
     * @param	env {minxx, minxy, maxxx, maxxy, selfr, [bullets], [basex, basey]}
     * @param	motions
     * @param limt
     * @return
     */
    public static function run(xx : Number, xy : Number, depth : uint, env : *, motions : Array, limt : uint = 100) : Object
    {
      var ret : Array = [0.0, 0.0];
      var maxval : Number = 0;
      for each(var m : Array in motions) {
        var val : Number = calcSurvivalTime(xx, xy, m, 0, depth, env, motions, limt);
        if (val > maxval) {
          maxval = val;
          ret = m;
        }
      }
      
      if (env.basex && env.basey && env.bullets.length == 0) {
        var mind2 : Number = Number.MAX_VALUE;
        for each(m in motions) {
          var d2 : Number = (xx + m[0] - env.basex) * (xx + m[0] - env.basex) + (xy + m[1] - env.basey) * (xy + m[1] - env.basey);
          if (d2 < mind2) {
            mind2 = d2;
            ret = m;
          }
        }
      }
      return { motion : ret, time : maxval };
    }
    
    /**
     * calculate survival time.
     * This function is recursive.
     * @param	xx current state of self. (at the time of t)
     * @param xy
     * @param motion
     * @param	et elapsed time
     * @param	depth depth remaining
     * @param	env enemies' information etc.
     * @param	motions movable motions
     * @param limt upper limit of time
     * @return survival time
     */
    private static function calcSurvivalTime(xx : Number, xy : Number, motion : Array, et : Number, depth : uint, env : * , motions : Array, limt : Number) : Number
    {
        var mint : Number = limt - et;
        var t : Number;
        
        var vx : Number = motion[0];
        var vy : Number = motion[1];
        var r : Number = env.selfr;
        
        // collision with wall
        if (vx > 0) { t = ((env.maxxx - r) - xx) / vx; if (t < mint) mint = t; }
        if (vx < 0) { t = ((env.minxx + r) - xx) / vx; if (t < mint) mint = t; }
        if (vy > 0) { t = ((env.maxxy - r) - xy) / vy; if (t < mint) mint = t; }
        if (vy < 0) { t = ((env.minxy + r) - xy) / vy; if (t < mint) mint = t; }
        
        // collision with bullets
        if(env.bullets){
          for each(var b : Bullet2D in env.bullets) {
            var colr : Number = (r + b.r) * (r + b.r); // collision radius
            // relative parameter
            var rxx : Number = xx - (b.xx + b.vx * et);
            var rxy : Number = xy - (b.xy + b.vy * et);
            var rvx : Number = vx - b.vx;
            var rvy : Number = vy - b.vy;
            if (rxx * rxx + rxy * rxy < colr) {
              mint = 0;
              break;
            }
            if (rvx * rvx + rvy * rvy > 0.1) {
              var ct : Number = -(rxx * rvx + rxy * rvy) / (rvx * rvx + rvy * rvy);
              if (ct <= 0) continue;
              var rxxt : Number = rxx + ct * rvx;
              var rxyt : Number = rxy + ct * rvy;
              var d2 : Number = rxxt * rxxt + rxyt * rxyt;
              if (d2 < colr) {
                ct -= Math.sqrt((colr - d2) / (rvx * rvx + rvy * rvy));
                if(ct < mint)mint = ct;
              }
            }
          }
        }
        
        mint = Math.floor(mint);
        if (mint + et == limt) return mint + depth;
        if(mint >= 2 && depth >= 1){
            // recursion
            var maxval : Number = 0;
            var tt : int = mint - 1; // move to the edge of collision
            
            var newxx : Number = vx * tt + xx;
            var newxy : Number = vy * tt + xy;
            for each(var m : Array in motions) {
              if (m == motion) continue;
              var val : Number = calcSurvivalTime(newxx, newxy, m, et + tt, depth - 1, env, motions, limt);
              if (val > maxval) {
                maxval = val;
              }
            }
            mint += maxval;
        }
        
        return mint;
    }
  }