Dead Code Preservation :: Archived AS3 works from wonderfl.net

[QuickBox2D]ROBOT

よたよた
Get Adobe Flash player
by tencho 30 May 2010
  • Related works: 1
  • Talk

    tencho at 29 May 2010 20:02
    QuickBox2DのmouseDrag()は重たいものは動かせないみたい。中を覗いたら、mouseJointのmaxForceが数値固定だった・・・
    tencho at 30 May 2010 05:44
    重量を軽くして動かせるようにしました。骨折率が酷い。

    Tags

    Embed
/**
 * Copyright tencho ( http://wonderfl.net/user/tencho )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/dBoZ
 */

/**
 * よたよた
 */
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(10);
			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);
	}
}