Hi everyone,
Just got back to defold after a long absence and excited to try new things!
I’ve been setting myself up to create a small class to handle physics in a new prototype i’m working on (I was surprised that there was nothing in the asset library for it actually).
Unfortunately, i’m facing an old nemesis: when colliding, the object slowly sink into the other one.
I’m using the collision_handler from one of the tutorial but it doesn’t work out.
I’ve put together a quick test project to isolate the issue, but can’t figure it out.
Could it be that the abstraction is taking too much time from the physic simulation?
The BODY class:
local class = require 'main.30log'
M = class("Body")
function M:init(position)
self.position = position or vmath.vector()
self.velocity = vmath.vector3()
self.forces = {}
self.correction = vmath.vector3()
self.active = true
end
function M:update(dt)
if self.active then
self:calculatePhysics(dt)
self.correction = vmath.vector3()
end
end
function M:calculatePhysics(dt)
local position = self.position
local velocity = self.velocity
local forces = self.forces
local acceleration = vmath.vector3()
for i, f in pairs(forces) do
acceleration = acceleration + f
end
velocity = velocity + acceleration * dt
position = position + velocity * dt
self.velocity = velocity
self.position = position
return velocity, position
end
function M:impulse(f)
self.velocity = self.velocity + f
end
function M:collision(c)
self.handle_obstacle_contact(self, c.normal, c.distance)
end
function M.handle_obstacle_contact(self, normal, distance)
-- project the correction vector onto the contact normal
-- (the correction vector is the 0-vector for the first contact point)
local proj = vmath.dot(self.correction, normal)
-- calculate the compensation we need to make for this contact point
local comp = (distance - proj) * normal
-- add it to the correction vector
self.correction = self.correction + comp -- CULPRIT!
-- apply the compensation to the player character
self.position = self.position + comp
-- project the velocity onto the normal
proj = vmath.dot(self.velocity, normal)
-- if the projection is negative, it means that some of the velocity points towards the contact point
if proj < 0 then
-- remove that component in that case
self.velocity = self.velocity - proj * normal
end
end
return M
The PLAYER script:
local body = require 'main.body' -- Req the class
function init(self)
self.body = body(go.get_position()) -- Add a BODY to the GO
self.body.forces = {vmath.vector3(0, -1000, 0)} -- Add a constant force (Gravity)
end
function update(self, dt)
self.body:update(dt) -- update the physics
go.set_position(self.body.position) -- update position accordingly
end
function on_message(self, message_id, message, sender)
if message_id == hash("contact_point_response") then
self.body:collision(message) -- handle collision
end
end
I thought that canceling the projection should be enough to stop it from sinking…
One of the reason i want to get my own physic class is also because i want to be able to throttle the physic update rate for doing slowmo…
Thanks in advance for your help!
K
EDIT2: Thanks britzl!