Reputation: 1
I am building a game which has random positioned objects inside the canvas. Depending on the quantity of objects there is a reasonable chance of getting an object placed on top of an other one and having the collision detection triggered.
Is there any easy way of preventing this in physics js?
Upvotes: 0
Views: 154
Reputation: 1193
There are a few ways to do this.
First (and most robust): You could add the collision detection module but not the collision response. Then listen for collision events and remove and re-add as necessary.
eg:
function removeOverlaps( data ){
var collisions = data.collisions
,col
,removed = []
;
for ( var i = 0, l = collisions.length; i < l; ++i ){
col = collisions[ i ];
// ensure that we haven't removed one of the bodies before
if ( Physics.util.indexOf(removed, col.bodyA ) === -1 &&
Physics.util.indexOf(removed, col.bodyB ) === -1
){
// pick bodyA... why not...
removed.push( col.bodyA );
world.remove( col.bodyA );
}
}
}
world.add(Physics.behavior('body-collision-detection'));
world.subscribe('collisions-detected', removeOverlaps);
var tries = 0;
while( tries < maxTries ){
addBodies();
world.step(tries); // "tries" pretends to be a timestamp
if ( world.getBodies().length >= bodiesWeNeed ){
break;
}
tries++;
}
world.unsubscribe('collisions:detected', removeOverlaps);
// continue with simulation...
The other way to do this, which is less accurate but more efficient is to check if the bodies' AABBs overlap
function checkOverlap( bodyA, bodyB ){
var aabbA = bodyA.aabb()
,aabbB = bodyB.aabb()
;
// check if the aabb has separation on the x axis
if (
(aabbA.pos.x + aabbA.halfWidth) < (aabbB.pos.x - aabbB.halfWidth)||
(aabbB.pos.x + aabbB.halfWidth) < (aabbA.pos.x - aabbA.halfWidth)
){
return true;
}
if (
(aabbA.pos.y + aabbA.halfHeight) < (aabbB.pos.y - aabbB.halfHeight)||
(aabbB.pos.y + aabbB.halfHeight) < (aabbA.pos.y - aabbA.halfHeight)
){
return true;
}
return false;
}
while( numBodies < maxBodies ){
var newBody = makeBody();
var toAdd = true;
for (//each body in added bodies)
if ( checkOverlap(newBody, body) ){
toAdd = false;
break;
}
}
if ( toAdd ){
world.add( newBody ); // and maybe add to a list you keep
}
}
hope that helps!
Upvotes: 1
Reputation: 5105
I think you should have a placement phase, where you build up your random positioned objects and then the other phases of your game after this.
During placement you try to add objects randomly and use the collision detection to decide if you have to try again to place the new additon until the random location does not lead to a collision.
In the later phases you change the handling in your collision detection handlers and do whatever you like.
Either replace the handlers during different phases, or differentiate what happens by some mode variable.
Might look funny though, maybe you can do this without rendering the objects or render the objects white on white first and then change colours.
Upvotes: 0