Box2D Forums

It is currently Tue May 21, 2013 2:24 am

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Flash site using box2d
PostPosted: Fri Jan 30, 2009 4:50 pm 
Offline

Joined: Fri Jan 30, 2009 4:37 pm
Posts: 7
Hi guys,

first off: FREAKING GREAT ENGINE!

second: here's a litlte site I just released using box2d. http://www.letsmoondance.nl/

Personally, I'm much satisfied with the result. It's a lot of fun using the engine, also when it's not for a very serious simulation but for an entertaining 'extra' in an otherwise simple site.

I hope you are as charmed with the result as I am ;)

Greetings,

Erik


Top
 Profile  
 
PostPosted: Tue Feb 03, 2009 7:43 am 
Offline

Joined: Tue Nov 18, 2008 3:37 am
Posts: 37
Hi Enrik,

I like it. Clean and nice.

How have you done the stars and lines?


Top
 Profile  
 
PostPosted: Tue Feb 03, 2009 2:59 pm 
Offline

Joined: Fri Jan 30, 2009 4:37 pm
Posts: 7
Thanks ;)

Getting the ropes right actually a lot of tinkering; I had a lot of problems getting the feel I wanted, even keeping the ropes from breaking. I had to experiment a lot with relative weights of the stars compared to the rope segments for example. I am quite happy with the way it turned out, as the rope has a nice elasticity to it but doesn't stretch too much or too easily.

In the end the setup looks like this:

- a static 'fitting' just outside the view above the top;
- a box acting as star,
- a variable number of segments of rope, depending on it's total length. Rope segments are actually small objects connected with distanceJoints. The masses of these objects reduce as they are are located lower in the rope.
- something that (I think) is something of a hack: explicitly setting the distanceJoint's 'm_length' property to the desired (initial) length. Without it, the ropes will stretch.

In the end it was baffling easy to set the whole thing up; yet very fiddly to get a dependable enough simulation with the rope properties I was looking for. I fiddled with any property I could find to get the behavior I liked most (without paying all that much attention to what you might call the simulation's physical correctness).

I read quite a bit about it on this forum and I learned that creating a good rope is not easy. The thing that meant a breakthrough for me was a post by mr. Catto; he suggested making the linking objects in the rope heavier for a dependable simulation. To keep the total weight of the rope as low as possible for a believable behavior, I made the elements lighter as they approach the bottom. The idea is: the lower the link, the less weight it should support.

Also, the number of segments has been reduced a few times. It's a little coarse now, but too many sections also made for ropes that stretched a bit too much.

Here's my source code for one element.
Code:
package nl.moondance.navigation
{
   import Box2D.Collision.b2AABB;
   import Box2D.Collision.Shapes.b2CircleDef;
   import Box2D.Collision.Shapes.b2PolygonDef;
   import Box2D.Collision.Shapes.b2PolygonShape;
   import Box2D.Collision.Shapes.b2Shape;
   import Box2D.Common.Math.b2Vec2;
   import Box2D.Dynamics.b2Body;
   import Box2D.Dynamics.b2BodyDef;
   import Box2D.Dynamics.b2DebugDraw;
   import Box2D.Dynamics.b2World;
   import Box2D.Dynamics.Joints.b2DistanceJoint;
   import Box2D.Dynamics.Joints.b2DistanceJointDef;
   import Box2D.Dynamics.Joints.b2Joint;
   import Box2D.Dynamics.Joints.b2MouseJoint;
   import Box2D.Dynamics.Joints.b2MouseJointDef;
   import flash.display.Sprite;

   /**
    * Project:      Moondance
    * Package:      nl.moondance.navigation
    * Class:      MobilePhysics
    *
    * The mobile for the moondance site. It uses Box2D for flash: http://box2dflash.sourceforge.net/
    *
    * @author       erik@hagreis.com
    * @version    0.1
    * @since      15-12-2008 17:00
    *
    * Copyright 2008 Erik Hagreis
   */
   public class MobilePhysics
   {
      // owner
      private var owner:Sprite;   
      
      // simulation stuff;
      private var world:b2World;
      private var mouseJoint:b2MouseJoint;
      private var iterations:int  = 10;
      private var timeStep:Number = 1 / 8;
      private var mousePVec:b2Vec2 = new b2Vec2();
      
      // used for visual rendering
      internal var fitting:b2Body;
      internal var star:b2Body;
      internal var ropeSegments:Array = new Array();

      // ___________________________________________________________________________________________________________________________
      //                                                                                                       C O N S T R U C T O R
      
      public function MobilePhysics( pOwner:Sprite, pDistanceFromTop:Number = 500 )
      {
         owner = pOwner;
         
         // World bounding box
         var worldAABB:b2AABB = new b2AABB();
         worldAABB.lowerBound.Set( -1000.0, -1000.0 );
         worldAABB.upperBound.Set(  2000.0,  2000.0 );
         
         // Define the gravity vector
         var gravity:b2Vec2 = new b2Vec2( 0.0, 100.0 );
         
         // Initialize world
         world = new b2World( worldAABB, gravity, true );
         
         // The fitting
         var fittingShapeDef:b2PolygonDef = new b2PolygonDef();
         fittingShapeDef.SetAsOrientedBox( 4, 4 );
         
         var fittingBodyDef:b2BodyDef = new b2BodyDef();
         fittingBodyDef.position.Set( 0, -100 );
         
         var fittingBody:b2Body = world.CreateBody( fittingBodyDef );
         fittingBody.CreateShape( fittingShapeDef );
         fitting = fittingBody;
         
         // The star (actually a box)
         var starSize:Number = 30;
         var starShapeDef:b2PolygonDef = new b2PolygonDef();
         starShapeDef.SetAsOrientedBox( 25, 25 );
         starShapeDef.density = 1;
         starShapeDef.friction = 0.3;
         starShapeDef.restitution = 0.3;
         
         var starBodyDef:b2BodyDef = new b2BodyDef();
         starBodyDef.position.Set( 0, pDistanceFromTop );
         starBodyDef.angle = Math.random() * Math.PI * 2;
         starBodyDef.linearDamping = 0.1;
         starBodyDef.angularDamping = 0.9;
         starBodyDef.massData.mass = 8;
         starBodyDef.massData.I = 44;
         
         var starBody:b2Body = world.CreateBody( starBodyDef );
         starBody.CreateShape( starShapeDef );
         
         ropeSegments.push( starBody );
         star = starBody;
         
         // the rope
         var ropeShapeDef:b2CircleDef = new b2CircleDef();
         ropeShapeDef.radius = 1;
         ropeShapeDef.density = 1;
         ropeShapeDef.filter.maskBits = 0;
            
         var ropeBodyDef:b2BodyDef = new b2BodyDef();
         ropeBodyDef.linearDamping = 0.2;
         ropeBodyDef.angularDamping = 0.2;
         ropeBodyDef.massData.mass = 1;
         ropeBodyDef.massData.I = 100;
            
         var ropeBody:b2Body;
         var ropeStart:b2Body = starBody;         
         var jointDef:b2DistanceJointDef = new b2DistanceJointDef();            
         var joint:b2DistanceJoint;
         var dY:Number = starBody.GetPosition().y - fittingBody.GetPosition().y;         
         var numSections:int = Math.ceil( dY / 55 );
         for ( var i:Number = 0; i < numSections - 1; i++ )
         {
            // One rope section body
            ropeBodyDef.position.Set( 0, starBody.GetPosition().y - dY * i / numSections );
            ropeBodyDef.massData.mass = 0.8 + 0.8 * i / numSections;
            
            //ropeBody.
            ropeBody = world.CreateBody( ropeBodyDef );            
            ropeBody.CreateShape( ropeShapeDef );
            
            ropeSegments.push( ropeBody );
            
            // One rope section joint
            jointDef.Initialize( ropeStart, ropeBody, ropeStart.GetPosition(), ropeBody.GetPosition() );
            joint = world.CreateJoint( jointDef ) as b2DistanceJoint;
            joint.m_length = dY / numSections; // this is probably something bad, but I need it for the whole thing to work.
            
            // update startpoint for next joint
            ropeStart = ropeBody;
         }
         // Final rope joint
         jointDef.Initialize( fittingBody, ropeStart, fittingBody.GetPosition(), ropeStart.GetPosition() );      
         joint = world.CreateJoint( jointDef ) as b2DistanceJoint;
         joint.m_length = dY / numSections;
         
         ropeSegments.push( fitting );
         
         // setup debug drawing
         var dbgDraw:b2DebugDraw = new b2DebugDraw();
         dbgDraw.m_sprite = owner;
         dbgDraw.m_drawScale = 1;
         dbgDraw.m_fillAlpha = 0.3;
         dbgDraw.m_lineThickness = 1.0;
         dbgDraw.m_drawFlags = b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit;
         //world.SetDebugDraw(dbgDraw);
      }
      
      // ___________________________________________________________________________________________________________________________
      //                                                                                                                 P U B L I C
      
      public function updateSimulation():void
      {
         mouseDrag();
         world.Step( timeStep, iterations );
      }
      
      public function destroy():void
      {
         owner = null;
      }
      
      
      // ___________________________________________________________________________________________________________________________
      //                                                                                             G E T T E R S  /  S E T T E R S
       
      private function get xMouse():Number
      {
         return owner.mouseX;
      }
      
      private function get yMouse():Number
      {
         return owner.mouseY;
      }
       
      // ___________________________________________________________________________________________________________________________
      //                                                                                                 E V E N T   H A N D L E R S
       
      
      // ___________________________________________________________________________________________________________________________
      //                                                                                                           P R O T E C T E D   
       
      
      
      // ___________________________________________________________________________________________________________________________
      //                                                                                                               P R I V A T E   
       

      private function mouseDrag():void
      {   
         // Test for mouse hitting the star
         var mouseOnStar:Boolean = isMouseAtStar();
         
         // Establish mouseJoint it if doesn't exist and the mouse is ON the star
         if ( !mouseJoint && mouseOnStar)
         {            
            var md:b2MouseJointDef = new b2MouseJointDef();
            md.body1 = world.GetGroundBody();
            md.body2 = star;
            md.target.Set( xMouse, yMouse );
            md.maxForce = 100.0 * star.GetMass();
            md.timeStep = timeStep;
            
            mouseJoint = world.CreateJoint(md) as b2MouseJoint;
            star.WakeUp();
         }
         // Destroy mouseJoint it if exists and the mouse is OFF the star
         else if ( mouseJoint && !mouseOnStar )
         {
            world.DestroyJoint(mouseJoint);
            mouseJoint = null;
         }
         
         // Update the position of the mouseJoint if we have one
         if (mouseJoint)
         {
            var p2:b2Vec2 = new b2Vec2( xMouse, yMouse );
            mouseJoint.SetTarget(p2);
         }
      }
      
      private function isMouseAtStar():Boolean
      {
         mousePVec.Set( xMouse, yMouse );         
         var starShape:b2Shape = star.GetShapeList();
         var inside:Boolean = starShape.TestPoint( starShape.GetBody().GetXForm(), mousePVec );
         
         return inside;
      }
   }   
}


Top
 Profile  
 
PostPosted: Tue Feb 03, 2009 7:08 pm 
Offline

Joined: Wed Jan 07, 2009 10:31 pm
Posts: 86
its great rope!!!


Top
 Profile  
 
PostPosted: Wed Feb 04, 2009 8:54 am 
Offline

Joined: Fri Jan 23, 2009 12:53 pm
Posts: 177
Maybe it's a good rope, but the code isn't good at all! Use functions! (Don't forget about classes).


Top
 Profile  
 
PostPosted: Thu Feb 05, 2009 2:36 pm 
Offline

Joined: Fri Jan 30, 2009 4:37 pm
Posts: 7
Personally I don't quite see how splitting up the constructor in a number of separate methods would mean a significant improvement. Sure, I could've done it because it contains a lot of code, but its fairly focused on one job imo.


Top
 Profile  
 
PostPosted: Wed Feb 18, 2009 7:19 am 
Offline

Joined: Tue Nov 18, 2008 3:37 am
Posts: 37
Thanks Erik for sharing!


Top
 Profile  
 
PostPosted: Tue Jun 09, 2009 11:42 am 
Offline

Joined: Tue Jun 09, 2009 4:08 am
Posts: 40
really lovely site, very professional, though the links are a little hard to click for someone using a touchpad like me


Top
 Profile  
 
PostPosted: Wed Nov 25, 2009 10:59 am 
Offline

Joined: Mon Nov 16, 2009 4:20 am
Posts: 4
Hello everybody, some will have an example ".Fla" implementing this excellent script and I can not get it working.
I hang a logo of two elastic cords can do with this same class :?:
Thank you very much :!:
Excuse my English ... :)


Top
 Profile  
 
PostPosted: Tue Dec 15, 2009 1:10 am 
Offline

Joined: Tue Dec 15, 2009 1:02 am
Posts: 1
Hi!

I have been looking for a good rope sim for a while now! I need it for a project that I'm working on. This one is GREAT! I think it might be what i need to make it happen.

Someone wanted a working version... the above code just needs a bit of tweakin to get it to render. Need to:
-= addEventListener(Event.ENTER_FRAME, updateSimulation, false, 0, true) to the constructor (or anywhere really)
-= change updateSimulation() to:

Code:
public function updateSimulation(e:Event):void
      {
         mouseDrag();
         world.Step( timeStep, iterations );
      }


-= create a .fla with this in the first frame:
Code:
import <point this to your copy of the "MobilePhysics">.MobilePhysics

var oSprite:Sprite = new Sprite()
addChild(oSprite)
oSprite.x = 100
var mobileTest = new MobilePhysics(oSprite)
oSprite.addChild(mobileTest)


Hope this helps!
Thanks for all the great work you guys/gals are doing.
-=b=-


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 18 posts ]  Go to page 1, 2  Next

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group