Hello there, how can I use Box2d minimally and just for collision detection ? Do I still need to define a ground box,etc. ? Thanks in advance.
Using Box2d just for collision detection(no physics)
(41 posts) (11 voices)-
Posted 2 years ago #
-
I'm not sure, because I'm noob too with physics engine, but I think even if you just want to use Box2d for collision detection you must provide it the minimal things for calculations, and I think ground box is include in the minimal part. I think if the ground box wasn't necessary it will not be included in all samples and tutorials.
Regards,
Posted 2 years ago # -
I'm interested in this too, anyone have info?
Posted 2 years ago # -
With version 2.1.0 shapes are now extracted out of b2bodies so you can do collision detection without needing to setup box2d state. So yeah you don't need a ground body since you don't even need a b2World.
I'm looking at some testbed examples and it seems to do it with:
b2CollidePolygons
b2CollideCircles
b2CollidePolygonAndCircleSo if I want a poly-poly collision
I create a b2Manifold (really easy just make one).
Now I'm assuming you should know what your shapes are and where they're located.So create a b2PolygonShape (I don't think I need to explain this since you've done this alot)
Create a b2Transform for that shape and set the world position and angle
b2Transform::Set(const b2Vec2& p, float32 angle)Now calling b2CollidePolygons will take your manifold and populate it with local collision points.
void b2CollidePolygons( b2Manifold* manifold, const b2PolygonShape* polygon1, const b2Transform& xf1, const b2PolygonShape* polygon2, const b2Transform& xf2);Example:
b2Manifold manifold; b2PolygonShape A,B; //... store the width.height with setBox for the shape region b2Transform transA, transB; //... store the position location and angle of shape A and B into transform with Set. b2CollidePolygons(&manifold, A, transA, B, transB); if(manifold.m_pointCount > 0){ NSLog(@"collided"); }If you just want to see if they collide and don't care about the collision point then you can just check if manifold.m_m_pointCount > 0
But if you want to get the points you probably want to convert the local manifold points to a b2WorldManifold for world coordinates.
void b2WorldManifold::Initialize(const b2Manifold* manifold, const b2Transform& xfA, float32 radiusA, const b2Transform& xfB, float32 radiusB);Then there should be two collided points for each contact from the other shape. Convert that to your pixel space ratio and you're done.
// Example
b2WorldManifold worldManifold; // put below all the code above worldManifold.Initialize(&manifold, transA, A.m_radius, transB, b.m_radius); NSLog(@"collided point (%f, %f)", worldManifold.m_points[0].x * PTM_RATIO, worldManifold.m_points[0].y * PTM_RATIO);Posted 2 years ago # -
Thanks for your great reply, Lam. I really appreciate it.
Posted 2 years ago # -
Hey Lam,
How can we have some debugDraw now that we don't have a world ?
Thanks.Posted 2 years ago # -
Yes you can have debug drawing still but...
You'd do your own drawing manually like how you're manually using collision detection.
If you want to draw those shapes then store it as an attribute/class variable. Then you can use it during the overridden draw call.
Draw debug data is doing pretty much the same thing so you can dig through it and understand the draw code.
You can instantiate a new GLESDebugDraw if you don't have a world. Now you can use it to draw again by explicitly passing in the shapes instead.
Or you can use DrawingPrimitives.m which house c functions for rendering shapes and lines as well.
All you need to do is understand what to pass into those functions but it's self explanatory so I don't think I need to explain that.
Once you've overridden the draw function and added the drawing code for those shapes you should see it on the screen.
Posted 2 years ago # -
I like this approach for it simplicity. But when I tried using b2CollidePolygons(&manifold, A, transA, B, transB);
I got the error r: cannot convert 'b2PolygonShape' to 'const b2PolygonShape*' for argument '2' to 'void b2CollidePolygons(b2Manifold*, const b2PolygonShape*, const b2Transform&, const b2PolygonShape*, const b2Transform&)'.
What am I doing wrong here?
Thanks.Posted 2 years ago # -
It's probably your argument passing.
Are you passing the address?
Posted 2 years ago # -
Got that right. Can you direct me to some of the testbed you mentioned for better understanding the Box2D handling this approach.
Thank you.Posted 2 years ago # -
PolyCollision.h in external/Box2d/Testbed/Tests provides the simple collision detection routine.
Posted 2 years ago # -
I don't know this helps you - however what you would want to do is set your objects as sensors. Then use a contact listener to yell out - who collided, when, where, and with what whom.
Here's what I'm using for that
Header file
#import "SunnyObject.h" #import "ContactListener.h" #import "Box2D.h" #import "b2Contact.h" class ContactListener : public b2ContactListener { public: ContactListener(); void* userData; /// Use this to store application specific body data. void BeginContact(b2Contact* contact); void EndContact(b2Contact* contact); };The .mm file
#import "ContactListener.h" #import "Box2D.h" #import "b2Contact.h" #import "GameScene.h" #import "SunnyObject.h" // Implement contact listener. ContactListener::ContactListener(){}; void ContactListener::BeginContact(b2Contact* contact) { b2Fixture* fixtureA = contact->GetFixtureA(); SunnyObject* actorA = (SunnyObject*) fixtureA->GetBody()->GetUserData(); b2Fixture* fixtureB = contact->GetFixtureB(); SunnyObject* actorB = (SunnyObject*) fixtureB->GetBody()->GetUserData(); // Return world box touch if(actorA == nil || actorB == nil) return; // For debug - randomly scale the objects so u can tell which were hit [actorA setScale:CCRANDOM_0_1() + 0.5]; [actorB setScale:CCRANDOM_0_1() + 0.5]; } // Implement contact listener. void ContactListener::EndContact(b2Contact* contact) { b2Fixture* fixtureA = contact->GetFixtureA(); SunnyObject* actorA = (SunnyObject*) fixtureA->GetBody()->GetUserData(); b2Fixture* fixtureB = contact->GetFixtureB(); SunnyObject* actorB = (SunnyObject*) fixtureB->GetBody()->GetUserData(); if(actorA == nil || actorB == nil) return; }In your scene which contains a box2d world:
//In the game _contactListener = new ContactListener(); _world->SetContactListener(_contactListener);When you create a body, simple set
b2Body* b; b->SetSensor(true);THERE IS A BUG IN THE CURRENT VERSION OF BOX2D USED IN COCOS2D 8.2!! (confirmed by erin catto)
See this post I made about the bug:
http://www.cocos2d-iphone.org/forum/topic/2734Good luck!
Oneday,
http://littlephysics.comPosted 2 years ago # -
Back from the swine flu thanks for help Lam. Still when I tried to put the function b2CollidePolygons in my Tick routine my application crashed.
My testing application combined 2 sprites(png file). both sprites are moving with the Move to command and I expect the b2CollidePolygons to detect collision between the 2 sprites. I set the box and store location transA and transB.
My sprites are moving only horizontally and I assume no world definition or contactListener is needed. So I try to put the the detection part in the Tick routine.
Any idea what I'm doing wrong in my approach?
Thank you.Posted 2 years ago # -
I'm using box2d to detect collisions without physics response in my current game, although I am creating a world and do have a contact listener set up.
I know this is a non-answer, but is there a specific reason you aren't just creating a b2world?
Posted 2 years ago # -
I'm trying to follow Lam suggestions 4 days ago that simply collision detection in case you do not need gravity (see title of this issue Using Box2d just for collision detection(no physics)). So I would like to use both approaches but start with no physics since in my case the sprites are moving horizontally and it seems it will simply the code.
Posted 2 years ago # -
If you sent something to have a density of 0, it won't be affected by gravity.
I'm using it in this way (collision only, no reaction) doing the same thing, and it's working well for me - however I understand your reasoning.I think trying to wrestle with the engine, in a way it was not really designed (or at least workflow optimized) to use will end up in more work. You might have to institute more workarounds later, and so fourth)
That's my opinion, though and of course there's no wrong way to go about it.
Posted 2 years ago # -
@onedatitwillmake
Umm... Erin Catto extracted out b2Shapes and created b2Fixtures for specifically this reason. He created examples to show how to use it so I'm not sure how doing this is wrong or "it was not really designed for" since he designed it for this specific purpose.@elik
Wow... hope you are recovering well. Do ask if it's not working.Posted 2 years ago # -
Well I definitely didn't know that, and i'm definitely wrong.
Posted 2 years ago # -
@Elik
It'll help if you can provide some code that crashes and if you could print a backtrace in the gdb that might also help. If it's too hard to figure out the problem I could also createa a quick cocos-box2d template of this.Posted 2 years ago # -
@Elik - With the new Box2d (i.e. the one cocos2d is using) you don't have to define a ground box or bounding dimensions for the world. You can also set the world gravity to 0. You can move your bodies horizontally by adjusting their LinearVelocity. If you also set your bodies to be "bullets" and move them in the Box2d world then they will not pass through each other whereas with the approach you are intending if the velocities are sufficiently high your sprites will pass through each other.
Posted 2 years ago # -
Thanks Lam. Trying to follow your steps I only try a test of one to one collision of two sprites. My understanding is that we do not need in this case to create body or fixture for the sprites. I did not understand the part you're talking about the template. But before I bother you with my code It might help to get such a template.
Thanks for your concern.Posted 2 years ago # -
@Elik
Yeah you are by-passing body and fixture creation. It's pretty transitive, since you need a world to create bodies and you need bodies to create fixtures.Steve is correct for collision detection for fast shapes. You would need to implement your own continuous collision detection routine to be able to handle fast shapes missing each other
What you are intending to do with simple collision detection?
Posted 2 years ago # -
@Elik
Ok well I guess maybe my tutorial isn't quite understandable but I've created the project to show the idea of the collision detection.Posted 2 years ago # -
Lam, look what the doctor would subscribe. I see your point and I'll try to do the same with sprites.
By the way, I'm using cocos 0.8.2 and when I compile project including yours I get hundreds of warning errors.
I've tried all the suggested solutions from the forum w/o any success.
Do you experience the same issue when compiling with Box2D?
I'll keep you posted and thanks for the collision detection ideas.Posted 2 years ago # -
@mrgando
Glad to have helped@Elik
Don't worry about the warnings. I used the base cocos box2d template and they've always had those warnings. There's a post about box2d warnings a while back explaining how to remove them and if your project doesn't have warnings then it's all fine.Posted 2 years ago # -
@Steve
Glad you mention the fast moving object issue but this is for the next phase. Thanks.@Lam
I forgot to answer your question from 23 hours ago. My scene is combined from very slow moving sprites and very fast moving objects.
Right now I'm concentrating on the slow objects and I'll try to implement it as mentions with sprite. I do need to find the way to attach the polygons shapes to the sprites w/o fixtures or body.
Thank you all.Posted 2 years ago # -
Out of curiosity what are the benefits of using this method. Is it significantly faster than actually having a box2d world?
In my own project, im creating a box2d world however I'm using a contact listener, and most of my objects are sensors. It works fine, and i have no interest in changing it at this point as i'm nearly done.
However, im curious what the benefits of this type implementation.
~Maria
Posted 2 years ago # -
I think it's similar to the problem of.
"Using a flamethrower to light a candle."You could:
Set up a b2world. Create a body sensor. Sub-classing the ContactListener to handle the contacts. Call the step method -> Just to check if the temporary shape is in contact.or
call b2Collide* to check if that temporary shape is in contact.
I'm not advising against setting up a box2d world. I'm just saying that at some point in your game state you probably need to check for intersection or collision in the simplest manner possible. This is what b2Collide* is good for.
And I wouldn't give an estimate on how faster it is than a b2World. It's a component of b2Worlds collision resolution phase so it's pretty darn fast in itself but that's not the point of using it. The point is to do a quick collision check in the most relatively painless manner possible.
I use b2World (and sensors) when I know I need a persistent region to check collisions and I use b2Collide* when it's a temporary quick check for collisions that I'll throw away.
Are they exclusive?
Posted 2 years ago # -
I see so this is a replacement to the former querying AABB type methods in previous versions. You're right that is useful!
Posted 2 years ago #
Reply »
You must log in to post.