Arpg 游戏 对象实体 entity(二)

设计一个 entity class,用于创建和管理游戏世界中的实体对象。这个类包含了大量的函数,用于处理实体的各种行为和属性,例如创建、移动、播放动画、同步状态等。

CreateTitle 函数的作用是创建和初始化一个实体的标题显示。在游戏或模拟程序中,实体的标题通常用于显示名称、生命值或其他重要信息。

function entity:CreateTitle(reset)
    -- 引入用于创建和管理实体标题的模块。
    local _T = require("logic/entity/entity_title");

    -- 如果reset参数为真,则释放现有的标题节点并重置_title变量。
    -- 这通常在实体的标题需要更新或更改时发生。
    if reset then
        if self._title and self._title.node then
            self._title.node:Release(); -- 释放标题节点资源。
            self._title.node = nil; -- 重置标题节点引用。
        end
        self._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);
        end
    else
        -- 如果标题节点创建失败,重置title.node为nil。
        title.node = nil;
    end

    -- 返回初始化后的标题表,包含标题节点和其他相关信息。
    return title;
end

详细逻辑分析:

  1. 模块引入:首先,函数通过require语句引入了处理实体标题的模块entity_title

  2. 重置检查:如果调用时传入了reset参数且为真值,函数会检查是否存在已初始化的标题,并对其进行释放和重置。

  3. 标题实例化:创建一个空的标题表title,然后通过entity_title.new()创建一个新的标题实例,并尝试调用其Create方法进行初始化。

  4. 节点创建:使用Create方法创建标题节点,传入的字符串包含了实体的唯一标识符self._guid,确保每个实体的标题节点都是唯一的。

  5. 文本标签添加:如果实体有名称,Create方法成功执行后,会使用AddTextLable方法在标题节点中添加一个文本标签,显示实体的名称。文本标签的位置和颜色是可配置的。

  6. 错误处理:如果Create方法失败,即标题节点创建不成功,title.node将被设置为nil

  7. 返回结果:无论是否成功创建标题节点,函数都会返回title表,其中包含了标题的所有相关信息。

Mount 函数在游戏或模拟程序中通常用于实现实体的骑乘(或称为“搭载”)功能。在这段代码中,Mount 函数的作用是允许一个实体骑乘另一个实体,比如骑上马或骑乘其他载具。

function entity:Mount()
    -- 检查是否存在车辆信息,车辆信息存储在self._vehicle中
    if self._vehicle then
        -- 尝试创建车辆实体,参数包括车辆模型路径、车辆实体名称前缀、车辆挂载点hs和车辆创建脚本cs
        if self._entity:CreateVehicle(self._vehicle.path, "entity.vehicle." .. self._guid, self._vehicle.hs, self._vehicle.cs) then
            -- 如果游戏世界存在并且需要更新显示玩家状态,调用相关方法
            local world = game_get_world()
            if world then
                world:UpdateIsShowPlayerSate(true)
            end
            
            -- 如果实体有动作名称和循环次数,播放动作
            if self._actionName and self._actionLoops then
                self:Play(self._actionName, self._actionLoops)
            end

            -- 如果实体是玩家控制的,启用遮挡器
            if self:IsPlayer() then
                self:EnableOccluder(true)
            end
            
            -- 设置实体颜色
            self:SetColor(g_db.db_get_map_entity_color())

            -- 返回true表示骑乘成功
            return true
        end
    end

    -- 如果没有车辆信息或骑乘失败,返回false
    return false
end

详细逻辑分析:

  1. 检查车辆信息:函数首先检查self._vehicle是否存在,这是一个包含车辆必要信息的表,比如车辆模型路径、挂载点等。

  2. 创建车辆实体:如果车辆信息存在,调用self._entity:CreateVehicle方法尝试创建车辆。这个方法需要车辆的模型路径、一个唯一的实体名称前缀(这里使用entity.vehicle.加上实体的GUID)、挂载点hs和创建脚本cs。

  3. 更新游戏世界:如果车辆创建成功,接下来检查是否存在游戏世界对象,如果存在,调用UpdateIsShowPlayerSate方法更新是否显示玩家状态。

  4. 播放动作:如果实体有指定的动作名称和循环次数,调用self:Play方法播放相应的动作。

  5. 启用遮挡器:如果骑乘的实体是玩家控制的,调用EnableOccluder方法启用遮挡器,这通常用于优化性能,避免渲染被遮挡的对象。

  6. 设置颜色:调用SetColor方法为实体设置颜色。

  7. 返回结果:如果以上步骤都成功执行,函数返回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" then
                    self:Play(db_common.engine.defaultAttackIdleAction, -1);
                else
                    self:Play(self._actionName, self._actionLoops)
                end
            end
        end
    end

    -- 返回false,表示已经从载具上下来
    return false;
end

详细逻辑分析:

  1. 检查车辆信息:函数首先检查self._vehicle是否存在,这表明实体是否之前有骑乘载具。

  2. 释放车辆实体:如果存在车辆信息,调用self._entity:ReleaseVehicle()方法释放与实体关联的车辆实体。这通常涉及到从游戏世界中移除车辆模型和相关资源。

  3. 播放动作:在释放车辆后,需要决定播放什么动作。这取决于实体是否有预先设定的动作名称和循环次数:

    • 如果当前游戏环境是“春天的世界”(g_game_context:GetIsSpringWorld()返回true),则调用PlaySpringIdleAct方法播放特定的空闲动作。
    • 否则,检查实体的默认动作名称。如果默认动作是“stand01”,则播放默认攻击空闲动作(db_common.engine.defaultAttackIdleAction),否则播放实体的默认动作。
  4. 返回结果:函数返回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
        );
        
        -- 如果物品链接成功并且有一个有效的ID
        if self._carryItem > 0 then
            -- 设置物品的颜色,这里使用全局数据库中获取的地图实体颜色
            self:SetLinkChildColor(self._carryItem, g_db.db_get_map_entity_color());
        end

        -- 如果携带物品的实体不是玩家,检查游戏世界是否应该显示这个实体
        if not self:IsPlayer() then
            local world = game_get_world();
            if world:IsShowPlayer(self) then
                -- 如果应该显示,调用ShowCarryItem显示物品
                self:ShowCarryItem(true)
            else
                -- 如果不应该显示,调用ShowCarryItem隐藏物品
                self:ShowCarryItem(false)
            end
        end
    end
    
    -- 调用PlayAction播放实体的动作
    self:PlayAction();

    -- 返回false,表示这是一个持续的过程,并没有特定的成功或失败状态
    return false;
end

详细逻辑分析:

  1. 检查有效性:函数首先检查传入的物品配置ID cfgID 是否有效,以及实体是否有一个有效的引擎实体对象 self._entity

  2. 获取物品配置:通过 db_models 表使用 cfgID 获取物品的配置信息。

  3. 链接物品模型:如果物品配置有效并且实体对象存在,调用 LinkHosterChild 方法将物品模型链接为实体的子对象。这个方法需要物品的模型路径、一个用于标识物品的名称、角色和物品的链接点,以及物品的缩放比例。

  4. 设置物品颜色:如果物品成功链接,并且有一个有效的ID,使用 SetLinkChildColor 方法设置物品的颜色。

  5. 显示或隐藏物品:如果携带物品的实体不是玩家,根据游戏世界的状态决定是否显示物品。这通过调用 ShowCarryItem 方法实现。

  6. 播放动作:无论物品是否成功链接,都调用 PlayAction 方法播放实体的动作。

  7. 返回结果:函数返回 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

详细逻辑分析:

  1. 参数接收:函数接收一个参数 s,这是一个布尔值,true 表示需要显示携带的物品,false 表示需要隐藏。

  2. 有效性检查:在执行任何操作之前,函数首先检查几个条件是否满足:

    • self._entity 是否存在且有效,即实体是否已经与引擎的实体对象建立了关联。
    • self._carryItem 是否存在且其值大于0,即是否已经成功创建了携带物品的子对象,并且该对象的ID是有效的。
  3. 显示或隐藏物品:如果上述检查通过,则调用 self._entity:LinkChildShow 方法。这个方法是引擎提供的功能,用于控制子对象的显示状态。传入的两个参数分别为携带物品的子对象ID self._carryItem 和显示状态 s

  4. 无返回值:该函数没有返回值,它直接在满足条件的情况下执行显示或隐藏操作。

UnCarryItem 函数在游戏或模拟程序中用于实现实体放下或停止携带某个物品的功能。以下是对 函数的详细注释和逻辑分析:

function entity:UnCarryItem()
    -- 检查是否已经链接了携带物品的子对象,并且子对象的ID是有效的
    if self._carryItem and self._carryItem > 0 then
        -- 如果存在有效的携带物品子对象,调用实体的RmvHosterChild方法
        -- 此方法用于从实体上移除子对象,传入携带物品的子对象ID
        self._entity:RmvHosterChild(self._carryItem);
    end

    -- 重置携带物品的子对象ID,表示当前不再携带任何物品
    self._carryItem = nil;

    -- 播放默认的攻击空闲动作,这通常用于在放下物品后恢复实体到正常待机状态
    self:Play(db_common.engine.defaultAttackIdleAction, -1);

    -- 返回false,表示已经从实体上移除了携带的物品
    return false;
end

详细逻辑分析:

  1. 检查携带物品:函数首先检查 self._carryItem 是否存在并且其ID大于0,这表明实体当前是否携带有物品。

  2. 移除物品:如果实体正在携带物品,调用 self._entity:RmvHosterChild(self._carryItem) 方法移除该物品。这个方法通过传入物品的子对象ID来从实体上解除物品的链接。

  3. 重置携带物品ID:执行完移除操作后,将 self._carryItem 设置为 nil,这表示实体现在不再携带任何物品。

  4. 播放动作:为了反映实体放下物品的动作,调用 self:Play(db_common.engine.defaultAttackIdleAction, -1) 方法播放一个默认的攻击空闲动作。这是为了让实体在放下物品后有一个自然的过渡到待机状态。

  5. 返回结果:函数返回 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

详细逻辑分析:

  1. 参数接收:函数接收一个参数 percent,这是一个整数值,表示血条应该显示的百分比。这个值的范围通常是0到100,其中0表示实体没有生命值,100表示实体处于满生命值状态。

  2. 有效性检查:在更新血条之前,函数首先检查几个条件是否满足:

    • self._title 是否存在,这表明实体是否有一个标题对象。
    • self._title.node 是否存在,这表明标题对象是否有一个节点用于显示。
    • self._title.bbar 是否存在,这表明标题节点是否有一个血条元素。
  3. 更新血条:如果上述检查通过,即实体具有标题节点和血条元素,调用 self._title.node:UpdateBloodBar 方法并传入血条元素 self._title.bbar 和百分比 percent 来更新血条的显示。这个方法通常会在用户界面上调整血条的长度或填充量,以反映实体的当前生命值。

  4. 无返回值:该函数没有返回值,它直接执行血条的更新操作。

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 then
            self._title.node:Release();
            self._title.node = nil; -- 重置标题节点引用
        end
        self._title = nil; -- 重置_title变量

        -- 如果存在实体对象,释放实体对象资源
        if self._entity then
            self._entity:Release();
            self._entity = nil; -- 重置实体引用
        end

        -- 释放与AI控制器相关的资源
        self:ReleaseAgent();

        -- 清理文本效果池,释放相关资源
        self._text_pool:Clear();

        -- 重置离开缓存的状态和时间
        self:ResetLeaveCache();

        -- 如果游戏世界存在,并且特殊怪物表中有该实体的GUID,从表中移除实体的GUID
        local world = game_get_world()
        if world and table.nums(world._specialMonsters) > 0 then
            if world._specialMonsters[self._guid] then
                world._specialMonsters[self._guid] = nil;
            end
        end
    end

    -- 重置资源创建状态
    self._resCreated = 1;
end

详细逻辑分析:

  1. 检查 Actor 状态:函数首先检查实体是否被标记为 _is_actor,这是一个标志,表明实体是否具有特定的行为和动画。

  2. 清除 Actor 标记:如果是,将 _is_actor 设置为 false,表示实体不再具有 actor 的特性。

  3. 从游戏注册中移除:使用 game_register_entity 函数从游戏的注册表中移除实体的 GUID,这通常意味着实体不再在游戏中被追踪或引用。

  4. 释放标题资源:如果存在标题节点,调用其 Release 方法来释放与标题相关的资源,并重置相关变量。

  5. 释放实体资源:如果存在实体对象,调用其 Release 方法来释放资源,并重置实体对象的引用。

  6. 释放 AI 控制器资源:调用 ReleaseAgent 方法来释放与 AI 控制器相关的资源。

  7. 清理文本效果:调用 _text_pool:Clear 方法清理文本效果池,释放相关资源。

  8. 重置缓存状态:调用 ResetLeaveCache 方法重置实体离开缓存的状态和时间。

  9. 从特殊怪物表中移除:如果游戏世界存在,并且特殊怪物表中有实体的 GUID,将其从表中移除。

  10. 重置资源创建状态:将 _resCreated 重置为 1,这可能表示资源创建的状态或计数器。

你可能感兴趣的:(ARPG,游戏开发,Lua语言开发,游戏,lua,架构)