Why is my box2d body lopsided?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Skeletonxf
Citizen
Posts: 87
Joined: Tue Dec 30, 2014 6:07 pm

Why is my box2d body lopsided?

Post by Skeletonxf »

I'm using a number of libraries which may complicate the issue a bit, but essentially I've noticed that applying thrust in the direction of my Body results in it turning anticlockwise. Even if I disable gravity this occurs, and although it happens less at low gravity and at high angular damping, it is still a problem.

I create the body like this, which is using https://github.com/SSYGEN/windfield. Essentially the collider is "a composition of a single body, fixture and shape".

Code: Select all

function factory.ship(gameState, x, y, size, callback)
  local world = gameState.physics.world
  -- create a triangle
  local shipBody = world:newPolygonCollider(
    {-size,-(2*size/3), 0,size, size,-(2*size/3)}
  )
  shipBody:setPosition(x, y)
  local weaponWidth = size*0.2
  -- place each weapon on each side of the ship
  shipWeapon1 = world:newRectangleCollider(
    x - size/2 - weaponWidth/2,
    -size/3,
    weaponWidth,
    size*1.2)
  shipWeapon2 = world:newRectangleCollider(
    x + size/2 - weaponWidth/2,
    -size/3,
    weaponWidth,
    size*1.2)
  -- place joint in centre of player, the weapons and the main
  -- body should collide with each other
  world:addJoint('WeldJoint', shipWeapon1, shipBody, x, y, true)
  world:addJoint('WeldJoint', shipWeapon2, shipBody, x, y, true)
  -- make collisions inellastic
  shipBody:setRestitution(0.2)
  shipWeapon1:setRestitution(0.2)
  shipWeapon2:setRestitution(0.2)
  -- minimise unwanted spinning, especially on welded weapons
  shipBody:setAngularDamping(20)
  shipWeapon1:setAngularDamping(20)
  shipWeapon2:setAngularDamping(20)
  -- make movement slow down
  shipBody:setLinearDamping(0.1)
  shipWeapon1:setLinearDamping(0.1)
  shipWeapon2:setLinearDamping(0.1)
...
If I remove the joint lines above then pressing up has the desired effect of moving the body in the direction it is facing (rotation by 90 degrees so the direction it is facing is the same as visually) without causing an rotation.

Code: Select all

    if gameState.inputs.up.down then
      local angle = player:getAngle() + math.pi/2
      local dx, dy = 50*math.cos(angle), 50*math.sin(angle)
      player:applyLinearImpulse(dx, dy)
    end
This makes me think the welds are causing the center of mass to be off centre, but visually they appear correct?

Image
Attachments
ship.love
(72.46 KiB) Downloaded 125 times
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: Why is my box2d body lopsided?

Post by pgimeno »

I can't reproduce the effect you mention with the attached .love file, but I see it start to turn left slowly immediately after I turn right. After a long turn left, it's stable as long as I don't turn right.

You can check the CoM of a body using regular body functions: https://love2d.org/wiki/Body:getMassData

I don't know how to use the library you're using.
drunken_munki
Party member
Posts: 134
Joined: Tue Mar 29, 2011 11:05 pm

Re: Why is my box2d body lopsided?

Post by drunken_munki »

I tried your code and can confirm that thrust forward veers the ship port-side.

I can confirm removing the joints removes the problem.

I removed the left weapon only and the ship now veers starboard.

Something is wrong deeper inside man, I made the guns shorter and moved them out of the main body:

Code: Select all

  shipWeapon1 = world:newRectangleCollider(
    x - size/2 - weaponWidth/2,
    size/3,
    weaponWidth,
    size*0.3)
  shipWeapon2 = world:newRectangleCollider(
    x + size/2 - weaponWidth/2,
    size/3,
    weaponWidth,
    size*0.3)
And she flies true now.

So maybe that type of collider doesn't work when intersecting the body, or it's off in the x direction. I tried to debug it but it's late and the ship is spawned upside down :{

Good luck.
Skeletonxf
Citizen
Posts: 87
Joined: Tue Dec 30, 2014 6:07 pm

Re: Why is my box2d body lopsided?

Post by Skeletonxf »

Thanks for the help

I've 'solved' it by turning off collisions between the weapons and the main body by changing the

Code: Select all

world:addJoint('WeldJoint', shipWeapon1, shipBody, x, y, true)
world:addJoint('WeldJoint', shipWeapon2, shipBody, x, y, true)
lines to

Code: Select all

world:addJoint('WeldJoint', shipWeapon1, shipBody, x, y, false)
world:addJoint('WeldJoint', shipWeapon2, shipBody, x, y, false)
Now the weapons can be knocked sideways and flop at very high impact collisions but the ship flies true.

So it seems that the collisions during flight with the intersecting colliders is causing the issue. I suppose I should forward this onto windfield.
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: Why is my box2d body lopsided?

Post by pgimeno »

I'm surprised it uses a joint in the first place, as opposed to a fixture.
Skeletonxf
Citizen
Posts: 87
Joined: Tue Dec 30, 2014 6:07 pm

Re: Why is my box2d body lopsided?

Post by Skeletonxf »

That may be my lack of understanding of how best to use box2d
User avatar
pgimeno
Party member
Posts: 3674
Joined: Sun Oct 18, 2015 2:58 pm

Re: Why is my box2d body lopsided?

Post by pgimeno »

I'm not experienced enough to tell you what are weld joints useful for, but I know that all kinds of joints are somewhat elastic, while fixtures are solid and unmovable. For this application, I think a fixture would work better, as you probably don't want the weapons to wobble when hit.
JoshGrams
Prole
Posts: 33
Joined: Sat May 27, 2017 10:58 am

Re: Why is my box2d body lopsided?

Post by JoshGrams »

Skeletonxf wrote: Wed Mar 28, 2018 12:31 pm I've 'solved' it by turning off collisions between the weapons and the main body by

it seems that the collisions during flight with the intersecting colliders is causing the issue. I suppose I should forward this onto windfield.
No, that's not a bug. If you're telling it that the welded together objects should collide, then you're telling Box2D that you want it to make sure that they don't overlap. So it will try to push them apart. Since those forces are usually pretty large, if rounding or anything makes it so that they're not perfectly balanced then it will often make things move funny.

There are cases where it's useful to have overlapping bodies detect collisions and then disable the collision response forces in a collision callback. But usually if things are supposed to overlap, telling the physics engine that it should try to keep them separated, is a bug in *your* code, not some library or the physics engine.

If you look at the docs for love.physics.newWeldJoint (or any of the other joint creation functions) you'll see that the collideConnected parameter defaults to false. You have to deliberately turn it on, which you should only do if you have a particular reason for it.

--Josh
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot] and 9 guests