cTrigger::get_trigger
get_trigger is the function in
the trigger class that you call every time the player’s character
moves. get_trigger will take the coordinates of the character you are checking
and
return the identification number of the first trigger found at that location (if
any). If
no triggers are found at the specified location, get_trigger returns a value of
zero.
A great deal is going on in
get_trigger, but things are not too complicated. As
the linked list of triggers is scanned, each trigger in question is checked to
see whether it and the specified coordinates share the same map space.
If so, the trigger’s
identification number is returned.
CAUTION
Never assign a value of zero to a trigger because the trigger class uses zero
to signify that no trigger is found when the get_trigger function is called.
long cTrigger::get_trigger(float x_pos, float y_pos, float z_pos)
{
for(sTrigger* trigger = m_root_trigger; trigger != NULL; trigger = trigger->next)
{
if(! trigger->enabled) // only bother if enabled
continue;
float x_diff, y_diff, z_diff, dist;
switch(trigger->type)
{
case TRIGGER_SPHERE:
// check distance from sphere (using radius)
x_diff = fabs(trigger->x1 - x_pos);
y_diff = fabs(trigger->y1 - y_pos);
z_diff = fabs(trigger->z1 - z_pos);
dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;
if(dist <= trigger->radius)
return trigger->id;
break;
case TRIGGER_BOX:
// check if inside box
if((x_pos >= trigger->x1 && x_pos <= trigger->x2) &&
(y_pos >= trigger->y1 && y_pos <= trigger->y2) &&
(z_pos >= trigger->z1 && z_pos <= trigger->z2))
{
return trigger->id;
}
break;
case TRIGGER_CYLINDER:
// first make sure within height bounds
if(y_pos >= trigger->y1 && y_pos <= trigger->y1 + trigger->y2)
{
// check distance from cylinder
x_diff = abs(trigger->x1 - x_pos);
y_diff = abs(trigger->y1 - y_pos);
z_diff = abs(trigger->z1 - z_pos);
dist = x_diff * x_diff + y_diff * y_diff + z_diff * z_diff;
if(dist <= trigger->radius)
return trigger->id;
}
break;
case TRIGGER_TRIANGLE:
// first make sure within height bounds
if(y_pos >= trigger->y1 && y_pos <= trigger->y1 + trigger->y2)
{
// check if point in front of all lines
D3DXVECTOR2 norm_vec;
// x1,z1 to x2,z2
D3DXVec2Normalize(&norm_vec, &D3DXVECTOR2(trigger->z2 - trigger->z1, trigger->x1 - trigger->x2));
if(D3DXVec2Dot(&D3DXVECTOR2(x_pos - trigger->x1, z_pos - trigger->z1), &norm_vec) < 0)
break;
// x2,z2 to x3,z3
D3DXVec2Normalize(&norm_vec, &D3DXVECTOR2(trigger->z3 - trigger->z2, trigger->x2 - trigger->x3));
if(D3DXVec2Dot(&D3DXVECTOR2(x_pos - trigger->x2, z_pos - trigger->z2), &norm_vec) < 0)
break;
// x3,z3 to xz,zz
D3DXVec2Normalize(&norm_vec, &D3DXVECTOR2(trigger->z1 - trigger->z3, trigger->x3 - trigger->x1));
if(D3DXVec2Dot(&D3DXVECTOR2(x_pos - trigger->x3, z_pos - trigger->z3), &norm_vec) < 0)
break;
return trigger->id;
}
break;
}
}
return 0; // means no trigger found
}
At this point, you check a trigger
that is enabled to see whether it intersects with
the coordinates passed in the x_pos, y_pos, and z_pos arguments of the
get_trigger function.
Each trigger has a special way of determining whether the specified coordinates
are within the trigger space, and by using a switch statement, the following
code can determine how to process that intersection check:
For spheres, you use a distance
check. If the coordinates have a distance equal to
or less than the radius of the sphere, the trigger is touched.
Box triggers use typical
bounding boxes to compare the coordinates of the opposing
corners to the coordinates being checked to see whether they intersect.
Cylinder triggers use a mixture
of spheres and bounding boxes.
The triangle trigger code shown
here checks whether the coordinate in question
is in front of all three edges of the triangle by using what’s called a
dot-product. For
each edge of the triangle, the dot-product is calculated and checked to see
whether
the coordinates in question are on the inside or the outside of the triangle.
You can think of the
dot-product as the distance of the coordinates in question
from a triangle edge. A negative distance means that the coordinates in question
are on the outside of the triangle, whereas a positive distance means that the
coordinates
in question are inside the triangle.
If all three dot-product checks
come up with positive values, the coordinates in question
must be inside the triangle. You use one last test to determine whether the
coordinates
in question fall within the height range defined in the sTrigger structure.