// Pendulum Clock? // // chaos code // i don't want to read this again later.. package { import Box2D.Collision.b2AABB; import Box2D.Collision.Shapes.b2CircleDef; import Box2D.Collision.Shapes.b2CircleShape; import Box2D.Collision.Shapes.b2PolygonDef; import Box2D.Collision.Shapes.b2PolygonShape; import Box2D.Collision.Shapes.b2Shape; import Box2D.Common.Math.b2Mat22; import Box2D.Common.Math.b2Vec2; import Box2D.Common.Math.b2XForm; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef; import Box2D.Dynamics.b2DebugDraw; import Box2D.Dynamics.b2World; import Box2D.Common.Math.b2Math import Box2D.Dynamics.Joints.b2GearJoint; import Box2D.Dynamics.Joints.b2GearJointDef; import Box2D.Dynamics.Joints.b2RevoluteJoint; import Box2D.Dynamics.Joints.b2RevoluteJointDef; import com.bit101.components.Label; import com.bit101.components.PushButton; import flash.display.JointStyle; import flash.display.Shape; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.text.TextField; import org.papervision3d.lights.PointLight3D; import org.papervision3d.materials.ColorMaterial; import org.papervision3d.materials.shadematerials.FlatShadeMaterial; import org.papervision3d.materials.shadematerials.PhongMaterial; import org.papervision3d.materials.utils.MaterialsList; import org.papervision3d.materials.WireframeMaterial; import org.papervision3d.objects.DisplayObject3D; import org.papervision3d.objects.primitives.Cube; import org.papervision3d.objects.primitives.Cylinder; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.view.BasicView; [SWF(width=465, height=465, frameRate=30, backgroundColor=0x222222)] public class MechanicalClock extends BasicView { public const Depth:Number = 35; public const BasicWheelSize:Number = 0.22; private var button:PushButton; public var m_world:b2World; private var dbgSprite:Sprite; private var physScale:Number = 60.0; private var timeStep:Number = 1 / 30; private var iteration:Number = 8; private var body:b2Body; private var cube:Cube; private var color:ColorMaterial; private var light:PointLight3D = new PointLight3D(); private var shade:PhongMaterial = new PhongMaterial(light, 0xfdfdfd, 0x555555,1); private var flatShade:FlatShadeMaterial = new FlatShadeMaterial(light, 0xfdfdfd,0x555555,1); private var boxArray:Vector.<b2Body> = new Vector.<b2Body>(); private var pvArray:Vector.<DisplayObject3D> = new Vector.<DisplayObject3D>(); private var count:Number = 0; private var cameraDirection:Number = 2; private var cameraMove:Boolean = false; private var pendulum:b2Body; public function MechanicalClock() { super(465,465,true,false,"Target"); addEventListener(Event.ADDED_TO_STAGE, onInit); } private function onInit(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE, onInit); createBox2DWorld(); createPV3DWorld(); button = new PushButton(this, 120, 430, "", onDrawDebugButton); button.setSize(90, 25); var tt:TextField = new TextField(); tt.text = "debug draw"; tt.selectable = false; button.addChild(tt); var cb:PushButton = new PushButton(this, 20, 430, "", onCameraMoveButton); cb.setSize(100, 25); tt = new TextField(); tt.text = "camera move/stop"; tt.selectable = false; cb.addChild(tt); addEventListener(Event.ENTER_FRAME, onEnter); addEventListener(MouseEvent.CLICK, onMouseDown); } private function onCameraMoveButton(e:MouseEvent):void { cameraMove = !cameraMove; } private function onDrawDebugButton(e:MouseEvent):void { if (m_world.m_debugDraw.m_drawFlags == 0x00) { m_world.m_debugDraw.m_drawFlags = 0x0001 | 0x0002; }else { m_world.m_debugDraw.m_drawFlags = 0x0000; } e.stopPropagation(); } private function createBox2DWorld():void { var gravity:b2Vec2 = new b2Vec2(0, 29.8); var b2_world:b2AABB = new b2AABB(); b2_world.lowerBound.Set( -5, -5); b2_world.upperBound.Set(10, 10); m_world = new b2World(b2_world, gravity, true); dbgSprite = new Sprite(); addChild(dbgSprite); setDebugDraw(); createDrumBarrel(); createSecondWheel(); createThirdWheel(); createEscapeWheel(); } private function createDrumBarrel():void { //body = createDoubleGears(0x00, 0x01, 1.7, 1.86, BasicWheelSize , 0.3, 10, 7.5); createGear(0x08, 1.7, 1.76, BasicWheelSize * 7.5, 0.3, 10 * 7.5,false,false,1,true); } private function createSecondWheel():void { createDoubleGears(0x08, 0x02, 1.8, 3.76, BasicWheelSize,0,10,8); } private function createThirdWheel():void { createDoubleGears(0x02, 0x04, 3.89, 3.5, BasicWheelSize, 1, 10, 10,false,true); } private function createEscapeWheel():void { var de:Number = 3; var categ1:uint = 0x04; var categ2:uint = 0x01; var xx:Number = 3.9; var yy:Number = 0.94; var rad:Number = BasicWheelSize; var offset:Number = 33; var num:int = 10; createAnchor(xx, 0.27); var j1:Array = createGear(categ1, xx, yy, rad, offset, num,true,false,de); var j2:Array = createGear(categ2, xx, yy, rad * 2, offset, num-7,false,true); var g:b2GearJointDef = new b2GearJointDef(); g.body1 = j1[0]; g.body2 = j2[0]; g.joint1 = j1[1]; g.joint2 = j2[1]; g.ratio = -1; m_world.CreateJoint(g); } private function createDoubleGears(categ1:uint,categ2:uint, _x:Number, _y:Number, _rad:Number,_offset:Number, num:int, scale:int, motor:Boolean = false, hands:Boolean = false):b2Body { var j1:Array = createGear(categ1, _x, _y, _rad, _offset, num); var j2:Array = createGear(categ2, _x, _y, _rad * scale, _offset, num*scale,motor,false,1,hands); var g:b2GearJointDef = new b2GearJointDef(); g.body1 = j1[0]; g.body2 = j2[0]; g.joint1 = j1[1]; g.joint2 = j2[1]; g.ratio = -1; m_world.CreateJoint(g); /* var h:Array = createHands(0x00, _x, _y); var g2:b2GearJointDef = new b2GearJointDef(); g2.body1 = j1[0]; g2.body2 = h[0]; g2.joint1 = j1[1]; g2.joint2 = h[1]; g2.ratio = -1; m_world.CreateJoint(g2); */ return g.body1; } private function createPV3DWorld():void { camera.z = -440; camera.y = -222; camera.x = 300; var tar:DisplayObject3D = new DisplayObject3D(); tar.y = -200; tar.x = 210; tar.z = 50; camera.target = tar; //BetweenAS3.tween(camera, { x:500, y: 0, z: -400 }, {x:500,y:-500,z:-450}, 3, Linear.easeInOut).play(); light.x = 100; light.y = 200; light.z = -300; } private function setDebugDraw():void { var dbgDraw:b2DebugDraw = new b2DebugDraw(); dbgDraw.m_sprite = dbgSprite; dbgSprite.x = dbgSprite.y = 50; dbgDraw.m_drawScale = physScale; dbgDraw.m_fillAlpha = 0.6; dbgDraw.m_lineThickness = 2; dbgDraw.m_drawFlags = 0x0000; m_world.SetDebugDraw(dbgDraw); } private function onEnter(e:Event):void { if (cameraMove) { camera.moveLeft(11); camera.moveDown(cameraDirection); if (camera.y > 220 || camera.y < -330) { cameraDirection *= -1; camera.moveDown(cameraDirection*2); } } light.copyPosition(camera); count += 1; m_world.Step(timeStep, iteration); for each(var body:b2Body in boxArray) { var xf:b2XForm = body.m_xf; for (var s:b2Shape = body.GetShapeList(); s; s = s.m_next) { var bits:uint = s.GetFilterData().categoryBits; if (bits == 0x02) { if (count % 2 == 0) { drawShape(s, xf); } }else if (bits == 0x01) { if (s.GetUserData().escape == 0) { if (count % 15 == 0) { drawShape(s, xf); } }else { drawShape(s, xf); } }else { drawShape(s, xf); } } } singleRender(); } private function drawShape(s:b2Shape, xf:b2XForm):void { var center:b2Vec2; var angle:Number = 0; var disp:DisplayObject3D; if (s is b2PolygonShape) { var ss:b2PolygonShape = s as b2PolygonShape; center = b2Math.b2MulX(xf, ss.GetCentroid()); if (ss.GetUserData().rev != false) { angle = Math.atan2( center.x - xf.position.x, center.y - xf.position.y) + Math.PI*0.5 ; }else { angle = Math.atan2( center.x - xf.position.x, center.y - xf.position.y) ; } var ee:Number = ss.GetUserData().escape; if(ee != -2) angle -= ss.GetUserData().escape; disp = ss.GetUserData().obj; }else if (s is b2CircleShape) { var sss:b2CircleShape = s as b2CircleShape; center = b2Math.b2MulX(xf, sss.GetLocalPosition()); if (sss.GetUserData().rev != null) { angle = -(sss.GetUserData().rev as b2RevoluteJoint).GetJointAngle(); }else { angle = -sss.GetBody().GetAngle(); } disp = sss.GetUserData().obj; } disp.x = center.x*physScale; disp.y = -center.y * physScale; disp.rotationZ = angle*180/Math.PI; } private function onMouseDown(e:MouseEvent):void { pendulum.ApplyImpulse(new b2Vec2( -6, 0), new b2Vec2(0, 6) ); } private function createAnchor(xx:Number, yy:Number):void { const hei:Number = 0.14; const boxWid:Number = 0.05; const boxHand:Number = 0.41; var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.position.Set(xx,yy); var boxDef1:b2PolygonDef = new b2PolygonDef(); boxDef1.SetAsOrientedBox(boxWid,hei,new b2Vec2(-boxHand,hei-0.1), -0.6); boxDef1.density = 0; boxDef1.friction = 0; boxDef1.restitution = 0; var boxDef2:b2PolygonDef = new b2PolygonDef(); boxDef2.SetAsOrientedBox(boxWid,hei,new b2Vec2(boxHand,hei-0.1),0.6); boxDef2.density = 0; boxDef2.friction = 0; boxDef2.restitution = 0; var boxDef3:b2PolygonDef = new b2PolygonDef(); boxDef3.SetAsOrientedBox(boxHand*1.5,boxWid,new b2Vec2(0,-0.1)); boxDef3.density = 0; boxDef3.friction = 1; boxDef3.restitution = 0; var boxDef4:b2PolygonDef = new b2PolygonDef(); boxDef4.SetAsOrientedBox(boxWid/2,2,new b2Vec2(0,1.3)); boxDef4.density = 0.001; boxDef4.friction = 0; boxDef4.restitution = 0; var circle:b2CircleDef = new b2CircleDef(); circle.radius = 0.3; circle.density = 11; circle.friction = 1; circle.restitution = 1; circle.localPosition = new b2Vec2(0,2.2); circle.filter.categoryBits = 0x10; boxDef4.filter.categoryBits = 0x10; var body:b2Body = m_world.CreateBody(bodyDef); var ss1:b2PolygonShape = body.CreateShape(boxDef1) as b2PolygonShape; var ss2:b2PolygonShape = body.CreateShape(boxDef2) as b2PolygonShape; var ss3:b2PolygonShape = body.CreateShape(boxDef3) as b2PolygonShape; var cir:b2CircleShape = body.CreateShape(circle) as b2CircleShape; var string:b2PolygonShape = body.CreateShape(boxDef4) as b2PolygonShape; var pivot:b2CircleDef = new b2CircleDef(); pivot.radius = 0.02; pivot.density = 0; pivot.friction = 0.3; pivot.restitution = 0.2; pivot.filter.categoryBits = 0x00; boxDef1.filter.categoryBits = boxDef2.filter.categoryBits = boxDef3.filter.categoryBits = pivot.filter.categoryBits = 0x01; boxDef1.filter.maskBits = boxDef2.filter.maskBits = boxDef3.filter.maskBits = pivot.filter.maskBits = 0x01; body.SetMassFromShapes(); body.ApplyImpulse(new b2Vec2(-9, 0), new b2Vec2(0,4) ); pendulum = body var bodyDef2:b2BodyDef = new b2BodyDef(); bodyDef2.position.Set(xx,yy); var joint:b2Body = m_world.GetGroundBody(); var revoluteJoint:b2RevoluteJointDef = new b2RevoluteJointDef(); revoluteJoint.Initialize(joint,body, new b2Vec2(xx, yy-0.1) ); var rev:b2RevoluteJoint = m_world.CreateJoint(revoluteJoint) as b2RevoluteJoint; addPVBox(0x10, ss1, boxWid*physScale, hei*physScale,true,-2); addPVBox(0x10, ss2, boxWid*physScale, hei*physScale,true, -2); addPVBox(0x10, ss3, boxWid * physScale, boxHand * 1.5 * physScale, true, -3); addPVBox(0x20, string,1.3*physScale, boxWid/2 * physScale,true,-1); addPVSphere(0x20, cir, 0.5 * physScale,rev); boxArray.push(body); } private function createHands(category:uint, xx:Number, yy:Number):Array { const w:Number = 0.05; const h:Number = 1; var boxDef:b2PolygonDef = new b2PolygonDef(); boxDef.SetAsOrientedBox(w,h,new b2Vec2(0,h)); boxDef.density = 0.001; boxDef.friction = 0; boxDef.restitution = 0; boxDef.filter.categoryBits = category; var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.position.Set(xx, yy); var body:b2Body = m_world.CreateBody(bodyDef); var ss:b2PolygonShape = body.CreateShape(boxDef) as b2PolygonShape; body.SetMassFromShapes(); boxArray.push(body); addPVHand(0x00,ss, w*physScale, h*physScale); var bodyDef2:b2BodyDef = new b2BodyDef(); bodyDef2.position.Set(xx, yy); var joint:b2Body = m_world.CreateBody(bodyDef2); var pivot:b2CircleDef = new b2CircleDef(); pivot.radius = 0.1; pivot.density = 0; pivot.friction = 0; pivot.restitution = 0; pivot.filter.categoryBits = 0x00; var c:b2CircleShape = joint.CreateShape(pivot) as b2CircleShape; boxArray.push(joint); var revoluteJoint:b2RevoluteJointDef = new b2RevoluteJointDef(); revoluteJoint.Initialize(joint,body, new b2Vec2(xx, yy) ); var rev:b2RevoluteJoint = m_world.CreateJoint(revoluteJoint) as b2RevoluteJoint; addPVCircle(0x00, c, 0.05 * physScale,rev,-2); return new Array(body, rev); } private function addPVHand(category:uint, base:b2PolygonShape, wid:Number, hei:Number):void { var obj:Cube = new Cube(new MaterialsList( { all:shade } ), wid * 2, Depth / 6 , hei * 2, 1, 1, 1); scene.addChild(obj); pvArray.push(obj); base.m_userData = { obj:obj, rev:false , escape:0 }; obj.z = -37; } private function AddBox(_x:Number, _y:Number, _halfwidth:Number, _halfheight:Number):b2Body { var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.position.Set(_x,_y); var boxDef:b2PolygonDef = new b2PolygonDef(); boxDef.SetAsBox(_halfwidth,_halfheight); boxDef.density = 1.0; boxDef.friction = 0.3; boxDef.restitution = 0.2; var body:b2Body = m_world.CreateBody(bodyDef); var ss:b2PolygonShape = body.CreateShape(boxDef) as b2PolygonShape; body.SetMassFromShapes(); boxArray.push(body); addPVBox(0x00,ss, _halfwidth*physScale, _halfheight*physScale); return body; } private function addPVBox(category:uint, base:b2PolygonShape, wid:Number, hei:Number, rev:Boolean = false, escape:Number = 0, dep:Number = 1):void { var obj:Cube = new Cube(new MaterialsList( { all:shade } ), wid * 2, Depth * dep, hei * 2, 1, 1, 1); if (escape == -1) { //string obj = new Cube(new MaterialsList( { all:flatShade } ), wid * 2, Depth * dep / 10, hei * 2, 1, 1, 1); escape = 0; }else if (escape < -1) { obj = new Cube(new MaterialsList( { all:shade } ), wid * 2, Depth * dep *1.8, hei * 2, 1, 1, 1); escape = -2; } scene.addChild(obj); pvArray.push(obj); switch(category) { case 0x01: obj.z = 0; break; case 0x02: obj.z = Depth; break; case 0x04: obj.z = Depth * 2; break; case 0x08: obj.z = 0; break; case 0x10: obj.z = -Depth*0.7; break; case 0x20: obj.z = -Depth * 1.3; break; } base.m_userData = { obj:obj, rev:rev , escape:escape}; if (dep != 1) { obj.z -= dep * Depth/3; } } private function AddCircle(_x:Number, _y:Number, _radius:Number):b2Body { var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.position.Set(_x,_y); var cirDef:b2CircleDef = new b2CircleDef(); cirDef.radius = _radius; cirDef.density = 1.0; cirDef.friction = 0.3; cirDef.restitution = 0.2; cirDef.filter.categoryBits = 0x04; var body:b2Body = m_world.CreateBody(bodyDef); var ss:b2CircleShape = body.CreateShape(cirDef) as b2CircleShape; body.SetMassFromShapes(); boxArray.push(body); addPVCircle(0x01, ss, _radius * physScale); return body; } private function addPVCircle(category:uint, base:b2CircleShape, rad:Number, rev:b2RevoluteJoint = null, dep:Number = 1):void { var obj:Cylinder = new Cylinder(shade, rad, Depth*dep, 15, 2); obj.rotationX = 90; switch(category) { case 0x01: obj.z = 0; break; case 0x02: obj.z = Depth; break; case 0x04: obj.z = Depth * 2; break; case 0x08: obj.z = 0; break; case 0x10: obj.z = -Depth; break; case 0x20: obj.z = -Depth * 1.3; break; } if (dep != 1) { obj.z -= dep * Depth/3; } if (dep == -2) { // axis obj.z -= Depth*0.7; } scene.addChild(obj); pvArray.push(obj); base.m_userData = { obj:obj, rev:rev }; } private function addPVSphere(category:uint, base:b2CircleShape, rad:Number, rev:b2RevoluteJoint = null, dep:Number = 1):void { var obj:Sphere = new Sphere(flatShade, rad,4,3); switch(category) { case 0x01: obj.z = 0; break; case 0x02: obj.z = Depth; break; case 0x04: obj.z = Depth * 2; break; case 0x08: obj.z = 0; break; case 0x10: obj.z = -Depth * 0.7; break; case 0x20: obj.z = -Depth * 1.3; break; } if (dep != 1) { obj.z -= dep * Depth/3; } scene.addChild(obj); pvArray.push(obj); base.m_userData = { obj:obj, rev:rev }; } private function addStaticBox(_x:Number, _y:Number, _halfWidth:Number, _halfHeight:Number, rot:Number=0):b2Body { var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.position.Set(_x, _y); var boxDef:b2PolygonDef = new b2PolygonDef(); boxDef.SetAsOrientedBox(_halfWidth, _halfHeight);// , null, rot); boxDef.density = 0; var body:b2Body = m_world.CreateBody(bodyDef); var ss:b2PolygonShape = body.CreateShape(boxDef) as b2PolygonShape; body.SetMassFromShapes(); boxArray.push(body); addPVBox(0x01, ss, _halfWidth*physScale, _halfHeight*physScale); return body; } private function createGear(categ:uint, _x:Number, _y:Number, _rad:Number,_offset:Number, num:int, motor:Boolean = false, escape:Boolean = false, dep:Number = 1, hands:Boolean = false):Array { var revoluteJoint:b2RevoluteJointDef= new b2RevoluteJointDef(); var pivot:b2CircleDef = new b2CircleDef(); pivot.radius = _rad; pivot.density = 0; pivot.friction = 0.01; pivot.restitution = 0.01; pivot.filter.categoryBits = categ; pivot.filter.maskBits = categ; /* var bodyDef3:b2BodyDef = new b2BodyDef(); bodyDef3.position.Set(_x, _y); var joint:b2Body = m_world.CreateBody(bodyDef2); var jj:b2CircleShape = joint.CreateShape(pivot) as b2CircleShape; joint.SetMassFromShapes(); var pivot:b2CircleDef = new b2CircleDef(); pivot.radius = _rad; pivot.density = 0; pivot.friction = 0.01; pivot.restitution = 0.01; pivot.filter.categoryBits = categ; pivot.filter.maskBits = categ; */ var bodyDef2:b2BodyDef = new b2BodyDef(); bodyDef2.position.Set(_x, _y); var joint:b2Body = m_world.CreateBody(bodyDef2); var jj:b2CircleShape = joint.CreateShape(pivot) as b2CircleShape; joint.SetMassFromShapes(); var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.position.Set(_x, _y); var body:b2Body = m_world.CreateBody(bodyDef); var gearWid:Number = 0.093; var gearHei:Number = 0.04; var angle:Number; var i:int; var xx:Number, yy:Number; var boxDef:b2PolygonDef; var ss:b2PolygonShape; if (escape == false) { for (i = 0; i < num; i++) { angle = i * (360 / num) * Math.PI / 180; angle += _offset * Math.PI / 180; xx = _rad * Math.cos(angle); yy = _rad * Math.sin(angle); boxDef = new b2PolygonDef(); //boxDef.SetAsOrientedBox(gearWid, gearHei, new b2Vec2(xx, yy), angle); var xfPosition:b2Vec2 = new b2Vec2(xx,yy); var xfR:b2Mat22 = new b2Mat22(); xfR.Set(angle); var center:b2Vec2 = new b2Vec2(xx, yy); var hx:Number = gearWid; var hy:Number = gearHei; /* boxDef.vertexCount = 4; boxDef.vertices[0].Set(0, -hy*1.2); boxDef.vertices[1].Set( hx, -hy/6); boxDef.vertices[2].Set( hx, hy/6); boxDef.vertices[3].Set(0, hy*1.2); for (var j:int = 0; j < 4; ++j) { center = boxDef.vertices[j]; hx = xfPosition.x + (xfR.col1.x * center.x + xfR.col2.x * center.y) center.y = xfPosition.y + (xfR.col1.y * center.x + xfR.col2.y * center.y) center.x = hx; } */ boxDef.vertexCount = 3; boxDef.vertices[0].Set(0, -hy*1.6); boxDef.vertices[1].Set( hx, 0); boxDef.vertices[2].Set( 0, hy*1.6); for (var j:int = 0; j < 3; ++j) { center = boxDef.vertices[j]; hx = xfPosition.x + (xfR.col1.x * center.x + xfR.col2.x * center.y) center.y = xfPosition.y + (xfR.col1.y * center.x + xfR.col2.y * center.y) center.x = hx; } boxDef.density = 0.01; boxDef.friction = 0; boxDef.restitution = 0; boxDef.filter.categoryBits = categ; boxDef.filter.maskBits = categ; ss = body.CreateShape(boxDef) as b2PolygonShape; addPVBox(categ,ss, gearWid*physScale, gearHei*physScale, true,0,dep); } }else { for (i = 0; i < num; i++) { var escapeAngle:Number = -0.5; angle = i * (360 / num) * Math.PI / 180; angle += _offset * Math.PI / 180; xx = _rad * Math.cos(angle); yy = _rad * Math.sin(angle); boxDef = new b2PolygonDef(); boxDef.SetAsOrientedBox(gearWid*1.7, gearHei, new b2Vec2(xx, yy),angle + escapeAngle); boxDef.density = 0.01; boxDef.friction = 0; boxDef.restitution = 0; boxDef.filter.categoryBits = categ; boxDef.filter.maskBits = categ; ss = body.CreateShape(boxDef) as b2PolygonShape; addPVBox(categ,ss, gearWid*1.7*physScale, gearHei/2*physScale, true, escapeAngle, dep); } } body.SetMassFromShapes(); boxArray.push(body); revoluteJoint.Initialize(joint, body, joint.GetPosition()); revoluteJoint.enableMotor = motor; revoluteJoint.motorSpeed = -2.5; revoluteJoint.maxMotorTorque = 0.007; var rev:b2RevoluteJoint= m_world.CreateJoint(revoluteJoint) as b2RevoluteJoint; addPVCircle(categ, jj, _rad * physScale,rev,dep); boxArray.push(joint); if (hands) { var h:Array = createHands(0x00, _x, _y); var g2:b2GearJointDef = new b2GearJointDef(); g2.body1 = joint; g2.body2 = h[0]; g2.joint1 = rev; g2.joint2 = h[1]; g2.ratio = -1; m_world.CreateJoint(g2); } return new Array(joint, rev); } } } [Box2D]Pendulum Clock (振り子時計のような何か)