设计一个 entity class
,用于创建和管理游戏世界中的实体对象。这个类包含了大量的函数,用于处理实体的各种行为和属性,例如创建、移动、播放动画、同步状态等。
CreateTitle
函数的作用是创建和初始化一个实体的标题显示。在游戏或模拟程序中,实体的标题通常用于显示名称、生命值或其他重要信息。
function entity:CreateTitle(reset)-- 引入用于创建和管理实体标题的模块。local _T = require("logic/entity/entity_title");-- 如果reset参数为真,则释放现有的标题节点并重置_title变量。-- 这通常在实体的标题需要更新或更改时发生。if reset thenif self._title and self._title.node thenself._title.node:Release(); -- 释放标题节点资源。self._title.node = nil; -- 重置标题节点引用。endself._title = nil; -- 重置_title变量。end-- 初始化一个空的标题表,用于存储标题的相关信息和节点。local title = { };-- 使用entity_title模块的new函数创建一个新的标题实例。title.node = _T.entity_title.new();-- 调用标题实例的Create方法来初始化标题节点。-- "entity_title_node_"加上self._guid作为节点的唯一标识符。if title.node:Create("entity_title_node_" .. self._guid) then-- 如果实体有名称(_name字段不为空),则在标题节点中添加文本标签。if self._name ~= "" then-- AddTextLable方法添加文本标签到标题节点,参数包括文本位置、颜色和文本内容。-- 这里使用16进制颜色值"0xffffffff",代表白色。title.name = title.node:AddTextLable(-0.5, 1, -0.25, 0.5, tonumber("0xffffffff", 16), self._name);endelse-- 如果标题节点创建失败,重置title.node为nil。title.node = nil;end-- 返回初始化后的标题表,包含标题节点和其他相关信息。return title;
end
详细逻辑分析:
-
模块引入:首先,函数通过
require
语句引入了处理实体标题的模块entity_title
。 -
重置检查:如果调用时传入了
reset
参数且为真值,函数会检查是否存在已初始化的标题,并对其进行释放和重置。 -
标题实例化:创建一个空的标题表
title
,然后通过entity_title.new()
创建一个新的标题实例,并尝试调用其Create
方法进行初始化。 -
节点创建:使用
Create
方法创建标题节点,传入的字符串包含了实体的唯一标识符self._guid
,确保每个实体的标题节点都是唯一的。 -
文本标签添加:如果实体有名称,
Create
方法成功执行后,会使用AddTextLable
方法在标题节点中添加一个文本标签,显示实体的名称。文本标签的位置和颜色是可配置的。 -
错误处理:如果
Create
方法失败,即标题节点创建不成功,title.node
将被设置为nil
。 -
返回结果:无论是否成功创建标题节点,函数都会返回
title
表,其中包含了标题的所有相关信息。
Mount
函数在游戏或模拟程序中通常用于实现实体的骑乘(或称为“搭载”)功能。在这段代码中,Mount
函数的作用是允许一个实体骑乘另一个实体,比如骑上马或骑乘其他载具。
function entity:Mount()-- 检查是否存在车辆信息,车辆信息存储在self._vehicle中if self._vehicle then-- 尝试创建车辆实体,参数包括车辆模型路径、车辆实体名称前缀、车辆挂载点hs和车辆创建脚本csif self._entity:CreateVehicle(self._vehicle.path, "entity.vehicle." .. self._guid, self._vehicle.hs, self._vehicle.cs) then-- 如果游戏世界存在并且需要更新显示玩家状态,调用相关方法local world = game_get_world()if world thenworld:UpdateIsShowPlayerSate(true)end-- 如果实体有动作名称和循环次数,播放动作if self._actionName and self._actionLoops thenself:Play(self._actionName, self._actionLoops)end-- 如果实体是玩家控制的,启用遮挡器if self:IsPlayer() thenself:EnableOccluder(true)end-- 设置实体颜色self:SetColor(g_db.db_get_map_entity_color())-- 返回true表示骑乘成功return trueendend-- 如果没有车辆信息或骑乘失败,返回falsereturn false
end
详细逻辑分析:
-
检查车辆信息:函数首先检查
self._vehicle
是否存在,这是一个包含车辆必要信息的表,比如车辆模型路径、挂载点等。 -
创建车辆实体:如果车辆信息存在,调用
self._entity:CreateVehicle
方法尝试创建车辆。这个方法需要车辆的模型路径、一个唯一的实体名称前缀(这里使用entity.vehicle.
加上实体的GUID)、挂载点hs和创建脚本cs。 -
更新游戏世界:如果车辆创建成功,接下来检查是否存在游戏世界对象,如果存在,调用
UpdateIsShowPlayerSate
方法更新是否显示玩家状态。 -
播放动作:如果实体有指定的动作名称和循环次数,调用
self:Play
方法播放相应的动作。 -
启用遮挡器:如果骑乘的实体是玩家控制的,调用
EnableOccluder
方法启用遮挡器,这通常用于优化性能,避免渲染被遮挡的对象。 -
设置颜色:调用
SetColor
方法为实体设置颜色。 -
返回结果:如果以上步骤都成功执行,函数返回
true
表示骑乘成功;如果任何步骤失败或没有车辆信息,函数返回false
表示骑乘失败。
Unmount
函数在游戏或模拟程序中用于实现实体从其骑乘的载具上下来的动作。以下是对 Unmount
函数的详细注释和逻辑分析:
function entity:Unmount()-- 检查实体是否有车辆实体与之关联if self._vehicle then-- 调用实体的ReleaseVehicle方法释放车辆实体self._entity:ReleaseVehicle();-- 如果实体有动作名称和循环次数,播放动作if self._actionName and self._actionLoops then-- 根据游戏的当前状态决定播放的动作if g_game_context:GetIsSpringWorld() then-- 如果是春天的世界,播放特定的空闲动作self:PlaySpringIdleAct()else-- 否则,播放实体的默认动作if self._actionName == "stand01" thenself:Play(db_common.engine.defaultAttackIdleAction, -1);elseself:Play(self._actionName, self._actionLoops)endendendend-- 返回false,表示已经从载具上下来return false;
end
详细逻辑分析:
-
检查车辆信息:函数首先检查
self._vehicle
是否存在,这表明实体是否之前有骑乘载具。 -
释放车辆实体:如果存在车辆信息,调用
self._entity:ReleaseVehicle()
方法释放与实体关联的车辆实体。这通常涉及到从游戏世界中移除车辆模型和相关资源。 -
播放动作:在释放车辆后,需要决定播放什么动作。这取决于实体是否有预先设定的动作名称和循环次数:
- 如果当前游戏环境是“春天的世界”(
g_game_context:GetIsSpringWorld()
返回true
),则调用PlaySpringIdleAct
方法播放特定的空闲动作。 - 否则,检查实体的默认动作名称。如果默认动作是“stand01”,则播放默认攻击空闲动作(
db_common.engine.defaultAttackIdleAction
),否则播放实体的默认动作。
- 如果当前游戏环境是“春天的世界”(
-
返回结果:函数返回
false
,表示实体已经从载具上下来。这个返回值可以用于游戏逻辑中判断实体是否成功执行了下马动作。
CarryItem
函数在游戏或模拟程序中用于实现实体携带物品的功能,例如任务变身。以下是对 CarryItem
函数的详细注释和逻辑分析:
function entity:CarryItem(cfgID)-- 检查传入的物品配置ID是否有效,以及实体是否具有与引擎交互的实体对象local cfg = db_models[cfgID];if cfg and self._entity then-- 尝试将物品模型链接为实体的子对象-- 这里使用物品配置中的路径,创建一个基于实体GUID和物品ID的名称-- 使用预设的角色链接点和物品链接点,以及物品的缩放比例self._carryItem = self._entity:LinkHosterChild(cfg.path, string.format("entity_carryitem_%s_item_%d", self._guid, cfgID), self._missionMode.mcfg.RoleLinkPoint, self._missionMode.mcfg.ItemLinkPoint, 0.0, cfg.scale);-- 如果物品链接成功并且有一个有效的IDif self._carryItem > 0 then-- 设置物品的颜色,这里使用全局数据库中获取的地图实体颜色self:SetLinkChildColor(self._carryItem, g_db.db_get_map_entity_color());end-- 如果携带物品的实体不是玩家,检查游戏世界是否应该显示这个实体if not self:IsPlayer() thenlocal world = game_get_world();if world:IsShowPlayer(self) then-- 如果应该显示,调用ShowCarryItem显示物品self:ShowCarryItem(true)else-- 如果不应该显示,调用ShowCarryItem隐藏物品self:ShowCarryItem(false)endendend-- 调用PlayAction播放实体的动作self:PlayAction();-- 返回false,表示这是一个持续的过程,并没有特定的成功或失败状态return false;
end
详细逻辑分析:
-
检查有效性:函数首先检查传入的物品配置ID
cfgID
是否有效,以及实体是否有一个有效的引擎实体对象self._entity
。 -
获取物品配置:通过
db_models
表使用cfgID
获取物品的配置信息。 -
链接物品模型:如果物品配置有效并且实体对象存在,调用
LinkHosterChild
方法将物品模型链接为实体的子对象。这个方法需要物品的模型路径、一个用于标识物品的名称、角色和物品的链接点,以及物品的缩放比例。 -
设置物品颜色:如果物品成功链接,并且有一个有效的ID,使用
SetLinkChildColor
方法设置物品的颜色。 -
显示或隐藏物品:如果携带物品的实体不是玩家,根据游戏世界的状态决定是否显示物品。这通过调用
ShowCarryItem
方法实现。 -
播放动作:无论物品是否成功链接,都调用
PlayAction
方法播放实体的动作。 -
返回结果:函数返回
false
,这通常表示操作是一个过程,并没有一个明确的成功或失败状态。
ShowCarryItem
函数的作用是控制实体携带物品的显示状态。这个函数可以根据游戏逻辑的需要,显示或隐藏实体所携带的物品。
function entity:ShowCarryItem(s)-- 's' 参数是一个布尔值,用于指示是否应该显示携带的物品-- 如果实体拥有一个有效的引擎实体对象,并且已经成功链接了携带物品的子对象,且子对象的ID是有效的if self._entity and self._carryItem and self._carryItem > 0 then-- 调用引擎实体对象的LinkChildShow方法,传入携带物品的子对象ID和'show'参数-- 'show'参数决定是否显示物品,true表示显示,false表示隐藏self._entity:LinkChildShow(self._carryItem, s)end
end
详细逻辑分析:
-
参数接收:函数接收一个参数
s
,这是一个布尔值,true
表示需要显示携带的物品,false
表示需要隐藏。 -
有效性检查:在执行任何操作之前,函数首先检查几个条件是否满足:
self._entity
是否存在且有效,即实体是否已经与引擎的实体对象建立了关联。self._carryItem
是否存在且其值大于0,即是否已经成功创建了携带物品的子对象,并且该对象的ID是有效的。
-
显示或隐藏物品:如果上述检查通过,则调用
self._entity:LinkChildShow
方法。这个方法是引擎提供的功能,用于控制子对象的显示状态。传入的两个参数分别为携带物品的子对象IDself._carryItem
和显示状态s
。 -
无返回值:该函数没有返回值,它直接在满足条件的情况下执行显示或隐藏操作。
UnCarryItem
函数在游戏或模拟程序中用于实现实体放下或停止携带某个物品的功能。以下是对 函数的详细注释和逻辑分析:
function entity:UnCarryItem()-- 检查是否已经链接了携带物品的子对象,并且子对象的ID是有效的if self._carryItem and self._carryItem > 0 then-- 如果存在有效的携带物品子对象,调用实体的RmvHosterChild方法-- 此方法用于从实体上移除子对象,传入携带物品的子对象IDself._entity:RmvHosterChild(self._carryItem);end-- 重置携带物品的子对象ID,表示当前不再携带任何物品self._carryItem = nil;-- 播放默认的攻击空闲动作,这通常用于在放下物品后恢复实体到正常待机状态self:Play(db_common.engine.defaultAttackIdleAction, -1);-- 返回false,表示已经从实体上移除了携带的物品return false;
end
详细逻辑分析:
-
检查携带物品:函数首先检查
self._carryItem
是否存在并且其ID大于0,这表明实体当前是否携带有物品。 -
移除物品:如果实体正在携带物品,调用
self._entity:RmvHosterChild(self._carryItem)
方法移除该物品。这个方法通过传入物品的子对象ID来从实体上解除物品的链接。 -
重置携带物品ID:执行完移除操作后,将
self._carryItem
设置为nil
,这表示实体现在不再携带任何物品。 -
播放动作:为了反映实体放下物品的动作,调用
self:Play(db_common.engine.defaultAttackIdleAction, -1)
方法播放一个默认的攻击空闲动作。这是为了让实体在放下物品后有一个自然的过渡到待机状态。 -
返回结果:函数返回
false
,表示物品已经成功从实体上移除。
UpdateBloodBar
函数的作用是更新实体的生命条(血条)显示,以反映实体当前的生命值状态。这通常用于用户界面上,让玩家能够直观地看到实体的健康状况。
function entity:UpdateBloodBar(percent)-- 'percent' 参数表示血条的当前百分比,这是一个从0到100的数值,表示实体当前生命值占最大生命值的比例-- 检查实体是否有标题节点,并且标题节点是否有血条元素if self._title and self._title.node and self._title.bbar then-- 调用标题节点的UpdateBloodBar方法来更新血条的显示-- 传入的参数是血条元素的引用和当前的百分比self._title.node:UpdateBloodBar(self._title.bbar, percent);end
end
详细逻辑分析:
-
参数接收:函数接收一个参数
percent
,这是一个整数值,表示血条应该显示的百分比。这个值的范围通常是0到100,其中0表示实体没有生命值,100表示实体处于满生命值状态。 -
有效性检查:在更新血条之前,函数首先检查几个条件是否满足:
self._title
是否存在,这表明实体是否有一个标题对象。self._title.node
是否存在,这表明标题对象是否有一个节点用于显示。self._title.bbar
是否存在,这表明标题节点是否有一个血条元素。
-
更新血条:如果上述检查通过,即实体具有标题节点和血条元素,调用
self._title.node:UpdateBloodBar
方法并传入血条元素self._title.bbar
和百分比percent
来更新血条的显示。这个方法通常会在用户界面上调整血条的长度或填充量,以反映实体的当前生命值。 -
无返回值:该函数没有返回值,它直接执行血条的更新操作。
Release
函数在游戏或模拟程序中通常用于释放或清除实体对象所占用的资源,特别是在对象不再需要时,例如当实体被销毁或从游戏中移除时。以下是对 Release
函数的详细注释和逻辑分析:
function entity:Release()-- 检查实体是否已经被标记为actor,actor通常指具有独立行为和动画的对象if self._is_actor then-- 将_is_actor标记为false,表示开始释放过程self._is_actor = false;-- 从游戏注册中移除该实体的GUID,解除全局引用game_register_entity(self._guid, nil);-- 如果存在标题节点,释放标题节点资源if self._title and self._title.node thenself._title.node:Release();self._title.node = nil; -- 重置标题节点引用endself._title = nil; -- 重置_title变量-- 如果存在实体对象,释放实体对象资源if self._entity thenself._entity:Release();self._entity = nil; -- 重置实体引用end-- 释放与AI控制器相关的资源self:ReleaseAgent();-- 清理文本效果池,释放相关资源self._text_pool:Clear();-- 重置离开缓存的状态和时间self:ResetLeaveCache();-- 如果游戏世界存在,并且特殊怪物表中有该实体的GUID,从表中移除实体的GUIDlocal world = game_get_world()if world and table.nums(world._specialMonsters) > 0 thenif world._specialMonsters[self._guid] thenworld._specialMonsters[self._guid] = nil;endendend-- 重置资源创建状态self._resCreated = 1;
end
详细逻辑分析:
-
检查 Actor 状态:函数首先检查实体是否被标记为
_is_actor
,这是一个标志,表明实体是否具有特定的行为和动画。 -
清除 Actor 标记:如果是,将
_is_actor
设置为false
,表示实体不再具有 actor 的特性。 -
从游戏注册中移除:使用
game_register_entity
函数从游戏的注册表中移除实体的 GUID,这通常意味着实体不再在游戏中被追踪或引用。 -
释放标题资源:如果存在标题节点,调用其
Release
方法来释放与标题相关的资源,并重置相关变量。 -
释放实体资源:如果存在实体对象,调用其
Release
方法来释放资源,并重置实体对象的引用。 -
释放 AI 控制器资源:调用
ReleaseAgent
方法来释放与 AI 控制器相关的资源。 -
清理文本效果:调用
_text_pool:Clear
方法清理文本效果池,释放相关资源。 -
重置缓存状态:调用
ResetLeaveCache
方法重置实体离开缓存的状态和时间。 -
从特殊怪物表中移除:如果游戏世界存在,并且特殊怪物表中有实体的 GUID,将其从表中移除。
-
重置资源创建状态:将
_resCreated
重置为 1,这可能表示资源创建的状态或计数器。