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

if (!canDodge) { gameover(); }

GAME :: 避けゲーっぽいの
* 
* 操作はマウスを動かすのみです。上方から降り注ぐ流星をひたすら避け続けます。
* Level 5 付近から結構きついです(主観)。
/**
 * Copyright uwi ( http://wonderfl.net/user/uwi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/qsv0
 */

// forked from daniwell's if (isHit) { gameover(); } 
/**
 * GAME :: 避けゲーっぽいの
 * 
 * 操作はマウスを動かすのみです。上方から降り注ぐ流星をひたすら避け続けます。
 * Level 5 付近から結構きついです(主観)。
 */
package  
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.ColorTransform;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.ui.Mouse;
	
	[SWF(backgroundColor = "0x333333", frameRate = "60", width = "465", height = "465")]
	public class Evade extends Sprite
	{
		private const WIDTH :uint = 390 / 3;
		private const HEIGHT:uint = 465 / 3;
		
		private var bmd :BitmapData;
		private var bmp :Bitmap;
		
		private var particles :Vector.<Vector.<Particle>> = new Vector.<Vector.<Particle>>(WIDTH);
		
		private var pos :int = 0;
		private var numList :Vector.<uint> = new Vector.<uint>(WIDTH);
		private var scoreText :TextField;
		private var tx :TextField = new TextField();
		
		private var lv :uint;
		private var speed :Number;
		private var particleNum :uint;
		
		public function Evade() 
		{
			bmd = new BitmapData(WIDTH, HEIGHT, false, 0);
			bmp = new Bitmap(bmd);
			bmp.scaleX = bmp.scaleY = 3;
			addChild(bmp);
			
			scoreText = new TextField();
			tx = new TextField();
			tx.autoSize = scoreText.autoSize = "left";
			tx.defaultTextFormat = scoreText.defaultTextFormat = new TextFormat("_等幅", 10, 0xffffff);
			
			scoreText.x = 395;
			scoreText.y = 435;
			addChild(scoreText);
			
			tx.text = "CLICK TO RESTART";
			tx.x = (465 - tx.width) / 2;
			tx.y = (465 - tx.height) / 2;
			addChild(tx);
			
			initialize();
		}
		private function initialize():void
		{
			var i:uint, j:uint, len:uint = 0;
			
			tx.visible = false;
			lv = pos = 0;
			
			for (i = 0; i < WIDTH; i++)
			{
				if (particles[i]) len = particles[i].length;
				for (j = 0; j < len; j++) particles[i][j] = null;
				
				numList[i] = i;
				particles[i] = new Vector.<Particle>();
			} 
			_particles = [];
			for (i = 0; i < WIDTH; i++)
			{
				var tmp:uint = numList[i];
				var r :uint = Math.random() * WIDTH;
				numList[i] = numList[r];
				numList[r] = tmp;
			}
			
//			Mouse.hide();
			stage.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener(MouseEvent.CLICK, onClick);
			
			mX = 100; mY = 100;
		}
		
		private var _mode : uint = 0;
		
		private function onClick(e : MouseEvent) : void
		{
			_mode = ++_mode % 2;
		}
		
		private function addParticle():void
		{
			if (particleNum < pos) return;
			
			var n :uint = numList[pos % WIDTH];
			var p:Particle = new Particle();
			
			p.x = n;
			p.y = 0;
			p.vy = Math.random() * speed + 1;
			particles[n].push(p);
			_particles.push(p);
		}
		
		private var mX : int;
		private var mY : int;
		private var _particles : Array;
		
		private function enterFrameHandler(e:Event):void
		{
			if (lv < Level.max && Level.counts[lv] <= pos)
			{
				speed = Level.speeds[lv];
				particleNum = Level.nums[lv];
				lv ++;	// level up
			}
			
			addParticle();
			pos ++;
			
			scoreText.text = "level: " + lv + "\nscore: " + pos;
			
			var i:uint, j:uint, len:uint = 0;
			var p:Particle;
			
			bmd.lock();
			bmd.colorTransform(bmd.rect, new ColorTransform (0.4, 0.4, 0.4));
			
			for (i = 0; i < WIDTH; i++)
			{
				len = particles[i].length;
				
				for (j = 0; j < len; j++)
				{
					p = particles[i][j];
					p.py = p.y;
					p.y += p.vy;
					if (HEIGHT <= p.y)
					{
						p.vy = Math.random() * speed + 1;
						p.y = 0;
					}
					bmd.setPixel(p.x, p.y, 0xffffff);
					p.reflect();
				}
			}
			
//			var mX :int = mouseX / 3;
//			var mY :int = mouseY / 3; 
			var ret : Object;
			
			if(_mode == 0){
				ret = VelocityStrokeDodgeAlgorithm2D.run(mX, mY, 3, {
					maxxx : 133, maxxy : 145, minxx : 0, minxy : 0,
					bullets : _particles, selfr : 1, basex : 133 / 2, basey : 100
				}, [[0, 0], [1, 0], [-1, 0]], LInfinityNorm.calcLinearCollisionTime2D,
				40, 40 
				);
			}else if(_mode == 1){
				ret = VelocityStrokeDodgeAlgorithm2D.run(mX, mY, 1, {
					maxxx : 133, maxxy : 145, minxx : 0, minxy : 0,
					bullets : _particles, selfr : 1, basex : 133 / 2, basey : 100
				}, [[0, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]], LInfinityNorm.calcLinearCollisionTime2D,
				40, 40 
				);
			}
			mX += ret.motion[0];
			mY += ret.motion[1];
			scoreText.appendText("\n" + ret.time);
			
			if (mX < 0) mX = 0; else if (WIDTH <= mX) mX = WIDTH - 1;
			
			// 衝突判定
			len = particles[mX].length;
			for (j = 0; j < len; j++)
			{
				p = particles[mX][j];
				if ( p.py <= mY && mY <= p.y )
				{
					Mouse.show();
					tx.visible = true;
					stage.removeEventListener(Event.ENTER_FRAME, enterFrameHandler);
					stage.addEventListener(MouseEvent.CLICK, clickHandler);
				}
			}
			
			bmd.setPixel(mX, mY, 0xff6600);	// mouse
			bmd.unlock();
		}
		private function clickHandler(e:MouseEvent):void
		{
			stage.removeEventListener(MouseEvent.CLICK, clickHandler);
			initialize();
		}
	}
}

/* Level 毎の 速さ調整 & 個数 管理 */
class Level
{
	public static const max :uint = 10;
	public static const counts :Array = [  0, 400, 800, 1200, 1500, 2000, 2500, 3000, 5000, 10000]; // pos
	public static const speeds :Array = [  0, 0.5,   1,    1,  1.5,  1.8,    2,  2.5,    3,     3]; // Particle 速さ
	public static const nums   :Array = [130, 150, 150,  180,  180,  200,  200,  200,  220,   260]; // Particle 個数
}

  interface IBullet
  {
    function step() : void;
    function predict(t : Number) : Array;
  }
  
  class Bullet2D implements IBullet
  {
    public var xx : Number;
    public var xy : Number;
    public var r : Number;
    public var t : Number;
    
    public function Bullet2D(xx : Number, xy : Number, r : Number, t : Number = 0) 
    {
      this.xx = xx; this.xy = xy;
      this.r = r;
      this.t = t;
    }
    
    public function step() : void
    {
    }
    
    public function predict(t : Number) : Array
    {
      return null;
    }
  }
  
  class LinearBullet2D extends Bullet2D implements IBullet
  {
    public var vx : Number;
    public var vy : Number;
    
    public function LinearBullet2D(xx : Number, xy : Number, vx : Number, vy : Number, r : Number, t : Number = 0)
    {
      super(xx, xy, r, t);
      this.vx = vx; this.vy = vy;
    }
    
    public override function step() : void
    {
      xx += vx; xy += vy;
    }
    
    public override function predict(t : Number) : Array
    {
      return [xx + vx * t, xy + vy * t];
    }
  }

class Particle extends LinearBullet2D
{
	public var x :Number = 0;
	public var y :Number = 0;
//	public var vy:Number = 0;
	public var py:Number = 0; // previous y
	
	public function Particle()
	{
		super(0, 0, 0, 0, 1);
	}
	
	public function reflect() : void
	{
		this.xx = x;
		this.xy = y;
	}
}

  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])];
      return [a[0] > b[0] ? a[0] : b[0], a[1] < b[1] ? a[1] : b[1]];
    }
  }
  
  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, collisionTimeCalculator : Function, width : Number = 0, limt : uint = 100) : Object
    {
      if (width > 0) env = filter(xx, xy, width, env, limt);
      
      var ret : Array = [0.0, 0.0];
      var maxval : Number = 0;
      var stability : Array = [];
      for each(var m : Array in motions) {
        var val : Number = calcSurvivalTime(xx, xy, m, 0, depth, env, motions, limt, collisionTimeCalculator);
        if(val >= limt)stability.push(m);
        if (val > maxval) {
          maxval = val;
          ret = m;
        }
      }
      
      if (stability.length >= 2) {
        var mind2 : Number = Number.MAX_VALUE;
        for each(m in stability) {
          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 };
    }
    private static var _t : uint = 0;
    private static var _s : Number = 0;
    
    /**
     * 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, calcCollisionTime : Function) : Number
    {
        var mint : Number = limt - et;
        var t : Number;
        var rxx : Number, rxy : Number, rvx : Number, rvy : Number;
        var colr2 : Number;
        var colt : Number;
        var rxxt : Number, rxyt : Number;
        var d2 : 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; }
        var self : LinearBullet2D = new LinearBullet2D(xx, xy, vx, vy, r);
        
        // collision with bullets
        if (env.bullets) {
          for each(var b : LinearBullet2D in env.bullets) {
            colt = calcCollisionTime(self, b, et);
            if (colt < mint) {
              mint = colt;
            }
          }
        }
        
        mint = Math.floor(mint);
        if (mint + et == limt) return mint + depth;
        if(mint >= 2 && depth >= 1){
            // recursion
            //var maxval : int = mint >= 10 ? mint / 10 - 1 : 0;
            //var tt : int = mint - 1 - maxval; // move to the edge of collision
            //mint -= maxval;
            var maxval : int = 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, calcCollisionTime);
              if (val > maxval) {
                maxval = val;
              }
            }
            mint += maxval;
        }
        
        return mint;
    }

      /**
     * develop tunnel vision
     * @param	w
     * @param	env
     * @return
     */
    private static function filter(xx : Number, xy : Number, w : Number, env : Object, limt : Number) : Object
    {
      var d : Number;
      
      var seen : Array = [];
      for each(var b : LinearBullet2D 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, limt];
        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);
        }
      }
      
      var ret : Object = { };
      for (var key : String in env) ret[key] = env[key];
      ret.bullets = seen;
      
      return ret;
    }
  }

  class LInfinityNorm
  {
    public static function calcLinearCollisionTime2D(a : LinearBullet2D, b : LinearBullet2D, tb : Number = 0) : Number
    {
      var colr : Number = a.r + b.r; // collision radius
      
      // relative parameter
      var rxx : Number = a.xx - (b.xx + b.vx * tb);
      var rxy : Number = a.xy - (b.xy + b.vy * tb);
      var rvx : Number = a.vx - b.vx;
      var rvy : Number = a.vy - b.vy;
      var d : Number;
      
      var range : Array = [0, Number.MAX_VALUE]; // collision time range
      if(rvx != 0){
        var txinf : Number = (rxx - colr) / -rvx;
        var txsup : Number = (rxx + colr) / -rvx;
        if (txsup < txinf) { d = txinf; txinf = txsup; txsup = d; }
        range = RangeUtils.intersection(range, [txinf, txsup]);
      }else {
        if (rxx > colr || rxx < -colr) range = null;
      }
      
      if(rvy != 0){
        var tyinf : Number = (rxy - colr) / -rvy;
        var tysup : Number = (rxy + colr) / -rvy;
        if (tysup < tyinf) { d = tyinf; tyinf = tysup; tysup = d; }
        range = RangeUtils.intersection(range, [tyinf, tysup]);
      }else {
        if (rxy > colr || rxy < -colr) range = null;
      }
      
      return range != null ? range[0] : Number.MAX_VALUE;
    }
  }