Math helper functions: "distanceBetween" and "angleBetween"

For the use of the community as a whole, I'm posting 2 math "helper" functions which I wrote and use for my own development. There is nothing really special about these; they use common geometry/trig formulas. Many of you have probably written your own already. If not, and if you need these for your game, please go ahead and use them. :)

Distance Between (two points/objects)

This is useful for alot of purposes. One of the most obvious is using this to calculate "constant" movement transitions. Since Corona utilizes time-based transitions, an object will move from point A to point B in a certain time, but the distance is not factored in. So, you'll get faster object movement when the points are farther apart. Using the DistanceBetween function, you can check the distance and use it as the divisor of a time amount, ensuring consistent movement speeds.

Here's the function. Pass two objects/events/whatever that contain an X and Y position. The function returns the distance between them. Notice that I used "x*x" and "y*y" for the squaring math, versus math.pow() or x^2 because Ansca says "x*x" is faster performance-wise.

1
2
3
4
5
6
local function distanceBetween( point1, point2 )
 
        local xfactor = point2.x-point1.x ; local yfactor = point2.y-point1.y
        local distanceBetween = math.sqrt((xfactor*xfactor) + (yfactor*yfactor))
        return distanceBetween
end

I just found this, pretty cool...but as I had posted on other threads, could it be possible to post a sample demo (perhaps in the 'code exchange').

RD

Second that - what I think we need is possibly a group effort sample listing, which includes lots of math library functions, etc.

Having said that, seeing as Corona (AFAIK) is mostly being used to build games, it would seem sensible to have the common functions, which we all seem to be building (distance, angle, etc.) as part of a library in the SDK, thereby making the operations faster as they would be executed at a lower code level.

Does anyone at Ansca have an opinion on this - would it be a good candidate for Requested Functionality?

Matt.

Very helpful for my game in development, thanks a lot...

Guys, keep me on the loop on this at cicaza @ anscamobile.com and use the subject VECTOR MATH

I have a bunch of routines that I used for curve fitting that want to post but haven't had time to review - lets get on a thread and I can share the code so we can release it at our code exchange.

Carlos

Carlos, have you had feedback via email on this? I intended to get it started but have been bogged down with work and the code I'd include is a bit far flung right now.

Matt

no feedback but you can send me what you have and we can collaborate together

although a bit busy this week due to shipping but we can get started....

c.

Perhaps we can use this function for creating Explosion.

Oh, I can also point you to the Vector2D class I'm using in Flash for an arcade game with seeking-missiles (actually working fine in as3).

Is there a lua vector2d? Maybe i've overseen it.

Nevertheless Here's an overview of the steering and seeking capabilities: http://rocketmandevelopment.com/2010/06/11/steering-behaviors-seeking/

And here's the as3 code:
http://rocketmandevelopment.com/wp-content/uploads/2010/03/Vector2D.as

I'm planning to port my game and the vector2d to lua, but maybe someone has more time on his hands and is able to port it quicker

And heres some more on that fascinating stuff:
http://www.red3d.com/cwr/steer/gdc99/
http://blog.soulwire.co.uk/laboratory/flash/as3-flocking-steering-behaviors

Not sure how efficient this is but math.atan2 works well for getting the angle between points.

1
2
3
local function angleBetweenObjects(obj1, obj2)
    return math.atan2(obj2.y-obj1.y, obj2.x-obj1.x)
end

I'm fairly new to Corona. Sorry for maybe a simple question, but you guys mentioned this could be used to rotate an object based on the touch position. I'm trying to figure that out, but I'm having no luck. Does anyone know if there are any tutorials on implementing this?

Basically, I'm trying to rotate a wheel based on the touch coordinates. So if I rotate my finger around the wheel, it rotates as well. Any help would be appreciated. I haven't had any luck finding info.
Thanks.

I recently implemented a dial - a wheel which turns with your touch, allowing it to be flicked to go fast or moved precisely. I also put in a tap event which causes the centre of the dial to be moved, meaning that tapping on the screen, rather than dragging, will move the dial. I'm not happy with the implementation, but I suspect I'm doing something wrong, in general. However, I've not had anyone correct my code, so maybe I'm not. I posted the initial problem, and my final solution, here:

https://developer.anscamobile.com/forum/2011/01/22/dial-not-behaving

matt

Thanks so much matt. I'll check it out soon.

Hi, i'd like to add a small if statement to the example.
I noticed that when the angle between the two point is exactly 0 or -180 the object gets flipped around facing the opposite direction.

hence the simple solution:

1
2
3
4
5
6
7
8
9
10
11
12
function angleBetween ( srcObj, dstObj )
 
        local xDist = dstObj.x-srcObj.x ; local yDist = dstObj.y-srcObj.y
        local angleBetween = math.deg( math.atan( yDist/xDist ) )
        if ( srcObj.x < dstObj.x ) then angleBetween = angleBetween+90 else angleBetween = angleBetween-90 end
 
        if (angleBetween == 0) then angleBetween = -180
        elseif (angleBetween == -180) then angleBetween = 0
        end
 
        return angleBetween
end

Thanks; Really appreciate that. It's been bugging me!

m

Hey all,

Theres another little hiccough in the angleBetween function.
If you try to calculate the angle between 2 identical points, it will return -1.#IND, and trying to set the rotation of a displayObject to -1.#IND will cause unpredictable behaviour.

so another quickfix, simplest i could come up with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function angleBetween ( srcObj, dstObj )
        -- make sure we never return -1.#IND if we try to find angle between identical points
        if(srcObj.x == dstObj.x and srcObj.y == srcObj.y) then return srcObj.rotation end
 
        -- Original angleBetween
        local xDist = dstObj.x-srcObj.x ; local yDist = dstObj.y-srcObj.y
        local angleBetween = math.deg( math.atan( yDist/xDist ) )
        if ( srcObj.x < dstObj.x ) then angleBetween = angleBetween+90 else angleBetween = angleBetween-90 end
 
        -- These tend to get flipped around, this is a quick fix
        if (angleBetween == 0) then angleBetween = -180
        elseif (angleBetween == -180) then angleBetween = 0
        end
 
        return angleBetween
end

Thanks to the original poster for the distance between function. I've used this today to get around the issue with transition.to

Thanks!

Tom

This will sound stupid.

Because the function has "point1, point2" in brackets, do you have to have a different code in the even listener?
Wha does it actually mean having a variable in the brackets?

local function distanceBetween( point1, point2 )
 

Hi Andrew,

Each of these is a separate "argument" passed to the function. I just use "point1" and "point2" as the example. A more realistic example would be something like ( player, enemy ), where these are both display objects in your game. Corona knows the X and Y position of each of these objects, and the function gives you the distance between them.

Another example would be something like "( origin, touchPosition )", where "origin" is some position on the screen and "touch" is where the user taps a finger, based on the "event" parameters of the touch (another topic entirely, but simple enough).

So would it still be

Runtime:addEventListener("enterframe" , distanceBetween)

Or do you but the argument in there too?

Hi Andrew,
The function wasn't necessarily intended for use in an event listener, but you can just set it up like this, for example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
local function distanceBetween( point1, point2 )
 
   local xfactor = point2.x-point1.x ; local yfactor = point2.y-point1.y
   local distanceBetween = math.sqrt((xfactor*xfactor) + (yfactor*yfactor))
   return distanceBetween
 
end 
 
local function checkDistance( event )
 
   local thisDistance = distanceBetween( [one object], [other object] )
   print(thisDistance) --for testing only, remove this line later
 
end
 
Runtime:addEventListener( "enterframe", checkDistance )

You should also be able to nest the "distanceBetween" function as follows. This should improve performance slightly, since Corona doesn't need to constantly up-value lookup the function for each pair of objects you need to work with.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
local function checkDistance( event )
 
   ---nest this function; should improve performance slightly
   local function distanceBetween( point1, point2 )
      local xfactor = point2.x-point1.x ; local yfactor = point2.y-point1.y
      local distanceBetween = math.sqrt((xfactor*xfactor) + (yfactor*yfactor))
      return distanceBetween
   end 
 
   local thisDistance = distanceBetween( [one object], [other object] )
   print(thisDistance) --for testing only, remove this line later
 
end
 
Runtime:addEventListener( "enterframe", checkDistance )
views:2295 update:2011/10/4 17:12:07
corona forums © 2003-2011