API Docs for: 0.1.0
Show:

File: cangaja/box2d/b2d-world.js

                        /**
                         * @description
                         *
                         * B2DWorld is a Box2dWeb wrapper with basic and easy methods for creating Box2d Objects like
                         * lines, circles, rectangles, polybodies, ropes and bridges. Custom B2D Objects that extends
                         * one of the basic B2D objects can added to the B2DWorld with the addCustom method.
                         * The CG.B2DWorld can attached to an CG.Screen object as layer. The B2DWorld will handle
                         * all physics and drawings.
                         *
                        ```
                        
                         var w = new CG.B2DWorld({
                             name: 'box2d-world',
                             scale: 40,
                             debug: true,
                             sleep: true
                         })
                        
                         ```
                         *
                         * @class CG.B2DWorld
                         * @xtend CG.Layer
                         */
                        
                        CG.Layer.extend('B2DWorld', {
                            /**
                             * Options:
                             * name {string}
                             * sleep {boolean}
                             * scale {number}
                             * debug {boolean}
                             *
                             * @method init
                             * @constructor
                             * @param options {object}
                             */
                            init: function (options) {
                        
                                CG._extend(this, {
                                    /**
                                     * @property framerate
                                     * @type {number}
                                     */
                                    framerate: 1 / 30,
                        
                                    /**
                                     * @property name
                                     * @type {String}
                                     */
                                    name: '',
                                    /**
                                     * @property debug
                                     * @type {Boolean}
                                     */
                                    debug: false,
                                    /**
                                     * @property x
                                     * @type {Number}
                                     */
                                    x: 0,
                                    /**
                                     * @property y
                                     * @type {Number}
                                     */
                                    y: 0,
                                    /**
                                     * @property elements
                                     * @type {Array}
                                     */
                                    elements: [],
                        
                                    /**
                                     * @property uid
                                     * @type {Number}
                                     */
                                    uid: 0, //uid counter for elements
                                    /**
                                     * @property scale
                                     * @type {Number}
                                     */
                                    scale: 40,
                                    /**
                                     * @property sleep
                                     * @type {Boolean}
                                     */
                                    sleep: true
                                })
                        
                                if (options) {
                                    CG._extend(this, options)
                                }
                        
                                /**
                                 * @property world
                                 * @type {b2World}
                                 */
                                this.world = new b2World(
                                    new b2Vec2(0, 10), //gravity
                                    this.sleep
                                )
                        
                                // add m_groundBody for use with b2MouseJoint
                                this.world.m_groundBody = this.world.CreateBody(new b2BodyDef());
                        
                                //setup debug draw
                                var debugDraw = new b2DebugDraw({
                                    scale: this.scale,
                                    canvas: Game.b_canvas,
                                    ctx: Game.b_ctx,
                                    flags: box2d.b2DrawFlags.e_shapeBit | box2d.b2DrawFlags.e_jointBit | box2d.b2DrawFlags.e_centerOfMassBit
                                })
                                this.world.SetDebugDraw(debugDraw)
                        
                            },
                            /**
                             * @method update
                             */
                            update: function () {
                        
                                this.world.Step(
                                    this.framerate   //frame-rate
                                    , 10       //velocity iterations
                                    , 10       //position iterations
                                )
                        
                                if (CG.mousedown) {
                                    this.mouseDownAt(mousex, mousey);
                                } else if (this.isMouseDown()) {
                                    this.mouseUp();
                                }
                        
                                for (var i = 0, l = this.elements.length; i < l; i++) {
                                    this.elements[i].update()
                                }
                        
                        
                            },
                            /**
                             * @method draw
                             */
                            draw: function () {
                                Game.b_ctx.save()
                                Game.b_ctx.translate(this.x, this.y)
                        
                                for (var i = 0, l = this.elements.length; i < l; i++) {
                                    this.elements[i].draw()
                                }
                        
                                if (this.debug) {
                                    this.world.DrawDebugData()
                                    this.world.ClearForces()
                                }
                        
                                Game.b_ctx.restore()
                            },
                            /**
                             * @description
                             *
                             * Custom extended objects can be added to the B2DWorld with this method.
                             *
                             * @method addCustom
                             * @param obj      object    custom B2D object
                             * @return {Object}
                             */
                            addCustom: function (obj) {
                                this.uid = this.uid + 1
                                obj.id.uid = this.uid
                                this.elements.push(obj)
                                return obj
                            },
                            /**
                             * @description
                             *
                             * Checks if a B2D body Exists
                             *
                             * @method deleteBodyAt
                             * @param body {Object}
                             * @return {Boolean}
                             */
                            checkIfBodyExists: function (body) {
                                if (body) {
                                    for (var i = 0, l = this.elements.length; i < l; i++) {
                                        //if b2entity found delete entity and b2body
                                        if (this.elements[i].body.m_userData.uid == body.m_userData.uid) {
                                            return true
                                        }
                                    }
                                }
                                return false
                            },
                            /**
                             * Options:
                             * name {string}
                             * image {mixed}  path to image, image or atlasimage from asset
                             * x {number}
                             * y {number}
                             * bodyType {number}
                             *
                             @example
                             b2world.createBox({
                                name: 'glowball',
                                image: this.asset.getImageByName('glowball'),
                                radius: 22,
                                x: this.mouse.x,
                                y: this.mouse.y,
                                bodyType: box2d.b2BodyType.b2_dynamicBody
                             })
                             * @description
                             *
                             * createBox creates a basic Box2D rectangle with some default settings.
                             *
                             * @method createBox
                             * @param options {object}
                             * @return {CG.B2DRectangle}
                             */
                            createBox: function (options) {
                                options.world = this.world
                                options.scale = this.scale
                                this.uid = this.uid + 1
                                var entity = new CG.B2DRectangle(options)
                                entity.id.uid = this.uid
                                this.elements.push(entity)
                                return entity
                            },
                            /**
                             * Options:
                             * name {string}
                             * startPoint {CG.Point}
                             * endPoint {CG.Point}
                             *
                             @example
                             b2world.createLine({
                                name:'testline2',
                                startPoint: new CG.Point(630, 200),
                                endPoint: new CG.Point(150, 250)
                             })
                             *
                             * @description
                             *
                             * createLine creates a basic Box2D line with some default settings.
                             *
                             * @method createLine
                             * @param options {object}
                             * @return {CG.B2DLine}
                             */
                            createLine: function (options) {
                                options.world = this.world
                                options.scale = this.scale
                                this.uid = this.uid + 1
                                var entity = new CG.B2DLine(options)
                                entity.id.uid = this.uid
                                this.elements.push(entity)
                                return entity
                            },
                            /**
                             * Options:
                             * name {string}
                             * image {mixed}  path to image, image or atlasimage from asset
                             * radius {number}
                             * x {number}
                             * y {number}
                             * bodyType {number}
                             *
                             @example
                             b2world.createCircle({
                                name: 'glowball',
                                image: this.asset.getImageByName('glowball'),
                                radius: 22,
                                x: this.mouse.x,
                                y: this.mouse.y,
                                bodyType: box2d.b2BodyType.b2_dynamicBody
                             })
                             * @description
                             *
                             * createCircle creates a basic Box2D circle with some default settings
                             *
                             * @method createCircle
                             * @param options {object}
                             * @return {CG.B2DCircle}
                             */
                            createCircle: function (options) {
                                options.world = this.world
                                options.scale = this.scale
                                this.uid = this.uid + 1
                                var entity = new CG.B2DCircle(options)
                                entity.id.uid = this.uid
                                this.elements.push(entity)
                                return entity
                            },
                            /**
                             * Options:
                             * name {string}
                             * image {mixed}  path to image, image or atlasimage from asset
                             * texturepacker {String}
                             * x {number}
                             * y {number}
                             * bodyType {number}
                             * bullet {boolean}
                             *
                             @example
                             b2world.createPolyBody({
                                name: 'powerstar75',
                                image: this.asset.getImageByName('powerstar75'),
                                texturepacker: this.asset.getJsonByName('powerstar75'),
                                x: 200,
                                y: -150,
                                bodyType: box2d.b2BodyType.b2_dynamicBody,
                                bullet: false
                             })
                             *
                             * @description
                             *
                             * createPolyBody creates a Box2D polybody. A PhysicsEditor json (Lime + Corona JSON Exporter) file is needed for this
                             * Box2D object. The polygonshape and some settings like density, bounce and friction are
                             * taken from the json file at the moment.
                             *
                             * @method createPolyBody
                             * @param options {object}
                             * @return {CG.B2DPolygon}
                             */
                            createPolyBody: function (options) {
                                options.world = this.world
                                options.scale = this.scale
                                this.uid = this.uid + 1
                                var entity = new CG.B2DPolygon(options)
                                entity.id.uid = this.uid
                                this.elements.push(entity)
                                return entity
                            },
                            /**
                             * Options:
                             * name {string}
                             * image {mixed}
                             * points {array}
                             * x {number}
                             * y {number}
                             *
                             @example
                             var terrainPolys =
                             [{
                                    outer: [{
                                        x: 0,
                                        y: 100.5
                                    }, {
                                        x: 1024,
                                        y: 100.5
                                    }, {
                                        x: 1024,
                                        y: 768
                                    }, {
                                        x: 0,
                                        y: 768
                                    }],
                                    holes: []
                                }]
                        
                             b2world.createTerrain({
                                 name: 'terrain',
                                 image: false
                                 terrainShape: terrainPolys,
                                 x:0,
                                 y:0
                             })
                             *
                             *
                             * @description
                             *
                             * createTerrain
                             *
                             * @method createPolyBody
                             * @param options {String}
                             * @return {CG.B2DTerrain}
                             */
                            createTerrain: function (options) {
                                options.world = this.world
                                options.scale = this.scale
                                this.uid = this.uid + 1
                                var entity = new CG.B2DTerrain(options)
                                entity.id.uid = this.uid
                                this.elements.push(entity)
                                return entity
                            },
                            /**
                             * Options:
                             * name {string}
                             * points {array}
                             * x {number}
                             * y {number}
                             *
                             @example
                             chainArray = [
                                 new CG.Point(0, 0),
                                 new CG.Point(50, 10),
                                 new CG.Point(100, 100),
                                 new CG.Point(200, 100),
                                 new CG.Point(250, 50),
                                 new CG.Point(300, 70)
                             ]
                        
                             b2world.createChainShape({
                                 name: 'chaneshape',
                                 points: chainArray,
                                 x: 0,
                                 y: 200
                             })
                             *
                             * @description
                             *
                             * createChainShape
                             *
                             * @method createChainShape
                             * @param options {object}
                             * @return {CG.B2DChainShape}
                             */
                            createChainShape: function (options) {
                                options.world = this.world
                                options.scale = this.scale
                                this.uid = this.uid + 1
                                var entity = new CG.B2DChainShape(options)
                                entity.id.uid = this.uid
                                this.elements.push(entity)
                                return entity
                            },
                            /**
                             * Options:
                             * name {string}
                             * image {mixed}  path to image, image or atlasimage from asset
                             * x {number}
                             * y {number}
                             * length {number}
                             * segments {number}
                             * segmentHeight {number}
                             *
                             @example
                             b2world.createBridge({
                                name:'chain',
                                image:this.asset.getImageByName('chain'),
                                x: 20,
                                y: 280,
                                length: 620,
                                segments: 27,
                                segmentHeight: 3
                             })
                             *
                             *
                             * @description
                             *
                             * This method creates a B2D bridge. Just play with the params to get a good result!
                             *
                             * @method createBridge
                             * @param options {object}
                             * @return {CG.B2DBridge}
                             */
                            createBridge: function (options) {
                                options.world = this.world
                                options.scale = this.scale
                                this.uid = this.uid + 1
                                var entity = new CG.B2DBridge(options)
                                entity.id.uid = this.uid
                                this.elements.push(entity)
                                return entity
                            },
                            /**
                             * Options:
                             * name {string}
                             * image {mixed}  path to image, image or atlasimage from asset
                             * x {number}
                             * y {number}
                             * length {number}
                             * segments {number}
                             * segmentWidth {number}
                             *
                             @example
                             b2world.createRope({
                                name: 'chain-v',
                                image: this.asset.getImageByName('chain-v'),
                                x: 580,
                                y: 0,
                                length: 200,
                                segments: 8,
                                segmentWidth: 3
                            })
                             *
                             *
                             * @description
                             *
                             * This method creates a B2D rope. Just play with the params to get a good result!
                             *
                             * @method createRope
                             * @param options {object}
                             * @return {CG.B2DRope}
                             */
                            createRope: function (options) {
                                options.world = this.world
                                options.scale = this.scale
                                this.uid = this.uid + 1
                                var entity = new CG.B2DRope(options)
                                entity.id.uid = this.uid
                                this.elements.push(entity)
                                return entity
                            },
                            /**
                             * @description
                             *
                             * Enables dragging B2D objects with the mouse.
                             *
                             * @method mouseDownAt
                             * @param x {Number}
                             * @param y {Number}
                             */
                            mouseDownAt: function (x, y) {
                                if (!this.mouseJoint) {
                                    var body = this.getBodyAt(x, y)
                        
                                    if (body) {
                                        var md = new b2MouseJointDef()
                                        md.bodyA = this.world.m_groundBody
                                        md.bodyB = body
                                        md.target.SetXY((x - this.x) / this.scale, (y - this.y) / this.scale)
                                        md.collideConnected = true
                                        md.maxForce = 300.0 * body.GetMass()
                                        this.mouseJoint = this.world.CreateJoint(md)
                                        body.SetAwake(true);
                                    }
                                } else {
                                    this.mouseJoint.SetTarget(new b2Vec2((x - this.x) / this.scale, (y - this.y) / this.scale))
                                }
                            },
                            /**
                             * @method mouseUp
                             */
                            mouseUp: function () {
                                this.world.DestroyJoint(this.mouseJoint);
                                this.mouseJoint = null;
                            },
                            /**
                             * @description
                             *
                             * Get a B2D body at the give x, y position.
                             *
                             * @method getBodyAt
                             * @param x {Number}
                             * @param y {Number}
                             * @return {*}
                             */
                            getBodyAt: function (x, y) {
                                var worldx = (x - this.x) / this.scale;
                                var worldy = (y - this.y) / this.scale
                        
                                var mousePVec = new b2Vec2(worldx, worldy)  //b2world offset for x and y!!!
                                var aabb = new b2AABB()
                                aabb.lowerBound.SetXY(worldx - 0.001, worldy - 0.001)
                                aabb.upperBound.SetXY(worldx + 0.001, worldy + 0.001)
                        
                                // Query the world for overlapping shapes.
                        
                                var selectedBody = null;
                                this.world.QueryAABB(function (fixture) {
                                    if (fixture.GetBody().GetType() != b2Body.b2_staticBody) {
                                        if (fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePVec)) {
                                            selectedBody = fixture.GetBody();
                                            return false;
                                        }
                                    }
                                    return true;
                                }, aabb);
                                return selectedBody;
                            },
                            /**
                             * @description
                             *
                             * Deletes a B2D body at the given x, y position
                             *
                             * @method deleteBodyAt
                             * @param x {Number}
                             * @param y (Number)
                             * @return {Boolean}
                             */
                            deleteBodyAt: function (x, y) {
                                body = this.getBodyAt(x, y)
                                if (body) {
                                    for (var i = 0, l = this.elements.length; i < l; i++) {
                                        //if b2entity found delete entity and b2body
                                        if (this.elements[i].body.m_userData.uid == body.m_userData.uid) {
                                            this.removeElementByIndex(i)
                                            this.world.DestroyBody(body)
                                            return true
                                        }
                                    }
                                }
                                return false
                            },
                            /**
                             * @method isMouseDown
                             * @return {Boolean}
                             */
                            isMouseDown: function () {
                                return (this.mouseJoint != null);
                            },
                            /**
                             * @method removeElementByIndex
                             * @param index
                             */
                            removeElementByIndex: function (index) {
                                this.elements.splice(index, 1);
                            },
                            /**
                             * @method removeElementByUid
                             * @param uid
                             */
                            removeElementByUid: function (uid) {
                                for (var i = 0, l = this.elements.length; i < l; i++) {
                                    if (typeof this.elements[i] === 'object' && typeof this.elements[i].id !== 'undefined') {
                                        if (this.elements[i].id.uid === uid) {
                                            this.elements.splice(i, 1);
                                        }
                                    }
                                }
                            },
                            /**
                             * @method applyImpulse
                             * @param body
                             * @param degrees
                             * @param power
                             */
                            applyImpulse: function (body, degrees, power) {
                                if (body) {
                                    body.ApplyLinearImpulse(new b2Vec2(Math.cos(degrees * CG.Const_PI_180) * power,
                                        Math.sin(degrees * CG.Const_PI_180) * power),
                                        body.GetWorldCenter());
                                }
                            },
                            /**
                             * @method addContactListener
                             * @param callbacks
                             */
                            addContactListener: function (callbacks) {
                                var listener = new box2d.b2ContactListener;
                                if (callbacks.BeginContact) listener.BeginContact = function (contact) {
                                    callbacks.BeginContact(contact.GetFixtureA().GetBody(),
                                        contact.GetFixtureB().GetBody());
                                }
                                if (callbacks.EndContact) listener.EndContact = function (contact) {
                                    callbacks.EndContact(contact.GetFixtureA().GetBody(),
                                        contact.GetFixtureB().GetBody());
                                }
                                if (callbacks.PostSolve) listener.PostSolve = function (contact, impulse) {
                                    callbacks.PostSolve(contact.GetFixtureA().GetBody(),
                                        contact.GetFixtureB().GetBody(),
                                        impulse.normalImpulses[0]);
                                }
                                if (callbacks.PreSolve) listener.PreSolve = function (contact, oldManifold) {
                                    callbacks.PreSolve(contact, oldManifold);
                                }
                                this.world.SetContactListener(listener);
                            },
                            /**
                             * @method getBodySpec
                             * @param b
                             * @return {Object}
                             */
                            getBodySpec: function (b) {
                                return {x: b.GetPosition().x, y: b.GetPosition().y, a: b.GetAngle(), c: {x: b.GetWorldCenter().x, y: b.GetWorldCenter().y}};
                            }
                        })