Hello guys, Im making a small action rpg, building its base at the moment
I've got
* An attacking character
* A n/s/w/e orientation and a defined position within a matrix
* An attack range
* An angle of attack
* A target point
I want to find out if the target point is withing the attacking area, defined by a direction, opening angle and range.
Could any one give me any algorithm idea?
Sorry if this is in the wrong session.
Check if target is within attacking angle
Quote:Original post by Dom_152The dot product of the two position vectors won't give you any useful information. Do you mean the dot product of the attacking character's forward vector and the (normalized) vector to the target?
You can use the dot product of the two position vectors to find the angle between them.
Quote:Original post by jyk
Do you mean the dot product of the attacking character's forward vector and the (normalized) vector to the target?
What exactly do you mean? I can possibly find the angle between the two points and use that and the distance?
This is confusing me, I'm not really being able to understand properly how to do it.
You can find the angle between two 2-d vectors as follows:
You can then determine whether the target is within the field of view as follows:
float signed_angle(vector2 v1, vector2 v2){ return atan2(perp_dot(v1, v2), dot(v1, v2));}
The input vectors need not be unit length. (The only requirement is that neither of them has a magnitude that is zero or near zero.)You can then determine whether the target is within the field of view as follows:
vector2 diff = target.position - character.position;float angle = abs(signed_angle(character.forward, diff));return angle <= field_of_view / 2;
Quote:Original post by jykQuote:Original post by Dom_152The dot product of the two position vectors won't give you any useful information. Do you mean the dot product of the attacking character's forward vector and the (normalized) vector to the target?
You can use the dot product of the two position vectors to find the angle between them.
Agreed. You'd need the forward vector of the attacker. And the thread asks for the angle. To get the angle you would need to use arc-cosine of the dot product.
// Pseudo-codevector3 diff = attacker.pos - other.pos;diff.normalize();float dot = attackerFwd.Dot(diff);float angle = acos(dot); // Note: make sure dot is between -1 or 1.
Yes, sorry about that. That is what I was thinking in my head but I clearly did not communicate that!
The easiest to solve is the question "is the target within range?" and that's found using the pythagorean theorem.
To keep this simple we'll define the vectors for the entities' position.
Player -> (p.x, p.y) = p
Enemy -> (e.x, e.y) = e
And the range is just a float
Range -> r
if ((e - p).LengthSquared() < r * r)
{
// Within range
}
If you want you can expand it out to:
if ((e.x - p.x) * (e.x - p.x) + (e.y - p.y) * (e.y - p.y) < r * r)
{
// Within range
}
Now we want to find if the enemy is within a given angle. The dot product can be used:
angleBetweenTwoVectors = acos((a.x * b.x + a.y * b.y) / (a.Length() * b.Length());
First we need to define N,S,W,E. Assuming x and y are positive right and down respectively then:
N -> (0, -1)
S -> (0, 1)
W -> (-1, 0)
E -> (1, 0)
We'll call this direction.
So we have one of the vectors given to us. The other one is created from (e - p). It can be thought of as the vector starting at p and going to e. Since the direction vector is already a unit vector (length of 1) then to find the angle plus or minus between them we can do:
angleBetweenDirectionAndPlayerToEnemy = acos((direction.x * (e.x - p.x) + direction.y * (e.y - p.y)) / sqrt((e.x - p.x) * (e.x - p.x) + (e.y - p.y) * (e.y - p.y)));
This is easier if you have a vector library:
angleBetweenDirectionAndPlayerToEnemy = Math.Acos(Vector2.Dot(direction, (e - p)) / (e - p).Length());
So yeah then you just do:
if (Math.Acos(Vector2.Dot(direction, (e - p)) / (e - p).Length()) < angleOfAttack)
{
// Within angle of attack
}
Put them together like:
if ((e - p).LengthSquared() < r * r && Math.Acos(Vector2.Dot(direction, (e - p)) / (e - p).Length()) < angleOfAttack)
{
// Player can attack the enemy
}
// edit hmm I must have had this open before replying. Anyway I had a cool example I used to give out when people asked this question:
Turret. Your problem seems more tile based though :P
To keep this simple we'll define the vectors for the entities' position.
Player -> (p.x, p.y) = p
Enemy -> (e.x, e.y) = e
And the range is just a float
Range -> r
if ((e - p).LengthSquared() < r * r)
{
// Within range
}
If you want you can expand it out to:
if ((e.x - p.x) * (e.x - p.x) + (e.y - p.y) * (e.y - p.y) < r * r)
{
// Within range
}
Now we want to find if the enemy is within a given angle. The dot product can be used:
angleBetweenTwoVectors = acos((a.x * b.x + a.y * b.y) / (a.Length() * b.Length());
First we need to define N,S,W,E. Assuming x and y are positive right and down respectively then:
N -> (0, -1)
S -> (0, 1)
W -> (-1, 0)
E -> (1, 0)
We'll call this direction.
So we have one of the vectors given to us. The other one is created from (e - p). It can be thought of as the vector starting at p and going to e. Since the direction vector is already a unit vector (length of 1) then to find the angle plus or minus between them we can do:
angleBetweenDirectionAndPlayerToEnemy = acos((direction.x * (e.x - p.x) + direction.y * (e.y - p.y)) / sqrt((e.x - p.x) * (e.x - p.x) + (e.y - p.y) * (e.y - p.y)));
This is easier if you have a vector library:
angleBetweenDirectionAndPlayerToEnemy = Math.Acos(Vector2.Dot(direction, (e - p)) / (e - p).Length());
So yeah then you just do:
if (Math.Acos(Vector2.Dot(direction, (e - p)) / (e - p).Length()) < angleOfAttack)
{
// Within angle of attack
}
Put them together like:
if ((e - p).LengthSquared() < r * r && Math.Acos(Vector2.Dot(direction, (e - p)) / (e - p).Length()) < angleOfAttack)
{
// Player can attack the enemy
}
// edit hmm I must have had this open before replying. Anyway I had a cool example I used to give out when people asked this question:
Turret. Your problem seems more tile based though :P
Quote:Original post by lordikonI'd actually recommend using atan2() rather than acos() (as shown above), as it does not require that the input vectors be unit length, and is a little more stable and robust. (In particular, it eliminates the need for clamping the dot product output to the range [-1, 1] to compensate for potential numerical error.)
*** Source Snippet Removed ***
Quote:Original post by SirisianSimilarly, I'd recommend using atan2() rather than acos().
Now we want to find if the enemy is within a given angle. The dot product can be used:
Another option would be to pre-compute and cache the cosine of half the field of view, and then simply compare the dot product of the forward vector and the normalized vector to the target to this value.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement