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

📄 cboid.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:

void CBoid::SetPredatorOf (BoidTypes type_v)
{

	m_my_predator = type_v;

}

// EatPrey.
// Eat a prey boid if we're close enough.

bool CBoid::EatPrey (void)
{

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

   // test:  are we within "eating distance" of our prey?

   if (m_dist_to_nearest_prey <= m_feeding_distance) {

#ifdef BOID_DEBUG
      myprintf("   Boid %s is eating boid %s!\n",m_id,m_nearest_prey->GetID());
#endif

      // sure are...eat'em up!

      // we're not as hungry now

      SetHunger(m_starting_hunger * RAND());

      // kill the unfortunate boid

      m_nearest_prey->SetAlive(FALSE);

      // let the flock know

      m_preys_flock->SetLiveCount(-1);
      m_preys_flock->SetDeadCount(1);

      // Ordinarily we'd probably delete the prey boid right here,
      // but since we have a big external list in main.cpp (this is
      // a demo, after all) we won't.  With the boid removed from
      // the Flock's list, he won't be updated or drawn.

      // clear the prey variables

      m_num_prey_seen             = 0;
      m_nearest_prey              = NULL;
      m_dist_to_nearest_prey      = INFINITY;

      // we're done--get outta here

      return (TRUE);

   }

#ifdef BOID_DEBUG
      myprintf("   Boid %s wasn't close enough to eat boid %s!\n",m_id,m_nearest_prey->GetID());
#endif

   // fell through..must not have been close enough to eat!

   return (FALSE);

}

// KillBoid.
// Kills the boid in question if he's died of hunger.

void CBoid::KillBoid (int flockid_v)
{

//#ifdef BOID_DEBUG
   myprintf("\nInside KillBoid\n");
   myprintf("   Boid %s has died of hunger and is being removed from flock %d.\n",m_id,flockid_v);
//#endif  

      // this poor boid has died of hunger--kill him

      SetAlive(FALSE);

   // Ordinarily we'd probably delete the prey boid right here,
   // but since we have a big external list in main.cpp (this is
   // a demo, after all) we won't.  With the boid removed from
   // the Flock's list, he won't be updated or drawn.

}

///////////////////////
// reproduction methods
///////////////////////

// CanReproduce.
// Indicates whether or not this boid can reproduce.

int CBoid::CanReproduce (void)
{

   return (m_reproduction_flag);

}

// MakeBaby.
// Makes a new boid for the flock in question, 
// assuming all reproduction rules have been met.

void CBoid::MakeBaby (int flockid_v)
{

   CBoid *ptr;

#ifdef REPRO_DEBUG
   myprintf("\nInside MakeBaby.\n");
   myprintf("   Flock %d is going to see if it can create a new boid!\n",flockid_v);
#endif

   // Can we SEE enough of our buddies to reproduce?

#ifdef REPRO_DEBUG
   myprintf(" checking boids we can see = %d\n",m_num_flockmates_seen);
#endif

   if (m_num_flockmates_seen >= NumBoidsForBaby) {

      // yep--any dead boids in this flock?

#ifdef REPRO_DEBUG
      myprintf("checking dead count = %d\n",CFlock::ListOfFlocks[flockid_v]->GetDeadCount());
#endif

      if ((CFlock::ListOfFlocks[flockid_v]->GetDeadCount()) > 0) {

         // Yep--that means there's room for a baby.  Go 
         // make one by "reactivating" one of the dead boids.

         // search through the list of boids in this flock until we find a dead one

         ptr = CFlock::ListOfFlocks[flockid_v]->GetFirstMember();

         while (ptr != NULL) {
      
            // test--is this guy dead?

#ifdef REPRO_DEBUG
            myprintf(" boid %s state = %d\n",ptr->GetID(),ptr->GetState());
#endif

            if (!(ptr->GetState())) {

#ifdef REPRO_DEBUG
               myprintf("  making new baby--reactivating boid %s\n",ptr->GetID());
#endif

               // yep, he's dead--bring him back to life

               ptr->SetAlive(TRUE);

               // let the flock know

               CFlock::ListOfFlocks[flockid_v]->SetLiveCount(1);
               CFlock::ListOfFlocks[flockid_v]->SetDeadCount(-1);

#ifdef REPRO_DEBUG
               myprintf("Flock live/dead count = %d %d\n",
                  CFlock::ListOfFlocks[flockid_v]->GetLiveCount(),
                  CFlock::ListOfFlocks[flockid_v]->GetDeadCount());
#endif

               // we're done--get outta here

               return;

            }

         // get next boid

         ptr = ptr->GetNext();

         }

      }
   }
}

// SetReproduction.
// Sets the reproduction flag for this boid.

void CBoid::SetReproduction (bool flag_v)
{

   m_reproduction_flag = flag_v;

}

//////////////////////
// personality methods
//////////////////////

// GetPerceptionRange.
// Returns the perception range of the boid in question.

float CBoid::GetPerceptionRange (void)
{

   return (m_perception_range);

}

// SetPerceptionRange.
// Sets the perception range of the boid in question.

void CBoid::SetPerceptionRange (float range_v)
{

   m_perception_range = range_v;

}

// GetKeepawayDist.
// Returns the preferred keepaway distance of the boid in question.

float CBoid::GetKeepawayDistance (void)
{

   return (m_keepaway_distance);

}

// GetPreferredSep.
// Retuns the preferred separation distance of the boid in question.

float CBoid::GetPreferredSep (void)
{

   return (m_preferred_separation);

}

// GetState.
// Returns the current state (alive/dead) of the boid in question.

bool CBoid::GetState (void)
{

   return (m_alive);

}

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

   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 < MaxFriendsVisible) {

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

   // not using truth, so check sighting

   if (m_perception_range > dist) return (dist);

   // fell through; can't see it

   return (INFINITY);

}

// CanISeeObstacle.
// Determine whether a given invoking boid can see the obstacle in question.
// Returns the distance to the obstacle if it can be seen, INFINITY if not.

float CBoid::CanISeeObstacle (CObstacle *ptr)

{

   float dist, radius;

   vector temp1, temp2;

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

   // If we're already higher than the obstacle, don't bother--we're not
   // going to run into it anyway, so no reason to worry about it.

   if (!(ptr->IsHeigher(m_pos.y))) {

      // Determine the distance to the obstacle in question.  Since the
      // obstacles are cones and have some diameter to them (unlike boids,
      // which we treat as point masses), we have to find the diameter of
      // the obstacle at our height and consider that as part of the sight
      // determination calculations.

      // what's the distance from my position to the centroid of the obstacle?

      temp1 = m_pos;                // position of boid
      temp2 = ptr->GetPos();        // position of obstacle

      // zero out Y values

      temp1.y = temp2.y = 0.0f;

      // compute the distance between the centroids (no altitude considered)

      dist = (temp1.GetDist(temp1, temp2));

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

      // Okay, we've got the basic distance between our boid and the centroid
      // of the obstacle.  However, the obstacle has a given size at this altitude,
      // so we have to determine what that is and factor that into the equation.

      radius = ptr->GetRelativeRadius(m_pos.y);

   #ifdef VISIBILITY_DEBUG
      myprintf("   relative radius of Obstacle %x is %f\n",ptr,radius);
      myprintf("   perception range = %f\n",m_perception_range);
   #endif

      // Okay, now we can check distance vs. our range of sight

      if (m_perception_range > (dist - radius)) return (dist-radius);

   }

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

}

// GetID.
// Returns the ID of the boid in question.

char * CBoid::GetID (void)
{

   return (m_id);

}

// 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 = %s @ %x\n", m_id,this);
   myprintf(" type = %d\n",m_type);
   myprintf(" prey = %d  predator = %d\n",m_my_prey, m_my_predator);

   myprintf(" starting hunger level = %f\n",m_starting_hunger);
   myprintf(" current hunger level = %f\n",m_hunger);
   if (m_nearest_prey) myprintf(" currently hunting %s\n",m_nearest_prey->GetID());

   myprintf(" perception range = %f\n", m_perception_range);
   myprintf(" preferred separation distance = %f\n",m_preferred_separation);

   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(" personal max speed        = %f\n", m_max_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_predators_seen        = %d\n", m_num_predators_seen);
   myprintf(" nearest_predator          = %x\n", m_nearest_predator);
   myprintf(" dist_to_nearest_predator  = %f\n", m_dist_to_nearest_predator);

   myprintf(" num_prey_seen             = %d\n", m_num_prey_seen);
   myprintf(" nearest_prey              = %x\n", m_nearest_prey);
   myprintf(" dist_to_nearest_prey      = %f\n", m_dist_to_nearest_prey);

   myprintf(" num_obstacles_seen        = %d\n", m_num_obstacles_seen);
   myprintf(" nearest_obstacle          = %x\n", m_nearest_obstacle);
   myprintf(" dist_to_nearest_obstacle  = %f\n", m_dist_to_nearest_obstacle);

}

⌨️ 快捷键说明

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