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

📄 cboid.cpp

📁 这是一个用OPENGL和VC++作的人工智能程序,大家可以借鉴一下
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* Copyright (C) Steven Woodcock, 2000.  * All rights reserved worldwide. * * This software is provided "as is" without express or implied * warranties. You may freely copy and compile this source into * applications you distribute provided that the copyright text * below is included in the resulting source code, for example: * "Portions Copyright (C) Steven Woodcock, 2000" *///*********************************************************************// Name:     CBoid.cpp// Purpose:  Class methods for individual boids (flock members).//*********************************************************************//// includes//#include <stdio.h>#include <math.h>#include "CFlock.h"#include "CBoid.h"#include "CBox.h"#include "vector.h"//// static variable initialization//// visible friends list (work space reused by each flock boid)CBoid * CBoid::VisibleFriendsList[] = {NULL};//// constructor and destructor methods//// Constructor #1.// Creates an individual boid with randomized position and velocity.CBoid::CBoid (short id_v){#ifdef BOID_DEBUG   myprintf("\nCBoid constructor #1 called for boid %d.\n",id_v);#endif   m_id               = id_v;   m_perception_range = Default_Perception_Range;   // generate random position   m_pos.x = RAND() * CBox::WorldPtr->GetBoxWidth()/3;   m_pos.y = RAND() * CBox::WorldPtr->GetBoxHeight()/3;   m_pos.z = RAND() * CBox::WorldPtr->GetBoxLength()/3;   // flip positions for greater randomness   if (RAND() > 0.5f) m_pos.x *= -1;   if (RAND() > 0.5f) m_pos.y *= -1;   if (RAND() > 0.5f) m_pos.z *= -1;   // generate random velocity   m_vel.x = RAND();   m_vel.z = RAND();   // flip velocities for greater randomness   if (RAND() > 0.5f) m_vel.x *= -1;   if (RAND() > 0.5f) m_vel.z *= -1;   // compute speed based on velocity   m_speed = m_vel.length();   // zero out orientation   m_ang.x = m_ang.y = m_ang.z = 0;   // other values   m_num_flockmates_seen       = 0;   m_nearest_flockmate         = NULL;   m_dist_to_nearest_flockmate = INFINITY;   m_num_enemies_seen          = 0;   m_nearest_enemy             = NULL;   m_dist_to_nearest_enemy     = INFINITY;   m_next = m_prev = NULL;#ifdef BOID_DEBUG   PrintData();#endif}  // Constructor #2.// Creates an individual boid with specific position and velocity.CBoid::CBoid (short id_v,              vector * pos_v, vector * vel_v, vector * ang_v){#ifdef BOID_DEBUG   myprintf("\nCBoid constructor #2 called for boid %d.\n",id_v);#endif   m_id               = id_v;   m_perception_range = Default_Perception_Range;   m_pos = pos_v;   m_vel = vel_v;   m_ang = ang_v;   m_speed = vel_v->length();   m_num_flockmates_seen       = 0;   m_nearest_flockmate         = NULL;   m_dist_to_nearest_flockmate = INFINITY;   m_num_enemies_seen          = 0;   m_nearest_enemy             = NULL;   m_dist_to_nearest_enemy     = INFINITY;   m_next = m_prev = NULL;#ifdef BOID_DEBUG   PrintData();#endif}  // Destructor.// Destroys indicated boid.CBoid::~CBoid (void){#ifdef BOID_DEBUG   myprintf("\nCBoid destructor called for boid %x\n",this);#endif}//////////////////////////// public flocking methods//////////////////////////// FlockIt.// Used for frame-by-frame updates; no time deltas on positions.void CBoid::FlockIt (int flock_id, CBoid *first_boid){   vector acc;#ifdef BOID_DEBUG   myprintf("\n=====\nUpdate for %d\n", m_id);   myprintf("pos before = %f %f %f\n",m_pos.x,m_pos.y,m_pos.z);#endif   // Step 1:  Update our position.   // Update our position based on the velocity   // vector we computed last time around.   m_oldpos = m_pos;     // save off our previous position   m_pos += m_vel;      // apply velocities.   // Step 2:  SeeFriends.   // Determine if we can see any of our flockmates.   SeeFriends (first_boid);   // Step 3:  Flocking behavior.   // Do we see any of our flockmates?  If yes, it's time to implement   // the first Three Rules (they don't matter if we can't see anybody)   if (m_num_flockmates_seen) {      // Step 4:  Implement Rule #1 (Separation).      // Try to maintain our desired separation distance from our nearest flockmate.      AccumulateChanges (acc, KeepDistance());      // Step 5:  Implement Rule #2 (Alignment).      // Try to move the same way our nearest flockmate does.      AccumulateChanges (acc, MatchHeading());      // Step 6:  Implement Rule #3 (Cohesion).      // Try to move towards the center of the flock.      AccumulateChanges (acc, SteerToCenter());      }   // Step 6:  The Fourth Rule (enemies)   // If we're supposed to react to enemy flocks, determine   // if there are any then avoid them if we can.   if (ReactToEnemies) {      SeeEnemies (flock_id);      AccumulateChanges (acc, FleeEnemies());   }   // Step 7:  Cruising.   // Flockmates or not, enemies or not, figure out   // how fast we'd move if it were all up to us.   AccumulateChanges (acc, Cruising());   // Step 8:  Constrain acceleration   // If our acceleration change is more than we allow, constrain it   if (acc.length() > MaxChange) {#ifdef BOID_DEBUG      myprintf("WARNING:  constraining acceleration for boid %x!\n",this);#endif      // definitely too much...constrain to maximum change      acc.SetMagnitudeOfVector (MaxChange);   }   // Step 9:  Implementation.   // Here's where we apply our newly computed acceleration vector   // to create a new velocity vector to use next update cycle.   m_oldvel = m_vel;     // save off our previous velocity   // now add in the acceleration   m_vel += acc;   // Step 10:  constraint Y velocity changes.   // Attempt to restrict flight straight up/down by damping out Y axis velocity.   // This isn't strictly necessary, but does lead to more realistic looking flight.   m_vel.y *= MaxUrgency;   // Step 11:  Constrain our speed.   // If we're moving faster than we're allowed to move, constrain our velocity.   if ((m_speed = m_vel.length()) > MaxSpeed) {      // definitely too fast...constrain to maximum speed#ifdef BOID_DEBUG      myprintf("WARNING:  constraining speed for boid %x!\n",this);      myprintf("          current speed = %f new speed = %f\n",m_speed, MaxSpeed);#endif      m_vel.SetMagnitudeOfVector (MaxSpeed);      m_speed = MaxSpeed;   }   // Step 12:  Compute roll/pitch/yaw.   // Compute our orientation after all this speed adjustment nonsense.   ComputeRPY();   // Step 13:  World boundaries.   // If we've wandered outside the world bounds put us back in.  You might   // not need to do this for your world, but that depends on your implementation.   WorldBound();#ifdef BOID_DEBUG   myprintf("final position     = %f %f %f\n",m_pos.x, m_pos.y, m_pos.z);   myprintf("final velocity     = %f %f %f\n",m_vel.x, m_vel.y, m_vel.z);   myprintf("final acceleration = %f %f %f\n",acc.x, acc.y, acc.z);#endif}///////////////////////////// private flocking methods///////////////////////////// Cruising.// Generates a vector indicating how a flock boid would// like to move, if it were all up to him and he was under// no other influences of any kind.vector CBoid::Cruising (void){   vector  change = m_vel;   float  diff = (m_speed - DesiredSpeed)/ MaxSpeed;   float  urgency = (float) fabs(diff);#ifdef BOID_DEBUG   myprintf("\nInside Cruising\n");   myprintf("   diff = %f  urgency = %f\n",diff, urgency);   myprintf("   m_speed = %f  desired speed = %f\n",m_speed, DesiredSpeed);   myprintf("   initial change vector from Cruising = %f %f %f\n",change.x, change.y, change.z);   if (diff > 0) {      myprintf("   slowing down to meet cruising speed...\n");   } else {      myprintf("   speeding up to meet cruising speed...\n");   }#endif   // constrain the urgency level   if (urgency < MinUrgency) urgency = MinUrgency;   if (urgency > MaxUrgency) urgency = MaxUrgency;   // Now add some "jitter" so that each boid has a    // bit of randomness just to keep things interesting.   // This will also get us moving if we happen to start   // things standing perfectly still (which is sorta boring).   float jitter = RAND();   if (jitter < 0.45f) {      change.x += MinUrgency * SIGN(diff);   } else if (jitter < 0.90f) {      change.z += MinUrgency * SIGN(diff);   } else {      change.y += MinUrgency * SIGN(diff);   // we don't like vertical motion all that much   }#ifdef BOID_DEBUG   myprintf("   intermediate change vector from Cruising = %f %f %f\n",change.x, change.y, change.z);#endif   // compute velocity change necessary to get to our desired cruising speed   change.SetMagnitudeOfVector ((urgency * (diff > 0 ? -1 : 1) ));#ifdef BOID_DEBUG   myprintf("   final change vector from Cruising = %f %f %f\n",change.x, change.y, change.z);#endif   return (change);}// FleeEnemies.// Generates a vector for a flock boid to avoid the // nearest enemy (boid of a different flock) it sees.vector CBoid::FleeEnemies (void){   vector change;#ifdef BOID_DEBUG   myprintf("\nInside FleeEnemies\n");#endif   // test:  Are we too close to our nearest enemy?   if (m_dist_to_nearest_enemy < KeepAwayDist) {#ifdef BOID_DEBUG      myprintf("   too close to %x\n",m_nearest_enemy);#endif      // yep...compute vector away from enemy      change = m_pos - m_nearest_enemy->m_pos;   }   // return change vector   return (change);#ifdef BOID_DEBUG   myprintf("   final change vector from Cruising = %f %f %f\n",change.x, change.y, change.z);#endif}// KeepDistance.// Generates a vector for a flock boid to maintain his// desired separation distance from the nearest flockmate he sees.vector CBoid::KeepDistance (void){   float ratio = m_dist_to_nearest_flockmate/SeparationDist;   // compute vector towards our nearest buddy   vector change = m_nearest_flockmate->m_pos - m_pos;   #ifdef BOID_DEBUG   myprintf("\nInside KeepDistance\n");#endif   // constrain computed ratio to our min/max Urgency levels   if (ratio < MinUrgency) ratio = MinUrgency;   if (ratio > MaxUrgency) ratio = MaxUrgency;   // test:  are we too close to our nearest flockmate?#ifdef BOID_DEBUG   myprintf("   dist_to_nearest_flockmate = %f  Sep = %f  ratio = %f\n",      m_dist_to_nearest_flockmate,SeparationDist,ratio);#endif   if (m_dist_to_nearest_flockmate < SeparationDist) {#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 > SeparationDist) {#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);}// SeeEnemies.// Determines which enemy flock boids a given flock boid can see.int CBoid::SeeEnemies (int flock_id){   float dist;   CBoid *enemy;#ifdef BOID_DEBUG   myprintf("\nInside SeeEnemies\n");#endif   // initialize enemy data   m_num_enemies_seen      = 0;   m_nearest_enemy         = NULL;   m_dist_to_nearest_enemy = INFINITY;   // loop over each flock and determine the closest one we can see   for (int i = 0; i < CFlock::FlockCount; i++) {

⌨️ 快捷键说明

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