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

📄 steering.cpp

📁 this keik game source
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
//
//  $Logfile:: /Quake 2 Engine/Sin/code/game/steering.cpp                     $
// $Revision:: 21                                                             $
//   $Author:: Markd                                                          $
//     $Date:: 11/18/98 8:53p                                                 $
//
// Copyright (C) 1998 by Ritual Entertainment, Inc.
// All rights reserved.
//
// This source may not be distributed and/or modified without
// expressly written permission by Ritual Entertainment, Inc.
//
// $Log:: /Quake 2 Engine/Sin/code/game/steering.cpp                          $
// 
// 21    11/18/98 8:53p Markd
// backed out change for NearestNode
// 
// 20    11/18/98 7:46p Markd
// made it so if path finding fails on the first node it will try without the
// current bounds and try again
// 
// 19    10/26/98 2:19p Markd
// Only jump if last_jump_time is less than level.time
// 
// 18    10/25/98 4:58a Jimdose
// added goalnode to chase so that when going to a pathnode we don't do a seek
// to the node after the path is done
// made chase's wander code check for ground
// 
// 17    10/23/98 11:33p Markd
// fixed some chase code stuff
// 
// 16    10/23/98 6:24p Jimdose
// FindCurrentNode wasn't advancing the node pointer, effectively duplicating
// the second node, causing the guys to sometimes spin on their path
// 
// 15    10/23/98 5:13a Jimdose
// Fixed followpath so that they don't turn the wrong direction at the end of
// the path
// 
// 14    10/19/98 11:45p Jimdose
// added FindCurrentNode to FollowPath
// 
// 13    10/18/98 3:21a Jimdose
// Simplified FollowPath
// 
// 12    10/17/98 4:43p Markd
// made ChooseRandomDirection choose backup as its default move
// 
// 11    10/16/98 1:55a Jimdose
// Added another NextNode function for finding the next node after the
// specified node.
// Made FollowPath check the node following the jump node to see if it should
// jump
// 
// 10    10/14/98 9:43p Markd
// Bullet proofed nextnode stuff in AI_JUMP for steering
// 
// 9     10/14/98 9:03p Markd
// tweaked jumping stuff
// 
// 8     10/14/98 5:21p Markd
// Added Jumping to the Chase steering method
// 
// 7     10/10/98 5:01p Markd
// Changed trace masks to edict->clipmasks
// 
// 6     10/10/98 4:35p Markd
// Fixed some avoidvec behavior for the characters
// 
// 5     10/04/98 5:31p Markd
// Fixed chase problems
// 
// 4     9/22/98 5:11p Jimdose
// Added Turn
// Added wander code to chase
// 
// 3     9/22/98 1:56a Jimdose
// Added ShowInfo
// Added ObstacleAvoidance2 temporarily
// 
// 2     9/18/98 10:57p Jimdose
// Separated from Behavior.cpp
// 
// 1     9/18/98 5:01p Jimdose
//
// DESCRIPTION:
// Steering behaviors for AI.
// 

#include "g_local.h"
#include "steering.h"
#include "actor.h"

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

  Steering Class Definition

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

CLASS_DECLARATION( Listener, Steering, NULL );

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

Steering::Steering()
	{
	steeringforce = vec_zero;

	origin = vec_zero;
	movedir  = vec_zero;
	maxspeed = 320;
	}

void Steering::ShowInfo
	(
	Actor &self
	)

	{
   gi.printf( "steeringforce: ( %f, %f, %f )\n", steeringforce.x, steeringforce.y, steeringforce.z );
   gi.printf( "origin: ( %f, %f, %f )\n", origin.x, origin.y, origin.z );
   gi.printf( "movedir: ( %f, %f, %f )\n", movedir.x, movedir.y, movedir.z );
   gi.printf( "maxspeed: %f\n", maxspeed );
	}

void Steering::Begin
	(
	Actor &self
	)

	{
	}

qboolean	Steering::Evaluate
	(
	Actor &self
	)

	{
	return false;
	}

void Steering::End
	(
	Actor &self
	)

	{
	}

void Steering::DrawForces
	(
	void
	)

	{
	G_Color3f( 0.3, 0.5, 1 );
	G_BeginLine();
	G_Vertex( origin );
	G_Vertex( origin + steeringforce * FRAMETIME );
	G_EndLine();

	G_Color3f( 1, 0, 1 );
	G_BeginLine();
	G_Vertex( origin );
	G_Vertex( origin + movedir * maxspeed * FRAMETIME );
	G_EndLine();
	}

void Steering::SetPosition
	(
	Vector pos
	)

	{
	origin = pos;
	}

void Steering::SetDir
	(
	Vector dir
	)

	{
	movedir = dir;
	}

void Steering::SetMaxSpeed
	(
	float speed
	)

	{
	maxspeed = speed;
	}


void Steering::ResetForces
	(
	void
	)

	{
	steeringforce = vec_zero;
	}

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

  Seek Class Definition

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

CLASS_DECLARATION( Steering, Seek, NULL );

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

Seek::Seek()
	{
	targetposition = vec_zero;
	targetvelocity = vec_zero;
	}

void Seek::SetTargetPosition
	(
	Vector pos
	)

	{
	targetposition = pos;
	}

void Seek::SetTargetVelocity
	(
	Vector vel
	)

	{
	targetvelocity = vel;
	}

void Seek::ShowInfo
	(
	Actor &self
	)

	{
   Steering::ShowInfo( self );

   gi.printf( "\ntargetposition: ( %f, %f, %f )\n", targetposition.x, targetposition.y, targetposition.z );
   gi.printf( "targetvelocity: ( %f, %f, %f )\n", targetvelocity.x, targetvelocity.y, targetvelocity.z );
	}

qboolean	Seek::Evaluate
	(
	Actor &self
	)

	{
	Vector	predictedposition;
	Vector	dir;
   Vector   xydelta;
	Vector	delta;
	Vector	ang1;
	Vector	ang2;
	float		dist;
   float    xydist;
	float		l;

	ResetForces();

	delta = targetposition - origin;
	dist = delta.length();
   //
   // null out z component
   //
   delta.z = 0;
	xydist = delta.length();

	predictedposition = targetposition + targetvelocity * ( dist / maxspeed );

	dir = predictedposition - origin;
	dir.normalize();

	ang1 = dir.toAngles();
	ang2 = movedir.toAngles();

	steeringforce.x = ang1.x - ang2.x;
	if ( steeringforce.x <= -180 )
		{
		steeringforce.x += 360;
		}
	if ( steeringforce.x >= 180 )
		{
		steeringforce.x -= 360;
		}

	steeringforce.y = ang1.y - ang2.y;
	if ( steeringforce.y <= -180 )
		{
		steeringforce.y += 360;
		}
	if ( steeringforce.y >= 180 )
		{
		steeringforce.y -= 360;
		}

	// if we're nearly there, turn directly toward our goal
	if ( xydist > self.movespeed )
		{
		if ( fabs( steeringforce.x ) > 1 )
			{
			steeringforce.x *= 0.4;
			}

		if ( fabs( steeringforce.y ) > 1 )
			{
			steeringforce.y *= 0.4;
			}
		}
	else 
		{
		l = self.total_delta.length();
		if ( xydist <= l )
			{
         //steeringforce = vec_zero;
			self.total_delta = self.animdir * xydist;
			return false;
			}
		}

	steeringforce.z = 0;
	
	return true;
	}

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

  ObstacleAvoidance Class Definition

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

CLASS_DECLARATION( Steering, ObstacleAvoidance, NULL );

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

ObstacleAvoidance::ObstacleAvoidance()
   {
   avoidwalls = true;
   }

void ObstacleAvoidance::AvoidWalls
   (
   qboolean avoid
   )

   {
   avoidwalls = avoid;
   }

void ObstacleAvoidance::ShowInfo
	(
	Actor &self
	)

	{
   Steering::ShowInfo( self );

   gi.printf( "\navoidwalls: %d\n", avoidwalls );
	}

qboolean	ObstacleAvoidance::Evaluate
	(
	Actor &self
	)

	{
	Vector	predictedposition;
	Vector	normal;
	Vector	angles;
	Vector	dir;
	Vector	right;
	Vector	delta;
	float		urgency;
	float		dot;
	trace_t	tracef;
#if 0
	trace_t	tracel;
	trace_t	tracer;
	Vector	leftposition;
	Vector	rightposition;
#endif
	Entity	*ent;

	ResetForces();

	angles = self.movedir.toAngles();
	angles.AngleVectors( NULL, &right, NULL );

   origin = self.worldorigin;
   origin.z += 1;
	predictedposition = origin + self.movedir * self.movespeed;//maxspeed;
#if 0
	leftposition = origin - right * 8;
	rightposition = origin + right * 8;
#endif

#if 0
	G_Color3f( 1, 1, 1 );
	G_BeginLine();
	G_Vertex( origin );
	G_Vertex( predictedposition );
	G_Vertex( origin );
	G_Vertex( leftposition );
	G_Vertex( origin );
	G_Vertex( rightposition );
	G_EndLine();
#endif

	tracef = G_Trace( origin, self.mins, self.maxs, predictedposition, &self, self.edict->clipmask, "ObstacleAvoidance forward" );
#if 0
	tracel = G_Trace( origin, self.mins, self.maxs, leftposition, &self, MASK_PLAYERSOLID, "ObstacleAvoidance left" );
	tracer = G_Trace( origin, self.mins, self.maxs, rightposition, &self, MASK_PLAYERSOLID, "ObstacleAvoidance right" );
   if ( tracel.fraction < 1 )
		{
		urgency = 1.1 - tracel.fraction;
		normal = tracel.plane.normal;
		ent = tracel.ent->entity;
		steeringforce = Vector( 0, -90, 0 );;
		}
	else if ( tracer.fraction < 1 )
		{
		urgency = 1.1 - tracer.fraction;
		normal = tracer.plane.normal;
		ent = tracer.ent->entity;
		steeringforce = Vector( 0, 90, 0 );;
		}
	else 
#endif
	if ( tracef.fraction < 1 )
		{
		urgency = 1.0 - tracef.fraction;
		normal = tracef.plane.normal;
		ent = tracef.ent->entity;
		if ( ent->getSolidType() != SOLID_BSP )
			{
			dot = -( right * ( ent->worldorigin - self.worldorigin ) );
			}
		else
			{
         if ( !avoidwalls )
            {
   			return true;
            }
         
         dot = right * normal;
			}

		if ( dot < 0 )
			{
			// turn left
			steeringforce = Vector( 0, 90, 0 );;
			}
		else
			{
			// turn right
			steeringforce = Vector( 0, -90, 0 );;
			}
		}
	else
		{
		return true;
		}

	steeringforce *= urgency;

	return true;
	}

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

  ObstacleAvoidance2 Class Definition

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

CLASS_DECLARATION( Steering, ObstacleAvoidance2, NULL );

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

ObstacleAvoidance2::ObstacleAvoidance2()
   {
   avoidwalls = true;
   }

void ObstacleAvoidance2::AvoidWalls
   (
   qboolean avoid
   )

   {
   avoidwalls = avoid;
   }

void ObstacleAvoidance2::ShowInfo
	(
	Actor &self
	)

	{
   Steering::ShowInfo( self );

   gi.printf( "\navoidwalls: %d\n", avoidwalls );
	}

qboolean	ObstacleAvoidance2::Evaluate
	(
	Actor &self
	)

	{
	Vector	predictedposition;
	Vector	normal;
	Vector	angles;
	Vector	dir;
	Vector	right;
	Vector	delta;
	float		urgency;
	float		dot;
	trace_t	tracef;
#if 0
	trace_t	tracel;
	trace_t	tracer;
	Vector	leftposition;
	Vector	rightposition;
#endif
	Entity	*ent;

	ResetForces();

	angles = self.movedir.toAngles();
	angles.AngleVectors( NULL, &right, NULL );

   origin = self.worldorigin;
   origin.z += 1;
	predictedposition = origin + self.movedir * self.movespeed;//maxspeed;
#if 0
	leftposition = origin - right * 8;
	rightposition = origin + right * 8;
#endif

#if 0
	G_Color3f( 1, 1, 1 );
	G_BeginLine();
	G_Vertex( origin );
	G_Vertex( predictedposition );
	G_Vertex( origin );
	G_Vertex( leftposition );
	G_Vertex( origin );
	G_Vertex( rightposition );
	G_EndLine();
#endif

	tracef = G_Trace( origin, self.mins, self.maxs, predictedposition, &self, self.edict->clipmask, "ObstacleAvoidance2 forward" );
#if 0
	tracel = G_Trace( origin, self.mins, self.maxs, leftposition, &self, MASK_PLAYERSOLID, "ObstacleAvoidance2 left" );
	tracer = G_Trace( origin, self.mins, self.maxs, rightposition, &self, MASK_PLAYERSOLID, "ObstacleAvoidance2 right" );
   if ( tracel.fraction < 1 )
		{
		urgency = 1.1 - tracel.fraction;
		normal = tracel.plane.normal;
		ent = tracel.ent->entity;
		steeringforce = Vector( 0, -90, 0 );;
		}
	else if ( tracer.fraction < 1 )
		{
		urgency = 1.1 - tracer.fraction;
		normal = tracer.plane.normal;
		ent = tracer.ent->entity;
		steeringforce = Vector( 0, 90, 0 );;
		}
	else 
#endif
	if ( tracef.fraction < 1 )
		{
		urgency = 1.0 - tracef.fraction;
		normal = tracef.plane.normal;
		ent = tracef.ent->entity;
		if ( ent->getSolidType() != SOLID_BSP )
			{
			dot = -( right * ( ent->worldorigin - self.worldorigin ) );
			}
		else
			{
         if ( !avoidwalls )
            {
   			return true;
            }
         
         dot = right * normal;
			}

		if ( dot < 0 )
			{
			// turn left
			steeringforce = Vector( 0, 22, 0 ) * urgency;
			}
		else
			{
			// turn right
			steeringforce = Vector( 0, 22, 0 ) * urgency;
			}
		}
	else
		{
		return true;
		}

	steeringforce *= urgency;

	return true;
	}

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

  FollowPath Class Definition

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

CLASS_DECLARATION( Steering, FollowPath, NULL );

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

FollowPath::FollowPath()
	{
	path = NULL;
   currentNode = NULL;
	}

FollowPath::~FollowPath()
	{
   currentNode = NULL;
   if ( path )
      {
	   delete path;
      }
	}

void FollowPath::FindCurrentNode
   (
   Actor &self
   )

   {
   // Sometimes the second node on the path is the proper node to start from.
   // This happens because instead of creating the shortest path from the actor,
   // we create the shortest path from his nearest node.  Often, this creates a
   // path where he may already be further along the path than the first node,
   // causing him to "go back" along the path.  By checking if we can get to the
   // second node, we get rid of the backtracking.
   PathNode *node;

   if ( !path )
      {
      currentNode = NULL;
      return;
      }

   currentNode = path->NextNode();
   if ( path->NumNodes() < 2 )
      {
      return;
      }

   node = path->GetNode( 2 );
   if ( self.CanMoveTo( node->worldorigin ) )
      {
      currentNode = path->NextNode();
      }
   }

void FollowPath::SetPath
	(
	Path *newpath
	)

	{
	if ( path )
		{
		delete path;
		}

   currentNode = NULL;

   path = newpath;
	}

Path *FollowPath::SetPath
	(
	Actor &self,
	Vector from,
	Vector to
	)

	{
	PathNode *goal;
	PathNode *node;
	StandardMovePath find;

	if ( path )
		{
		delete path;
		path = NULL;
		}

   currentNode = NULL;

   goal = PathManager.NearestNode( to, &self );
	if ( !goal )
		{
	   return NULL;
		}

	node = PathManager.NearestNode( from, &self );
	if ( !node || ( goal == node ) )
		{
		return NULL;
		}

	find.heuristic.setSize( self.size );
	find.heuristic.entnum = self.entnum;

	path = find.FindPath( node, goal );

	return path;
	}

void FollowPath::DrawForces

⌨️ 快捷键说明

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