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

📄 steering.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	(
	void
	)

	{
   seek.DrawForces();
	}

qboolean FollowPath::DoneWithPath
	(
	Actor &self
	)

	{
	if ( !path )
		{
		return true;
		}

	return ( currentNode == NULL );
	}

void FollowPath::ShowInfo
	(
	Actor &self
	)

	{
   Steering::ShowInfo( self );

   if ( path )
      {
      gi.printf( "\npath : ( %f, %f, %f ) to ( %f, %f, %f )\n", 
         path->Start()->worldorigin.x, path->Start()->worldorigin.y, path->Start()->worldorigin.z, 
         path->End()->worldorigin.x, path->End()->worldorigin.y, path->End()->worldorigin.z );
      }
   else
      {
      gi.printf( "\npath : NULL\n" );
      }

   gi.printf( "seek:\n" );
   seek.ShowInfo( self );

   if ( currentNode )
      {
      gi.printf( "currentNode: ( %f, %f, %f )\n", 
         currentNode->worldorigin.x, currentNode->worldorigin.y, currentNode->worldorigin.z );
      }
   else
      {
      gi.printf( "currentNode: NULL\n" );
      }
	}

void FollowPath::Begin
	(
	Actor &self
	)

	{
	seek.Begin( self );
	}

qboolean	FollowPath::Evaluate
	(
	Actor &self
	)

	{
	PathNode *lastnode;
   Vector delta;
   Vector targetpos;

   ResetForces();

   if ( !path )
      {
      return false;
      }
   
   // the first time we come through here with a path, currentNode is NULL.
   if ( !currentNode )
      {
      FindCurrentNode( self );
      if ( !currentNode )
         {
         delete path;
         path = NULL;
         return false;
         }
      }

   targetpos = currentNode->worldorigin;

   // check if the remaining distance is less than the
   // distance we'll travel this frame.
   delta = targetpos - self.worldorigin;

   // check if the squared distance remaining is less than 
   // the squared distance we'll travel
   if ( delta * delta <= self.frame_delta * self.frame_delta )
      {
      lastnode = currentNode;
      currentNode = path->NextNode();

      // check if we should jump to our next node
      if ( currentNode && ( lastnode->nodeflags & AI_JUMP ) && ( currentNode->targetname == lastnode->target ) )
         {
         if ( self.last_jump_time < level.time )
            {
      	   self.SetVariable( "jumptarget", lastnode->target.c_str() );
            self.ForceAction( "jump" );
            }

			return true;
         }

      // if we're not done with the path, steer toward the next node
      if ( currentNode )
         {
         targetpos = currentNode->worldorigin;
         }
      else
         {
         delete path;
         path = NULL;

         return false;
         }
		}

   // steer toward our next path node
	seek.SetTargetPosition( targetpos );
	seek.SetTargetVelocity( vec_zero );
	seek.SetMaxSpeed( self.movespeed );
	seek.SetPosition( origin );
	seek.SetDir( self.movedir );
	seek.Evaluate( self );

	steeringforce = seek.steeringforce;

	return ( currentNode != NULL );
	}

void FollowPath::End
	(
	Actor &self
	)

	{
	seek.End( self );
	}

/****************************************************************************

  Turn Class Definition

****************************************************************************/

CLASS_DECLARATION( Steering, Turn, NULL );

ResponseDef Turn::Responses[] =
	{
		{ NULL, NULL }
	};

Turn::Turn()
	{
	dir = Vector( 1, 0, 0 );
	mode = 0;
	ent = NULL;
	}

void Turn::SetDirection
	(
	float yaw
	)

	{
	Vector ang;

	ang = Vector( 0, yaw, 0 );
	this->yaw = anglemod( yaw );
	ang.AngleVectors( &dir, NULL, NULL );
	mode = 1;
	}

void Turn::SetTarget
	(
	Entity *ent
	)

	{
	this->ent = ent;
	mode = 2;
	}

void Turn::ShowInfo
	(
	Actor &self
	)

	{
   Steering::ShowInfo( self );

   gi.printf( "\nseek:\n" );
   seek.ShowInfo( self );

   if ( ent )
      {
      gi.printf( "\nent: #%d '%s'\n", ent->entnum, ent->targetname.c_str() );
      }
   else
      {
      gi.printf( "\nent: NULL\n" );
      }
   
   gi.printf( "dir: ( %f, %f, %f )\n", dir.x, dir.y, dir.z );
   gi.printf( "yaw: %f\n", yaw );
   gi.printf( "mode: %d\n", mode );
	}

void Turn::Begin
	(
	Actor &self
	)

	{
	seek.Begin( self );
	}

extern float angledist( float ang );

qboolean	Turn::Evaluate
	(
	Actor &self
	)

	{
	Vector delta;
	float ang;

	switch( mode )
		{
		case 1 :
			ang = angledist( yaw - self.angles.yaw() );
			if ( fabs( ang ) < 1 )
				{
				steeringforce = Vector( 0, ang, 0 );
				return false;
				}

			seek.SetTargetPosition( self.worldorigin + dir );
			seek.SetTargetVelocity( vec_zero );
			break;

		case 2 :
			if ( !ent )
				{
				return false;
				}

			delta = ent->worldorigin - self.worldorigin;
			yaw = delta.toYaw();
			//if ( self.angles.yaw() == yaw )
			//	{
			//	return false;
			//	}

			seek.SetTargetPosition( ent->worldorigin );
			seek.SetTargetVelocity( vec_zero );
			break;

		default :
			return false;
		}

	seek.SetPosition( self.worldorigin );
	seek.SetDir( self.movedir );
	seek.SetMaxSpeed( self.movespeed );
	seek.Evaluate( self );
	//seek.DrawForces();

	steeringforce = seek.steeringforce;

	return true;
	}

void Turn::End
	(
	Actor &self
	)

	{
	seek.End( self );
	}

/****************************************************************************

  Chase Class Definition

****************************************************************************/

CLASS_DECLARATION( Steering, Chase, NULL );

ResponseDef Chase::Responses[] =
	{
		{ NULL, NULL }
	};

Chase::Chase()
	{
	goalent = NULL;
	goal = vec_zero;
	goalnode = NULL;
   usegoal = false;
   newpathrate = 2;
	}

void Chase::SetPath
	(
	Path *newpath
	)

	{
	follow.SetPath( newpath );
	path = newpath;	
	}

void Chase::SetGoalPos
	(
	Vector goalpos
	)

	{
	goal = goalpos;
   usegoal = true;
	goalent = NULL;
   goalnode = NULL;
	}

void Chase::SetGoal
	(
	PathNode *node
	)

	{
   goalnode = node;
   usegoal = false;
   goalent = NULL;
	}

void Chase::SetTarget
	(
	Entity *ent
	)

	{
	goalent = ent;
   goalnode = NULL;
   usegoal = false;
	}

void Chase::SetPathRate
   (
   float rate
   )

   {
   newpathrate = rate;
   }

void Chase::ShowInfo
	(
	Actor &self
	)

	{
   Steering::ShowInfo( self );

   gi.printf( "\nseek:\n" );
   seek.ShowInfo( self );

   gi.printf( "\nfollow:\n" );
   follow.ShowInfo( self );

   gi.printf( "\nnextpathtime: %f\n", nextpathtime );

   if ( path )
      {
      gi.printf( "\npath : ( %f, %f, %f ) to ( %f, %f, %f )\n", 
         path->Start()->worldorigin.x, path->Start()->worldorigin.y, path->Start()->worldorigin.z, 
         path->End()->worldorigin.x, path->End()->worldorigin.y, path->End()->worldorigin.z );
      }
   else
      {
      gi.printf( "\npath : NULL\n" );
      }

   gi.printf( "goal: ( %f, %f, %f )\n", goal.x, goal.y, goal.z );

   if ( goalent )
      {
      gi.printf( "\ngoalent: #%d '%s'\n", goalent->entnum, goalent->targetname.c_str() );
      }
   else
      {
      gi.printf( "\ngoalent: NULL\n" );
      }

   if ( goalnode )
      {
      gi.printf( "\ngoalnode: #%d '%s' ( %f, %f, %f )\n", goalnode->nodenum, goalnode->targetname.c_str(),
         goalnode->worldorigin.x, goalnode->worldorigin.y, goalnode->worldorigin.z );
      }
   else
      {
      gi.printf( "\ngoalnode: NULL\n" );
      }

   gi.printf( "avoid:\n" );
   avoid.ShowInfo( self );

   gi.printf( "\ntime: %f\n", avoidtime );

   gi.printf( "usegoal: %d\n", usegoal );
   gi.printf( "newpathrate: %f\n", newpathrate );
   gi.printf( "wander: %d\n", wander );
   gi.printf( "stuck: %d\n", stuck );
   gi.printf( "avoidvec : ( %f, %f, %f )\n", avoidvec.x, avoidvec.y, avoidvec.z );
	}

void Chase::Begin
	(
	Actor &self
	)

	{
	nextpathtime = 0;
	path = NULL;
	seek.Begin( self );
	follow.Begin( self );
   avoid.AvoidWalls( false );
	avoid.Begin( self );
 	turnto.Begin( self );
   anim = self.animname;
   stuck = 0;
   wander = 0;
	}

Vector Chase::ChooseRandomDirection
   (
   Actor &self
   )

   {
   Vector dir;
   Vector ang;
   Vector bestdir;
   float bestfraction;
   trace_t trace;
   trace_t groundtrace;
   int i;
   int j;
   int t;
   int u;
   Vector s;
   Vector start;
   Vector end;
   Vector groundend;

	s = Vector( 0, 0, STEPSIZE );
	start = self.worldorigin + s;

   // quantize to nearest 45 degree
   u = ( ( int )( self.worldangles.y * ( 1 / 45 ) + 22.5 ) ) * 45;
   bestfraction = -1;
   //
   // in case we don't find anything!
   //
   bestdir = self.worldorigin - ( Vector( self.orientation[ 0 ] ) * 100 );

   for( i = 0; i <= 180; i += 20 )
      {
      if ( rand() < 0.3 )
         {
         i += 20;
         }
      t = i;
      if ( rand() < 0.5 )
         {
         // sometimes we choose left first, other times right.
         t = -t;
         }
      for( j = -1; j < 2; j += 2 )
         {
         if ( ( j == 1 ) && ( i == 180 ) )
            {
            ang.y = self.worldangles.y + ( t * j );
            }
         else
            {
            ang.y = u + t * j;
            }

         ang.AngleVectors( &dir, NULL, NULL );

         end = self.worldorigin + dir * 140 + s;
         trace = G_Trace( start, self.mins, self.maxs, end, &self, 
            self.edict->clipmask, "Chase::ChooseRandomDirection 1" );
         if ( ( trace.fraction > bestfraction ) && ( !trace.startsolid ) && !( trace.allsolid ) )
            {
            if ( trace.endpos != avoidvec )
               {
               // check if we're near the ground 
               end = self.worldorigin + dir * 32 + s;
               groundend = end;
               groundend.z -= STEPSIZE * 2;
               groundtrace = G_Trace( end, self.mins, self.maxs, groundend, &self, 
                  self.edict->clipmask, "Chase::ChooseRandomDirection 2" );
               if ( groundtrace.fraction != 1 )
                  {
                  bestdir = trace.endpos;
                  bestfraction = trace.fraction;
                  }
               }
            }

         if ( i == 0 )
            {
            break;
            }
         }
      }

   return bestdir;
   }

qboolean	Chase::Evaluate
	(
	Actor &self
	)

	{
	qboolean result;
	trace_t trace;

	if ( !usegoal && !goalnode && ( !goalent || goalent->deadflag ) )
		{
		return false;
		}

	ResetForces();

   if ( !wander )
      {
      if ( self.lastmove == STEPMOVE_OK )
         {
         stuck = 0;
         }
      else
         {
         stuck++;
         if ( stuck >= 2 )
            {
            stuck = 3;
            wander = 1;
            }
         }
      }

   switch( wander )
      {
      case 1 :
         stuck--;
         if ( !stuck )
            {
            wander = 0;
            nextpathtime = 0;
            path = NULL;
            break;
            }
         wanderstart = self.worldorigin;
         avoidvec = ChooseRandomDirection( self );
         wandertime = level.time + 1;
         wander = 2;
         
      case 2 :
		   seek.SetTargetPosition( avoidvec );
		   seek.SetTargetVelocity( vec_zero );
		   seek.SetPosition( self.worldorigin );
		   seek.SetDir( self.movedir );
		   seek.SetMaxSpeed( self.movespeed );
		   result = seek.Evaluate( self );
         if ( result )
            {
            if ( ( level.time > wandertime ) && ( self.lastmove != STEPMOVE_OK ) )
               {
               wander = 0;
               stuck = 0;
               }
         	self.Accelerate( seek.steeringforce );
            return true;
            }
         wander = 0;
         nextpathtime = 0;
         path = NULL;
         break;

         //self.SetAnim( "idle" );
         turnto.SetDirection( ( wanderstart - self.worldorigin ).toYaw() );
         wander = 3;
         wandertime = level.time + 1;

      case 3 :
         if ( level.time < wandertime )
            {
            turnto.Evaluate( self );
         	self.Accelerate( turnto.steeringforce );
            return true;
            }

         //self.SetAnim( anim );
         wander = 0;
         nextpathtime = 0;
         path = NULL;
         break;
      }

	if ( path && follow.DoneWithPath( self ) )
		{
		path = NULL;
		nextpathtime = 0;
		}

	if ( goalent && ( goalent->edict->solid != SOLID_NOT ) && ( goalent->edict->solid != SOLID_TRIGGER ) )
		{
		trace = G_Trace( self.worldorigin, self.mins, self.maxs, self.worldorigin + 
			Vector( self.orientation[ 0 ] ) * self.movespeed * 0.1, &self, self.edict->clipmask, "Chase" );
		if ( trace.ent->entity == goalent )
			{
			return false;
			}
      }

	if ( nextpathtime < level.time )
		{
		nextpathtime = level.time + newpathrate;
      if ( goalnode )
         {
         path = follow.SetPath( self, self.worldorigin, goalnode->worldorigin );
         }
      else if ( goalent )
			{
			path = follow.SetPath( self, self.worldorigin, goalent->worldorigin );
			}
		else
			{
			path = follow.SetPath( self, self.worldorigin, goal );
			}
		}

	if ( !path )
		{
      if ( goalnode )
         {
			seek.SetTargetPosition( goalnode->worldorigin );
			seek.SetTargetVelocity( vec_zero );
         }
		else if ( goalent )
			{
			seek.SetTargetPosition( goalent->worldorigin );
			seek.SetTargetVelocity( goalent->velocity );
			}
		else
			{
			seek.SetTargetPosition( goal );
			seek.SetTargetVelocity( vec_zero );
			}

		seek.SetPosition( self.worldorigin );
		seek.SetDir( self.movedir );
		seek.SetMaxSpeed( self.movespeed );
		result = seek.Evaluate( self );
		//seek.DrawForces();

		steeringforce = seek.steeringforce;

		if ( !result )
			{
			return false;
			}
		}
	else
		{
		follow.SetPosition( self.worldorigin );
		follow.SetDir( self.movedir );
		follow.SetMaxSpeed( self.movespeed );
      if ( !follow.Evaluate( self ) )
         {
         nextpathtime = 0;
         if ( goalnode )
            {
            self.frame_delta = goalnode->worldorigin - self.worldorigin;
            return false;
            }
         }
		//follow.DrawForces();
		steeringforce = follow.steeringforce;
		}

	if ( avoidtime < level.time )
		{
		avoid.SetMaxSpeed( self.movespeed );
		avoid.SetPosition( self.worldorigin );
		avoid.SetDir( self.movedir );
		avoid.Evaluate( self );

		if ( avoid.steeringforce == vec_zero )
			{
			avoidtime = level.time + 0.1;
			}
		else
			{
			steeringforce += avoid.steeringforce;
			}
		}

	self.Accelerate( steeringforce );

	return true;
	}

void Chase::End
	(
	Actor &self
	)

	{
   //if ( wander && ( self.newanimnum != -1 ) )
      //{
      //self.SetAnim( anim );
      //}
	seek.End( self );
	follow.End( self );
	avoid.End( self );
	path = NULL;
   turnto.End( self );
	}

⌨️ 快捷键说明

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