Forum

narrowing findradius down to a semicircle

Discuss programming in the QuakeC language.

Moderator: InsideQC Admins

narrowing findradius down to a semicircle

Postby Nocebo » Sat Mar 10, 2007 10:28 am

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.
Nocebo
 
Posts: 6
Joined: Mon May 09, 2005 1:22 am

Re: narrowing findradius down to a semicircle

Postby Preach » Sat Mar 10, 2007 11:34 am

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: Select all
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: Select all
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.
Preach
 
Posts: 122
Joined: Thu Nov 25, 2004 7:20 pm

Postby Nocebo » Sat Mar 10, 2007 5:52 pm

Very clever not to mention helpful and clear, thanks a lot Preach!

I'll play around with this.
Nocebo
 
Posts: 6
Joined: Mon May 09, 2005 1:22 am

Postby Urre » Thu Mar 15, 2007 10:02 am

Preach rocks!
I was once a Quake modder
User avatar
Urre
 
Posts: 1109
Joined: Fri Nov 05, 2004 2:36 am
Location: Moon


Return to QuakeC Programming

Who is online

Users browsing this forum: No registered users and 1 guest