So I wanted to apply a bomb, to my small physics based app I’m creating. However I found out that in Box2D, there’s no built in method to do that. Which after reading a little more into it, makes sense.
So what you do is apply force to all the objects yourself, OR you can throw out X number of Rays (bullets) – and they’ll hit the objects going outward but that’s a bit more expensive for the iPhone. Maybe it’s not, i don’t know but this is what I did.
It’s quick, and doesn’t take into account the proper fall of (inverse square of the distance). I’m not great at writing tutorials, so I’ll post this for now and edit/update it based any questions I receive in the comments.
// Pos comes from the ccTouchesEnded function. I've already converted it to Cocos2D coordinates. -(void) launchBomb:(CGPoint)pos { BOOL doSuction = YES; // Very cool looking implosion effect instead of explosion. //In Box2D the bodies are a linked list, so keep getting the next one until it doesn't exist. for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext()) { //Box2D uses meters, there's 32 pixels in one meter. PTM_RATIO is defined somewhere in the class. b2Vec2 b2TouchPosition = b2Vec2(pos.x/PTM_RATIO, pos.y/PTM_RATIO); b2Vec2 b2BodyPosition = b2Vec2(b->GetPosition().x, b->GetPosition().y); //Don't forget any measurements always need to take PTM_RATIO into account float maxDistance = 9 // In your head don't forget this number is low because we're multiplying it by 32 pixels; int maxForce = 22; CGFloat distance; CGFloat strength; float force; CGFloat angle; if(doSuction) // Get sucked towards the mouse { // Get the distance, and cap it distance = b2Distance(b2BodyPosition, b2TouchPosition); if(distance > maxDistance) distance = maxDistance - 0.01; // Get the strength //strength = distance / maxDistance; // Uncomment and reverse these two. and ones further away will get more force instead of less strength = (maxDistance - distance) / maxDistance; // This makes it so that the closer something is - the stronger, instead of further force = strength * maxForce; // Get the angle angle = atan2f(b2TouchPosition.y - b2BodyPosition.y, b2TouchPosition.x - b2BodyPosition.x); //NSLog(@" distance:%0.2f,force:%0.2f", distance, force); // Apply an impulse to the body, using the angle b->ApplyImpulse(b2Vec2(cosf(angle) * force, sinf(angle) * force), b->GetPosition()); } else // To go towards the press, all we really change is the atanf function, and swap which goes first to reverse the angle { distance = b2Distance(b2BodyPosition, b2TouchPosition); if(distance > maxDistance) distance = maxDistance - 0.01; // Normally if distance is max distance, it'll have the most strength, this makes it so the opposite is true - closer = stronger strength = (maxDistance - distance) / maxDistance; // This makes it so that the closer something is - the stronger, instead of further force = strength * maxForce; angle = atan2f(b2BodyPosition.y - b2TouchPosition.y, b2BodyPosition.x - b2TouchPosition.x); //NSLog(@" distance:%0.2f,force:%0.2f,angle:%0.2f", distance, force, angle); // Apply an impulse to the body, using the angle b->ApplyImpulse(b2Vec2(cosf(angle) * force, sinf(angle) * force), b->GetPosition()); } } }
That’s it – it’s quick and dirty, and probably has some mistakes so feel free to point them out.
Tags: Uncategorized
Love your articles. Keep up the great work.
Thanks for the awesome sample code. Just FYI for anyone that arrives here from google: the current Box2D API method is b->ApplyLinearImpluse with the same arguments.
Np Nick, thanks for the heads up.
This is the number one point of entry for this blog, so im sure people will find that info useful.
I been meaning to update this actually… so maybe ill do that now – cus that doSuction conditional really only differs by 1 line