app开发做网站,慧聚创新网站建设,中国西陆最新军事新闻,网站建设营销策划方案这段Lua脚本定义了一个名为 ai_autofight_find_way 的类#xff0c;继承自 ai_base 类。
lua 游戏架构 之 游戏 AI #xff08;一#xff09;ai_base-CSDN博客文章浏览阅读238次。定义了一套接口和属性#xff0c;可以基于这个基础类派生出具有特定行为的AI组件。例如ai_autofight_find_way 的类继承自 ai_base 类。
lua 游戏架构 之 游戏 AI 一ai_base-CSDN博客文章浏览阅读238次。定义了一套接口和属性可以基于这个基础类派生出具有特定行为的AI组件。例如可以创建追逐敌人的AI、巡逻的AI或使用特定策略的AI等都继承自这个基础类https://blog.csdn.net/heyuchang666/article/details/140624481?spm1001.2014.3001.5502
这个类用于处理游戏中AI在自动战斗模式下寻找路径的逻辑。以下是对代码的具体解释
1. **引入基类** - 使用 require 函数引入 ai_base 类作为基础类。
2. **定义 ai_autofight_find_way 类** - 使用 class 关键字定义了 ai_autofight_find_way 类并继承自 BASE即 ai_base。
3. **构造函数 (ctor)** - 构造函数接受一个 entity 参数并设置 _type 属性为 eAType_AUTOFIGHT_FIND_WAY表示自动战斗中寻找路径的行为。 - 初始化 _target 为 nil用于后续存储找到的目标。
4. **IsValid 方法** - 这个方法用于验证AI是否应该寻找路径。它首先检查实体是否开启了自动战斗_AutoFight是否死亡或无法攻击。 - 检查实体的行为如果处于准备战斗或禁止攻击状态则返回 false。 - 计算警报范围 radius可能基于实体的属性或世界配置。 - 根据不同的地图类型和条件确定是否需要寻找路径。
5. **OnEnter 方法** - 当AI组件进入激活状态时执行。根据当前地图类型和条件计算目标位置并使实体移动到该位置。
6. **OnLeave 方法** - 当AI组件离开激活状态时执行。当前实现中直接返回 true。
7. **OnUpdate 方法** - 每帧调用用于更新AI状态。如果基类的 OnUpdate 方法返回 true则当前方法也返回 true。
8. **OnLogic 方法** - 逻辑更新方法如果基类的 OnLogic 方法返回 true则当前方法返回 false表示只执行一次。
9. **创建组件函数** - create_component 函数用于创建 ai_autofight_find_way 类的新实例传入一个实体和一个优先级。
代码中的一些关键点
- IsDead()检查实体是否死亡。- CanAttack()检查实体是否可以攻击。- GetPropertyValue(ePropID_alertRange)获取实体的警报范围属性。- game_get_world()获取游戏世界配置。- Test(eEBPrepareFight) 和 Test(eEBDisAttack)检查实体的行为状态。- MoveTo()移动到指定位置。
这个脚本为游戏中的AI提供了一个自动战斗中寻找路径的基础框架可以根据具体游戏的需求进行扩展和修改。以下是一些具体的逻辑处理
- 根据不同的地图类型如 g_BASE_DUNGEON、g_ACTIVITY 等AI的行为可能会有所不同。- 计算与目标的距离并根据距离决定是否移动。- 考虑地图上的特定点如物品掉落点、怪物刷新点来决定移动路径。- 使用 vec3_dist 函数计算两个位置之间的距离并根据距离决定是否移动到该位置。
整体而言这个类的目的是在自动战斗模式下根据游戏世界的当前状态和配置为AI实体找到合适的移动路径。
重点解释一下 OnEnter:
function ai_autofight_find_way:OnEnter()if BASE.OnEnter(self) thenlocal entity self._entity;local radius entity:GetPropertyValue(ePropID_alertRange);local logic game_get_logic();local world game_get_world();if world then-- 如果世界配置中有自动战斗半径则使用该值if world._cfg.autofightradius thenradius world._cfg.autofightradius;end-- 根据不同的地图类型执行不同的逻辑if world._mapType g_BASE_DUNGEON or world._mapType g_ACTIVITY or ... then-- 检查所有掉落物品如果物品处于激活状态则移动到该物品位置for k,v in pairs(world._ItemDrops) doif v and v:GetStatus() eSItemDropActive thenlocal _pos logic_pos_to_world_pos(v._curPos);entity:MoveTo(_pos);return false; -- 移动到物品位置后退出函数endend-- 如果地图类型是开放区域并且有怪物刷新点或当前活动区域if world._openType g_FIELD then-- 寻找一个有活着的怪物的刷新点local _pos nil;local isfind false;for k1,v1 in pairs(world._curArea._spawns) dofor k2,v2 in pairs(v1._monsters) doif not v2:IsDead() thenisfind true;break;endendif isfind then_pos v1._cfg.pos;break;endend-- 如果没有找到有活着的怪物的刷新点使用第一个刷新点的位置if not _pos then_pos world._curArea._spawns[1]._cfg.pos;end-- 计算实体当前位置到刷新点或地图增益点的距离local dist vec3_dist(entity._curPos,world_pos_to_logic_pos(_pos));local mindist dist;-- 寻找最近的地图增益点for k,v in pairs(world._mapbuffs) doif v and v:GetStatus() 1 thenlocal distbuff vec3_dist(v._curPos,entity._curPos);if distbuff mindist and distbuff db_common.droppick.AutoFightMapbuffAutoRange thenmindist distbuff;_pos logic_pos_to_world_pos(v._curPos);endendend-- 移动实体到计算出的位置entity:MoveTo(_pos);end-- 其他地图类型的逻辑...elseif world._mapType g_FIELD or world._mapType g_Life then-- 对于其他地图类型寻找最近的地图增益点并移动实体-- ...endendreturn false; -- 如果没有找到目标位置或执行了移动逻辑则返回falseendreturn false; -- 如果没有调用基类的OnEnter或基类返回false则返回false
end
在 OnEnter 方法中首先调用基类的 OnEnter 方法如果它返回 false则直接返回 false。如果基类的 OnEnter 方法返回 true则继续执行以下逻辑
获取实体的警报范围 radius。检查游戏世界配置如果存在自动战斗半径配置则使用该配置值覆盖实体的警报范围。根据当前的地图类型执行不同的逻辑来寻找目标位置。例如 如果是 g_BASE_DUNGEON、g_ACTIVITY 等地图类型会检查所有物品掉落点寻找激活的物品并移动到该位置。如果是开放区域g_FIELD会寻找有活着的怪物的刷新点或最近的地图增益点并移动实体到该位置。使用 vec3_dist 函数计算实体当前位置到目标位置的距离并根据这个距离来确定是否移动实体。如果找到目标位置则调用 entity:MoveTo(_pos) 方法移动实体到该位置然后返回 false 退出函数。如果没有找到目标位置或不满足移动条件则返回 false。
整体而言OnEnter 方法的目的是确定AI在自动战斗模式下应该移动到哪个位置并执行移动操作。
全部代码实现
----------------------------------------------------------------
module(..., package.seeall)local require requirelocal BASE require(logic/entity/ai/ai_base).ai_base;------------------------------------------------------
ai_autofight_find_way class(ai_autofight_find_way, BASE);
function ai_autofight_find_way:ctor(entity)self._type eAType_AUTOFIGHT_FIND_WAY;self._target nil;
endfunction ai_autofight_find_way:IsValid()local entity self._entity;if not entity._AutoFight thenreturn false;endif entity:IsDead() or not entity:CanAttack() thenreturn false;endif entity._behavior:Test(eEBPrepareFight) thenreturn false;endif entity._behavior:Test(eEBDisAttack) thenreturn false;endlocal radius entity:GetPropertyValue(ePropID_alertRange);local world game_get_world();if world thenif world._cfg.autofightradius thenradius world._cfg.autofightradius;endlocal target entity._alives[2][1]; -- 敌方if entity._alives[3][1] then--中立local trap entity._alives[3][1];if trap.entity and trap.entity._traptype eSTrapActive thentarget entity._alives[3][1]; endendif target thenif target.dist radius thenif target.entity._groupType eGroupType_N and target.dist db_common.droppick.AutoFightMapbuffAutoRange thenelsereturn false;endendelseif world._mapType g_TOURNAMENT thenreturn false;endendif world._mapType g_BASE_DUNGEON or world._mapType g_ACTIVITY or world._mapType g_FACTION_DUNGEON or world._mapType g_TOWER or world._mapType g_WEAPON_NPC or world._mapType g_RIGHTHEART or world._mapType g_ANNUNCIATE or world._mapType g_FIGHT_NPC or world._mapType g_Pet_Waken thenif world._openType g_FIELD thenif #world._spawns 0 and not world._curArea then return falseendelselocal spawnID math.abs(g_game_context:GetDungeonSpawnID())if spawnID 0 thenreturn falseendlocal dist nil;if spawnID ~ 0 thenspawnPointID db_spawn_area[spawnID].spawnPoints[1]_pos db_spawn_point[spawnPointID].posdist vec3_dist(entity._curPos,world_pos_to_logic_pos(_pos))if dist and dist 100 thenreturn falseend endendelseif world._mapType g_FIELD or world._mapType g_Life thenif entity._PVPStatus ~ g_PeaceMode thenreturn false;endlocal dist vec3_dist(entity._curPos,entity._AutoFight_Point)if dist radius thenreturn false;endlocal value g_game_context:getAutoFightRadius()if value and value g_OneMap thenreturn false;endelse -- TODOreturn false;endendreturn true;
endfunction ai_autofight_find_way:OnEnter()if BASE.OnEnter(self) thenlocal entity self._entity;local radius entity:GetPropertyValue(ePropID_alertRange)local logic game_get_logic();local world game_get_world();if world thenif world._cfg.autofightradius thenradius world._cfg.autofightradiusendif world._mapType g_BASE_DUNGEON or world._mapType g_ACTIVITY or world._mapType g_FACTION_DUNGEON or world._mapType g_TOWER or world._mapType g_WEAPON_NPC or world._mapType g_RIGHTHEART or world._mapType g_ANNUNCIATE or world._mapType g_FIGHT_NPC or world._mapType g_Pet_Waken thenfor k,v in pairs(world._ItemDrops) doif v and v:GetStatus() eSItemDropActive thenlocal _pos logic_pos_to_world_pos(v._curPos)entity:MoveTo(_pos)return false;endendif world._openType g_FIELD thenif #world._spawns 0 or world._curArea thenlocal _pos nil;local isfind falsefor k1,v1 in pairs(world._curArea._spawns) dofor k2,v2 in pairs(v1._monsters) doif not v2:IsDead() thenisfind true;break;endendif isfind then_pos v1._cfg.pos;break;endendif not _pos then_pos world._curArea._spawns[1]._cfg.posend--local _pos world._curArea._spawns[1]._cfg.poslocal dist vec3_dist(entity._curPos,world_pos_to_logic_pos(_pos))local mindist distfor k,v in pairs(world._mapbuffs) doif v and v:GetStatus() 1 thenlocal distbuff vec3_dist(v._curPos,entity._curPos)if distbuff mindist and distbuff db_common.droppick.AutoFightMapbuffAutoRange thenmindist distbuff_pos logic_pos_to_world_pos(v._curPos)endendendentity:MoveTo(_pos)endelselocal _pos nillocal spawnID math.abs(g_game_context:GetDungeonSpawnID())local dist 99999999999;if spawnID ~ 0 thenspawnPointID db_spawn_area[spawnID].spawnPoints[1]_pos db_spawn_point[spawnPointID].posdist vec3_dist(entity._curPos,world_pos_to_logic_pos(_pos)) endlocal mindist distlocal isspawn truefor k,v in pairs(world._mapbuffs) doif v and v:GetStatus() 1 thenlocal distbuff vec3_dist(v._curPos,entity._curPos)if distbuff mindist and distbuff db_common.droppick.AutoFightMapbuffAutoRange thenmindist distbuffisspawn false;_pos logic_pos_to_world_pos(v._curPos)endendendif mindist 150 and isspawn and g_game_context:GetDungeonSpawnID() 0 theng_game_context:SetDungeonSpawnID(0);_pos nil;endif _pos thenentity:MoveTo(_pos)endendelseif world._mapType g_FIELD or world._mapType g_Life thenfor k,v in pairs(world._mapbuffs) doif v and v:GetStatus() 1 thenlocal distbuff vec3_dist(v._curPos,entity._AutoFight_Point)if distbuff radius and distbuff db_common.droppick.AutoFightMapbuffAutoRange thenlocal _pos logic_pos_to_world_pos(v._curPos)entity:MoveTo(_pos)return false;endendendendendreturn false;endreturn false;
endfunction ai_autofight_find_way:OnLeave()if BASE.OnLeave(self) thenreturn true;endreturn false;
endfunction ai_autofight_find_way:OnUpdate(dTime)if BASE.OnUpdate(self, dTime) thenreturn true;endreturn false;
endfunction ai_autofight_find_way:OnLogic(dTick)if BASE.OnLogic(self, dTick) thenreturn false; -- only one frameendreturn false;
endfunction create_component(entity, priority)return ai_autofight_find_way.new(entity, priority);
end