silverlight与游戏中的人工智能基本追逐与闪躲(二)

 在上次的文章中,我们做了一个最简单的基本的追逐与闪躲的功能,就是根据猎物坐标来修改追击者的坐标,使得两者之间的距离渐渐缩短。上次的文章中,我们主要是根据物体屏幕坐标改变,来产生追逐动画,他们改变的坐标位子是连续的,也就是坐标点与坐标点的变化,这种叫做连续环境,但是在游戏中用得更广泛的是另一种方式,砖块环境。今天,我们就来一起在silverlight中实现下砖块环境下的追逐与闪躲。

       何为砖块环境?

在砖块环境构成的游戏中,游戏屏幕会被切割成不连续的砖块:正方形,三角形,六边形等等。一般会选择正方形,因为正方形在处理上面相比其它形状更简单。

有了切割成的方块后,整个游戏画面就像是这个样子的:

 

游戏玩家的位置会固定在某个砖块上面,移动的时候都是以砖块为单位,并且前进方向也是有限制的,而在上次文章中的连续环境下,是以坐标点作为游戏玩家角色的位置,这样可以在任何方向移动。而砖块环境下,如果以正方形为基本单元,那么,游戏玩家就只能有八个方向的运动如下:

 

其实,不管是连续环境还是砖块环境下,其基本追逐闪躲代码是通用的,只不过,上次我们是以点为移动的基本单元,而今天,我们是以砖块为基本单元,如:上次移动一步是从坐标(0,0)移动到坐标(1,1)。而现在移动一步是从第一个砖块移动到下一个砖块。好了,基本原理就是这样,那么在silverlight中我们又该如何实现呢?

我是这样实现的,只是提供一个参考,并不是最好的,大家或许有更好的办法:)

既然要实现砖块环境的移动,但是我们清楚,他的本质还是和连续环境下的移动一样,为了重用上次文章中的核心追逐与闪躲代码,我们只要把上次移动坐标的结果反映到移动砖块的结果上面就行了。可以这么想,通过一个方法,放大坐标移动的效果,如果你移动一个坐标点,如(1,0)到(2,0);将这个操作放大到从第一个砖块移动到下一个相对应的砖块。这样在屏幕上产生的效果将会被放大,之前只移动一点点,而放大后就是移动一个方块的距离,由此我们需要一个逻辑坐标集合屏幕坐标集合并通过一些坐标转换方法,来使得他们之间产生通信。

转换函数如下:

Code:
  1. public Point ChangeLogicToViewP(double x,double y)           //把逻辑坐标转换成屏幕坐标   
  2.   
  3.        {   
  4.              
  5.                x = 350+x*60;   
  6.                y = 10+y*60;   
  7.              
  8.            return new Point(x,y);   
  9.           
  10.        }  

里面的数字350,60,10 这要根据你自己设定的砖块大小和屏幕边距来进行确定,具体可以自己测试。这里我们设定的砖块长宽为60,而画布左边距是350,所以对应把坐标(0,0)换算到屏幕上第一个砖块的位置是350+x*60.

追逐代码和上次的类似:

Code:
  1. public void Catch(double monX, double monY, double humX, double humY)   
  2.        {   
  3.            monsterX = GetRow(monX);   
  4.            monsterY = GetColunm(monY);   
  5.            humanX = GetRow(humX);   
  6.            humanY = GetColunm(humY);   
  7.               
  8.            if (monsterX < humanX)   
  9.            {   
  10.                monsterX++;   
  11.                monsterX=SetRow(monsterX);   
  12.                humanX = SetRow(humanX);   
  13.            }   
  14.            else if (monsterX > humanX)   
  15.            {   
  16.                monsterX--;   
  17.                monsterX=SetRow(monsterX);   
  18.                humanX = SetRow(humanX);   
  19.            }   
  20.            else if (monsterX == humanX)   
  21.            {   
  22.                monsterX = SetRow(monsterX);   
  23.                humanX = SetRow(humanX);   
  24.            }   
  25.            if (monsterY > humanY)   
  26.            {   
  27.                monsterY--;   
  28.                monsterY=SetColnm(monsterY);   
  29.                humanY = SetColnm(humanY);   
  30.   
  31.            }   
  32.            else if (monsterY < humanY)   
  33.            {   
  34.                monsterY++;   
  35.                monsterY=SetColnm(monsterY);   
  36.                humanY = SetColnm(humanY);   
  37.            }   
  38.            else if (monsterY == humanY)   
  39.            {   
  40.                monsterY = SetColnm(monsterY);   
  41.                humanY = SetColnm(humanY);   
  42.            }   
  43.           
  44.        }  

其中的SetRow()和SetColnm()方法也是坐标转换方法,具体如下:

Code:
  1. public double SetRow(double x)   
  2.        {   
  3.            return x * 60 + 350;   
  4.        }   
  5.        public double SetColnm(double y)   
  6.        {   
  7.            return y * 60 + 10;   
  8.        }  

好了,今天就写到这里,具体源码就不贴出来了,这里我只是提供下我自己的思路,相信大家会有更好的方法,而且我代码写的有点乱,如何有需要的朋友可以留言,到时候我整理下,到时候发到你们邮箱:)

测试效果:http://www.ophoneba.com/SL/SLAI-2.html

原文地址:https://www.cnblogs.com/vimsk/p/1865108.html