-
Notifications
You must be signed in to change notification settings - Fork 21
C2D 07 Adding Physics
Making objects in a Cadet Scene behave in a physically realistic way is something that can be achieved using a combination of Geometry, Behaviours and a Process.
All of the Components required to achieve this already exist in the Cadet Library, so we can get up and running with a physics scene fairly quickly. In later tutorials we will show how you can add your own Behaviours to manipulate these physical objects, but for now we will simply get a working example running.
The Cadet2DBox2D
library contains behaviours and processes which are designed to add 2D physics to a 2D scene, hence Cadet2D-Box2D.
For this example, create a new class named CadetHelloPhysics
in the default package, set it to be the default application and copy and paste the code below into it.
package
{
import flash.display.Sprite;
import flash.events.Event;
import cadet.core.CadetScene;
import cadet.core.ComponentContainer;
import cadet2D.components.geom.RectangleGeometry;
import cadet2D.components.renderers.Renderer2D;
import cadet2D.components.skins.GeometrySkin;
import cadet2D.components.transforms.Transform2D;
import cadet2DBox2D.components.behaviours.RigidBodyBehaviour;
import cadet2DBox2D.components.behaviours.RigidBodyMouseDragBehaviour;
import cadet2DBox2D.components.processes.PhysicsProcess;
[SWF( width="700", height="400", backgroundColor="0x002135", frameRate="60" )]
public class CadetHelloPhysics extends Sprite
{
private var cadetScene : CadetScene;
public function CadetHelloPhysics()
{
cadetScene = new CadetScene();
var renderer:Renderer2D = new Renderer2D();
renderer.viewportWidth = stage.stageWidth;
renderer.viewportHeight = stage.stageHeight;
cadetScene.children.addItem(renderer);
renderer.enable(this);
cadetScene.children.addItem( new PhysicsProcess() );
for ( var i:int = 0; i < 30; i++ )
{
var x:Number = Math.random() * stage.stageWidth;
var y:Number = Math.random() * 100;
var width:Number = 20 + Math.random() * 20;
var height:Number = 20 + Math.random() * 20;
addRectangleEntity( x, y, width, height );
}
// Create the floor. We pass 'true' as the 'fixed' property to make the floor static.
addRectangleEntity( 0, stage.stageHeight-50, stage.stageWidth, 50, true );
addEventListener(Event.ENTER_FRAME, enterFrameHandler);
}
private function addRectangleEntity( x:Number, y:Number, width:Number, height:Number, fixed:Boolean = false ):ComponentContainer
{
var entity:ComponentContainer = new ComponentContainer();
entity.children.addItem( new Transform2D(x, y) );
entity.children.addItem( new GeometrySkin() );
entity.children.addItem( new RectangleGeometry(width, height) );
entity.children.addItem( new RigidBodyBehaviour(fixed) );
entity.children.addItem( new RigidBodyMouseDragBehaviour() );
cadetScene.children.addItem(entity);
return entity;
}
private function enterFrameHandler( event:Event ):void
{
cadetScene.step();
}
}
}
In the constructor we are still creating a CadetScene
and a Renderer2D
as usual. What’s new is the PhysicsProcess
Component we’re adding in initScene()
. This Process is responsible for wrapping up a physics engine and stepping the simulation, in this case, the engine is Box2D. If you take a look at addRectangleEntity()
you'll see that besides the usual Transform2D
, RectangleGeometry
and GeometrySkin
, we're also adding two new behaviours: RigidBodyBehaviour
and RigidBodyMouseDragBehaviour
.
The RigidBodyBehaviour
wraps up a Box2D body and associates it with the behaviour's siblings: Transform2D
and RectangleGeometry
via the addSiblingReference()
function, seen earlier. The PhysicsProcess
is responsible for stepping the Box2D simulation, but when each RigidBodyBehaviour
is stepped, the matrix (scale, rotation, translation) of the Box2D body is passed to the Transform2D
. The GeometrySkin
listens in to changes in the Transform2D
, so is updated after the RigidBodyBehaviour
is stepped.
The RigidBodyMouseDragBehaviour
listens in to TouchEvents
from the Renderer2D
viewport, which it grabs a reference to via addSceneReference()
. If the behaviour has a Skin as a sibling, it checks to see whether that Skin has been interacted with; if so, a Box2D mouse joint is created between the mouse position and the Box2D body on the RigidBodyBehaviour
, hence RigidBodyMouseDragBehaviour
.