游戏AI-1:追逐和闪躲

代码https://resources.oreilly.com/examples/9780596005559/

追逐/闪躲问题由两部分组成。首先要做出追或逃的决策判断。其次是开始追或逃,也就是让追击者追猎物,或者让猎物尽可能离追击者远一点,免得被抓到。

追逐猎物是最简单、最容易写而且也是最常用的方法,就是在每次的游戏循环中,更新追击者的坐标,让追击者和猎物的坐标离得愈来愈近。这种算法不去管追击者和猎物各自行进的方向和速度。

除了这种最简单的方法之外,还有其他方法可以用,也许更能满足你的需求,审视你的游戏所需的条件。如根据速度和相对位置的信息,试图阻拦猎物。另一种方法是利用势函数(potential function),以某种方式改变追击者的行为,或让猎物引起追击者的注意。同样地,你也可以用类似的势函数,让猎物逃离追击者,或让追击者对猎物产生排斥感。

基本的追逐和闪躲

最简单的追逐算法是根据猎物的坐标来修改追击者的坐标,使两者间的距离逐渐缩短,反则扩大距离。猎物prey,追击者predator

基本追逐

if (predatorX > preyX)
    predatorX--;
else if (predatorX < preyX)
    predatorX++;

if (predatorY > preyY)
    predatorY--;
else if (predatorY < preyY)
    predatorY++;

基本闪躲

if (preyX > predatorX)
    preyX++;
else if (preyX < predatorX)
    preyX--;

if (preyY > predatorY)
    preyY++;
else if (preyY < predatorY)
    preyY--;

在砖块式构成的游戏中,游戏领域会切割成不连续的砖块(正方形、六边形等),以砖块为单位,前进的方向是有限制的。

而在连续环境中,则以点坐标表示位置,玩家也可以往任何方向移动。

以上算法的轨迹是一条折线,比较自然的做法是走直线。

视线追逐

右图表示猎物在运动的情况

在连续环境,移动单位是像素,不会影响动作的流畅感。

而在砖块环境,由于只有八种可能的移动方向,会引发一个有趣的问题:从数学观点来看,没有任何一个方向可以精确表达目标的真正方向。我们需要做的是找出邻近的八个砖块中,有哪一个是移动后,尽可能以直线走向玩家的。

解决方式是使用标准线段(standard line)算法。如Bresenham线段算法,它与其他线段绘制算法不同,绝不会在线段最短的那个轴上画出两个相邻的像素。

Bresenham算法的原理是比较起始点和终点之间的横轴和纵轴的长度,哪个轴比较长,就往该方向前进,等长就往斜边前进。

void ai_Entity::BuildPathToTarget(void)
{
	int nextCol=col;
	int	nextRow=row;
	int deltaRow=endRow-row;
	int deltaCol=endCol-col;
	int stepCol; 
	int stepRow;
	int currentStep;
	int fraction;
    // 清空
	for (currentStep=0;currentStep<kMaxPathLength;currentStep++)
		{
			pathRow[currentStep]=-1;
			pathCol[currentStep]=-1;
		}
	currentStep=0;
	pathRowTarget=endRow;
	pathColTarget=endCol;

  if (deltaRow < 0) stepRow=-1; else stepRow=1;
  if (deltaCol < 0) stepCol=-1;	else stepCol=1;
  deltaRow=abs(deltaRow*2);
  deltaCol=abs(deltaCol*2);

	pathRow[currentStep]=nextRow;
	pathCol[currentStep]=nextCol;
	currentStep++;
	if (currentStep>=kMaxPathLength)
		return;
	// Bresenham算法	
	if (deltaCol > deltaRow) 
		{
			fraction = deltaRow * 2 - deltaCol;
			while (nextCol != endCol) 
				{
					if (fraction >= 0) 
						{
							nextRow += stepRow;
							fraction = fraction - deltaCol;
						}
					nextCol = nextCol + stepCol;
					fraction = fraction + deltaRow;
					pathRow[currentStep]=nextRow;
					pathCol[currentStep]=nextCol;
					currentStep++;
					if (currentStep>=kMaxPathLength)
						return;
			}
	  } 
	 else 
	 {
		fraction = deltaCol * 2 - deltaRow;
		while (nextRow != endRow) 
			{
				if (fraction >= 0) 
					{
						nextCol = nextCol + stepCol;
						fraction = fraction - deltaRow;
					}
				nextRow = nextRow + stepRow;
				fraction = fraction + deltaCol;
				pathRow[currentStep]=nextRow;
				pathCol[currentStep]=nextCol;
				currentStep++;
				if (currentStep>=kMaxPathLength)
					return;
			}
	  }
	} 

连续环境的视线追逐

Bresenham算法对砖块环境而言是相当有效的方法。而在连续环境中,可以结合物理引擎使用---个体移动都是由力和扭力(force & torque)来推动的,比如飞机、飞船等。

拦截

直接朝着猎物方向前进,从空间或者时间的角度来看,不一定都是追上猎物的最短路径。比较合理的解决办法,是让追击者在猎物路径上的某个点予以拦截。这样从时空角度来看,可以让追击者以最短的时间或路径追到猎物。另外,拦截算法甚至可以让速度较慢的追击者,有机会拦截到速度较快的猎物。

拦截算法的基本原理是能够预测猎物未来的位置,然后直接到那个位置去,使其能和猎物同时到达同一位置。

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值