Box2D suggestions

Issue #1365 new
itraykov created an issue

Hello, first of all I'd like to thank everybody working on the Love2D back-end. Keep up the great work! I make games primarily using Box2D and have a few suggestions:

1.Small redundancy in the setMass API: body:setMass(mass) and body:setMassData(x,y,mass,inertia) Could be merged into: body:setMass(mass, x,y, inertia) -- where the last 3 arguments are optional

2.I propose an efficient way of checking for "touching" contact between two bodies Please consider including the following function on the back-end. I know it can be done from Lua, but it's quite common. My games run this code all the time for things like sensors/triggers - I suspect the same is true for others, Pseudocode:

function Body:isTouching(other)
  assert(self ~= other)
  -- iterate possible collisions
  local contacts = self:getContactList()
  for i = 1, #contacts do
    if contacts[i]:isTouching() then
      -- return true if contacts[i].edge.other == other
    end
  end
  return false
end

3.Regarding Contact:getFixtures(): It's kind of a hassle to use contactLists when you don't have access to contact.edge.other which is designed to "provide quick access to the other body attached." http://www.learn-cocos2d.com/api-ref/1.0/Box2D/html/structb2_contact_edge.html Game logic deals with bodies, which is common practice in Box2D, so it's kind of a useful to have access to "contact.edge.other". What I'm saying is that it would be good to have something like contact:getOtherBody()

Thanks for reading and much love. :)

Comments (16)

  1. Alex Szpakowski

    I think a typical way people might do an isTouching is to use Fixture:setUserData to associate a table with a fixture, and then use the begin/end contact callbacks on the World to set state on a fixture's associated table and query that in other code. Not that it disqualifies the suggestions, but there are other ways to be efficient.

  2. itraykov reporter

    Alex, the collision callbacks are good if you want to check every body in the simulation - so you end up running Lua code for every collision event (not very efficient in my case). On the other hand, ContactLists are better in cases where you only have a few triggers in the scene and you don't care for the rest of the simulation.

  3. Alex Szpakowski

    This may not be important for your specific use case, but I tend to be hesitant to make non-callback collision detection preferable, since (from box2d's manual):

    Accessing contacts off b2World and b2Body may miss some transient contacts that occur in the middle of the time step. Use b2ContactListener (i.e. World callbacks in LÖVE) to get the most accurate results.

  4. itraykov reporter

    It's true, there are "transient" contacts (due to Box2D's sub-stepping). Collision callbacks are good for certain things like playing sound effects or when the order of events is important. The downside is that there may be thousands or tens of thousands of callbacks per frame (plus you're not allowed to make changes to the simulation during callbacks). For resting contact and triggers, "contactlists" are typically the way the go.

  5. itraykov reporter

    Alex, thanks for adding this, but I think there is a small omission: if (ce->other == otherbody) should be: if (ce->other == otherbody && ce->contact->IsTouching())

  6. itraykov reporter

    Hey Alex, thanks so much for adding my previous suggestion. I've been doing some profiling and have noticed a common bottleneck:

    Basically, I want to sync the positions of box2d bodies with sprites on the screen. I am running the following code for each body:

    x,y = body:getPosition()
    r = body:getAngle()
    

    I believe that merging these two, would reduce the number of function calls in half:

    x,y,r = body:getTransform()
    

    I know this doesn't seem like a big deal - but might be more noticeable on mobile devices. Furthermore, this sort of code is very common. In fact, it could be considered 'critical' since it needs to run all the time. My hope is that code like this would become super efficient - to the point that it doesn't even appear in the profiler report. Of course, having body:setTransform(x,y,r) would be good too, although it's not as important in my case. :)

    Please let me know what you think, Ivan

  7. Log in to comment