⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cboid.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
      // test:  if this is OUR flock, skip it

      if (i == flock_id) continue;

#ifdef VISIBILITY_DEBUG
   myprintf("   Testing to see if %x can see anybody in flock %d\n",this,i);
#endif

      // not our flock, so check it out

      enemy = CFlock::ListOfFlocks[i]->GetFirstMember();

      while (enemy != NULL) {
      
#ifdef VISIBILITY_DEBUG
      myprintf("   looking at %x\n",enemy);
#endif

         // if this enemy is visible...

         if ((dist = CanISee(enemy)) != INFINITY) {

            // I can see it..increment counter

            m_num_enemies_seen++;

            // Test:  Closest enemy?

            if (dist < m_dist_to_nearest_enemy) {
               
               // yes...save it off

               m_dist_to_nearest_enemy = dist;
               m_nearest_enemy = enemy;
            }
         }

         // get next enemy in flock

         enemy = enemy->GetNext();

      }
   }

#ifdef VISIBILITY_DEBUG
   myprintf("\n");
   myprintf("   total enemies seen = %d\n",m_num_enemies_seen);
   myprintf("   nearest enemy is %x at %f\n",m_nearest_enemy,m_dist_to_nearest_enemy);
#endif

   return (m_num_enemies_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);
}

// 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;
   }

}

////////////////////////
// miscellaneous methods
////////////////////////

// AccumulateChanges.
// Adds vector values in changes into the accumumlator vector.
// Returns:  magnitude of accumulator vector after adding changes.

float CBoid::AccumulateChanges (vector &accumulator, vector changes)
{

#ifdef BOID_DEBUG
   myprintf("\nInside AccumulateChanges\n");
#endif  

   // apply the change

   accumulator += changes;

   //accumulator.x += changes.x;
   //accumulator.y += changes.y;
   //accumulator.z += changes.z;

   return (accumulator.length());

}

// AddToVisibleList.
// Adds a boid to the list of visible boids.
// This visibility list is regenerated for each boid each update cycle,
// and acts much like a push-down queue; the latest boid added to the
// list becomes the first one when the list is sequentially accessed.
// Mostly I did this for speed reasons, as this allows for fast inserts
// (and we don't delete from this list, we just rebuild it each update cycle).

void CBoid::AddToVisibleList (CBoid *ptr)
{

   // test:  do we see enough buddies already?

   if (m_num_flockmates_seen < Max_Friends_Visible) {

      // nope--we can add to this one to the list

      VisibleFriendsList[m_num_flockmates_seen] = ptr;

      // increment counter

      m_num_flockmates_seen++;

   }

#ifdef VISIBILITY_DEBUG
   int i;

   myprintf("visibility list for %x after adding %x:\n",this,ptr);

   for (i = 0; i < m_num_flockmates_seen; i++) {
      if (VisibleFriendsList[i] != NULL) {
         myprintf("VFL = %x\n",VisibleFriendsList[i]);
      } else {
         break;
      }
   }
#endif

}

// ClearVisibleList.
// Clears the visibility list.

void CBoid::ClearVisibleList (void)
{

   // walk down the list and clear each visible entry

   for (int i = 0; i < Max_Friends_Visible; i++) {
      VisibleFriendsList[i] = NULL;
   }

   // clear other visibility info

   m_num_flockmates_seen       = 0;
   m_nearest_flockmate         = NULL;
   m_dist_to_nearest_flockmate = INFINITY;

}

// Determine whether a given invoking boid can see the boid in question.
// Returns the distance to the boid.

float CBoid::CanISee (CBoid *ptr)
{

#ifdef VISIBILITY_DEBUG
   myprintf("\n   Inside CanISee.\n");
#endif

   // Test:  if we're looking at ourselves, never mind

   if (this == ptr) return (INFINITY);

   // figure out distance

   float dist = (m_pos.GetDist(m_pos, ptr->m_pos));

#ifdef VISIBILITY_DEBUG
   myprintf("   dist between %x and %x = %f\n",this,ptr,dist);
#endif

   // if we're using truth data, don't bother to check sighting

   if (UseTruth) return (dist);

   // not using truth, so check sighting

   if (m_perception_range > dist) return (dist);

   // fell through; can't see it

   return (INFINITY);

}

// ComputeRPY.
// Computes the roll/pitch/yaw of the flock boid based on its
// latest velocity vector changes.  Roll/pitch/yaw are stored in
// the "ang" data boid as follows:
//   pitch is about the x axis
//   yaw is about the y axis
//   roll is about the z axis
//
// All calculations assume a right-handed coordinate system:
//   +x = through the left side of the object
//   +y = up
//   +z = through the nose of the model
//
// All angles are computed in radians.
//
// NOTE:  This algorithm was generously provided by Christopher Kline, who originally
//        developed it for *his* flocking applications.  Thanks Christopher!

void CBoid::ComputeRPY (void)
{

   float  roll, pitch, yaw;

   // Determine the direction of the lateral acceleration.

   vector lateralDir = (m_vel % (m_vel - m_oldvel)) % m_vel;

   lateralDir.GetDirection();

   // Set the lateral acceleration's magnitude. The magnitude is the vector
   // projection of the appliedAcceleration vector onto the direction of the
   // lateral acceleration).
  
   float lateralMag = (m_vel - m_oldvel) * lateralDir;
  
   // compute roll

   if (lateralMag == 0) {
      roll = 0.0f;  
   } else {
      roll = (float) -atan2(GRAVITY, lateralMag) + HALF_PI;
   }

   // compute pitch

   pitch = (float) -atan(m_vel.y / sqrt((m_vel.z*m_vel.z) + (m_vel.x*m_vel.x)));

   // compute yaw

   yaw = (float) atan2(m_vel.x, m_vel.z);

   // store them

   m_ang.x = pitch;

   m_ang.y = yaw;

   m_ang.z = roll;

#ifdef BOID_DEBUG
   myprintf("   roll = %f  pitch = %f  yaw = %f\n",roll, pitch, yaw);
#endif

}

// SetNext.
// Set the "next" pointer of an individual boid.

void CBoid::SetNext (CBoid *ptr)
{

   m_next = ptr;

}

// GetNext.
// Returns the "next" pointer of the invoking boid.

CBoid * CBoid::GetNext()
{

   return (m_next);

}

// SetPrev.
// Set the "prev" pointer of an individual boid.

void CBoid::SetPrev (CBoid *ptr)
{

   m_prev = ptr;

}

// GetOrient.
// Returns the orientation of the boid in question.

vector * CBoid::GetOrient (void)
{

   return (&m_ang);

}

// GetPos.
// Returns the position of the boid in question.

vector * CBoid::GetPos (void)
{

   return (&m_pos);

}

// LinkOut.
// Removes a boid from a list.

void CBoid::LinkOut ()
{

   // test location of boid

   if ((m_next == NULL) && (m_prev == NULL)) {

      SetNext(NULL);
      SetPrev(NULL);

   } else if (m_next == NULL) {

      m_prev->SetNext(NULL);

   } else if (m_prev == NULL) {
      
      m_next->SetPrev(NULL);

   } else {

      m_prev->SetNext(m_next);
      m_next->SetPrev(m_prev);
   }
}

// PrintData
// Dumps all data describing a given boid.

void CBoid::PrintData (void)
{

   myprintf("===================\n");
   myprintf("Data for boid = %d @ %x\n", m_id,this);

   myprintf(" perception_range = %f\n", m_perception_range);

   myprintf(" pos x, y, z = %f %f %f\n", m_pos.x, m_pos.y, m_pos.z);
   myprintf(" vel x, y, z = %f %f %f\n", m_vel.x, m_vel.y, m_vel.z);
   myprintf(" roll, pitch, yaw = %f %f %f\n", m_ang.z, m_ang.x, m_ang.y);

   myprintf(" speed                     = %f\n", m_speed);

   myprintf(" num_flockmates_seen       = %d\n", m_num_flockmates_seen);
   myprintf(" nearest_flockmate         = %x\n", m_nearest_flockmate);
   myprintf(" dist_to_nearest_flockmate = %f\n", m_dist_to_nearest_flockmate);

   myprintf(" num_enemies_seen          = %d\n", m_num_enemies_seen);
   myprintf(" nearest_enemy             = %x\n", m_nearest_enemy);
   myprintf(" dist_to_nearest_enemy     = %f\n", m_dist_to_nearest_enemy);

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -