physics based collision detection not working?

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.
User avatar
gladius2metal
Prole
Posts: 26
Joined: Thu Nov 22, 2012 2:08 am

physics based collision detection not working?

Post by gladius2metal »

Hi,
my physics objects (all "dynamic" bodies+shapes+fixtures) don't collide according to the visuals and world:getContactCount(). Although applyForce() works fine. Since the tutorial works fine and I checked both codes several times I guess it is a either a stupid error or something non-obvious for noobs ;)
just did a few more tests, actually now very rarely a collision occurs, which is just more confusing...

I thought it was a "representation problem" (objects displayed at wrong locations) at first, but I tried to draw them only with the physics data (see code in SpaceObject:draw()) and the collisions didn't happen either.

.love attached

thx in advance
gladius
Attachments
second.love
(4.82 KiB) Downloaded 196 times
User avatar
Przemator
Party member
Posts: 107
Joined: Fri Sep 28, 2012 6:59 pm

Re: physics based collision detection not working?

Post by Przemator »

Hey, I'm not a pro but I dedicated quite some time to solving your problem.

First of all, you are doing a hundred things wrong :). You should NOT use applyForce with a dt inside it. You only pass it to world:update.
Also, you DON'T want to use a variable dt in world:update() as it may cause loss of speed of objects in your game.
Next, make sure you set a proper Meter size. You had 64, which made your 20px space ship a micro machine. I set it to 10, so now your spaceship has some 2 meters in size :P.

Now, about the error. You made a mistake in the line when you create a shape. A shape is always attached to the center of the body, so you should write 0,0 instead of x,y.

Moreover, you should not rotate your object like you do, you should use applyTorque.

I corrected all these things for you (except the world:update(dt), which is tricky), some heavy code manipulation, hope you gonna recognize it ;). Hope this helps.
Attachments
second2.love
Second2
(6.74 KiB) Downloaded 203 times
User avatar
gladius2metal
Prole
Posts: 26
Joined: Thu Nov 22, 2012 2:08 am

Re: physics based collision detection not working?

Post by gladius2metal »

wow, thx a lot!!!

setmeter was originally at 2, but prior to sending the attachment I changed it.

gonna try out the new code tomorrow!
User avatar
gladius2metal
Prole
Posts: 26
Joined: Thu Nov 22, 2012 2:08 am

Re: physics based collision detection not working?

Post by gladius2metal »

first, thx a lot the code works great.

I have a few questions:
1) why "alpha" and is there no built-in value in body/shape?

Code: Select all

spaceObject.alpha = 1 -- angular acceleration
2)
Also, you DON'T want to use a variable dt in world:update() as it may cause loss of speed of objects in your game.
do you mean using dt within love.update()? world:update() needs an argument, also world:update(dt) is taken straight from the tutorial.
I am not quite sure if I am off the tracks again or?

3)
Now, about the error. You made a mistake in the line when you create a shape. A shape is always attached to the center of the body, so you should write 0,0 instead of x,y.
I can't find that in the code!?

your code:

Code: Select all

	
spaceObject.body = love.physics.newBody(world, x, y, "dynamic")
spaceObject.shape = love.physics.newRectangleShape(spaceObject.image:getWidth(), spaceObject.image:getHeight())
spaceObject.fixture = love.physics.newFixture(spaceObject.body, spaceObject.shape, spaceObject.density) -- A higher density gives it more mass.	
my old code:

Code: Select all

	
spaceObject.physics.body = love.physics.newBody(world, x, y, "dynamic")
spaceObject.physics.shape = love.physics.newRectangleShape(x, y, spaceObject.image:getWidth(), spaceObject.image:getHeight(), spaceObject.angle)
spaceObject.physics.fixture = love.physics.newFixture(spaceObject.physics.body, spaceObject.physics.shape, spaceObject.density) -- A higher density gives it more mass.	
User avatar
Przemator
Party member
Posts: 107
Joined: Fri Sep 28, 2012 6:59 pm

Re: physics based collision detection not working?

Post by Przemator »

gladius2metal wrote:first, thx a lot the code works great.

I have a few questions:
1) why "alpha" and is there no built-in value in body/shape?

Code: Select all

spaceObject.alpha = 1 -- angular acceleration
http://en.wikipedia.org/wiki/Angular_acceleration

This property is just the desired acceleration, the rate of torque that you want to exert on the body. I put it in object constructor, but it might as well be outside, near the key controls.

linear and angular physics, a simple comparison:

Code: Select all

force = mass * acceleration
[newton] = [kg] * [m/s^2]

torque = inertia * angular_acc
[newton meter] = [kg*m^2] * [1/s^2]
2) do you mean using dt within love.update()? world:update() needs an argument, also world:update(dt) is taken straight from the tutorial.
I am not quite sure if I am off the tracks again or?
when you write world:update(dt), some bad things may happen. For example, try accelerating your space ship and then grab the window with the mouse for 1 second, then release. You will see the game freeze and then the space ship losing its speed.

This happens because when you grab the window, the game is not updated. When you release it, the dt will equal 1 second instead of 1/60. The world:update() is designed for constant dt value. If it varies too much, the simulation will break down. Now, I haven't found an ideal fix for this, you may find some on the forum. For now I suggest doing this:

Code: Select all

world:update(math.min(dt, 1/60))
This bit of code will protect you from having too large dt passed to the world:update.
3) I can't find that in the code!?
My code:

Code: Select all

love.physics.newRectangleShape(WIDTH, HEIGHT)
Your code:

Code: Select all

love.physics.newRectangleShape(x, y, WIDTH, HEIGHT, ANGLE)
If you refer to https://love2d.org/wiki/love.physics.newRectangleShape you will see, that you can just provide WIDTH and HEIGHT, or all 5 arguments. However, X and Y are relative to the center of the body, and you are using world coordinates. So what happens is: a body placed at x=400 has a shape attached at 400 right to its center (so 800 in world coordinates). If you want to use all 5 arguments, you would need to write 0, 0 or rather -width/2, -height/2.

Hope it's clear.
User avatar
gladius2metal
Prole
Posts: 26
Joined: Thu Nov 22, 2012 2:08 am

Re: physics based collision detection not working?

Post by gladius2metal »

thx
User avatar
gladius2metal
Prole
Posts: 26
Joined: Thu Nov 22, 2012 2:08 am

Re: physics based collision detection not working?

Post by gladius2metal »

one final(?) question, I just recognized that my ship actually seems to be limited to a maximum velocity, which I thought I needed to add "manually".
Any hints on how I can calculate the maximum velocity / "terminal velocity" of an object?
User avatar
Przemator
Party member
Posts: 107
Joined: Fri Sep 28, 2012 6:59 pm

Re: physics based collision detection not working?

Post by Przemator »

gladius2metal wrote:one final(?) question, I just recognized that my ship actually seems to be limited to a maximum velocity, which I thought I needed to add "manually".
Any hints on how I can calculate the maximum velocity / "terminal velocity" of an object?
The slowing down of objects (both linear and angular) is currently achieved with:

Code: Select all

spaceObject.body:setLinearDamping(0.5)
spaceObject.body:setAngularDamping(3.0)
If you want to have more control, you would have to disable these.

However, you would have to think what kind of physics reality are you trying to create here. If this is space, then there is no atmosphere, so nothing to hold your space ship back. The space ship would accelerate as long as you deliver fuel to the jet engine.

If you want to introduce atmosphere, then air resistance would come into play. The basic equation for air resistance (drag) is:

Code: Select all

drag = - object_velocity ^ 2 * drag_coefficient 
as you can see, drag is the square of velocity, so if you deliver a constant force to the space ship, the resistance will act in the opposite direction with bigger and bigger force, ultimately matching the it and causing the space ship to stop accelerating.

How to find maximum velocity? At maximum speed the forces are equal:

Code: Select all

engine_force = v * v * drag_coefficient
v = sqrt(engine_force / drag_coefficient)
example: sqrt(1800 newtons / 2 kg/m) = 30 m/s
User avatar
gladius2metal
Prole
Posts: 26
Joined: Thu Nov 22, 2012 2:08 am

Re: physics based collision detection not working?

Post by gladius2metal »

thx, I tried that formular but it is about 3 times off, which is way better than before because it was about 100 times off ;)

formular in pseudocode + code. I assume probably lineardamping and/or meter_pixel_ratio need to be changed/remove:

Code: Select all

force = acceleration * meter_pixel_ratio * mass / lineardamping
v = sqrt (force / lineardaming)

local max_v = math.sqrt( spaceObject.acceleration * METER_PIXEL_RATIO * spaceObject.body:getMass() / spaceObject.body:getLinearDamping())
or maybe my calculation of current velocity is incorrect?

Code: Select all

I use: v_current = v_linear_x * v_linear_x + v_linear_y * v_linear_y

local vx,vy = playerShip.body:getLinearVelocity( )
love.graphics.print("speed      :"..math.floor(math.sqrt(vx^2 + vy^2)), 10, 40)
another possibility would be that I am not patient enough to wait til the speed reaches the maximum, but right now it accelerates up to 199 and then it stays at this value.
User avatar
Przemator
Party member
Posts: 107
Joined: Fri Sep 28, 2012 6:59 pm

Re: physics based collision detection not working?

Post by Przemator »

gladius2metal wrote:another possibility would be that I am not patient enough to wait til the speed reaches the maximum, but right now it accelerates up to 199 and then it stays at this value.
Remember that getVelocity returns pixels per second, not meters per second. I could not grasp the code you pasted, so I'm going to paste mine:

(i'm writing from memory, there may be errors)

Code: Select all

function love.load()
  m = 10
  engine_force = 1600 --N
  drag_coeff = 2 --kg/m
  ship = newShip()
end

function love.update(dt)
  world.update(math.min(dt, 1/60))
  if love.keyboard.isDown("up") then ship.body:applyForce(ship.body:getWorldVector(engine_force * m, 0)) end
  local vx, vy = ship.body:getLinearVelocity()
  local dx = - vx * math.abs(vx) * drag_coeff
  local dy = - vy * math.abs(vy) * drag_coeff
  ship.body:applyForce(dx, dy) -- air resistance
end

--ship.speed = sqrt(vx*vx + vy*vy) / m
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot] and 54 guests