Love.physics: Shooting objects towards the mouse pos?

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.
PurpleDrain
Prole
Posts: 5
Joined: Mon Dec 05, 2011 7:29 pm

Love.physics: Shooting objects towards the mouse pos?

Post by PurpleDrain »

Hello everyone!

I have been trying to figure out this problem to make an object shoot towards the mouse's X and Y coordinates using both applyForce() and applyImpulse(), but since math and physics aren't not my strongest subjects I've failed to do so. How would you go about this using one of these functions?
SomethingMoreUnique
Prole
Posts: 12
Joined: Sat Dec 24, 2011 6:03 pm

Re: Love.physics: Shooting objects towards the mouse pos?

Post by SomethingMoreUnique »

Actually, you don't need to use love.physics to do that. It can be done with some trig. Basically what you do is found out the angle between the origin of the object and the mouse position. You form a right triangle from that and the hypotenuse will be the speed of your moving object. I'll provide a more detailed response later today when I have more time to
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Love.physics: Shooting objects towards the mouse pos?

Post by ivan »

What you need to do is:
1.convert the mouse cursor to physics world coordinates

Code: Select all

wmx, wmy = mx * scale + ox, my * scale + oy
where mx and my is the mouse cursor position
scale measures how many pixels equal 1 meter in box2d
ox and oy are offsets from the center of the camera/world

2.find the vector between the mouse cursor (in world coords) and the body's position

Code: Select all

dx, dy = bx - wmx, by - wmy
where bx and by are the body's position

3.normalize the vector and multiply it by the impulse magnitude

Code: Select all

d = math.sqrt ( dx * dx + dy * dy )
ndx, ndx = dx / d, dy / d
impulse = 300
ix, iy = ndx * impulse, ndy * impulse
4.apply the impulse vector to the body (at its position)

Code: Select all

body:applyImpulse ( ix, iy, bx, by )
applyForce is used when you want to continually apply a force to a body throughout several frames
SomethingMoreUnique
Prole
Posts: 12
Joined: Sat Dec 24, 2011 6:03 pm

Re: Love.physics: Shooting objects towards the mouse pos?

Post by SomethingMoreUnique »

PurpleDrain, I wrote a tutorial on how to fire a bullet toward the mouse position. You can find it here. I hope it's helpful and if you have any questions please feel free to ask them.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Love.physics: Shooting objects towards the mouse pos?

Post by vrld »

Ivans method is better. Because it's faster.
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
SomethingMoreUnique
Prole
Posts: 12
Joined: Sat Dec 24, 2011 6:03 pm

Re: Love.physics: Shooting objects towards the mouse pos?

Post by SomethingMoreUnique »

vrld wrote:Ivans method is better. Because it's faster.
Thanks for that info. I didn't know that. Could you explain why it's faster? I'm curious as to all things LOVE.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: Love.physics: Shooting objects towards the mouse pos?

Post by vrld »

Well, with target.x, target.y denoting the target position (i.e. mouse) and pos.x, pos.y denoting the objects position, your code boils down to:

Code: Select all

local angle = math.atan2(target.y - pos.y, target.x - pos.x)
local dx = math.cos(angle) * speed
local dy = math.sin(angle) * speed
That's two subtractions and two multiplications, which are done in practically no time, but three calls to relatively expensive trigonometric functions, math.atan, math.cos and math.sin.

Ivans method is based on vectors:

Code: Select all

local dx = target.x - pos.x
local dy = target.y - pos.y
local len = math.sqrt(dx*dx + dy*dy)
dx = dx/len * speed -- can be packed into len
dy = dy/len * speed
I.e. one sum, two subtractions, four multiplications, and two divisions (all of which are pretty fast) and only one more expensive call to math.sqrt.

Benchmarking both approaches against each other:

Code: Select all

function trig(target, pos, speed)
    local angle = math.atan2(target.y - pos.y, target.x - pos.x)
    local dx = math.cos(angle) * speed
    local dy = math.sin(angle) * speed
    return dx,dy
end

function vectors(target, pos, speed)
    local dx = target.x - pos.x
    local dy = target.y - pos.y
    local len = math.sqrt(dx*dx + dy*dy)
    dx = dx/len * speed
    dy = dy/len * speed
    return dx,dy
end

function nothing() end

function profile(func, iterations)
    math.randomseed(1) -- to get the same numbers
    local start = os.clock()
    for i=1,iterations do
        local target = {x = (math.random()*2 - 1) * 100, y = (math.random()*2 - 1) * 100}
        local pos = {x = (math.random()*2 - 1) * 100, y = (math.random()*2 - 1) * 100}
        func(target, pos, math.random() * 10 + 5)
    end
    return os.clock() - start
end
Yields (results may vary):

Code: Select all

> print("time:", profile(nothing, 1000000) )
time:	3.14
> print("time:", profile(trig, 1000000) )
time: 	4.78
> print("time:", profile(vectors, 1000000) )
time: 	3.97
> print("relative time:", (profile(vectors, 1000000) - profile(nothing, 1000000)) / (profile(trig, 1000000) - profile(nothing, 1000000)) )
relative time:	0.49056603773585
So you can see that excluding the boilerplate code, the vector approach is about 50% faster than the trigonometry one.

In the end it probably doesn't matter, but I for one prefer to work with vectors. Interestingly both methods are equivalent (see here).

Edit: code correction (atan2)
Last edited by vrld on Mon Dec 26, 2011 11:36 am, edited 1 time in total.
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine
SomethingMoreUnique
Prole
Posts: 12
Joined: Sat Dec 24, 2011 6:03 pm

Re: Love.physics: Shooting objects towards the mouse pos?

Post by SomethingMoreUnique »

Thanks for the reply vrld. So doesn't that mean that if you manually coded in the vector math rather than using love.physics it would go eve faster (because it wouldn't deal with anything else that the love.physics call did)? I'll update my tutorial on the wiki to use vectors tomorrow.
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Love.physics: Shooting objects towards the mouse pos?

Post by ivan »

Hi again.
Yes, vrld is correct however the difference in performance would be practically unnoticeable in most cases.
Also:

Code: Select all

    local angle = math.atan(target.y - pos.y, target.y - pos.y)
Shouldn't it be:

Code: Select all

    local angle = math.atan2(target.y - pos.y, target.y - pos.y)

Code: Select all

local len = math.sqrt(dx*dx + dy*dy)
dx = dx/len * speed -- can be packed into len
dy = dy/len * speed
I never though about it about it but you're right:

Code: Select all

local len = 1/math.sqrt(dx*dx + dy*dy)*speed
dx = dx * len
dy = dy * len
Would be another optimization.
SomethingMoreUnique
Prole
Posts: 12
Joined: Sat Dec 24, 2011 6:03 pm

Re: Love.physics: Shooting objects towards the mouse pos?

Post by SomethingMoreUnique »

Thanks everyone for the clarifications and explanation. I'll be sure to update the tutorial tomorrow using this new stuff that I've learned.

Keep on being awesome :awesome:
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 9 guests