get_ procs

by Bravo1
A helpful set of procs for angular and positional data!
ID:1117528
 
Greetings everyone, this is a short functional library to give some helpful get_ procs based on positional and angular inputs.

It also includes a helpful replacement for get_dir called get_dir_angle()
As it stands, get_dir will return NORTH, SOUTH, EAST, and WEST only when the target atom is at exactly that direction from the source.
Otherwise it returns a combination, such as NORTHEAST. Let's have an example...

A=source, B=target

_____________________________________
| |
| A |
| B |
|_____________________________________|


In the example above, B is 26 spaces tot he right of A, while it's only 1 space lower. BYOND's get_dir returns SOUTHEAST in this situation.
The issue is that if you want A's dir to look intuitively toward B, it would return EAST, as the offset in the Y position is far outweighed by that in the X position.

That is what get_dir_angle() does. First it uses get_angle() to calculate the proper angle between A and B, and uses that angle to return a more appropriate direction.

This is helpful in projects that use 8 directional icons, or just want to have more approprite returned angle. I've also included a version for 4 directional calls in case you'd like
to only return NORTH, EAST, SOUTH, or WEST, and never anything inbetween. There is also a slightly more accurate version for mobs, in case you want step offsets to be applied as well.


Procs:
get_dir_angle(atom/a,atom/b) - This uses the angle between atoms (a) and (b) to give a more appropriate result than get_dir.

get_dir_angle4(aton/a,atom/b) - much like get_dir_angle, but only resolves the four cardinal directions.

get_angle(atom/a,atom/b) - a basic angle proc for two atoms based on loc, this proc is used for get_dir_angle, as sometimes you want the angle for atoms. This uses get_angle_nums to process its return.

get_angle_nums(ax,ay,bx,by) - a basic angle proc for numerical values. This is used if you already have four numbers to pass as arguments instead of atoms. This is used by get_angle().

get_pix_pos(atom/a) - This proc is used by get_angle() in the event that any of the arguments are atoms. It returns a list of the atoms position (in pixels) in two variables. Ex: list(320,336)

get_angle_dir(atom/a) - this proc gives you the angle based on a given atom (or dir). This is helpful if you're using accurate angles already and you wish to find the angle of a dir.

get_turn(a,b) - when working with angles, find which direction, clockwise or counterclockwise, the angle (a) should be adjusted in order to reach the angle provided (b).

between(a,b,c,strict) - find whether or not value (a) is between (b) and (c). Strict denotes that (a) cannot be equal to (b) or (c).

get_dist_sq(atom/a,atom/b) - a helper proc I added for the hell of it. Returns a true distance in pixels based on pythagorean theorem a^2+b^2=c^2


Updates:
2/1/2013 - Updates to make it get_angle_nums a bit faster. Thanks to FIREking and Mangun2k for their input!
Removed the need for get_angle_step and any other code that was argument specific. get_angle now accepts atoms, mobs, or numeric values.
Added two helper procs one that are used in the library. get_pix_pos() and get_dist_sq()
Included demo files so that some simple profiling can be done.

1/10/2013 - Updated to change how get_turn works. Much more efficient at grabbing the proper direction to turn now. Cut the proc down to 1/3 it's original size.

1/10/2013 - Updated to include between() proc, fixed get_angle_step to work for any world.icon_size.
yes!
I'm guessing you found this useful? =P
In response to Bravo1
Bravo1 wrote:
I'm guessing you found this useful? =P

Yes! I have a target system in Legends Online, and players face their current targets. The built-in calculation was often strange looking as mobs only have cardinal directions. get_dir_angle returns a much more desired result.
Cool beans.
Good work and pretty useful :)
I plan to expand on this as well, basically I want to make it a mass of slightly useful procs so that everyone can use it in some way shape or form.

So keep an eye out for updates! =D
Do you have a function that can figure out if a is behind b based on b's direction?

it would work like this

===
=A=
B->
===

b is facing east, a is north east of b, a is not behind b

===
A==
B->
===

b is facing east, a is north of b, a is behind b

====
A===
=B->
====

b is facing east, a is northwest of b, a is behind b.
Hmm, that would be entirely based on what scopes you'd want to add, but you can actually find this out by using get_angle(a,b) and comparing it to get_angle_dir(b). Then you just need to find out the difference in the angles returned and if it's far enough then yes, A is behind B.

However, I will work on a simplified version of this and include it at a later date.
In response to FIREking
I'd imagine if the direction from A to B is the same (or however similar you want) as B's direction, A is behind B.
The idea is to prevent b from firing at a unless b is properly looking at a. so if a is north of b while b is facing east, its not possible for b to fire at a until b faces north east or north.
Kaio I believe he's referring to B having an FOV based on direction. I'll make something up for it. =P
In response to Kaiochao
Kaiochao wrote:
I'd imagine if the direction from A to B is the same (or however similar you want) as B's direction, A is behind B.

Generically speaking, yes. The similarities would be as I've described in post #10.
In response to Bravo1
Bravo1 wrote:
Kaio I believe he's referring to B having an FOV based on direction. I'll make something up for it. =P

Pretty much!
In response to FIREking
Of course. Your example in #7 shows an angle of 90 degrees.
If the direction from A and B is within 90 degrees of B's facing direction, A is behind B.
It looks like you have your angles increasing clockwise. You might want to change that to counter-clockwise, as that's how most math functions work and will make your library compatible with other systems.
In response to DarkCampainger
BYOND's turn procs (turn(), icon.Turn()) use angles that increase clockwise, so that's probably why this dir-based library stuck to that.

My ProcLib makes a distinction between "angles" and "bearings", which I picked up from Jtgibson's jt_vectors.
//  angle       increases counter-clockwise, 0 points to the east.
// bearing increases clockwise, 0 points to the north.

The conversion between the two is simply (90 - [angle or bearing]).
In response to Kaiochao
Kaiochao wrote:
BYOND's turn procs (turn(), icon.Turn()) use angles that increase clockwise, so that's probably why this dir-based library stuck to that.

My ProcLib makes a distinction between "angles" and "bearings", which I picked up from Jtgibson's jt_vectors.
> //    angle       increases counter-clockwise, 0 points to the east.
> // bearing increases clockwise, 0 points to the north.
>

The conversion between the two is simply (90 - [angle or bearing]).

Pretty much. If it weren't for how BYOND's turn() proc acts, I would've gone anticlockwise.
I've made another library for exactly what Fireking needs. It's the FOV library and it's already up and ready to go. It does require the get_ library but you guys probably have it already.

http://www.byond.com/developer/Bravo1/FOV
Your get_angle() could be simplified a lot less. I'm not sure if it's actually faster, I'll get around to testing it sometime, but here's my version.

proc

// Credit to Lummox JR for the atan2()
atan2(x, y)
if(!(x || y))
return 0
. = arccos(x / sqrt(x * x + y * y))
return y >= 0 ? . : -.

get_angle(atom/a, atom/b)
var/deltaX = (b.x - a.x)
var/deltaY = (b.y - a.y)
return atan2(deltaY, deltaX) * 180 / 3.14159265359
Page: 1 2