Forked from: hokori's 距離ジョイントを繋げて離す diff:1 forked from: 距離ジョイントを繋げて離す 距離ジョイントを繋げて離す クリックでジョイントが外れる はずれた玉はクリックで飛び跳ねる taka_milk forked:0favorite:0lines:220license : MIT License modified : 2009-05-14 13:32:06 Embed Tweet // forked from hokori's 距離ジョイントを繋げて離す //距離ジョイントを繋げて離す //クリックでジョイントが外れる //はずれた玉はクリックで飛び跳ねる package { import Box2D.Collision.b2Bound; import Box2D.Dynamics.b2World; import Box2D.Dynamics.b2Body; import Box2D.Dynamics.b2BodyDef import Box2D.Dynamics.Joints.b2Joint; import Box2D.Dynamics.Joints.b2DistanceJoint; import Box2D.Dynamics.Joints.b2DistanceJointDef; import Box2D.Dynamics.Joints.b2JointEdge; import Box2D.Dynamics.Joints.b2RevoluteJointDef; import Box2D.Collision.b2AABB; import Box2D.Collision.Shapes.b2Shape; import Box2D.Collision.Shapes.b2CircleDef; import Box2D.Collision.Shapes.b2PolygonDef; import Box2D.Common.Math.b2Vec2; import flash.events.MouseEvent; import flash.events.Event; import flash.display.Sprite; import flash.display.Graphics; public class Sample05 extends Sprite { private var m_disp_grp:Sprite; private var m_color:int; public function Sample05() { //Box2D初期設定 this.B2Base(); m_disp_grp = new Sprite(); this.addChild(m_disp_grp); m_color = Math.random() * 0x00FFFF; this.createNoren(50, 0, 1, 15); this.createNoren(250, 0, 1, 10); this.createNoren(450, 0, 1, 15); this.createWalls(); this.addEventListener(Event.ENTER_FRAME, update, false, 0, true); this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown, false, 0, true); } //壁と棚作成 private function createWalls():void { //壁作成 this.makeB2BodyBox(500, 10, 250, 0, 0, 0, 0.5, 0.5); this.makeB2BodyBox(500, 10, 250, 500, 0, 0, 0.5, 0.5); this.makeB2BodyBox(10, 500, 0, 250, 0, 0, 0.5, 0.5); this.makeB2BodyBox(10, 500, 500, 250, 0, 0, 0.5, 0.5); //棚作成 var self:Sample05 = this; var make_tana:Function = function(x:int, y:int, w:int, h:int):void { var disp:Sprite = new Sprite(); disp.graphics.beginFill(self.m_color, 0.5); disp.graphics.drawRect( - w / 2, - h / 2, w, h); disp.graphics.endFill(); self.makeB2BodyBox(w, h, x, y, 0, 0 , 0.5, 0.5, disp, self.m_disp_grp); } make_tana(250, 300, 200, 10); make_tana(250, 400, 360, 10); } //距離ジョイントで繋げたものを揺らす private function createNoren(x:int, y:int, set_to:int, num: int):void { var bodies:Array = new Array(); var density:int = 0; for (var i:int = 0; i < num; i++) { var size:int = Math.random() * 10 + 10; var disp:Sprite = new Sprite(); disp.graphics.beginFill(m_color, 1); disp.graphics.drawCircle(0, 0, size); disp.buttonMode = true; disp.addEventListener(MouseEvent.MOUSE_OVER, function(e:MouseEvent):void { e.target.alpha = 0.5; }); disp.addEventListener(MouseEvent.MOUSE_OUT, function(e:MouseEvent):void { e.target.alpha = 1.0; }); var body:b2Body = this.makeB2BodyCircle(size * 2, x, y, density, 0.5, 0.5, disp , m_disp_grp); bodies[i] = body; y += (size + 15) * set_to; density = 1; } //距離ジョイントで繋ぐ for (var j:int = 0; j < num - 1; j++){ var d_joint_def:b2DistanceJointDef = new b2DistanceJointDef(); d_joint_def.collideConnected = true; d_joint_def.Initialize(bodies[j], bodies[j + 1], bodies[j].GetPosition(), bodies[j + 1].GetPosition()); this.m_b2_world.CreateJoint(d_joint_def); } //ちょっと力を加えて動かす bodies[num -1].ApplyForce(new b2Vec2(1000, 0), bodies[num - 1].GetPosition()); } private function onMouseDown(e:MouseEvent):void { var m_x:Number = this.mouseX / this.m_b2_physcale; var m_y:Number = this.mouseY / this.m_b2_physcale; //マウスの下の物体取得 var body:b2Body = this.GetBodyAtMouse(m_x, m_y); if (body is b2Body) { if(body.GetJointList() is b2JointEdge){ //ジョイント繋がってたら、、ジョイントをはずすよ if(body.GetJointList().joint is b2Joint){ this.m_b2_world.DestroyJoint(body.GetJointList().joint); } } else { //ジョイント繋がってなかったら、上に力加える body.ApplyForce(new b2Vec2(0, -5000), body.GetPosition()); } } } //マウスの下の物体取得 //Box2DのTestBedのコピペ private var mousePVec:b2Vec2 = new b2Vec2(); public function GetBodyAtMouse(mouseXWorldPhys:Number, mouseYWorldPhys:Number, includeStatic:Boolean=false):b2Body{ // Make a small box. mousePVec.Set(mouseXWorldPhys, mouseYWorldPhys); var aabb:b2AABB = new b2AABB(); aabb.lowerBound.Set(mouseXWorldPhys - 0.001, mouseYWorldPhys - 0.001); aabb.upperBound.Set(mouseXWorldPhys + 0.001, mouseYWorldPhys + 0.001); // Query the world for overlapping shapes. var k_maxCount:int = 10; var shapes:Array = new Array(); var count:int = m_b2_world.Query(aabb, shapes, k_maxCount); var body:b2Body = null; for (var i:int = 0; i < count; ++i) { if (shapes[i].GetBody().IsStatic() == false || includeStatic) { var tShape:b2Shape = shapes[i] as b2Shape; var inside:Boolean = tShape.TestPoint(tShape.GetBody().GetXForm(), mousePVec); if (inside) { body = tShape.GetBody(); break; } } } return body; } private function update(e:Event):void{ var self:Sample05 = this; this.m_b2_world.Step(this.m_b2_timeStep, this.m_b2_iterations); var disp_gra:Graphics = this.m_disp_grp.graphics; disp_gra.clear(); disp_gra.lineStyle(1, m_color); for (var bb:b2Body = this.m_b2_world.m_bodyList; bb; bb = bb.m_next){ if (bb.m_userData is Sprite){ bb.m_userData.x = bb.GetPosition().x * m_b2_physcale; bb.m_userData.y = bb.GetPosition().y * m_b2_physcale; bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI); } //ジョイントの線 if (bb.m_jointList is b2JointEdge) { for (var joint:b2Joint = bb.m_jointList.joint; joint; joint=joint.m_next){ var anc1:b2Vec2 = joint.GetAnchor1(); var anc2:b2Vec2 = joint.GetAnchor2(); disp_gra.moveTo(anc1.x * this.m_b2_physcale, anc1.y * this.m_b2_physcale); disp_gra.lineTo(anc2.x * this.m_b2_physcale, anc2.y * this.m_b2_physcale); } } } } //----------------------------------------------------------------------------------- //Box2D用まとめ //wonderfl上でクラスを複数置く方法がわからない...。 //----------------------------------------------------------------------------------- protected var m_b2_world:b2World; protected var m_b2_physcale:Number = 10; protected var m_b2_iterations:int = 10; protected var m_b2_timeStep:Number = 24.0; public function B2Base(fps:int = 24, physcale:Number = 10, gravity:Number = 10):void{ this.m_b2_timeStep = 1.0 / fps; this.m_b2_physcale = physcale; this.createB2World(gravity); } private function createB2World(gravity:Number):void { var worldAABB:b2AABB = new b2AABB(); worldAABB.lowerBound.Set(-1000, -1000); worldAABB.upperBound.Set(1000, 1000); var vec_gravity:b2Vec2 = new b2Vec2(0.0, 10.0); var doSleep:Boolean = true; this.m_b2_world = new b2World(worldAABB, vec_gravity, doSleep); } protected function makeB2BodyBox(w:int, h:int, x:Number, y:Number, angle:Number, density:Number, friction:Number, restitution:Number, viewdata:Sprite = null, viewgroup:Sprite = null) :b2Body { var b2_boxdef:b2PolygonDef = this.createB2BoxDef(w, h, density, friction, restitution); var b2_bodydef:b2BodyDef = this.createB2BodyDef(x, y, angle, viewdata, viewgroup); var b2_body:b2Body = this.m_b2_world.CreateBody(b2_bodydef); b2_body.CreateShape(b2_boxdef); b2_body.SetMassFromShapes(); return b2_body; } protected function makeB2BodyCircle(radius:int, x:Number, y:Number, density:Number, friction:Number, restitution:Number, viewdata:Sprite = null, viewgroup:Sprite = null) :b2Body { var b2_boxdef:b2CircleDef = this.createB2CircleDef(radius, density, friction, restitution); var b2_bodydef:b2BodyDef = this.createB2BodyDef(x, y, 0, viewdata, viewgroup); var b2_body:b2Body = this.m_b2_world.CreateBody(b2_bodydef); b2_body.CreateShape(b2_boxdef); b2_body.SetMassFromShapes(); return b2_body; } private function createB2BoxDef(width:int, height:int, density:Number, friction:Number, restitution:Number):b2PolygonDef { var boxdef:b2PolygonDef = new b2PolygonDef(); boxdef.SetAsBox(width / 2 / this.m_b2_physcale, height/ 2 / this.m_b2_physcale); boxdef.density = density; boxdef.friction = friction; boxdef.restitution = restitution; return boxdef; } private function createB2CircleDef(diameter:int, density:Number, friction:Number, restitution:Number):b2CircleDef { var cdef:b2CircleDef = new b2CircleDef(); cdef.radius = diameter / 2 / this.m_b2_physcale; cdef.density = density; cdef.friction = friction; cdef.restitution = restitution; return cdef; } private function createB2BodyDef(x:Number, y:Number, angle:Number, viewdata:Sprite = null, viewgroup:Sprite = null):b2BodyDef { var bodydef:b2BodyDef = new b2BodyDef(); bodydef.position.Set(x / this.m_b2_physcale, y / this.m_b2_physcale); bodydef.angle = (angle / 180) * Math.PI; bodydef.allowSleep = true; if(viewdata != null){ bodydef.userData = viewdata; bodydef.userData.width = viewdata.width; bodydef.userData.height = viewdata.height; if(viewgroup != null){ viewgroup.addChild(bodydef.userData); } } return bodydef; } protected function createB2Vec(x:Number, y:Number):b2Vec2 { var vec:b2Vec2 = new b2Vec2(x / this.m_b2_physcale, y / this.m_b2_physcale); return vec; } } } Code Fullscreen Preview Fullscreen