// forked from paq's [Box2D]ダンボー遊び!forked from :(略)ダンボーを作った // forked from rsakane's Box2Dジョイントの練習でダンボーを作った(何故か左にスライド) /* * 根本的に書き直した。(あまり意味はない) * ドラッグで動かせるようにした。 * ダンボーを増やした。 * 何となく手をブラブラ(体から取れそう) * * 倒れても、自動で立ち上がるようになっています。(なんかカワイイ) * たまに倒れたままの事がある。 * * ダンボー同士がぶつかり合うとケンカになります。注意を。 * ケンカをするとまれに足が骨折します。(足をつかむと完治します。) * * ボール遊びが好きなようで、ボールを与えると投げて遊びます。 * * * 左にスライドする現象はとりあえずOKかな。 * */ package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import Box2D.Dynamics.*; import Box2D.Collision.*; import Box2D.Collision.Shapes.*; import Box2D.Dynamics.Joints.*; import Box2D.Dynamics.Contacts.*; import Box2D.Common.*; import Box2D.Common.Math.*; [SWF(backgroundColor="0x000000", frameRate=60)] public class Main extends Sprite { public var m_sprite:Sprite; public var m_world:b2World; public var m_physScale:Number = 30.0; public var m_iterations:int = 10; public var m_timeStep:Number = 1.0/60.0; public var m_mouseJoint:b2MouseJoint; static public var mouseXWorldPhys:Number; static public var mouseYWorldPhys:Number; static public var mouseXWorld:Number; static public var mouseYWorld:Number; private var mousePVec:b2Vec2 = new b2Vec2(); private var mouseDown:Boolean = false; public function Main():void { //コンテナ m_sprite = new Sprite(); addChild(m_sprite); stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); stage.addEventListener(MouseEvent.CLICK, onMouseUp); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave); addEventListener(Event.ENTER_FRAME, update, false, 0, true); //WORLD var worldAABB:b2AABB = new b2AABB(); worldAABB.lowerBound.Set(-1000.0, -1000.0); worldAABB.upperBound.Set(1000.0, 1000.0); var gravity:b2Vec2 = new b2Vec2(0.0, 10.0); var doSleep:Boolean = true; m_world = new b2World(worldAABB, gravity, doSleep); //デバック用 var dbgDraw:b2DebugDraw= new b2DebugDraw(); var dbgSprite:Sprite= new Sprite(); m_sprite.addChild(dbgSprite); dbgDraw.m_sprite= dbgSprite; dbgDraw.m_drawScale= 30.0; dbgDraw.m_fillAlpha = 0.3; dbgDraw.m_lineThickness= 1.0; dbgDraw.m_alpha=1.0; dbgDraw.m_xformScale=1.0; dbgDraw.m_drawFlags = b2DebugDraw.e_shapeBit; m_world.SetDebugDraw(dbgDraw); createDunbor(232/m_physScale, 1.1); createDunbor(232/m_physScale, 3.5); createDunbor(232/m_physScale, 5.1); createOtherObject(); createWall(); } private function createOtherObject():void { var circ:b2CircleDef = new b2CircleDef(); var bd:b2BodyDef = new b2BodyDef(); var body:b2Body; circ.radius = 10 / m_physScale; circ.density = 1.0; circ.friction = 0.0; circ.restitution = 0.0; bd = new b2BodyDef(); bd.position.Set(50 / m_physScale, 100 / m_physScale); var circbd:b2Body = m_world.CreateBody(bd); circbd.CreateShape(circ); circbd.SetMassFromShapes(); } private function createDunbor(x:Number,y:Number):void { // 頭 var bodyDef1:b2BodyDef = new b2BodyDef(); bodyDef1.position.Set(x, y); bodyDef1.userData = new Head(); addChild(bodyDef1.userData); var polygonDef1:b2PolygonDef = new b2PolygonDef(); polygonDef1.SetAsBox(0.8, 0.5); polygonDef1.density = 0.2; polygonDef1.friction = 0.4; polygonDef1.restitution = 2; var body1:b2Body = m_world.CreateBody(bodyDef1); body1.CreateShape(polygonDef1); body1.SetMassFromShapes(); // 体 var bodyDef2:b2BodyDef = new b2BodyDef(); bodyDef2.position.Set(x, y+1.1); bodyDef2.userData = new Body(); addChild(bodyDef2.userData); var polygonDef2:b2PolygonDef = new b2PolygonDef(); polygonDef2.SetAsBox(0.5, 0.6); polygonDef2.density = 1; polygonDef2.friction = 0.4; polygonDef2.restitution = 5; var body2:b2Body = m_world.CreateBody(bodyDef2); body2.CreateShape(polygonDef2); body2.SetMassFromShapes(); // 左足 var bodyDef3:b2BodyDef = new b2BodyDef(); bodyDef3.position.Set(x-0.3, y+2.1); var polygonDef3:b2PolygonDef = new b2PolygonDef(); polygonDef3.SetAsBox(0.2, 0.4); polygonDef3.density = 10; polygonDef3.friction = 0.4; polygonDef3.restitution = 0.3; var body3:b2Body = m_world.CreateBody(bodyDef3); body3.CreateShape(polygonDef3); body3.SetMassFromShapes(); // 右足 var bodyDef4:b2BodyDef = new b2BodyDef(); bodyDef4.position.Set(x+0.3, y+2.1); var polygonDef4:b2PolygonDef = new b2PolygonDef(); polygonDef4.SetAsBox(0.2, 0.4); polygonDef4.density = 10; polygonDef4.friction = 0.4; polygonDef4.restitution = 0.3; var body4:b2Body = m_world.CreateBody(bodyDef4); body4.CreateShape(polygonDef4); body4.SetMassFromShapes(); // 左手 var bodyDef5:b2BodyDef = new b2BodyDef(); bodyDef5.position.Set(x-0.8, y+0.9); bodyDef5.angle = 30 * Math.PI / 180; var polygonDef5:b2PolygonDef = new b2PolygonDef(); polygonDef5.SetAsBox(0.2, 0.4); polygonDef5.density = 1; polygonDef5.friction = 0.4; polygonDef5.restitution = 0.3; var body5:b2Body = m_world.CreateBody(bodyDef5); body5.CreateShape(polygonDef5); body5.SetMassFromShapes(); // 右手 var bodyDef6:b2BodyDef = new b2BodyDef(); bodyDef6.position.Set(x+0.8, y+0.9); bodyDef6.angle = 330 * Math.PI / 180; var polygonDef6:b2PolygonDef = new b2PolygonDef(); polygonDef6.SetAsBox(0.2, 0.4); polygonDef6.density = 1; polygonDef6.friction = 0.4; polygonDef6.restitution = 0.3; var body6:b2Body = m_world.CreateBody(bodyDef6); body6.CreateShape(polygonDef5); body6.SetMassFromShapes(); // 頭と体をジョイント var distance1:b2DistanceJointDef = new b2DistanceJointDef(); distance1.Initialize(body1, body2, new b2Vec2(x-0.4, y+0.5), new b2Vec2(x-0.4, y+0.51)); m_world.CreateJoint(distance1); var distance2:b2DistanceJointDef = new b2DistanceJointDef(); distance2.Initialize(body1, body2, new b2Vec2(x+0.4, y+0.5), new b2Vec2(x+0.4, y+0.51)); m_world.CreateJoint(distance2); // 体と左足をジョイント distance1.Initialize(body2, body3, new b2Vec2(x-0.5, y+1.7), new b2Vec2(x-0.5, y+1.71)); m_world.CreateJoint(distance1); distance2.Initialize(body2, body3, new b2Vec2(x-0.1, y+1.7), new b2Vec2(x-0.1, y+1.71)); m_world.CreateJoint(distance2); // 体と右足をジョイント distance1.Initialize(body2, body4, new b2Vec2(x+0.1, y+1.7), new b2Vec2(x+0.1, y+1.71)); m_world.CreateJoint(distance1); distance2.Initialize(body2, body4, new b2Vec2(x+0.5, y+1.7), new b2Vec2(x+0.5, y+1.71)); m_world.CreateJoint(distance2); // 体と左手をジョイント distance1.Initialize(body2, body5, new b2Vec2(x-0.51, y+0.5), new b2Vec2(x-0.51, y+0.51)); m_world.CreateJoint(distance1); //distance2.Initialize(body2, body5, new b2Vec2(x-0.7, y+0.5), body5.GetWorldCenter()); //m_world.CreateJoint(distance2); // 体と右手をジョイント distance1.Initialize(body2, body6, new b2Vec2(x+0.5, y+0.5), new b2Vec2(x+0.51, y+0.51)); m_world.CreateJoint(distance1); //distance2.Initialize(body1, body6, new b2Vec2(x+0.8, y+0.5), body6.GetWorldCenter()); //m_world.CreateJoint(distance2); } private function createWall():void { var wallObject:b2PolygonDef = new b2PolygonDef(); wallObject.density = 0.0; var wallDef:b2BodyDef = new b2BodyDef(); var wallBody:b2Body; //Left wallDef.position.Set(-6 / m_physScale, 465/2 / m_physScale); wallObject.SetAsBox(10/2 / m_physScale, 465/2 / m_physScale); wallBody = m_world.CreateBody(wallDef); wallBody.CreateShape(wallObject); wallBody.SetMassFromShapes(); //Right wallDef.position.Set((465+14/2) / m_physScale, 465/2 / m_physScale); wallObject.SetAsBox(10/2 / m_physScale, 465/2 / m_physScale); wallBody = m_world.CreateBody(wallDef); wallBody.CreateShape(wallObject); wallBody.SetMassFromShapes(); //Top wallDef.position.Set(465/2 / m_physScale, -7 / m_physScale); wallObject.SetAsBox(465/2 / m_physScale, 10/2 / m_physScale); wallBody = m_world.CreateBody(wallDef); wallBody.CreateShape(wallObject); wallBody.SetMassFromShapes(); //Bottom wallDef.position.Set(465/2 / m_physScale, (465-10/2) / m_physScale); wallObject.SetAsBox(465/2 / m_physScale, 10/2 / m_physScale); wallBody = m_world.CreateBody(wallDef); wallBody.CreateShape(wallObject); wallBody.SetMassFromShapes(); } private function update(event:Event):void { m_world.Step(m_timeStep, m_iterations); m_sprite.graphics.clear(); UpdateMouseWorld(); MouseDrag(); for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next) { if (bb.m_userData is Sprite) { bb.m_userData.x = bb.GetPosition().x * 30; bb.m_userData.y = bb.GetPosition().y * 30; bb.m_userData.rotation = bb.GetAngle() * 180 / Math.PI; } } // joints for (var jj:b2Joint = m_world.m_jointList; jj; jj = jj.m_next){ DrawJoint(jj); } } private function onMouseDown(event:MouseEvent):void { mouseDown = true; } private function onMouseUp(event:MouseEvent):void { mouseDown = false; } private function onMouseMove(event:MouseEvent):void { if (mouseDown != event.buttonDown){ mouseDown = event.buttonDown; } } public function onMouseLeave(e:Event):void { mouseDown = false; MouseDrag(); } //====================== // Update mouseWorld //====================== public function UpdateMouseWorld():void { mouseXWorldPhys = (mouseX)/m_physScale; mouseYWorldPhys = (mouseY)/m_physScale; mouseXWorld = (mouseX); mouseYWorld = (mouseY); } //====================== // Mouse Drag //====================== public function MouseDrag():void { // mouse press if (mouseDown && !m_mouseJoint){ var body:b2Body = GetBodyAtMouse(); if (body) { var md:b2MouseJointDef = new b2MouseJointDef(); md.body1 = m_world.GetGroundBody(); md.body2 = body; md.target.Set(mouseXWorldPhys, mouseYWorldPhys); md.maxForce = 300.0 * body.GetMass(); md.timeStep = m_timeStep; m_mouseJoint = m_world.CreateJoint(md) as b2MouseJoint; body.WakeUp(); } } // mouse release if (!mouseDown){ if (m_mouseJoint) { m_world.DestroyJoint(m_mouseJoint); m_mouseJoint = null; } } // mouse move if (m_mouseJoint) { var p2:b2Vec2 = new b2Vec2(mouseXWorldPhys, mouseYWorldPhys); m_mouseJoint.SetTarget(p2); } } //====================== // GetBodyAtMouse //====================== public function GetBodyAtMouse(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_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; } //====================== // Draw Joint //====================== public function DrawJoint(joint:b2Joint):void { var b1:b2Body = joint.m_body1; var b2:b2Body = joint.m_body2; var x1:b2Vec2 = b1.m_linearVelocity; var x2:b2Vec2 = b2.m_linearVelocity; var p1:b2Vec2 = joint.GetAnchor1(); var p2:b2Vec2 = joint.GetAnchor2(); m_sprite.graphics.lineStyle(1,0x44aaff,1/1); switch (joint.m_type) { case b2Joint.e_distanceJoint: case b2Joint.e_mouseJoint: m_sprite.graphics.moveTo(p1.x * m_physScale, p1.y * m_physScale); m_sprite.graphics.lineTo(p2.x * m_physScale, p2.y * m_physScale); break; case b2Joint.e_pulleyJoint: var pulley:b2PulleyJoint = joint as b2PulleyJoint; var s1:b2Vec2 = pulley.m_groundAnchor1; var s2:b2Vec2 = pulley.m_groundAnchor2; m_sprite.graphics.moveTo(s1.x * m_physScale, s1.y * m_physScale); m_sprite.graphics.lineTo(p1.x * m_physScale, p1.y * m_physScale); m_sprite.graphics.moveTo(s2.x * m_physScale, s2.y * m_physScale); m_sprite.graphics.lineTo(p2.x * m_physScale, p2.y * m_physScale); break; default: if (b1 == m_world.m_groundBody){ m_sprite.graphics.moveTo(p1.x * m_physScale, p1.y * m_physScale); m_sprite.graphics.lineTo(x2.x * m_physScale, x2.y * m_physScale); } else if (b2 == m_world.m_groundBody){ m_sprite.graphics.moveTo(p1.x * m_physScale, p1.y * m_physScale); m_sprite.graphics.lineTo(x1.x * m_physScale, x1.y * m_physScale); } else{ m_sprite.graphics.moveTo(x1.x * m_physScale, x1.y * m_physScale); m_sprite.graphics.lineTo(p1.x * m_physScale, p1.y * m_physScale); m_sprite.graphics.lineTo(x2.x * m_physScale, x2.y * m_physScale); m_sprite.graphics.lineTo(p2.x * m_physScale, p2.y * m_physScale); } } } } } import flash.display.Sprite; class Head extends Sprite { public function Head() { graphics.beginFill(0x00000); graphics.drawCircle(-30, -15, 10); graphics.drawCircle(30, -15, 10); graphics.moveTo(0, 5); graphics.lineTo(-15, 23); graphics.lineTo(15, 23); graphics.lineTo(0, 5); graphics.endFill(); scaleX = scaleY = 0.333; } } class Body extends Sprite { public function Body() { graphics.beginFill(0x777777); graphics.drawCircle(30, -45, 8); graphics.endFill(); graphics.beginFill(0x000000); graphics.drawRect(26, -45, 8, 2); graphics.endFill(); scaleX = scaleY = 0.333; } } forked from: [Box2D]ダンボー遊び!forked from :(略)ダンボーを作った