Creating custom Box2D shape components in PushButton Engine


If you ever need to use other ways of creating Box2D shapes that are not currently available in PushButton Engine, you can simply make one yourself. You’ll just need to create a subclass of CollisionShape and use it just like the PBE shape classes.

Here’s a sample class we use to create an oriented box shape:

package cavalcade.box2D
{
    import Box2D.Collision.Shapes.b2PolygonDef;
    import Box2D.Collision.Shapes.b2ShapeDef;
    import Box2D.Common.Math.b2Vec2;

    import com.pblabs.box2D.CollisionShape;

    import flash.geom.Point;

    public class OrientedBoxCollisionShape extends CollisionShape
    {
        public var halfWidth:Number = 0.5;
        public var halfHeight:Number = 0.5;
        public var center:Point = new Point();
        public var angle:Number = 0;

        public function OrientedBoxCollisionShape()
        {
            super();
        }

        override protected function doCreateShape():b2ShapeDef
        {
            var scale:Number = _parent.manager.inverseScale;            

            var shape:b2PolygonDef = new b2PolygonDef();
            shape.SetAsOrientedBox(halfWidth * scale * _parent.size.x, halfHeight * scale * _parent.size.y, b2Vec2.Make(center.x, center.y), angle);
            return shape;
        }
    }
}

As you can see, the class inherits from CollisionShape and overrides the doCreateShape method in order to create the actual Box2D oriented box shape from there. Use it in the level files like this:

<component type="com.pblabs.box2D.Box2DSpatialComponent" name="Cart">
    <collidesWithTypes childType="String">
        <_0>Platform</_0>
    </collidesWithTypes>

    <collisionShapes childType="com.pblabs.box2D.CollisionShape">
        <_0 type="cavalcade.box2D.OrientedBoxCollisionShape">
            <halfWidth>0.42</halfWidth>
            <halfHeight>0.12</halfHeight>
            <density>50</density> <!-- you can still use the same properties in CollisionShape -->
            <friction>2</friction>
            <restitution>0</restitution>
            <angle>3</angle> <!-- specify an angle of rotation -->
            <center> <!-- you can override the location of the box so it won't be positioned somewhere other than the center of the entity -->
                <x>1</x>
                <y>-0.5</y> 
            </center>
        </_0>                
    </collisionShapes>
    <collisionType childType="String">
        <_0>Renderable</_0>
    </collisionType>
    <manager componentReference="SpatialDB" />
        <position type="">
            <x>0</x>
            <y>110</y>
        </position>
        <size type="">
            <x>60</x>
            <y>45</y>
        </size>
</component>