I’m working on click(touch)-to-move for my project and the script is not consistent. I found a script here on the forum and added a few things, like acceleration, but this issue was happening before that as well. Basically, sometimes when the GO reaches the point that was clicked it stops and sometimes it doesn’t. There are no error messages so I don’t know why it’s happening. It seems to be that when you click on the screen further away from the GO it’s more likely to not stop than when you click close to it.
The main collection only has 1 GO (player), and the GO has only 1 script(below) and a sprite. No collision objects of any kind, so there’s nothing to complicate things.
My question is, simply, does anyone know why this code would work sometimes but not other times? And a follow up question; if it’s not obvious, what debugging things can I do to try to solve it?
local input_touch = hash("touch")
local function target_reached(target, current)
return math.floor(target.x) == math.floor(current.x) and math.floor(target.y) == math.floor(current.y)
end
function init(self)
msg.post(".", "acquire_input_focus")
self.target_position = vmath.vector3()
self.direction = vmath.vector3()
self.moving = false
self.speed = 0
self.acceleration = 5
end
function update(self, dt)
if self.moving then
local position = go.get_position()
if vmath.length(self.direction) > 0 then
self.speed = self.speed + self.acceleration * dt
position = position + self.direction * self.speed * dt
go.set_position(position)
end
if target_reached(self.target_position, position) then
self.speed = 0
self.moving = false
self.target_position = vmath.vector3()
go.set_position(position)
end
end
end
function on_input(self, action_id, action)
if action_id == input_touch and action.released then
self.target_position = vmath.vector3(action.x, action.y, 1)
self.moving = true
self.direction = vmath.normalize(self.target_position - go.get_position())
end
end
I would not use this
to check that current reached target. In my opinion this is too prone to approximation errors. I would prefer something like:
local MIN_DIST = 1.0 (or some other small value)
local dx = current.x - target.x
local dy = current.y - target.y
return dx * dx + dy * dy < MIN_DIST
However, I may be wrong and this is not the problem in your code.
Ciao!
3 Likes
Well, that seems to have worked. I’ve clicked around for a few minutes and it always stops. Thanks!
3 Likes
Can confirm this problem. I was using math.floor and I had several instances where it never reaches within range of the target.
This suggestion worked like a charm.
Thanks much (4 years later).
2 Likes
For reference, this is from the tutorial puzzle where I needed to make the tanks move to random targets and then move to a new random target. (War Battles Tutorial)
if target_reached(self.target_position, self.current_position) then
self.target_position = random_vector()
self.direction = vmath.normalize(self.target_position-self.current_position)
local new_position = self.current_position + self.direction * self.speed * dt
go.set_position(new_position)
self.current_position = go.get_position()
else
self.direction = vmath.normalize(self.target_position-self.current_position)
local new_position = self.current_position + self.direction * self.speed * dt
go.set_position(new_position)
self.current_position = go.get_position()
end
update_animation(self)
With math.floor, the test fails most often and they never get a new position.
local function target_reached(target, current)
return math.floor(target.x) == math.floor(current.x) and math.floor(target.y) == math.floor(current.y)
end
With the minimum test here, it works every time.
local function target_reached(target, current)
local min_dist = 1.0
local dx = current.x - target.x
local dy = current.y - target.y
return dx * dx + dy * dy < min_dist
end
random_vector() works like this:
local function random_vector()
local screen_width = tonumber(sys.get_config("display.width"))
local screen_height = tonumber(sys.get_config("display.height"))
local random_vector = vmath.vector3(math.random(5,screen_width), math.random(5,screen_height), 1)
return random_vector
end