**Example 4-4. Wide-field-of-view check**

.

.

.

if(WideView)

{

InView = ((w.y > 0) || ((w.y < 0) &&

(fabs(w.x) >

fabs(w.y)*

_BACK_VIEW_ANGLE_FACTOR)));

RadiusFactor = _WIDEVIEW_RADIUS_FACTOR;

}

.

.

.

In the code shown here, the *BACK_VIEW_ANGLE_FACTOR* represents a field-of-view angle factor. If it is set to a value of *1*, the field-of-view bounding lines will be 45 degrees from the x-axis. If the factor is greater than *1*, the lines will be closer to the x-axis, essentially creating a larger blind spot. Conversely, if the factor is less than *1*, the lines will be closer to the y-axis, creating a smaller blind spot.

You'll also notice here that the *RadiusFactor* is set to some predefined value, *_WIDEVIEW_RADIUS_FACTOR*. This factor controls the radius parameter shown in Figure 4-1. By the way, when tuning this example, this radius factor is one of the parameters that require adjustment to achieve the desired behavior.

The other two visibility model checks are very similar to the wide-view model; however, they each represent smaller and smaller fields of view. These two models are illustrated in Figures 4-4 and 4-5.

In the limited-view model, the visibility arc is restricted to the local positive y-axis of the unit. This means each unit cannot see anything behind itself. In this case, the test is relatively simple, as shown in Example 4-5, where all you need to determine is whether the y-coordinate of *Units[j]*, expressed in *Units[i]* local coordinates, is positive.

**Example 4-5. Limited-field-of-view check**

.

.

.

if(LimitedView)

{

InView = (w.y > 0);

RadiusFactor = _LIMITEDVIEW_RADIUS_FACTOR;

}

.

.

.

The narrow-field-of-view model restricts each unit to seeing only what is directly in front of it, as illustrated in Figure 4-5.

The code check in this case is very similar to that for the wide-view case, where the visibility arc can be controlled by some factor. The calculations are shown in Example 4-6.

**Example 4-6. Narrow-field-of-view check**

.

.

.

if(NarrowView)

{

InView = (((w.y > 0) && (fabs(w.x) <

fabs(w.y)*

_FRONT_VIEW_ANGLE_FACTOR)));

RadiusFactor = _NARROWVIEW_RADIUS_FACTOR;

}

.

.

.

In this case, the factor, *_FRONT_VIEW_ANGLE_FACTOR*, controls the field of view directly in front of the unit. If this factor is equal to *1*, the lines bounding the view cone are 45 degrees from the x-axis. If the factor is greater than *1*, the lines move closer to the x-axis, effectively increasing the field of view. If the factor is less than *1*, the lines move closer to the y-axis, effectively reducing the field of view.

If any of these tests pass, depending on which view model you selected for this demo, another check is made to see if *Units[j]* is also within a specified distance from *Units[i]*. If *Units[j]* is within the field of view and within the specified distance, it is visible by *Units[i]* and will be considered a neighbor for subsequent calculations.

The last *if* block in Example 4-3 shows this distance test. If the magnitude of the **d** vector is less than the *Units[i]*'s length times the *RadiusFactor*, *Units[j]* is close enough to *Units[i]* to be considered a neighbor. Notice how this prescribed separation threshold is specified in terms of the unit's length times some factor. You can use any value here depending on your needs, though you'll have to tune it for your particular game; however, we like using the radius factor times the unit's length because it scales. If for some reason you decide to change the scale (the dimensions) of your game world, including the units in the game, their visibility will scale proportionately and you won't have to go back and tune some new visibility distance at the new scale.

Comments

comments powered by Disqus