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. :slight_smile:

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.

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  
Angle Between (two points/objects)

This one is useful for determining the rotation angle between two objects. For example, if two objects collide, you can call this function to determine the angle between them at the exact moment of collision. Another use might be to pass a click/touch position as one of the arguments, and set the other argument’s rotation to that angle… i.e. if you have a tank, you can click somewhere on the screen and the tank will rotate to face that touch location (via a transition) or just snap to that rotation instantly (object.rotation = ...).

srcObj can be your player or whatever; dstObj can be a touch location, another object on the screen (i.e. some enemy), or another object involved in a collision with the srcObj.

local 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  
 return angleBetween  
end  

If you have any suggestions on how to improve them or make them more efficient, please let me know. These functions can obviously be bundled into an external module if you prefer, or just included at the top of your main.lua file and called like normal functions.

Brent Sorrentino
Ignis Design LLC [import]uid: 9747 topic_id: 3709 reply_id: 303709[/import]

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 [import]uid: 7856 topic_id: 3709 reply_id: 15699[/import]

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. [import]uid: 8271 topic_id: 3709 reply_id: 16101[/import]

Very helpful for my game in development, thanks a lot… [import]uid: 12632 topic_id: 3709 reply_id: 16727[/import]

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 [import]uid: 24 topic_id: 3709 reply_id: 16828[/import]

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 [import]uid: 8271 topic_id: 3709 reply_id: 17326[/import]

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. [import]uid: 24 topic_id: 3709 reply_id: 17336[/import]

Perhaps we can use this function for creating Explosion. [import]uid: 15629 topic_id: 3709 reply_id: 17727[/import]

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
[import]uid: 12870 topic_id: 3709 reply_id: 17774[/import]

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

local function angleBetweenObjects(obj1, obj2) return math.atan2(obj2.y-obj1.y, obj2.x-obj1.x) end [import]uid: 7202 topic_id: 3709 reply_id: 18505[/import]

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.
[import]uid: 11144 topic_id: 3709 reply_id: 18561[/import]

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 [import]uid: 8271 topic_id: 3709 reply_id: 18577[/import]

Thanks so much matt. I’ll check it out soon. [import]uid: 11144 topic_id: 3709 reply_id: 18580[/import]

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:

[code]
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
[/code] [import]uid: 59229 topic_id: 3709 reply_id: 38031[/import]

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

m [import]uid: 8271 topic_id: 3709 reply_id: 38033[/import]

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:

[code]
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
[/code] [import]uid: 59229 topic_id: 3709 reply_id: 38238[/import]

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 [import]uid: 55068 topic_id: 3709 reply_id: 38611[/import]

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 )
  [import]uid: 79135 topic_id: 3709 reply_id: 53846[/import]

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).
[import]uid: 9747 topic_id: 3709 reply_id: 53848[/import]

So would it still be

Runtime:addEventListener(“enterframe” , distanceBetween)

Or do you but the argument in there too? [import]uid: 79135 topic_id: 3709 reply_id: 53873[/import]