Page 1 of 2

Love.physics: Shooting objects towards the mouse pos?

Posted: Sat Dec 24, 2011 3:51 pm
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?

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

Posted: Sat Dec 24, 2011 6:07 pm
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

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

Posted: Sun Dec 25, 2011 2:51 am
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

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

Posted: Sun Dec 25, 2011 3:30 am
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.

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

Posted: Sun Dec 25, 2011 2:28 pm
by vrld
Ivans method is better. Because it's faster.

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

Posted: Sun Dec 25, 2011 4:04 pm
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.

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

Posted: Sun Dec 25, 2011 10:17 pm
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)

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

Posted: Mon Dec 26, 2011 1:25 am
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.

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

Posted: Mon Dec 26, 2011 3:47 am
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.

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

Posted: Mon Dec 26, 2011 5:35 am
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: