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

fussa-fussa

ランキングを見るとふさふさ系が多い印象だったので、手持ちの古いコードをASに変換。
尻尾で敵を倒すシューティングゲームを作った際にひねり出したアルゴリズム。
IKもFKも知らなかった際のものなので、かなり不安定(少し動かすと毛先が
はげしく乱れる)けど、限定的には使えると思う
これを使ってマッチの煙を表現しようと思ったけど、完成せず。今日は断念
とりあえずUP(2010/4/1)
基部をドラッグすると移動
下部のマイナス丸印をクリックすると吸引
Get Adobe Flash player
by zendenmushi 31 Mar 2010
/**
 * Copyright zendenmushi ( http://wonderfl.net/user/zendenmushi )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/xEwN
 */

// ランキングを見るとふさふさ系が多い印象だったので、手持ちの古いコードをASに変換。
// 尻尾で敵を倒すシューティングゲームを作った際にひねり出したアルゴリズム。
// IKもFKも知らなかった際のものなので、かなり不安定(少し動かすと毛先が
// はげしく乱れる)けど、限定的には使えると思う

// これを使ってマッチの煙を表現しようと思ったけど、完成せず。今日は断念
// とりあえずUP(2010/4/1)


// 基部をドラッグすると移動
// 下部のマイナス丸印をクリックすると吸引
package  
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.filters.BlurFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	import frocessing.core.F5BitmapData2D;
	/**
	 * ...
	 * @author TMaeda
	 */
    [SWF(width=465,height=465,backgroundColor=0,frameRate=60)]
	public class ClackledHair extends Sprite
	{
		private var canvas : F5BitmapData2D;
		private var hairs : Vector.<Tail> = new Vector.<Tail>;
		private var blur : BlurFilter = new BlurFilter(4, 4, 1);
		private var colorTrans : ColorTransform = new ColorTransform(0.8, 0.8, 0.9, 0.99);
		
		private var center : Point = new Point();
		private var isDown : Boolean = false;
		private var tempPos : Point = new Point();
		private var lastPos : Point = new Point();
		private var rootPos : Point = new Point();
		private var zeroPos : Point = new Point(0, 0);
		private var plusBall : Point = new Point();
		private var negative : Boolean = true;
		private var selIndex : int = -1;
		private var rad : Number = 0;
		
		public function ClackledHair() 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event=null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			addEventListener(Event.ENTER_FRAME, enterFrame);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
			stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
			
			canvas = new F5BitmapData2D(stage.stageWidth, stage.stageHeight, true, 0xff000000);
			addChild( new Bitmap(canvas.bitmapData) );
			
			center.x = stage.stageWidth / 2;
			center.y = stage.stageHeight*2 / 3;
			for (var i : int = 0 ; i < 100; i++) {
				hairs[i] = new Tail();
				hairs[i].init(center, 270+Math.random()*20-10, 16, 16, 1, true);
			}
			
			rootPos.x = center.x;
			rootPos.y = center.y;
			plusBall.x = center.x;
			plusBall.y = stage.stageHeight - 30;
		}
		
		private function dist(a : Point, b : Point): Number
		{
			return Math.sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
		}
		
		private function mouseDown(e:MouseEvent):void 
		{
			lastPos.x = e.stageX;
			lastPos.y = e.stageY;
			selIndex = (dist(lastPos, plusBall) < 8) ? 0 : (dist(lastPos, rootPos) < 8) ? 1 : -1;
			isDown = true;
		}
		
		private function mouseUp(e:MouseEvent):void 
		{
			if ((dist(lastPos, plusBall) < 1) && (selIndex == 0)) {
				negative = !negative;
			}
			isDown = false;
		}
		
		private function enterFrame(e:Event):void 
		{
			var i : int, j : int;
			var hair_len : int;
			var hair_cnt : int = hairs.length;
			
			
			canvas.bitmapData.colorTransform(canvas.bitmapData.rect, colorTrans);
			canvas.bitmapData.applyFilter(canvas.bitmapData, canvas.bitmapData.rect, zeroPos, blur);
			if (isDown) {
				switch (selIndex) {
					case 0: {
						plusBall.x = stage.mouseX;
						plusBall.y = stage.mouseY;
						break;
					}
					case 1: {
						rootPos.x += (stage.mouseX-rootPos.x)/4;
						rootPos.y += (stage.mouseY-rootPos.y)/4;
						break;
					}
				}
			}
			
			rad += Math.random();
			
			canvas.beginDraw();
			canvas.bitmapData.lock();
			canvas.stroke(0xff, 0xff, 0xff);
			canvas.noFill();
			canvas.circle(rootPos.x, rootPos.y, 8);
			
			canvas.circle(plusBall.x, plusBall.y, 8);
			canvas.moveTo(plusBall.x - 3, plusBall.y);
			canvas.lineTo(plusBall.x + 3, plusBall.y);
			if (!negative) {
				canvas.moveTo(plusBall.x , plusBall.y - 3);
				canvas.lineTo(plusBall.x , plusBall.y + 3);
			}
			
			for (i = 0; i < hair_cnt; i++) {
				var tail : Tail = hairs[i];
				tempPos.x = rootPos.x + Math.cos(rad) * 4;
				tempPos.y = rootPos.y + Math.sin(rad) * 4;
				
				tail.stepFrame(tempPos, 0, negative? null : plusBall);
				hair_len = tail.tails.length;
				canvas.moveTo(tail.rootpos.x, tail.rootpos.y);
				for (j = 0; j < hair_len; j++) {
					canvas.stroke(0xff*j/hair_len, 0x80, 0x40);
					canvas.lineTo(tail.tails[j].term.x, tail.tails[j].term.y);
				}
			}
			canvas.bitmapData.unlock();
			canvas.endDraw();
		}
		
	}

}

import flash.geom.Point;

class Tail
{
	public  var tails : Vector.<TailItem>;
	public  var rootpos : Point = new Point();
	public  var rootangle : Number;
	private var flexAngle : Number;
	private var segLen : int;
	public  var segCnt : int;
	private var temppos1 : Point = new Point();
	private var temppos2 : Point = new Point();
	private var befterm : Point = new Point();
	private var autoWave : Boolean;
	private var waveState : int;
	private var absorb : Number = 0;
	
	private const maxlen : int = 32;
	
	public function Tail()
	{
		tails = new Vector.<TailItem>;
	}
	
	public function init(pos : Point, angle : Number, seglen : int, len : int, flexlevel : Number, autowave : Boolean = true ) : void
	{
		flexAngle = Math.min(flexlevel, 1.0)*2 * Math.PI;
		rootangle = angle * Math.PI / 180;
		segCnt = Math.min(maxlen, len);
		segLen = seglen;
		autoWave = autowave;
		waveState = 0;
		
		rootpos.x = pos.x;
		rootpos.y = pos.y;
		
		for (var i : int = 0; i < segCnt; i++) {
			/*if (i < tails.length)*/ tails[i] = new TailItem;
			tails[i].pos.x = pos.x;
			tails[i].pos.y = pos.y;
			tails[i].len = segLen+Math.random()*(segLen);
			tails[i].angle = 0;
		}
		
	}
	
	public function tailPos(index : int, /*out*/ pos : Point, term : Point = null) : void
	{
		if (index < segCnt) {
			pos.x = tails[index].pos.x;
			pos.y = tails[index].pos.y;
			if (term) {
				term.x = tails[index].term.x;
				term.y = tails[index].term.y;
			}
		}
	}
	
	public function stepFrame(newpos : Point, rotate_angle : Number, tail_target : Point = null) : void
	{
		var i : int, cosa : Number, sina : Number, rad : Number;
		var angle : Number = rootangle+rotate_angle;
		waveState = (waveState + 1) & 0x3f;
		if (autoWave) {
			if (waveState >= 0x20) {
				angle = angle + (0x20 - (waveState & 0x1f) - 0x10)*Math.PI/180;
			} else {
				angle = angle + (waveState-0x10)*Math.PI/180;
			}
		}
		
		if (tail_target) {
			absorb = 1.0;
		} else if (absorb > 0) {
			absorb /= 2;
		} else absorb = 0;
		
		rootpos.x = newpos.x;
		rootpos.y = newpos.y;
		
		for (i = 0; i < segCnt; i++) {
			if (i == 0) {
				tails[i].pos.x = newpos.x;
				tails[i].pos.y = newpos.y;
				if (autoWave) {
					tails[i].pos.x += Math.random() * 8-4;
					tails[i].pos.y += Math.random() * 8-4;
				}
			} else {
				tails[i].pos.x += (tails[i-1].term.x-tails[i].pos.x)/((i*absorb/4+1));
				tails[i].pos.y += (tails[i-1].term.y-tails[i].pos.y)/((i*absorb/4+1));
			}
			computeUnitVector(Math.cos(angle) * segLen, Math.sin(angle) * segLen, 0, 0, temppos1);
			if (!computeUnitVector(tails[i].term.x, tails[i].term.y, tails[i].pos.x, tails[i].pos.y, temppos2)) {
				temppos2.x = temppos1.x;
				temppos2.y = temppos1.y;
			}
			cosa = dotProduct(temppos1.x, temppos1.y, temppos2.x, temppos2.y);
			sina = crossProductZ(temppos1.x, temppos1.y, temppos2.x, temppos2.y);
			if (cosa < -1) rad = Math.PI; else if (cosa > 1) rad = 0; else rad = Math.acos(cosa);
			//trace(cosa + " " + rad);
			if (cosa < 0) rad = Math.PI-rad;
			if (sina < 0) rad = -rad;
			//trace(">"+cosa + " " + rad);
			
			if ((rad < 0) && ( -flexAngle > rad)) rad = -flexAngle;
			if ((rad > 0) && (  flexAngle < rad)) rad =  flexAngle;
			
			rad += (0-rad) /4;
			tails[i].angle = angle+rad;
			angle = tails[i].angle;
			
			tails[i].term.x = tails[i].pos.x + Math.cos(angle)*tails[i].len;
			tails[i].term.y = tails[i].pos.y + Math.sin(angle)*tails[i].len;
			
			
		}
		if (tail_target) {
			befterm.x = tail_target.x;
			befterm.y = tail_target.y;
			for (i = segCnt - 1; i > 0; i--) {
				temppos2.x = tails[i].term.x + (befterm.x - tails[i].term.x) / ((segCnt - i)/2 + 1) ;
				temppos2.y = tails[i].term.y + (befterm.y - tails[i].term.y) / ((segCnt - i)/2 + 1) ;
				if (computeUnitVector(temppos2.x, temppos2.y, tails[i].pos.x, tails[i].pos.y, temppos1)) {
					tails[i].term.x = temppos2.x;
					tails[i].term.y = temppos2.y;
					tails[i].pos.x = temppos2.x - (temppos1.x)*tails[i].len;
					tails[i].pos.y = temppos2.y - (temppos1.y)*tails[i].len;
					befterm.x = tails[i].pos.x;
					befterm.y = tails[i].pos.y;
				}
			}
		}
	}

	public function computeUnitVector(x0 : Number, y0 : Number, x1 : Number, y1 : Number, /*out*/ u : Point) : Boolean
	{
		var len : Number = Math.sqrt( (y0 - y1) * (y0 - y1) + (x0 - x1) * (x0 - x1) );
		if (len > 0) {
			u.x = (x0 - x1) / len;
			u.y = (y0 - y1) / len;
			return true;
		} else return false;
	}

	public function dotProduct(x0 : Number, y0 : Number, x1 : Number, y1 : Number) : Number
	{
		return x0 * x1 + y0 * y1;
	}
	
	public function crossProductZ(x0 : Number, y0 : Number, x1 : Number, y1 : Number) : Number
	{
		return x0 * y1 - y0 * x1;
	}
	
	
}
	
class TailItem
{
	public var pos : Point = new Point();
	public var angle : Number;
	public var term : Point = new Point();
	public var len : Number;
}