My character is slowly drifting when Im not pressing anything.
It’s my first attempt making a smooth movement script, I couldn’t find any good examples online so any help is appreciated
Script
go.property("acceleration", 80)
go.property("maxspeed", 3)
go.property("friction", 20)
go.property("w", hash("w"))
go.property("a", hash("a"))
go.property("s", hash("s"))
go.property("d", hash("d"))
function init(self)
msg.post(".", "acquire_input_focus")
msg.post("@render:", "use_fixed_projection", { near = -1, far = 1, zoom = 1 })
msg.post("/cam#camera", "acquire_camera_focus")
self.delta = 0
self.direction = vmath.vector3()
end
function update(self, dt)
self.delta = dt
local position = go.get_position() + (dt * self.acceleration) * self.direction
go.set_position(position)
if self.direction.x > 0 then
self.direction.x = self.direction.x - self.friction * dt
elseif self.direction.x < 0 then
self.direction.x = self.direction.x + self.friction * dt
end
if self.direction.y > 0 then
self.direction.y = self.direction.y - self.friction * dt
elseif self.direction.y < 0 then
self.direction.y = self.direction.y + self.friction * dt
end
end
function on_input(self, action_id)
if action_id == self.a then
if self.direction.x > -self.maxspeed then
self.direction.x = self.direction.x - self.acceleration * self.delta
end
elseif action_id == self.d then
if self.direction.x < self.maxspeed then
self.direction.x = self.direction.x + self.acceleration * self.delta
end
elseif action_id == self.w then
if self.direction.y < self.maxspeed then
self.direction.y = self.direction.y + self.acceleration * self.delta
end
elseif action_id == self.s then
if self.direction.y > -self.maxspeed then
self.direction.y = self.direction.y - self.acceleration * self.delta
end
end
end
You need an extra check after applying self.friction
to self.direction
. Rather than stopping at zero, the value ends up going the other side of zero which introduces that drift you’re seeing.
I wont write it all out but here’s what I mean:
if self.direction.x > 0 then
self.direction.x = self.direction.x - self.friction * dt
if self.direction.x < 0 then
self.direction.x = 0 -- clamp to zero
end
end
4 Likes
Thanks!
I’ll leave the full script here, maybe it’ll help someone in the future
movement.script
go.property("acceleration", 80)
go.property("maxspeed", 3)
go.property("friction", 15)
function init(self)
msg.post(".", "acquire_input_focus")
msg.post("@render:", "use_fixed_projection", { near = -1, far = 1, zoom = 1 })
msg.post("/cam#camera", "acquire_camera_focus")
self.w = hash("w")
self.a = hash("a")
self.s = hash("s")
self.d = hash("d")
self.delta = 0
self.direction = vmath.vector3()
end
function update(self, dt)
self.delta = dt
local position = go.get_position() + (dt * self.acceleration) * self.direction
go.set_position(position)
if self.direction.x > 0 then
self.direction.x = self.direction.x - self.friction * dt
if self.direction.x < 0 then
self.direction.x = 0
end
elseif self.direction.x < 0 then
self.direction.x = self.direction.x + self.friction * dt
if self.direction.x > 0 then
self.direction.x = 0
end
end
if self.direction.y > 0 then
self.direction.y = self.direction.y - self.friction * dt
if self.direction.y < 0 then
self.direction.y = 0
end
elseif self.direction.y < 0 then
self.direction.y = self.direction.y + self.friction * dt
if self.direction.y > 0 then
self.direction.y = 0
end
end
end
function on_input(self, action_id)
if action_id == self.a then
if self.direction.x > -self.maxspeed then
self.direction.x = self.direction.x - self.acceleration * self.delta
end
elseif action_id == self.d then
if self.direction.x < self.maxspeed then
self.direction.x = self.direction.x + self.acceleration * self.delta
end
elseif action_id == self.w then
if self.direction.y < self.maxspeed then
self.direction.y = self.direction.y + self.acceleration * self.delta
end
elseif action_id == self.s then
if self.direction.y > -self.maxspeed then
self.direction.y = self.direction.y - self.acceleration * self.delta
end
end
end
2 Likes