the actual code is split between a couple of functions in a class, the first 2 blocks are in the init function, and the last one is in the update function. the issue is that whenever I run the code, if the enemy is towards the top left of the player, they end up going down and to the left of the player. I'm guessing that I've done something wrong with math.tan(), though this is my first time using trigonometry in games, so I'm not sure what, I'm going off of this PDF if that helps.

I don't think the problem is in the last part, as it was copy-pasted from another project using the crank as a movement system.

Your snippet doesn’t really explain what you are trying to achieve, but a tangent function returns a slope from an angle. To do the reverse, you need to use arcus tangent (atan).

Unfortunately atan only works for angles from -pi/2 to pi/2, so you need to do some extra math. Something like this (untested):

local angle = math.atan((y - y0)/(x - x0))
if (x <= x0 and angle < 0) then
angle = (2 * math.pi) + angle
elseif (angle < 0) then
angle = math.pi + angle
elseif (angle >= 0 and x > x0) then
angle = angle + (math.pi)
end

swapping it out for atan worked, I’m guessing It’s equivalent to tan^-1? I’ve done trigonometry before, just not in game dev, so I was kind of just flailing around and hoping something worked
the goal I wanted to achieve is to get an enemy to walk towards a target position at a certain speed, I’m doing that by getting the angle to the player (now using atan) then using sin and cos to get the vx and vy. I’m just now realising that I somehow managed to leave out the sin and cos step in the original snippet, sorry about that

after some experimentation, i see what you mean about it only working within a certain range, the behaviour I’m seeing is that it ends up going in the opposite direction from intended whenever It’s on the right half of the screen. I don’t fully understand the if condition you came up with, though my plan is to just flip the velocity if the enemy is to the right of its target, that way it ends up going in the right direction. it would make the heading inaccurate, though I won’t need the heading past this point anyway. that said, if someone can explain what’s going on in the if statement it would be appreciated, both by me and likely other people if they come across this post

I have the solution thanks to this thread, first of all i was using tan instead of atan, which was the problem i was referring to originally, then to solve atan only working between 0 and 180 degrees (or 0 and pi radians) you can check if you're to the right of the target, and if you are, add 180 degrees (pi radians) to the heading.

The snippet was some old code of mine (probably copy-pasted from somewhere), but I can't really remember the details. In nutshell, an unit circle has four quarters that you have to account for - thus the three ifs.

Not sure if the problem you were facing was different, but in my case the problem only surfaced when the target enemy was to the right of the target, and since the direction it would go was directly away, turning it around did the trick