[SOLVED] Math + angle + following object on click

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
User avatar
var77
Citizen
Posts: 52
Joined: Wed May 02, 2018 1:57 pm

[SOLVED] Math + angle + following object on click

Post by var77 »

Hi everyone,

It's been a while to me on posting something on that forum that I also had to change my account, nevermind.
I got a little Math problem i guess with something that i couldn't figure out with research on that forum.

More about my issue, i was trying to do a simple following object on click that work pretty well (like in any
point and click), but when i wanted to add the angle about the click position something wrong happend.


More about the code:

Code: Select all

-- my object 
user = { x = screen.w/8, y = screen.h/2 + screen.h/8, w=32, h=32, speed = 150, scale = 3, img = nil, angle = 0}
--mouse position
mpX = 0
mpY = 0

--my load function
function love.load(arg)
user.img = love.graphics.newImage('assets/2.png')
user.img:setFilter("nearest", "nearest", 0)
end

-- my update function
function love.update(dt)
if love.mouse.isDown(1) then	
	mpX = love.mouse.getX()
	mpY = love.mouse.getY()
	
	user.angle = math.pi/2 + math.atan2(mpY - (user.y + (user.h/2*user.scale)), mpX - (user.x + (user.w/2*user.scale)))
	end
end


--my draw function
function love.draw(dt)
-- DRAW USER	
love.graphics.setColor(1,1,1, 1)
-- problem with offset i guess!!
love.graphics.draw(user.img, user.x, user.y,user.angle,user.scale)
--test that ain't work
--love.graphics.draw(user.img, user.x, user.y,user.angle,user.scale,user.scale,user.w/2,user.h/2)
end
I didn't write the whole code with interaction with mouse.click ('cause it's works) and my issue is more about
the final rendering (or position) of the object. I guess that it's more a math problem 'cause i try several combination
(as you could see on the attached zip of this post) and unfortunately none of them works. Hope i put
everything to be as clear as possible, so if anyone as a suggestion it 'll be very cool to solve this issue.

files:
main.zip
(4.26 KiB) Downloaded 199 times
Thanks all in advance.
Last edited by var77 on Fri May 04, 2018 2:50 pm, edited 2 times in total.
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: Math + angle + following object on click

Post by pgimeno »

Your user.x and user.y are incorrect. They are at the top left of the sprite, not at the centre. The final, correct user.x and user.y must be the clicked position. It's only at the time of drawing when you have to apply the compensation to centre the sprite. Your second, commented out love.graphics.draw() line is correct; adding user.w/2*user.scale (or .h) all over the place is not. The last atan2 formula works.

Then there's the problem that you first move at 45° multiples until one of the coordinates matches the click position, due to the use of ceil(). That means that the actual motion angle varies as the sprite moves, and none of your formulas takes into account the actual current angle (the angle between the previous position and the last position). Is that really how you intend your sprite to move, or do you want it to move in a straight line at angles other than 45° multiples?

Note that by applying math.ceil() at every step, you're advancing an integral number of steps every frame, and the final movement is going to be FPS-dependent.

On an unrelated note, you've also forgotten to apply dt to the varf increment.
User avatar
var77
Citizen
Posts: 52
Joined: Wed May 02, 2018 1:57 pm

Re: Math + angle + following object on click

Post by var77 »

First of all thanks for your fast replies pgimeno and for taking time to watch full code.

Actually i checked that the last formula

Code: Select all

user.angle = math.pi/2 + math.atan2(mpY - user.y, mpX - user.x)
seems to be the good one to get the angle (i got it on this forum).
As you wrote none of my formula involved the variation angle while moving (guess it's also one of my other mistake
and also why it's so buggy).

What i'm intend to do is getting the angle following the position. Like in League of legend or other game like that, you click and
the player is oriented by the position of your click (destination). More, as you wrote, want it to move in a straight line at angles.
But my approach (lack of knowledge) wasn't the best i guess.

By the way "varf" was just use for the visual effect but thanks for the tips.

Sorry for answering late couldn't connect to the forum/site (idk why).
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: Math + angle + following object on click

Post by pgimeno »

Sorry if my previous answer was in a somewhat rude tone. I was tired and in a bad mood.

What I meant is that you need to remove all mentions of +user.w/2*user.scale and +user.h/2*user.scale to make it work, because these displace the graphic but won't work when it is rotated. The idea is that you keep your player position where the centre of your sprite is, rather than using the top left corner. That will let you rotate with the desired pivot point, which is the problem here all along.

Then use the right atan2 formula, then uncomment the draw command that you have commented out.

Once you have that part working, we can talk about how to fix it for going in a straight line, which involves getting rid of the math.ceil() calls every time.
User avatar
var77
Citizen
Posts: 52
Joined: Wed May 02, 2018 1:57 pm

Re: Math + angle + following object on click

Post by var77 »

Sorry if you thought that i let you think your previews comment was rude, i didn't take it like that.
On the contrary it's really helpfull.

Now with your last comment i guess i'm progressing on solving mistakes.
So more about the code I use this formula to get the angle on click

Code: Select all

user.angle = math.pi/2 + math.atan2(mpY - user.y, mpX - user.x)
and this one to draw the player (actually "user" in code)

Code: Select all

love.graphics.draw(user.img, user.x, user.y,user.angle,user.scale,user.scale,user.w/2,user.h/2)
It solve a lot and is close to the final result but there are still unwanted displacement. And I guess
it's caused about the displacement code in itself (if I following well).

I join to this post an update of the code to helping you guiding me on this.
main_update.zip
(5.31 KiB) Downloaded 184 times
User avatar
var77
Citizen
Posts: 52
Joined: Wed May 02, 2018 1:57 pm

Re: Math + angle + following object on click

Post by var77 »

Sorry I may answering to fast without making some test.
Nevermind thanks a lot i finally removed +user.w/2*user.scale and +user.h/2*user.scale
from the displacement code and it's work well better now (if i just follow what you wrote :crazy: ).

Now i guess i have to work on that straight line movement itself. To be clear with what i did for displacement
i used math.ceil 'cause without it, it's like i have a large float number [ex: 397.80697635088 (user.x) 398 (mouse.click.x) ]
while it should be the same (user.x and mouse.click.x). But its just a trick i found it's not a straight line movement.
So if you have any suggestion it'll be very helpfull.

Thanks again by the way.

that can still help others maybe:
main_updateworking.zip
(5.19 KiB) Downloaded 174 times
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: Math + angle + following object on click

Post by pgimeno »

It was me who felt it a bit rude when I re-read it :) Anyway, glad you got that part... almost working. Note that you forgot to remove that addition in the point where it checks if the target is reached and disables movev, therefore movev is never reset now. Remove those as well.

To get rid of the 45° angles, some work is needed. First, you need to find the distance between the current sprite position and the target position. Since the axes are perpendicular, by subtracting the target and the user position you get the sides of a right triangle, and the length of the hypothenuse is the distance, so you can calculate it using Pythagoras:

Code: Select all

        dist = math.sqrt((mpX - user.x)^2 + (mpy - user.y)^2)
The vector (mpX - user.x), (mpY - user.y) is the direction vector pointing from the player to the target, but the length of the vector is not useful for being used as velocity, so it needs to be adjusted. Divide it by the distance to obtain a vector of length 1, which you can then multiply by the required speed to obtain a good velocity vector:

Code: Select all

        local velX = (mpX - user.x)/dist * user.speed
        local velY = (mpY - user.y)/dist * user.speed
And finally, you can apply it:

Code: Select all

        user.x = user.x + velX * dt
        user.y = user.y + velY * dt
Now, checking whether the sprite reached its destination needs a bit more vector algebra. You need two vectors: one goes from the original position where the sprite started to the target position (you'll need to store the original position on click too), and the other goes from the current position of the sprite to the target position. If these two point in the same direction, you are too short; if they point in opposite directions, you have overshot, and if the second one is zero, you're exactly at the target level.

Remember that a vector that goes from A to B is calculated as B - A (component by component, i.e. its x component will be Bx - Ax and its y component will be By - Ay).

You can check whether they point in the same direction or opposite directions, by calculating their dot product. The dot product is a single number, and is calculated by adding the products of the components: A·B = Ax*Bx+Ay*By. The sign of the dot product will tell you what you need: zero means exactly there, positive means same direction (therefore not there yet) and negative means opposite directions.

Once it's zero or negative, you can just set the position of the player to the target position, to prevent overshooting, and clear movev.

I insist on the varf effect. It may be too fast if the frame rate is high. You can use e.g. 2.4*dt which gives exactly 0.04 for 60Hz, and that way the timing of the effect will be the same no matter the framerate.

Finally, posting two messages in a row in a short period of time is called double posting, and the rules of the forum don't allow that. You are supposed to edit your previous post to add the new info. I know it's annoying because you can't make sure the other person will see the edits, but hey, I didn't make that rule. Sometimes I have to wait for someone else's reply, check if they saw my edit and if not, write a new post to ensure that they see it e.g. "Don't miss my edit".
User avatar
var77
Citizen
Posts: 52
Joined: Wed May 02, 2018 1:57 pm

Re: [in progress] Math + angle + following object on click

Post by var77 »

So I took time to understand whole of your post to don't miss anything. :)

Code: Select all

varf = varf + 2.4*dt	
frame rate animation checked !

Code: Select all

if movev == true then
	dist = math.sqrt((mpX - user.x)^2 + (mpY - user.y)^2)
	local velX = (mpX - user.x)/dist * user.speed
	local velY = (mpY - user.y)/dist * user.speed
	user.x = user.x + velX * dt
        user.y = user.y + velY * dt
end
moving position checked !

I also add two var to get the start position (user.sx / user.sy) for the next step but...
The only stuff i don't get is the dot product. Didn't get it at school that's why i missed that part of algebra
and was sure that's start with math issue. But after few search on youtube i found what's meaning and what
you wrote about the result of the equation (0 = exact, - = opposite direction, + = same direction).

Unfortunatly i didn't find how you handle it in lua. Try looking on math."something" but none of them
handle dot product, and don't find how to translate the "A·B" in lua or even the whole formula (A·B = Ax*Bx+Ay*By).

So as previews if you can clear my light ?
progress:
main_update2.zip
(5.43 KiB) Downloaded 185 times
Btw sorry for double post i didn't checked that rule on this forum. I'm an outlaw :cool: , but will follow it now.
User avatar
pgimeno
Party member
Posts: 3548
Joined: Sun Oct 18, 2015 2:58 pm

Re: [in progress] Math + angle + following object on click

Post by pgimeno »

It's not complicated. Perhaps you're overthinking it?

First you need the two vectors to calculate the dot product of. Remember those are the vector from the start position to the mouse, and the vector from the current position to the mouse. The first one is (mpX - user.sx, mpY - user.sy), because the vector from point P1 to point P2 is P2 - P1. The second one is (mpX - user.x, mpY - user.y). You have to calculate the dot product of these two vectors.

If you call Ax = mpX - user.sx and Ay = mpY - user.sy, you have vector A. If you call Bx = mpX - user.x and By = mpY - user.y, you have vector B. With both, you can use the formula I gave.

All together, the dot product is calculated as: (mpX - user.sx) * (mpX - user.x) + (mpY - user.sy) * (mpY - user.y)

If you prefer, you can expand it as above:

Code: Select all

local Ax, Ay = mpX - user.sx, mpY - user.sy
local Bx, By = mpX - user.x, mpY - user.y
local dot = Ax * Bx + Ay * By
if dot <= 0 then
  -- clear movement, set user.x and user.y to the mouse position
The sign of that will tell you whether you're overshot. If it's negative, you've overshot; if it's 0, you're there.
User avatar
var77
Citizen
Posts: 52
Joined: Wed May 02, 2018 1:57 pm

Re: [in progress] Math + angle + following object on click

Post by var77 »

First of all a big thanks for your explanation. Guess you're a good teacher :)
Very helpful to understand where was my mistake and how to understand it
(yes too much complex overthinking :nyu: ). Now that i understand how to use
those algebra i can even try it on other works (even if it's maybe basic for others).

Then i just wondering one last question on the result i got a float for user.position
while mouse.position seems more an integer. Guess it's maybe caused by the "dt"
that's not involved in dot product ? What's your point of view ?

For others who might need it:
main_final.zip
(5.33 KiB) Downloaded 188 times
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 87 guests