📄 cboid.cpp
字号:
#ifdef BOID_DEBUG
myprintf(" too close!\n");
#endif
// too close...move away from our neighbor
change.SetMagnitudeOfVector (-ratio);
} else if (m_dist_to_nearest_flockmate > m_preferred_separation) {
#ifdef BOID_DEBUG
myprintf(" too far away!\n");
#endif
// too far away...move towards our neighbor
change.SetMagnitudeOfVector (ratio);
} else {
#ifdef BOID_DEBUG
myprintf(" just right!\n");
#endif
// in the UNLIKELY event we're exactly the right distance away, do nothing
change.SetMagnitudeOfVector (0.0);
}
// return change vector
#ifdef BOID_DEBUG
myprintf(" final change vector from KeepDistance = %f %f %f\n",change.x, change.y, change.z);
#endif
return (change);
}
// MatchHeading.
// Generates a vector for a flock boid to try
// to match the heading of its nearest flockmate.
vector CBoid::MatchHeading (void)
{
// copy the heading of our nearest buddy
vector change = m_nearest_flockmate->m_vel;
#ifdef BOID_DEBUG
myprintf("\nInside MatchHeading\n");
#endif
// normalize and then scale our vector change a bit...after
// all we can't instantly snap to a new heading, can we?
change.SetMagnitudeOfVector (MinUrgency);
// return change vector
#ifdef BOID_DEBUG
myprintf(" final change vector from MatchHeading = %f %f %f\n",change.x, change.y, change.z);
#endif
return (change);
}
// SeePredators.
// Determines which predator boids a given flock boid can see.
int CBoid::SeePredators (int flock_id)
{
float dist;
CBoid *predator;
#ifdef BOID_DEBUG
myprintf("\nInside SeePredators\n");
#endif
// initialize predator data
m_num_predators_seen = 0;
m_nearest_predator = NULL;
m_dist_to_nearest_predator = INFINITY;
// loop over each flock and determine the closest one we can see
for (int i = 0; i < CFlock::FlockCount; i++) {
// test: if this is OUR flock, skip it
if (i == flock_id) continue;
#ifdef VISIBILITY_DEBUG
myprintf(" \nTesting to see if %s can see anybody in flock %d\n",m_id,i);
#endif
// not our flock, so check it out
predator = CFlock::ListOfFlocks[i]->GetFirstMember();
// is this flock a predator of our boid?
#ifdef VISIBILITY_DEBUG
myprintf(" my type = %d his type = %d\n",m_type,predator->GetType());
#endif
if (predator != NULL) {
if (IsPredator(predator)) {
// it sure is....find the closest one
while (predator != NULL) {
#ifdef VISIBILITY_DEBUG
myprintf(" looking at %x\n",predator);
#endif
// if this predator is visible...
if ((dist = CanISee(predator)) != INFINITY) {
#ifdef VISIBILITY_DEBUG
myprintf(" Yep, I see him!\n");
#endif
// I can see it..increment counter
m_num_predators_seen++;
// Test: Closest predator?
if (dist < m_dist_to_nearest_predator) {
// yes...save it off
m_dist_to_nearest_predator = dist;
m_nearest_predator = predator;
}
}
// get next predator in flock
predator = predator->GetNext();
}
}
}
}
#ifdef VISIBILITY_DEBUG
myprintf("\n");
myprintf(" total predators seen = %d\n",m_num_predators_seen);
myprintf(" nearest predator is %x at %f\n",
m_nearest_predator,m_dist_to_nearest_predator);
#endif
return (m_num_predators_seen);
}
// 3.
// Determines which prey boids a given flock boid can see.
int CBoid::SeePrey (int flock_id)
{
float dist;
CBoid *prey;
#ifdef BOID_DEBUG
myprintf("\nInside SeePrey\n");
#endif
// initialize prey data
m_num_prey_seen = 0;
m_nearest_prey = NULL;
m_dist_to_nearest_prey = INFINITY;
// loop over each flock and determine the closest one we can see
for (int i = 0; i < CFlock::FlockCount; i++) {
// test: if this is OUR flock, skip it
if (i == flock_id) continue;
#ifdef VISIBILITY_DEBUG
myprintf(" \nTesting to see if %s can see anybody in flock %d\n",m_id,i);
#endif
// not our flock, so check it out
prey = CFlock::ListOfFlocks[i]->GetFirstMember();
// is this flock prey for our boid?
#ifdef VISIBILITY_DEBUG
myprintf(" my type = %d his type = %d\n",m_type,prey->GetType());
#endif
if (prey != NULL) {
if (IsPrey(prey)) {
// it sure is....find the closest one
while (prey != NULL) {
#ifdef VISIBILITY_DEBUG
myprintf(" looking at %s\n",prey->GetID());
#endif
// if this prey is visible...
if ((dist = CanISee(prey)) != INFINITY) {
#ifdef VISIBILITY_DEBUG
myprintf(" Yep, I see him!\n");
#endif
// I can see it..increment counter
m_num_prey_seen++;
// Test: Closest prey?
if (dist < m_dist_to_nearest_prey) {
// yes...save it off
m_dist_to_nearest_prey = dist;
m_nearest_prey = prey;
m_preys_flock = CFlock::ListOfFlocks[i];
}
}
// get next prey in flock
prey = prey->GetNext();
}
}
}
}
#ifdef VISIBILITY_DEBUG
myprintf("\n");
myprintf(" total prey seen = %d\n",m_num_prey_seen);
myprintf(" nearest prey is %x at %f\n",m_nearest_prey,m_dist_to_nearest_prey);
#endif
return (m_num_prey_seen);
}
// SeeFriends.
// Determines which flockmates a given flock boid can see.
int CBoid::SeeFriends (CBoid *first_boid)
{
float dist;
CBoid *flockmate = first_boid;
#ifdef BOID_DEBUG
myprintf("\nInside SeeFriends\n");
#endif
#ifdef VISIBILITY_DEBUG
myprintf(" Building visibilty list for %x...\n",this);
#endif
// clear the existing visibility list of any holdover from last round
ClearVisibleList();
// now figure out who we can see
while (flockmate != NULL) {
// Test: Within sight of this boid?
#ifdef VISIBILITY_DEBUG
myprintf(" looking at %x\n",flockmate);
#endif
if ((dist = CanISee(flockmate)) != INFINITY) {
// add it to the list
AddToVisibleList(flockmate);
// Test: If this guy is closer than the current
// closest, make him the current closest
if (dist < m_dist_to_nearest_flockmate) {
m_dist_to_nearest_flockmate = dist;
m_nearest_flockmate = flockmate;
}
}
// next flockmate
flockmate = flockmate->GetNext();
}
#ifdef VISIBILITY_DEBUG
myprintf("\n");
myprintf(" total flockmates seen = %d\n",m_num_flockmates_seen);
myprintf(" nearest flockmate is %x at %f\n",
m_nearest_flockmate, m_dist_to_nearest_flockmate);
#endif
return (m_num_flockmates_seen);
}
// SeeObstacles.
// Determines if a given boid sees any obstacles near him.
// Returns the number of obstacles seen if it does.
int CBoid::SeeObstacles (void)
{
float dist;
CObstacle *obstacle;
#ifdef VISIBILITY_DEBUG
myprintf("\nInside SeeObstacles with boid %s\n",m_id);
#endif
// initialize obstacle data
m_num_obstacles_seen = 0;
m_nearest_obstacle = NULL;
m_dist_to_nearest_obstacle = INFINITY;
// loop over every obstacle and determine the closest one we can see
for (int i = 0; i < CObstacle::ObstacleCount; i++) {
#ifdef VISIBILITY_DEBUG
myprintf(" Testing to see if boid %x can see obstacle %d\n",
this,CObstacle::ListOfObstacles[i]->GetID());
#endif
// not our flock, so check it out
obstacle = CObstacle::ListOfObstacles[i];
// if this obstacle is visible...
if ((dist = CanISeeObstacle(obstacle)) != INFINITY) {
// I can see it..increment counter
m_num_obstacles_seen++;
// Test: Closest enemy?
if (dist < m_dist_to_nearest_obstacle) {
// yes...save it off
m_dist_to_nearest_obstacle = dist;
m_nearest_obstacle = obstacle;
}
}
}
#ifdef VISIBILITY_DEBUG
myprintf("\n");
myprintf(" total obstacles seen = %d\n",m_num_obstacles_seen);
myprintf(" nearest obstacle is %x at a distance of %f\n",
m_nearest_obstacle,m_dist_to_nearest_obstacle);
#endif
return (m_num_obstacles_seen);
}
// SteerToCenter.
// Generates a vector to guide a flock boid towards
// the "center of mass" of the flockmates he can see.
vector CBoid::SteerToCenter (void)
{
vector center, change;
#ifdef BOID_DEBUG
myprintf("\nInside SteerToCenter\n");
#endif
// walk down the visibility list and sum up their position vectors
for (int i = 0; i < m_num_flockmates_seen; i++) {
if (VisibleFriendsList[i] != NULL) center += VisibleFriendsList[i]->m_pos;
}
#ifdef BOID_DEBUG
myprintf(" perceived center before averaging = %f %f %f\n",center.x, center.y, center.z);
myprintf(" num_flockmates_seen = %d\n",m_num_flockmates_seen);
#endif
// average the positions to get the perceived center of the flock
center /= m_num_flockmates_seen;
#ifdef BOID_DEBUG
myprintf(" perceived center after averaging = %f %f %f\n",center.x, center.y, center.z);
#endif
// now that we have the perceived center, computer a vector towards it
change = center - m_pos;
// Scale the change vector so we don't turn on a dime..
change.SetMagnitudeOfVector (MinUrgency);
#ifdef BOID_DEBUG
myprintf(" final change vector from SteerToCenter = %f %f %f\n",
change.x, change.y, change.z);
#endif
// return change vector
return (change);
}
// WorldBound.
// Implements a world boundary so that flocks don't fly
// infinitely far away from the camera, instead remaining
// in a nice viewable area. It does this by wrapping flock
// boids around to the other side of the world, so (for example)
// they move out the right and return on the left.
// Returns: nothing.
void CBoid::WorldBound (void)
{
float maxX = CBox::WorldPtr->GetBoxWidth()/2;
float maxY = CBox::WorldPtr->GetBoxHeight()/2;
float maxZ = CBox::WorldPtr->GetBoxLength()/2;
float minX = -maxX;
float minY = -maxY;
float minZ = -maxZ;
#ifdef BOID_DEBUG
myprintf("\nInside Worldbound\n");
#endif
// test position of flock boid and
// 'warp' if they've strayed out of bounds
if (m_pos.x > maxX) {
m_pos.x = minX;
} else if (m_pos.x < minX) {
m_pos.x = maxX;
} else if (m_pos.y > maxY) {
m_pos.y = minY;
} else if (m_pos.y < minY) {
m_pos.y = maxY;
} else if (m_pos.z > maxZ) {
m_pos.z = minZ;
} else if (m_pos.z < minZ) {
m_pos.z = maxZ;
}
}
////////////////////////
// predator/prey methods
////////////////////////
// SetAlive.
// Sets the alive/dead flag on this boid.
void CBoid::SetAlive (bool flag_v)
{
m_alive = flag_v;
}
// IsPredator.
// Determines whether or not the boid in question is
// a predator of the boid making the inquiry.
bool CBoid::IsPredator (CBoid *ptr)
{
return (ptr->GetType() == m_my_predator);
}
// IsPrey.
// Determines whether or not the boid in question is prey
// for the boid making the inquiry.
bool CBoid::IsPrey (CBoid *ptr)
{
return (ptr->GetType() == m_my_prey);
}
// GetType.
// Gets the type of the boid in question.
BoidTypes CBoid::GetType (void)
{
return (m_type);
}
// SetType.
// Sets the type of the boid in question.
void CBoid::SetType (BoidTypes type_v)
{
m_type = type_v;
// adjust personal max speed based on type (so predators are faster than prey)
m_max_speed *= m_type;
}
// GetHunger.
// Returns the hunger level of the boid in question.
float CBoid::GetHunger (void)
{
return (m_hunger);
}
// SetHunger.
// Changes the hunger level of the boid in question by the value supplied.
void CBoid::SetHunger (float inc_v)
{
m_hunger += inc_v;
}
// GetPreyOf.
// Returns the type of boid (if any) which is the prey of the
// boid making the inquiry.
BoidTypes CBoid::GetPreyOf (void)
{
return (m_my_prey);
}
// GetPreyPtr.
// Returns a pointer to the boid (if any) which is the prey of the
// boid making the inquiry.
CBoid * CBoid::GetPreyPtr (void)
{
return (m_nearest_prey);
}
// GetPreyVector.
// Returns a vector the the prey (if any) of the current boid.
vector * CBoid::GetPreyVector (void)
{
return (&m_prey_vector);
}
// SetPreyOf.
// Sets the prey type of the boid making the call.
void CBoid::SetPreyOf (BoidTypes type_v)
{
m_my_prey = type_v;
}
// GetPredatorOf.
// Returns the type of boid (if any) which is the predator of
// the boid making the inquiry.
BoidTypes CBoid::GetPredatorOf (void)
{
return (m_my_predator);
}
// GetPredatorPtr.
// Returns the type of boid (if any) which is the predator of
// the boid making the inquiry.
CBoid * CBoid::GetPredatorPtr (void)
{
return (m_nearest_predator);
}
// SetPredatorOf.
// Sets the predator type of the boid making the call.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -