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

BigDogを目指して

難しいね
Get Adobe Flash player
by tencho 30 May 2010
/**
 * Copyright tencho ( http://wonderfl.net/user/tencho )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/5tWA
 */

/**
 * 難しいね
 */
package  {
	import com.actionsnippet.qbox.*;
	import com.actionsnippet.qbox.objects.*;
	import flash.display.*;
	import flash.events.*;
	import flash.geom.*;
	import flash.utils.*;
	import mx.utils.*;
	public class QboxWalker extends Sprite {
		private const BOX2D_SCALE:Number = 30;
		private const CAMERA_SCALE:Number = 1;
		private const SCENE_SCALE:Number = 0.35;
		private const QBOX_CODE:XML = <code>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</code>;
		private var sim:QuickBox2D;
		private var scene:SceneData;
		private var container:MovieClip;
		private var bg:Sprite;
		private var bgImage:BitmapData;
		private var bgMatrix:Matrix = new Matrix();
		//コンストラクタ
		public function QboxWalker() {
			Wonderfl.disable_capture();
			//Wonderfl.capture_delay(3);
			bgImage = new BitmapData(100, 20, false, 0xffEEEEEE);
			bgImage.fillRect(new Rectangle(0, 0, 50, 20), 0xFFE0E0E0);
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.addEventListener(Event.RESIZE, onResizeStage)
			bg = addChild(new Sprite()) as Sprite;
			container = addChild(new MovieClip()) as MovieClip;
			container.scaleX = container.scaleY = CAMERA_SCALE;
			refreshBackground()
			decode(QBOX_CODE);
		}
		//ステージサイズ変更時
		private function onResizeStage(e:Event):void {
			refreshBackground();
		}
		//背景パターン塗り直し
		private function refreshBackground():void {
			bgMatrix.tx = container.x;
			bgMatrix.ty = container.y;
			bg.graphics.clear();
			bg.graphics.beginBitmapFill(bgImage, bgMatrix, true, false);
			bg.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
		}
		//コードをBase64デコードしてシーンを生成する
		private function decode(code:String):void {
			var base64:Base64Decoder = new Base64Decoder();
			base64.decode(code);
			var ba:ByteArray = base64.toByteArray();
			ba.uncompress();
			var qbox:QboxModeler = new QboxModeler();
			sim = new QuickBox2D(container);
			scene = qbox.createByXML(new XML(ba.toString()), sim, SCENE_SCALE);
			setCameraPosition(0, 0);
			sim.mouseDrag();
			sim.start();
			addEventListener(Event.ENTER_FRAME, onSimulate);
		}
		//カメラ位置設定
		private function setCameraPosition(x:Number, y:Number):void {
			container.x = stage.stageWidth / 2 - x * BOX2D_SCALE * CAMERA_SCALE;
			container.y = stage.stageHeight / 2 - y * BOX2D_SCALE * CAMERA_SCALE;
			refreshBackground();
		}
		//シミュレーション中
		private function onSimulate(e:Event):void {
			//カメラで追跡するオブジェクトがあれば追う
			if (scene.trackingList.length) {
				var xx:Number = 0;
				var yy:Number = 0;
				for each(var qo:QuickObject in scene.trackingList) {
					var px:Number = 0;
					var py:Number = 0;
					if (scene.group[qo]) {
						var rp:Point = Coordinate.rotatePoint(new Point(qo.x, qo.y), scene.group[qo].angle);
						px = scene.group[qo].x + rp.x;
						py = scene.group[qo].y + rp.y;
					} else {
						px = qo.x;
						py = qo.y;
					}
					if (isNaN(px) || isNaN(py)) {
						scene.trackingList.splice(scene.trackingList.indexOf(qo), 1);
					} else {
						xx += px;
						yy += py;
					}
				}
				xx /= scene.trackingList.length;
				yy /= scene.trackingList.length;
				if (scene.trackingList.length) {
					container.x += ((stage.stageWidth / 2 - xx * BOX2D_SCALE * CAMERA_SCALE) - container.x) * 0.2;
					container.y += ((stage.stageHeight / 2 - yy * BOX2D_SCALE * CAMERA_SCALE) - container.y) * 0.2;
					refreshBackground();
				}
			}
			//角度が大きすぎると描画できなくなるので-360~360°に収める
			for each(var qbody:QuickObject in scene.bodyList) {
				if (!qbody.body.IsStatic() && Math.abs(qbody.angle) > Math.PI * 2) qbody.angle = qbody.angle % (Math.PI * 2);
			}
		}
	}
}
import Box2D.Collision.Shapes.*;
import com.actionsnippet.qbox.*;
import com.actionsnippet.qbox.objects.*;
import flash.events.*;
import flash.geom.*;
import flash.utils.*;
class QboxModeler {
	private var primitives:Array;
	public function QboxModeler() {
	}
	/**
	 * XMLからQuickBoxシーンを生成
	 */
	public function createByXML(xml:XML, sim:QuickBox2D, scale:Number = 1):SceneData {
		var scene:SceneData = new SceneData();
		var S:Number = scale;
		var joints:Array = new Array();
		var groups:Array = new Array();
		var unit:Object;
		primitives = new Array();
		for each(var node:XML in xml.children()) {
			unit = { density:2, fricyion:0.5, restitution:0.5, strength:0.25, damping:0.1, density:2, motorSpeed:15, reverse:false, motorTorque:100 };
			for each(var atr:XML in node.attributes()) unit[String(atr.name())] = XMLtoVALUE(atr.toString());
			if(node.name() == "primitive") primitives.push(unit);
			if(node.name() == "joint") joints.push(unit);
			if(node.name() == "list") groups.push(unit);
		}
		primitives.sortOn("z", Array.NUMERIC);
		var primitiveOffset:Dictionary = new Dictionary();
		var bg:QuickObject = sim.addCircle( { x:0, y:0, radius:0.1, density:0, maskBits:0, categoryBits:0, lineAlpha:0, fillAlpha:0 } );
		primitiveOffset[bg] = new Point();
		var fixList:Object = new Object();
		for each(unit in primitives) {
			var unitOffset:Point = new Point();
			var param:Object = {
				lineAlpha: int(unit.border),
				fillColor: unit.color,
				fillAlpha: unit.alpha,
				x: unit.position[0] * S,
				y: -unit.position[1] * S,
				angle: -unit.angle,
				friction: unit.friction,
				restitution: unit.restitution,
				maskBits:unit.maskbits,
				categoryBits:unit.maskbits,
				density: unit.density,
				isBullet: false
			}
			if (unit.type == "wall") {
				var unitPos:Point = new Point(unit.position[0] * S, -unit.position[1] * S);
				var adjust:Point = adjustPlanePos(unitPos.x, unitPos.y, unit.angle + Math.PI / 2).subtract(unitPos);
				unitOffset = new Point(Math.cos(unit.angle) * -15 * S, Math.sin(unit.angle) * 15 * S).add(adjust);
				param.x = unitPos.x + unitOffset.x,
				param.y = unitPos.y + unitOffset.y,
				param.width = 30 * S;
				param.height = 300 * S;
				param.density = 0;
				unit.qbox = sim.addBox(param);
			}
			if (unit.type == "box") {
				param.width = unit.size[0] * S;
				param.height = unit.size[1] * S;
				unit.qbox = sim.addBox(param);
			}
			if (unit.type == "circle") {
				param.radius = unit.radius * S;
				unit.qbox = sim.addCircle(param);
			}
			primitiveOffset[unit.qbox] = unitOffset;
			scene.bodyList.push(unit.qbox);
			if (unit.fix != null) {
				if (fixList["_" + unit.fix] == null) fixList["_" + unit.fix] = [unit.qbox];
				else fixList["_" + unit.fix].push(unit.qbox);
			}
		}
		for (var k:String in fixList) {
			if (k == "_0") {
				for each(var qo:QuickObject in fixList[k]) qo.body.SetMass(new b2MassData());
			} else {
				var o:QuickObject;
				var xy:Point = new Point();
				for each(o in fixList[k]) xy.offset(o.x, o.y);
				var center:Point = new Point(xy.x / fixList[k].length, xy.y / fixList[k].length);
				for each(o in fixList[k]) o.setLoc(o.x - center.x, o.y - center.y);
				var group:GroupObject = sim.addGroup( { objects:fixList[k], x:center.x, y:center.y } ) as GroupObject;
				for each(o in fixList[k]) scene.group[o] = group;
			}
		}
		for each(unit in groups) {
			if (unit.name == "tracked") {
				for each(var id:Number in unit.groups) {
					var obj:QuickObject = getObjectByGroup(id);
					if(obj) scene.trackingList.push(obj);
				}
			}
		}
		for each(unit in joints) {
			var prim0:QuickObject = (!unit.target0)? bg : getObjectByID(unit.target0);
			var prim1:QuickObject = (!unit.target1)? bg : getObjectByID(unit.target1);
			if (!prim0 || !prim1 || (!unit.target0 && !unit.target1) || (prim0.body.IsStatic() && prim1.body.IsStatic())) continue;
			var pos0:Point = new Point(prim0.x, prim0.y).add(Coordinate.rotatePoint(new Point(unit.offset0[0] * S, -unit.offset0[1] * S), prim0.angle)).subtract(primitiveOffset[prim0]);
			var pos1:Point = new Point(prim1.x, prim1.y).add(Coordinate.rotatePoint(new Point(unit.offset1[0] * S, -unit.offset1[1] * S), prim1.angle)).subtract(primitiveOffset[prim1]);
			if (scene.group[prim0]) pos0.offset(scene.group[prim0].x, scene.group[prim0].y);
			if (scene.group[prim1]) pos1.offset(scene.group[prim1].x, scene.group[prim1].y);
			var pos:Point = Point.interpolate(pos0, pos1, 0.5);
			var body0:* = (scene.group[prim0])? scene.group[prim0].body : prim0.body;
			var body1:* = (scene.group[prim1])? scene.group[prim1].body : prim1.body;
			if (unit.type == "spring")
				unit.qbox = sim.addJoint( {
					type: "distance",
					lineAlpha: 1,
					a: body0,
					b: body1,
					x1: pos0.x,
					y1: pos0.y,
					x2: pos1.x,
					y2: pos1.y,
					length: unit.length * S,
					collideConnected: true,
					dampingRatio: unit.damping,
					frequencyHz: unit.strength * 100
				} );
			if (unit.type == "nut"){
				unit.qbox = sim.addJoint( {
					type: "revolute",
					lineAlpha: 0,
					enableMotor: unit.motor,
					maxMotorTorque: unit.motorTorque,
					motorSpeed: unit.motorSpeed * (int(unit.reverse)*2 - 1),
					collideConnected: false,
					a: body0,
					b: body1,
					x1: pos.x,
					y1: pos.y
				});
			}
			scene.jointList.push(unit.qbox);
		}
		return scene;
	}
	private function XMLtoVALUE(data:String):* {
		if (data == "true" || data == "false") return (data == "true");
		if (data.substr(0, 1) == "[" && data.substr( -1) == "]") {
			var values:Array = data.substr(1, data.length - 2).split(",");
			for (var i:int = 0; i < values.length; i++) values[i] = Number(values[i]);
			return values;
		}
		if (isNaN(Number(data))) return String(data);
		return Number(data);
	}
	private function adjustPlanePos(x:Number, y:Number, angle:Number):Point {
		return Line.crossVertical(new Point(x, y), new Point(x + Math.cos(angle) * 100, y - Math.sin(angle) * 100), new Point(0, 0));
	}
	private function getObjectByGroup(groupID:int):QuickObject {
		for each(var unit:Object in primitives) if (groupID == unit.group) return unit.qbox;
		return null;
	}
	private function getObjectByID(id:int):QuickObject {
		for each(var unit:Object in primitives) if (id == unit.id) return unit.qbox;
		return null;
	}
}
/**
 * シーンデータ
 */
class SceneData {
	public var group:Dictionary = new Dictionary();
	public var trackingList:Array = new Array();
	public var bodyList:Array = new Array();
	public var jointList:Array = new Array();
	public function SceneData() {
	}
}
class Line {
	/**
	 * 2点を通る直線とある点からおろした垂線との交点を求める
	 */
	static public function crossVertical(p1:Point, p2:Point, p3:Point):Point {
		var x1:Number = p1.x, y1:Number = p1.y;
		var x2:Number = p2.x, y2:Number = p2.y;
		var x3:Number = p3.x, y3:Number = p3.y;
		var xgap:Number = x1 - x2, ygap:Number = y1 - y2;
		if (ygap == 0) return new Point(p3.x, p1.y);
		var a1:Number = -xgap / ygap;
		var c1:Number = xgap * x3 / ygap + y3;
		var a2:Number = -ygap;
		var b2:Number = xgap;
		var c2:Number = -x1 * a2 + y1 * -b2;
		var z:Number = a1 * b2 + a2;
		return new Point((-c2 - b2 * c1) / z, (a2 * c1 - a1 * c2) / z);
	}	
}
class Coordinate {
	/**
	 * 回転後の座標を取得
	 */
	static public function rotatePoint(p:Point, rad:Number):Point {
		var x:Number = p.x * Math.cos(rad) - p.y * Math.sin(rad);
		var y:Number = p.x * Math.sin(rad) + p.y * Math.cos(rad);
		return new Point(x, y);
	}
}