GO not always stops when target reached [SOLVED]

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