Inside3D!
     

narrowing findradius down to a semicircle

 
Post new topic   Reply to topic    Inside3d Forums Forum Index -> QuakeC Programming
View previous topic :: View next topic  
Author Message
Nocebo



Joined: 09 May 2005
Posts: 6

PostPosted: Sat Mar 10, 2007 10:28 am    Post subject: narrowing findradius down to a semicircle Reply with quote

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
View user's profile Send private message
Preach



Joined: 25 Nov 2004
Posts: 122

PostPosted: Sat Mar 10, 2007 11:34 am    Post subject: Re: narrowing findradius down to a semicircle Reply with quote

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
View user's profile Send private message
Nocebo



Joined: 09 May 2005
Posts: 6

PostPosted: Sat Mar 10, 2007 5:52 pm    Post subject: Reply with quote

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

I'll play around with this.
Back to top
View user's profile Send private message
Urre



Joined: 05 Nov 2004
Posts: 1073
Location: Sweden

PostPosted: Thu Mar 15, 2007 10:02 am    Post subject: Reply with quote

Preach rocks!
_________________
Look out for Twigboy
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    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