From 2d52d53bf0927bf791542cb2431b91aaf02384ee Mon Sep 17 00:00:00 2001 From: liabru Date: Mon, 24 Mar 2014 00:30:16 +0000 Subject: [PATCH] composites are now an actual tree structure --- src/body/Composite.js | 71 ++++++++++++++++++++++++++++++++-------- src/body/World.js | 24 ++++++-------- src/core/Engine.js | 28 +++++++++------- src/core/Metrics.js | 7 ++-- src/module/Outro.js | 3 +- src/render/Render.js | 23 +++++++------ src/render/RenderPixi.js | 10 +++--- 7 files changed, 108 insertions(+), 58 deletions(-) diff --git a/src/body/Composite.js b/src/body/Composite.js index 6ecff44..59187e0 100644 --- a/src/body/Composite.js +++ b/src/body/Composite.js @@ -18,26 +18,22 @@ var Composite = {}; * @return {composite} A new composite */ Composite.create = function(options) { - return Common.extend({ bodies: [], constraints: [], composites: [] }, options); + return Common.extend({ + bodies: [], + constraints: [], + composites: [] + }, options); }; /** * Description - * @method add + * @method addComposite * @param {composite} compositeA * @param {composite} compositeB * @return {composite} The original compositeA with the objects from compositeB added */ - Composite.add = function(compositeA, compositeB) { - if (compositeA.bodies && compositeB.bodies) - compositeA.bodies = compositeA.bodies.concat(compositeB.bodies); - - if (compositeA.constraints && compositeB.constraints) - compositeA.constraints = compositeA.constraints.concat(compositeB.constraints); - - if (compositeA.composites && compositeB.composites) - compositeA.composites = compositeA.composites.concat(compositeB.composites); - + Composite.addComposite = function(compositeA, compositeB) { + compositeA.composites.push(compositeB); return compositeA; }; @@ -49,7 +45,6 @@ var Composite = {}; * @return {composite} The original composite with the body added */ Composite.addBody = function(composite, body) { - composite.bodies = composite.bodies || []; composite.bodies.push(body); return composite; }; @@ -62,9 +57,57 @@ var Composite = {}; * @return {composite} The original composite with the constraint added */ Composite.addConstraint = function(composite, constraint) { - composite.constraints = composite.constraints || []; composite.constraints.push(constraint); return composite; }; + /** + * Returns all bodies in the given composite, including all bodies in its children, recursively + * @method allBodies + * @param {composite} composite + * @return {body[]} All the bodies + */ + Composite.allBodies = function(composite) { + var bodies = [].concat(composite.bodies); + + for (var i = 0; i < composite.composites.length; i++) + bodies = bodies.concat(Composite.allBodies(composite.composites[i])); + + return bodies; + }; + + /** + * Returns all constraints in the given composite, including all constraints in its children, recursively + * @method allConstraints + * @param {composite} composite + * @return {constraint[]} All the constraints + */ + Composite.allConstraints = function(composite) { + var constraints = [].concat(composite.constraints); + + for (var i = 0; i < composite.composites.length; i++) + constraints = constraints.concat(Composite.allConstraints(composite.composites[i])); + + return constraints; + }; + + /** + * Removes all bodies, constraints and composites from the given composite (non-recursive) + * @method clear + * @param {world} world + * @param {boolean} keepStatic + */ + Composite.clear = function(composite, keepStatic) { + if (keepStatic) { + composite.bodies = composite.bodies.filter(function(body) { return body.isStatic; }); + } else { + composite.bodies.length = 0; + } + + composite.constraints.length = 0; + composite.composites.length = 0; + + return composite; + }; + })(); \ No newline at end of file diff --git a/src/body/World.js b/src/body/World.js index 8b7481b..6740155 100644 --- a/src/body/World.js +++ b/src/body/World.js @@ -17,33 +17,29 @@ var World = {}; * @return {world} A new world */ World.create = function(options) { + var composite = Composite.create(); + var defaults = { gravity: { x: 0, y: 1 }, - bodies: [], - constraints: [], bounds: { min: { x: 0, y: 0 }, max: { x: 800, y: 600 } } }; - return Common.extend(defaults, options); - }; - - /** - * Description - * @method clear - * @param {world} world - * @param {boolean} keepStatic - */ - World.clear = function(world, keepStatic) { - world.bodies = keepStatic ? world.bodies.filter(function(body) { return body.isStatic; }) : []; - world.constraints = []; + return Common.extend(composite, defaults, options); }; // World is a Composite body // see src/module/Outro.js for these aliases: + /** + * An alias for Composite.clear since World is also a Composite (see Outro.js) + * @method clear + * @param {world} world + * @param {boolean} keepStatic + */ + /** * An alias for Composite.add since World is also a Composite (see Outro.js) * @method addComposite diff --git a/src/core/Engine.js b/src/core/Engine.js index bb2f162..1b3f89f 100644 --- a/src/core/Engine.js +++ b/src/core/Engine.js @@ -240,28 +240,31 @@ var Engine = {}; broadphasePairs = [], i; + var allBodies = Composite.allBodies(world), + allConstraints = Composite.allConstraints(world); + Metrics.reset(engine.metrics); if (engine.enableSleeping) - Sleeping.update(world.bodies); + Sleeping.update(allBodies); - Body.applyGravityAll(world.bodies, world.gravity); + Body.applyGravityAll(allBodies, world.gravity); - MouseConstraint.update(engine.mouseConstraint, world.bodies, engine.input); + MouseConstraint.update(engine.mouseConstraint, allBodies, engine.input); - Body.updateAll(world.bodies, delta * engine.timeScale, correction, world.bounds); + Body.updateAll(allBodies, delta * engine.timeScale, correction, world.bounds); // update all constraints for (i = 0; i < engine.constraintIterations; i++) { - Constraint.updateAll(world.constraints); + Constraint.updateAll(allConstraints); } // broadphase pass: find potential collision pairs if (broadphase.controller) { - broadphase.controller.update(broadphase.instance, world.bodies, engine); + broadphase.controller.update(broadphase.instance, allBodies, engine); broadphasePairs = broadphase.instance.pairsList; } else { - broadphasePairs = world.bodies; + broadphasePairs = allBodies; } // narrowphase pass: find actual collisions, then create or update collision pairs @@ -287,12 +290,12 @@ var Engine = {}; for (i = 0; i < engine.positionIterations; i++) { Resolver.solvePosition(pairs.list); } - Resolver.postSolvePosition(world.bodies); + Resolver.postSolvePosition(allBodies); Metrics.update(engine.metrics, engine); // clear force buffers - Body.resetForcesAll(world.bodies); + Body.resetForcesAll(allBodies); return engine; }; @@ -311,7 +314,7 @@ var Engine = {}; Engine.clear(engineA); - var bodies = engineA.world.bodies; + var bodies = Composite.allBodies(engineA.world); for (var i = 0; i < bodies.length; i++) { var body = bodies[i]; @@ -324,7 +327,7 @@ var Engine = {}; if (broadphase.controller === Grid) { var grid = broadphase.instance; Grid.clear(grid); - Grid.update(grid, engineA.world.bodies, engineA, true); + Grid.update(grid, bodies, engineA, true); } } }; @@ -348,7 +351,8 @@ var Engine = {}; Grid.clear(broadphase.instance); if (broadphase.controller) { - broadphase.controller.update(broadphase.instance, world.bodies, engine, true); + var bodies = Composite.allBodies(world); + broadphase.controller.update(broadphase.instance, bodies, engine, true); } }; diff --git a/src/core/Metrics.js b/src/core/Metrics.js index 99ce074..5edc88a 100644 --- a/src/core/Metrics.js +++ b/src/core/Metrics.js @@ -64,14 +64,15 @@ var Metrics = {}; Metrics.update = function(metrics, engine) { if (metrics.extended) { var world = engine.world, - broadphase = engine.broadphase[engine.broadphase.current]; + broadphase = engine.broadphase[engine.broadphase.current], + bodies = Composite.allBodies(world); metrics.collisions = metrics.narrowDetections; metrics.pairs = engine.pairs.list.length; - metrics.bodies = world.bodies.length; + metrics.bodies = bodies.length; metrics.midEff = (metrics.narrowDetections / (metrics.midphaseTests || 1)).toFixed(2); metrics.narrowEff = (metrics.narrowDetections / (metrics.narrowphaseTests || 1)).toFixed(2); - metrics.broadEff = (1 - (metrics.broadphaseTests / (world.bodies.length || 1))).toFixed(2); + metrics.broadEff = (1 - (metrics.broadphaseTests / (bodies.length || 1))).toFixed(2); metrics.narrowReuse = (metrics.narrowReuseCount / (metrics.narrowphaseTests || 1)).toFixed(2); //if (broadphase.instance) // metrics.buckets = Common.keys(broadphase.instance.buckets).length; diff --git a/src/module/Outro.js b/src/module/Outro.js index 71a0207..1b5f0e5 100644 --- a/src/module/Outro.js +++ b/src/module/Outro.js @@ -1,8 +1,9 @@ // aliases -World.addComposite = Composite.add; +World.addComposite = Composite.addComposite; World.addBody = Composite.addBody; World.addConstraint = Composite.addConstraint; +World.clear = Composite.clear; // exports diff --git a/src/render/Render.js b/src/render/Render.js index 49d1506..7c73c75 100644 --- a/src/render/Render.js +++ b/src/render/Render.js @@ -91,6 +91,8 @@ var Render = {}; canvas = render.canvas, context = render.context, options = render.options, + bodies = Composite.allBodies(world), + constraints = Composite.allConstraints(world), i; if (options.wireframes) { @@ -106,35 +108,35 @@ var Render = {}; context.globalCompositeOperation = 'source-over'; /*if (options.showShadows && !options.wireframes) - Render.bodyShadows(engine, world.bodies, context);*/ + Render.bodyShadows(engine, bodies, context);*/ if (!options.wireframes || (engine.enableSleeping && options.showSleeping)) { // fully featured rendering of bodies - Render.bodies(engine, world.bodies, context); + Render.bodies(engine, bodies, context); } else { // optimised method for wireframes only - Render.bodyWireframes(engine, world.bodies, context); + Render.bodyWireframes(engine, bodies, context); } if (options.showBounds) - Render.bodyBounds(engine, world.bodies, context); + Render.bodyBounds(engine, bodies, context); if (options.showAxes || options.showAngleIndicator) - Render.bodyAxes(engine, world.bodies, context); + Render.bodyAxes(engine, bodies, context); if (options.showPositions) - Render.bodyPositions(engine, world.bodies, context); + Render.bodyPositions(engine, bodies, context); if (options.showVelocity) - Render.bodyVelocity(engine, world.bodies, context); + Render.bodyVelocity(engine, bodies, context); if (options.showIds) - Render.bodyIds(engine, world.bodies, context); + Render.bodyIds(engine, bodies, context); if (options.showCollisions) Render.collisions(engine, engine.pairs.list, context); - Render.constraints(world.constraints, context); + Render.constraints(constraints, context); if (options.showBroadphase && engine.broadphase.current === 'grid') Render.grid(engine, engine.broadphase[engine.broadphase.current].instance, context); @@ -154,6 +156,7 @@ var Render = {}; world = engine.world, render = engine.render, options = render.options, + bodies = Composite.allBodies(world), space = " "; if (engine.timing.timestamp - (render.debugTimestamp || 0) >= 500) { @@ -163,7 +166,7 @@ var Render = {}; if (engine.metrics.extended) { text += "delta: " + engine.timing.delta.toFixed(3) + space; text += "correction: " + engine.timing.correction.toFixed(3) + space; - text += "bodies: " + world.bodies.length + space; + text += "bodies: " + bodies.length + space; if (engine.broadphase.controller === Grid) text += "buckets: " + engine.metrics.buckets + space; diff --git a/src/render/RenderPixi.js b/src/render/RenderPixi.js index 5faba68..272a78e 100644 --- a/src/render/RenderPixi.js +++ b/src/render/RenderPixi.js @@ -151,6 +151,8 @@ var RenderPixi = {}; context = render.context, stage = render.stage, options = render.options, + bodies = Composite.allBodies(world), + constraints = Composite.allConstraints(world), i; if (options.wireframes) { @@ -159,11 +161,11 @@ var RenderPixi = {}; RenderPixi.setBackground(render, options.background); } - for (i = 0; i < world.bodies.length; i++) - RenderPixi.body(engine, world.bodies[i]); + for (i = 0; i < bodies.length; i++) + RenderPixi.body(engine, bodies[i]); - for (i = 0; i < world.constraints.length; i++) - RenderPixi.constraint(engine, world.constraints[i]); + for (i = 0; i < constraints.length; i++) + RenderPixi.constraint(engine, constraints[i]); context.render(stage); };