// forked from pboy2000's forked from: [Box2D]ダンボー遊び!forked from :(略)ダンボーを作った // 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="0x5060c0", 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; private var ball:b2Body; 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); ball = createOtherObject(); createWall(); } private function createOtherObject():b2Body { var circ:b2CircleDef = new b2CircleDef(); var bd:b2BodyDef = new b2BodyDef(); var body:b2Body; circ.radius = 35 / m_physScale; circ.density = 0.125; circ.friction = 0.7; circ.restitution = 0.5; bd = new b2BodyDef(); bd.position.Set(50 / m_physScale, 100 / m_physScale); var circbd:b2Body = m_world.CreateBody(bd); circbd.CreateShape(circ); circbd.SetMassFromShapes(); return circbd; } private function createBox(userData:Sprite, x:Number, y:Number, angle:Number, width:Number, height:Number, density:Number, friction:Number, restitution:Number):b2Body { var bodyDef:b2BodyDef = new b2BodyDef(); bodyDef.position.Set(x, y); bodyDef.angle = angle; bodyDef.userData = userData; if (userData) addChild(userData); var polygon:b2PolygonDef = new b2PolygonDef(); polygon.SetAsBox(width, height); polygon.density = density; polygon.friction = friction; polygon.restitution = restitution; var body:b2Body = m_world.CreateBody(bodyDef); body.CreateShape(polygon); body.SetMassFromShapes(); return body; } private function createJoint(body1:b2Body, x1:Number, y1:Number, body2:b2Body, x2:Number, y2:Number):b2Joint { var joint:b2DistanceJointDef = new b2DistanceJointDef(); joint.Initialize(body1, body2, new b2Vec2(x1, y1), new b2Vec2(x2, y2)); return m_world.CreateJoint(joint); } private function createDunbor(x:Number,y:Number):void { // 頭 var body1:b2Body = createBox(new Head(), x, y, 0, 0.85, 0.52, 0.15, 0.4, 2); // 体 var body2:b2Body = createBox(new Body(), x, y+1.1, 0, 0.55, 0.61, 0.98, 0.4, 5); // 左足 var body3:b2Body = createBox(null, x-0.3, y+2.1, 0, 0.2, 0.33, 10, 0.4, 0.3); // 右足 var body4:b2Body = createBox(null, x+0.3, y+2.1, 0, 0.2, 0.33, 10, 0.4, 0.3); // 左手 var body5:b2Body = createBox(null, x-0.8, y+0.85, 30 * Math.PI / 180, 0.2, 0.4, 1, 0.6, 0.3); // 右手 var body6:b2Body = createBox(null, x+0.8, y+0.85, 330 * Math.PI / 180, 0.2, 0.4, 1, 0.6, 0.3); // 頭と体をジョイント createJoint(body1, x-0.4, y+0.5, body2, x-0.4, y+0.51); createJoint(body1, x+0.4, y+0.5, body2, x+0.4, y+0.51); // 体と左足をジョイント createJoint(body2, x-0.5, y+1.7, body3, x-0.5, y+1.71); createJoint(body2, x-0.1, y+1.7, body3, x-0.1, y+1.71); // 体と右足をジョイント createJoint(body2, x+0.5, y+1.7, body4, x+0.5, y+1.71); createJoint(body2, x+0.1, y+1.7, body4, x+0.1, y+1.71); // 体と左手をジョイント createJoint(body2, x-0.51, y+0.5, body5, x-0.51, y+0.51); // 体と右手をジョイント createJoint(body2, x+0.51, y+0.5, body6, x+0.51, y+0.51); } 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; } var a:Number = Math.abs(bb.GetAngle() * 180 / Math.PI) % 360; if (a <= 30) { var dx:Number = ball.GetPosition().x - bb.GetPosition().x; var dy:Number = ball.GetPosition().y - bb.GetPosition().y; bb.ApplyForce(new b2Vec2(dx * 2, dy * 2), bb.GetPosition()); } } // 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(0x000000); graphics.drawCircle(-30, -10, 10); graphics.drawCircle( 30, -10, 10); graphics.beginFill(0x802030); graphics.moveTo( 0, 8); graphics.lineTo(-18, 5); graphics.lineTo( 0, 25); graphics.lineTo( 18, 5); graphics.endFill(); scaleX = scaleY = 0.4; } } 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]ダンボー遊び!