Page 1 of 1

Enemy following player

Posted: Wed Jan 16, 2013 8:55 pm
by Linuus
I'm trying to make an enemy follow the player using trigonometry for smooth movement in every direction.
It works fine except for negative x movement, where it just keeps walking to the right instead of left.
Is the math wrong?

Code: Select all

--Calculate distance between enemy and player
distX =  playerX - enemyX
distY =  playerY - enemyY

--Calculate the angle (direction to run)
--sin(A) = a/c
--sin(A)= a/(a^2+b^2)
--A = arcsin(a/(a^2+b^2))
dir = math.asin(distY/(math.sqrt((distY^2)+(distX^2))))

--Move in towards player
v.x = v.x + (50 * math.cos(dir)) * dt
v.y = v.y + (50 * math.sin(dir)) * dt

Re: Enemy following player

Posted: Thu Jan 17, 2013 5:13 am
by Qcode
Linuus wrote:

Code: Select all

--Calculate distance between enemy and player
distX =  playerX - enemyX
distY =  playerY - enemyY
I'm no math whiz but does this work?

Code: Select all

--Calculate distance between enemy and player
distX =  math.abs(playerX) - math.abs(enemyX)
distY =  math.abs(playerY) - math.abs(enemyY)

Re: Enemy following player

Posted: Thu Jan 17, 2013 6:49 am
by micha
The problem in your code is, that you use sine for determining the angle. For example the sine of 80° is the same as the sine of 100° (symmetric around 90°). That's why you code cannot distinguish between these two cases. The same problem holds for cos and tan.

If you really need to calculate the angle, then use atan2. This is a function that takes two arguments (x and y) and correctly calculates the angle of the corresponding line segment.

Code: Select all

distX =  playerX - enemyX
distY =  playerY - enemyY
angle = math.atan2(distX,distY)
However, in your case you don't even need to calculate the angle. Look: First you calculate the angle by an inverse of a trigonometric function and then you apply a trigonometric function to it, to get a vector again. You can save one step with the following approach:
First calculate the distance vector. Then calculate the distance and divide the distance vector by it. You get a vector of length one, that points into the desired direction. You then only have to multiply this by the movement speed of your enemy:

Code: Select all

distX =  playerX - enemyX
distY =  playerY - enemyY
distance = math.sqrt(distX*distX+distY*distY)
velocityX = distX/distance*speed
velocityY = distY/distance*speed
v.x = v.x + velocityX*dt
v.y = v.y + velocityY*dt
Note: The only case where you really need an angle, is when you want to rotate the image of your enemy. The love.graphics.draw routine needs an angle. In all other cases you can avoid calculating angles.

Re: Enemy following player

Posted: Thu Jan 17, 2013 9:24 am
by Linuus
Hm.. how stupid of me!

Thank you so much! :)

Re: Enemy following player

Posted: Thu Jan 17, 2013 11:58 am
by bartbes
I'd like to note that math.atan2 wants its arguments y, x, not x, y.