Index | FAQ | Search | Memberlist | Usergroups | Profile | Log in to check your private messages | Log in | Register

narrowing findradius down to a semicircle

| Inside3d Forums Forum Index -> QuakeC Programming

View previous topic :: View next topic
Author | Message
--- | ---
Nocebo Joined: 09 May 2005 Posts: 6 |

Posted: Sat Mar 10, 2007 10:28 am Post subject: narrowing findradius down to a semicircle |

I'm finally moving beyond your tutorials and striking out into the depths of quakec on my own, but I'm hitting some snags. After a lot of trial and error I managed to make a circular attack centered on the player using findradius. Is there any sneaky math I can use to exclude entities behind the player or on the left side of the player or what have you? I assume it'll be something have to do with comparing the relative positions of the entities' origins, but I'm not sure how to pull that off.

Back to top |

Preach Joined: 25 Nov 2004 Posts: 122 |

Posted: Sat Mar 10, 2007 11:34 am Post subject: Re: narrowing findradius down to a semicircle |

Nocebo wrote:
I'm finally moving beyond your tutorials and striking out into the depths of quakec on my own, but I'm hitting some snags. After a lot of trial and error I managed to make a circular attack centered on the player using findradius. Is there any sneaky math I can use to exclude entities behind the player or on the left side of the player or what have you? I assume it'll be something have to do with comparing the relative positions of the entities' origins, but I'm not sure how to pull that off.

Ok, I'm guessing you already know about how to cycle through the entites returned by a findradius using
e = e.chain;
I think the instinctive way to do this would be converting vectors to angles and comparing them, but I'm gonna suggest a slicker way using dot products. We start by doing the findradius as before, but then put an extra check in for the angles

Code:
local vector face, ofs; local entity e; //do findradius stuff and put the first entity returned in e here //also I'm assuming at this point that self is the player // These two lines assign to the vector face the direction
// that the player is facing
// Important to note that v_forward is a unit length vector
makevectors(self.angles);
face = v_forward;
// then we have the loop to go through all the entities
while(e)
{
// we want ofs to be a unit vector pointing in the direction
// of the target entity from the player
ofs = normalize(e.origin - self.origin);
// Now we test using the dot product of these two vectors
if(ofs * face < 0.7071)
{
//do the rest of the damage code here
//eg. check if e takes damage, do the damage, blood
}
e = e.chain;
}

That's all it takes, but the dot product does appear to be magic, so I'll explain. The dot product of two vectors a and b has two equivalent definitions. One is
a_x * b_x + a_y * b_y + a_z * b_z
multiplying the pairs of components then summing them.
The other definition is
length(a) * length(b) * cos(x)
where x is the angle between the vectors. Since face and ofs are both unit length vectors, face * ofs = cos(x).
cos(45) = 0.7071 , so our test checks whether the angle between our two vectors is less than 45. If it is, then the target entity e is inside the 45 degree cone in front of the player. Changing the value 0.7071 will give you a different size cone, so lookup some cosine values or just plug in random values between 1 and -1. 0 will give you everything in the 180 degrees in front of the player.
There are two other expansions to this idea you might want to try. Changing the definition of face is one, if you set it to face = v_right and set the cosine value to -0.7071, you'd get everything not in the left hand cone. You could also do arbitrary angles by, for instance:

Code:
makevectors(self.angles + '0 30 0'); face = v_forward;

for 30 degrees to the right.
The other change would be to use semi circles rather than cones. Essentially we want to reduce this to a 2-d problem, so we just go through and set all the z components to zero. We must be careful to renomalise after we've done this!
face = v_forward;
face_z = 0;
face = normalize(face);
and
ofs = e.origin - self.origin;
ofs_z = 0;
ofs = normalize(ofs);
Hope that's helpful and fairly clear.

Back to top |

Nocebo Joined: 09 May 2005 Posts: 6 |

Posted: Sat Mar 10, 2007 5:52 pm Post subject: |

Very clever not to mention helpful and clear, thanks a lot Preach! I'll play around with this.

Back to top |

Urre Joined: 05 Nov 2004 Posts: 1073 Location: Sweden |

Posted: Thu Mar 15, 2007 10:02 am Post subject: |

Preach rocks! _________________ Look out for Twigboy

Back to top |

Display posts from previous:

| Inside3d Forums Forum Index -> QuakeC Programming | All times are GMT
Page 1 of 1

Jump to:

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2004 phpBB Group