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

紙ふぶき

------------------------------------------------------------------------
2010年4月9日
なんちゃって紙ふぶき
実はそれぞれの紙切れは, 一定の回転軸のまわりを, 一定の速さで回転しながら, 
一定の移動速度で落下しているのだけど, 移動方向がフラフラ変わることと, 
数多く同時に散らしていることで, なんとなく紙吹雪らしく見えている.
... しかし、これまた重くなった (^^;
------------------------------------------------------------------------
/**
 * Copyright tenasaku ( http://wonderfl.net/user/tenasaku )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/tVmM
 */

/*	------------------------------------------------------------------------
	2010年4月9日
	なんちゃって紙ふぶき
	実はそれぞれの紙切れは, 一定の回転軸のまわりを, 一定の速さで回転しながら, 
	一定の移動速度で落下しているのだけど, 移動方向がフラフラ変わることと, 
	数多く同時に散らしていることで, なんとなく紙吹雪らしく見えている.
	... しかし、これまた重くなった (^^;
	------------------------------------------------------------------------
*/
package {

	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
//	import flash.text.*;

	public class Main extends Sprite {

		private const NUM_KAMIKIRE:int = 400;
		private var kamiFubuki:Array;
		private var frameCount:uint;

		private function drawBackGround():void {
			var mat:Matrix = new Matrix();
			mat.createGradientBox(stage.stageWidth,stage.stageHeight,Math.PI/2,0,0);
			this.graphics.clear();
			this.graphics.beginGradientFill(
				GradientType.LINEAR,
				[0x00ccff,0x0000ff,0x000099],[1,1,1],[0,200,255],
				mat,
				SpreadMethod.PAD);
			this.graphics.drawRect(0,0,stage.stageWidth, stage.stageHeight);
			this.graphics.endFill();
		}

		private function atEveryFrame(e:Event):void {
			var i:int;
			// 最初の一秒ほどで撒き散らす
			if ( (frameCount+1)*25 < kamiFubuki.length ) {
				for ( i = frameCount*25 ; i < (frameCount+1)*25 ; ++i ) {
					if ( i >= kamiFubuki.length ) break;
					kamiFubuki[i].x 
						= Kamikire.SIZE/Math.SQRT2 
							+ (stage.stageWidth-Kamikire.SIZE*Math.SQRT2)*(i/kamiFubuki.length);
					kamiFubuki[i].y = 30;
					kamiFubuki[i].visible = true;
				}
				frameCount++;
			}
			// 紙切れを落とす.  画面の外に出たら反対側から入ってくる(トーラス空間)
			for ( i = 0 ; i < kamiFubuki.length ; ++i ) {
				kamiFubuki[i].fall();
				if (kamiFubuki[i].x - Kamikire.SIZE/Math.SQRT2 > stage.stageWidth) {
					kamiFubuki[i].x -= stage.stageWidth;
				}
				if (kamiFubuki[i].x + Kamikire.SIZE/Math.SQRT2 < 0 ) {
					kamiFubuki[i].x += stage.stageWidth;
				}
				if (kamiFubuki[i].y - Kamikire.SIZE/Math.SQRT2 > stage.stageHeight) {
					kamiFubuki[i].y -= stage.stageHeight;
				}
			}
		}
		
		private function onResize(e:Event):void {
			drawBackGround();
			var i:int;
			for ( i = 0 ; i < kamiFubuki.length ; ++i ) {
					kamiFubuki[i].visible = false;
			}
			frameCount = 0;
		}

		private function initialize(e:Event):void {
			this.removeEventListener(Event.ADDED_TO_STAGE, initialize);
			stage.align = StageAlign.TOP_LEFT;
			stage.scaleMode = StageScaleMode.NO_SCALE;
			drawBackGround();
			kamiFubuki = new Array();
			while ( kamiFubuki.length < NUM_KAMIKIRE ) {
				kamiFubuki.unshift(new Kamikire());
				kamiFubuki[0].visible = false; // 出し方をヒネったので最初は見えなくする
				this.addChild(kamiFubuki[0]);
			}
			stage.frameRate = 24;
			frameCount = 0;
			stage.addEventListener(Event.RESIZE, onResize);
			stage.addEventListener(Event.ENTER_FRAME, atEveryFrame);
		}
		// The Main constructor simply calles initialize() function.

		public function Main():void {
			if ( stage != null ) {
				initialize(null);
			} else {
				this.addEventListener(Event.ADDED_TO_STAGE, initialize);
			}
		}

	} // end of class Main
} // end of package


// 固有の軸のまわりを固有の角速度で3D回転しながらフラフラと落下する正方形の紙切れ
import flash.display.*;
class Kamikire extends Shape {
	public static const SIZE:Number = 10;
	private var _faceColor:uint;
	private var _backColor:uint;
	private var _theta:Number; // amount of rotation along the axis
	private var _omega:Number; // angular velocity
	private var _fallTheta:Number;
	private var _fallSpeed:Number;
	private var _Ax:Number,_Ay:Number,_Az:Number; // axis of rotation
	private var _Bx:Number,_By:Number,_Bz:Number; // a unit vector perp to A
	private var _Cx:Number,_Cy:Number,_Cz:Number; // a unit vector perp to A and B
	public function Kamikire() {
		var t:Number = Math.random()*Math.PI*2;
		var r:int = Math.floor((1+Math.cos(t))*127.9999);
		var g:int = Math.floor((1+Math.cos(t+Math.PI*2/3))*127.9999);
		var b:int = Math.floor((1+Math.cos(t-Math.PI*2/3))*127.9999);
		_faceColor = (r<<16)|(g<<8)|b;
		_backColor = 0x010101*Math.floor(127+Math.random()*64);
		_omega = (Math.random()*2-1)*Math.PI/4;
		_fallTheta = 0;
		_fallSpeed = 3+Math.random()*2;
		_theta = Math.random()*Math.PI*2;
		_Ax = 1;
		_Ay = Math.random();
		_Az = Math.random()*2-1;
		var _l:Number = Math.sqrt(_Ax*_Ax+_Ay*_Ay+_Az*_Az);
		_Ax /= _l;
		_Ay /= _l;
		_Az /= _l;
		var _s:Number = Math.sqrt(_Ax*_Ax+_Ay*_Ay);
		if ( _s == 0 ) { // then A == ( 0, 0, -1 );
			_Bx = 1.0; _By = 0.0; _Bz = 0.0;
			_Cx = 0.0; _Cy = 1.0; _Cz = 0.0;
		} else {
			_Bx = _Ay; _By = -_Ax; _Bz = 0;
			_Cx = _Ax*_Az; _Cy = _Ay*_Az; _Cz = -(_s*_s);
			_Bx /= _s; _By /= _s;
			_Cx /= _s*_l; _Cy /= _s*_l; _Cz /= _s*_l;
		}
		this.graphics.beginFill(_faceColor);
		this.graphics.drawRect(-SIZE/2,-SIZE/2,SIZE,SIZE);
		this.graphics.endFill();
	}
	// rotate along the axis (_Ax,_Ay,_Az)...
	public function set rotation3D(theta:Number):void {
		_theta = theta - (Math.PI*2)*Math.floor(theta/(Math.PI*2));
		var _cos:Number = Math.cos(_theta);
		var _sin:Number = Math.sin(_theta);
		// vector F is the rotated image of (1,0,0);
		var _Fx:Number = _Ax*_Ax+(_Bx*_Bx+_Cx*_Cx)*_cos;
		var _Fy:Number = _Ax*_Ay+(_Bx*_By+_Cx*_Cy)*_cos+(_Bx*_Cy-_Cx*_By)*_sin;
		var _Fz:Number = _Ax*_Az+(_Bx*_Bz+_Cx*_Cz)*_cos-(_Bx*_Cz-_Cx*_Bz)*_sin;
		// vector G is the rotated image of (0,1,0);
		var _Gx:Number = _Ax*_Ay+(_By*_Bx+_Cy*_Cz)*_cos+(_By*_Cx-_Cy*_Bx)*_sin;
		var _Gy:Number = _Ay*_Ay+(_By*_By+_Cy*_Cy)*_cos;
		var _Gz:Number = _Ay*_Az+(_By*_Bz+_Cy*_Cz)*_cos+(_By*_Cz-_Cy*_Bz)*_sin;
		// let's see whether the piece shows its face or its back...
		var cc:uint = ( (_Az*_Az+(_Bz*_Bz+_Cz*_Cz)*_cos) >= 0 )?_faceColor:_backColor;
		// We can draw the image now...
		this.graphics.clear();
		this.graphics.beginFill(cc);
		this.graphics.moveTo(_Fx*SIZE/2+_Gx*SIZE/2,_Fy*SIZE/2+_Gy*SIZE/2);
		this.graphics.lineTo(-_Fx*SIZE/2+_Gx*SIZE/2,-_Fy*SIZE/2+_Gy*SIZE/2);
		this.graphics.lineTo(-_Fx*SIZE/2-_Gx*SIZE/2,-_Fy*SIZE/2-_Gy*SIZE/2);
		this.graphics.lineTo(_Fx*SIZE/2-_Gx*SIZE/2,_Fy*SIZE/2-_Gy*SIZE/2);
		this.graphics.lineTo(_Fx*SIZE/2+_Gx*SIZE/2,_Fy*SIZE/2+_Gy*SIZE/2);
		this.graphics.endFill();
	}
	public function get rotation3D():Number {
		return _theta - (Math.PI*2)*Math.floor(_theta/(Math.PI*2));
	}
	public function fall():void {
		this.rotation3D += this._omega;
		this.x += _fallSpeed*Math.sin(_fallTheta);
		this.y += _fallSpeed*Math.cos(_fallTheta);
		_fallTheta += (Math.random()*2-1)*Math.PI/12;
		if ( _fallTheta < -Math.PI/2 ) {
			_fallTheta = -Math.PI - _fallTheta;
		}
		if ( _fallTheta > Math.PI/2 ) {
			_fallTheta = Math.PI - _fallTheta;
		}
	}
} // end of class Kamikire