游戏服务器之ai

本文详细介绍了游戏服务器中NPC的AI设计,包括NPC的循环流程、AI状态机、AI类型处理、死亡循环以及NPC配置。AI状态机涵盖游荡、追击、攻击和回归状态,并使用A*算法优化寻路。NPC配置结构和场景NPC对象的管理也进行了说明。
摘要由CSDN通过智能技术生成

ai是游戏的一个重要组成部分,指的是玩家与npc之间的相互活动。

设计上:

npc  ai流程:逻辑线程主循环-->场景管理器遍历->场景循环-->遍历所有npc-->npc循环-->ai状态机切换和ai状态处理

ai主要功能包括

正常状态:ai状态切换和ai状态处理

死亡状态:死亡状态机


ai状态切换

根据状态机来切换。

游荡状态->追击状态 或 攻击状态

追击状态->攻击状态 或 回归状态

攻击状态->追击状态 或 回归状态

回归状态->游荡状态


ai状态处理

(1)发呆状态(不做事情)

(2)游荡状态 (随机移动)

(3)追击状态(ai的寻路是使用网格计算,目前是a星的优化算法)

(4)攻击状态(战斗使用普通屏索引、优化计算使用有效屏索引)

(5)回归状态 (目前刷新到出生点)

 

数据结构

AI状态控制器

ai类型(ai活动逻辑)


ai状态机

(1)ai类型之间的切换(ai状态机切换)。

(2)ai类型的执行。

(3)ai对象的死亡循环执行。


处理时机

(1)在npc的循环里执行ai状态的切换和ai类型动作

(2)处理技能状态定时器和npc定时状态

(3)死亡状态下会有死亡循环。

 1、npc总体流程

npc的ai循环的调用层次:

逻辑线程主循环-->场景管理器遍历->场景循环-->遍历所有npc-->npc循环-->ai状态机切换和ai状态处理

(1)npc循环

bool scene_npc::loop()
{
	const SceneObjectState &state = getEntryState();
	if(state == SceneObject_Normal)//npc 正常状态
	{
		if (AIC)//ai控制器
		{
			if(this->base->npcType == MSG::NpcType_Gun)
			{
				gunAction();//特殊类型npc 的ai状态
			}
			else
			{
				AIC->processPhase();//ai状态机切换
				normalAction();//ai状态处理
			}
		}

		if(_one_sec(main_logic_thread::currentTime))
		{
			this->statem->stateTimer();//技能状态管理器定时器(执行技能状态对象),参考:http://blog.csdn.net/chenjiayi_yun/article/details/19429133
			this->statem->loop();//技能状态循环(回收标识销毁的技能状态对象)
			//死亡状态life  为0 ,_life_timer 定时器到时
			if(npcState.life && (_life_timer)(main_logic_thread::currentTime))
			{
				killMe();//npc死亡九屏同步,死亡处理
			}
			timeCount++;
			//根据策划配置时间定时回血 ,采集状态检查
			......
    	                
		}
	}
	else if(state == SceneObject_Death)
	{
                this->statem->deleteAll();//npc死亡删除状态管理器的所有状态对象
		deathLoop();//npc 对象死亡状态后的死亡循环处理
	}
        return true;
}


2、ai状态机

(1)ai类型

ai类型实际上就是复杂动作的一个结合体。可以直接在c++代码里面写,也可以写在脚本方便热切换 ,针对ai的处理又要耗费较多的cpu时间,所以一般就在c++里面写。

ai类型之间的切换是在AI状态切换控制器里面管理的。


目前主要的ai类型有如下:

enum eAIType
{
	NPC_AI_NORMAL,///游荡
	NPC_AI_MOVETO,///追击
	NPC_AI_ATTACK,///攻击
	NPC_AI_RETURN_TO_REGION,///回归
	NPC_AI_STUN,//发呆
};


ai类型定义:

struct t_NpcAIDefine
{
///类型,NPC在该阶段的主要动作
eAIType type;
///位置 根据不同动作位置的意义也略不相同
///移动时表示目的地,其他表示活动范围中心
nPos pos;
///追击目标点
nPos chaseLoc;
///范围 
///移动时表示到达目的地的判定范围,其他表示活动范围
int32 regionX, regionY;
};

(2)AI状态控制器

AI状态控制器(是npc对象scene_npc的成员)来修改ai状态,记录当前ai动作类型,来根据当前ai类型执行动作。

AI控制器:

保存当前和上一个ai类型

当前ai类型的转换(切换条件判断)

class NpcAIController
{
	///本控制器控制的npc
	scene_npc * npc;
	///当前的AI类型和保存的前一个AI类型
	t_NpcAIDefine curAI,oldAI;
	///活动范围的中心
	nPos actPos;
	//追击的半径
	nPos chasePos;
	///活动范围的宽和高
	int actRegionX, actRegionY;
	/**
	 * \description 判断Npc是否走出了活动范围之外
	 * 如果没有在跟踪用户状态,需要在活动范围行走
	 * 追逐时范围扩大10
	 * \return 是否超出活动范围
	 */
	bool outOfRegion() const;
	//回到活动范围,追踪敌人超出范围时以5倍速返回
	/**
	 * \description 设置回到范围的AI使NPC回到活动范围
	 * 如果NPC是跟踪敌人而超出了活动范围,则以5倍速返回活动范围内,同时放弃跟踪目标
	 */
	void returnToRegion();
	/**
	 * \description 判断npc是否到达某位置的某范围内(范围判断函数)
	 * \param pos 中心位置,默认是当前AI的目标位置
	 * \param regionX 范围宽,默认是当前AI的范围宽
	 * \param regionY 范围高,默认是当前AI的范围高
	 * \return 是否在范围内
	 */
	bool arrived(nPos pos = nPos(0,0), int x = -1, int y = -1);
	
	void setNormalAI();
	/**
	 * \description 设置NPC的活动范围
	 * \param pos 中心位置
	 * \param x,y 范围的宽和高
	 * \return 
	 */
	void setActRegion(nPos pos = nPos(0,0), int x = -1, int y = -1);
	/**
	 * \description 设置NPC的活动范围
	 * \param pos 左上位置
	 * \param x,y 范围的宽和高
	 * \return 
	 */
	void setActRegionS(nPos pos = nPos(0,0), int x = -1, int y = -1);
	/**
	 * \description 得到NPC的活动范围
	 * \param pos 输出:中心位置
	 * \param x,y 输出:范围的宽和高
	 */
	void getActRegion(nPos &, int &, int  &);
	/**
	 * \description 状态切换管理
	 * 该方法在scene_npc::loop中执行
	 */
	void processPhase();
	//当前ai定义
	t_NpcAIDefine *GetCurAI() {return &curAI;}
};

(2-1)ai类型切换

ai的状态切换函数处理,进行ai状态的切换条件的判断和执行切换

void NpcAIController::processPhase()
{
	switch(curAI.type)
	{
		case NPC_AI_STUN://发呆状态
		{
			if(this->stunTime  < main_logic_thread::currentTime._msec &&this->npc->enm->enemySize == 0)//没有敌人,并在发呆时间内
			{
				int rand = nMisc::randBetween(0,100);//随机跳入游荡状态
				if(rand > 90)
				{
					curAI.type = NPC_AI_NORMAL;
				}
				return;
			}
			else
			{
				curAI.type = NPC_AI_NORMAL;
			}
		}
		break;
		case NPC_AI_NORMAL://游荡状态
		{
			//获取仇恨列表中的最近的玩家
			scene_player* player = (scene_player*)this->npc->enm->getNearestEnemy();
			if(!player)//在仇恨列表里没有目标则搜索警戒范围内的目标
			{
				//警戒范围之内发现了目标,切换Ai,移向敌人
				//指定范围上的点是根据npc对象的坐标点为中心的,一定
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值