Talking about Actionscript 3, Box2D and Flash.
If you watched all demos in the official Box2D AS3 page, you should know you can achieve buoyancy effect using a buoyancy controller.
I played a bit with it, and I wasn’t satisfied your controller must cover the entire world, just allowing you to limit it with an offset. It would have been way better if you could define an area in which bodies are affected by buoyancy controller. This way you could create a pool.
Look at this example:
Click with the mouse to release a random box from the top at mouseX
position. You will see only bodies falling in the “pool” are affected by buoyancy controller.
The trick is made by creating a sensor with the same shape of the desired buoyancy controller, and adding bodies to the controller only if they touch the shape.
This way you can create pools
Look at the source code:
package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import Box2D.Dynamics.*; import Box2D.Collision.Shapes.*; import Box2D.Common.Math.*; import Box2D.Dynamics.Controllers.*; import Box2D.Dynamics.Contacts.*; public class Main extends Sprite { private var world:b2World=new b2World(new b2Vec2(0,10),true); var buoyancyController:b2BuoyancyController = new b2BuoyancyController(); private var worldScale:int=30; public function Main() { debugDraw(); buoyancyController.normal.Set(0,-1); buoyancyController.offset=-180/worldScale; buoyancyController.useDensity=true; buoyancyController.density=2.0; buoyancyController.linearDrag=5; buoyancyController.angularDrag=2; world.AddController(buoyancyController); addBox(320,480,640,20,b2Body.b2_staticBody,false); addBox(320,340,320,20,b2Body.b2_staticBody,false); addBox(170,230,20,200,b2Body.b2_staticBody,false); addBox(470,230,20,200,b2Body.b2_staticBody,false); addBox(320,245,280,170,b2Body.b2_staticBody,true); var waterCanvas:Sprite=new Sprite(); addChild(waterCanvas); waterCanvas.graphics.beginFill(0x0000ff,0.2); waterCanvas.graphics.drawRect(180,160,280,170); waterCanvas.graphics.endFill(); addEventListener(Event.ENTER_FRAME,update); stage.addEventListener(MouseEvent.CLICK,mouseClick); } private function mouseClick(e:MouseEvent):void { addBox(mouseX,-100,Math.random()*50+25,Math.random()*50+25,b2Body.b2_dynamicBody,false); } private function addBox(pX:Number,pY:Number,w:Number,h:Number,bodyType:Number,isSensor:Boolean):void { var bodyDef:b2BodyDef=new b2BodyDef(); bodyDef.position.Set(pX/worldScale,pY/worldScale); bodyDef.type=bodyType; var polygonShape:b2PolygonShape=new b2PolygonShape(); polygonShape.SetAsBox(w/2/worldScale,h/2/worldScale); var fixtureDef:b2FixtureDef=new b2FixtureDef(); fixtureDef.isSensor=isSensor; fixtureDef.shape=polygonShape; fixtureDef.density=1; fixtureDef.restitution=0.4; fixtureDef.friction=0.5; var body:b2Body=world.CreateBody(bodyDef); body.CreateFixture(fixtureDef); } private function debugDraw():void { var debugDraw:b2DebugDraw=new b2DebugDraw(); var debugSprite:Sprite=new Sprite(); addChild(debugSprite); debugDraw.SetSprite(debugSprite); debugDraw.SetDrawScale(worldScale); debugDraw.SetFlags(b2DebugDraw.e_shapeBit|b2DebugDraw.e_jointBit); debugDraw.SetFillAlpha(0.5); world.SetDebugDraw(debugDraw); } private function update(e:Event):void { world.Step(1/30,10,10); for (var currentBody:b2Body=world.GetBodyList(); currentBody; currentBody=currentBody.GetNext()) { if (currentBody.GetType()==b2Body.b2_dynamicBody) { var currentBodyControllers:b2ControllerEdge=currentBody.GetControllerList(); if (currentBodyControllers!=null) { buoyancyController.RemoveBody(currentBody); } for (var c:b2ContactEdge=currentBody.GetContactList(); c; c=c.next) { var contact:b2Contact=c.contact; var fixtureA:b2Fixture=contact.GetFixtureA(); var fixtureB:b2Fixture=contact.GetFixtureB(); if (fixtureA.IsSensor()) { var bodyB:b2Body=fixtureB.GetBody(); var bodyBControllers:b2ControllerEdge=bodyB.GetControllerList(); if (bodyBControllers==null) { buoyancyController.AddBody(bodyB); } } if (fixtureB.IsSensor()) { var bodyA:b2Body=fixtureA.GetBody(); var bodyAControllers:b2ControllerEdge=bodyA.GetControllerList(); if (bodyAControllers==null) { buoyancyController.AddBody(bodyA); } } } } } world.ClearForces(); world.DrawDebugData(); } } }
The code is not commented because I play to optimize it a bit, but if you have doubts, just ask. You can also download the source code.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.