小地图是玩家定位的第一信息源:角色位置、队友标记、BOSS 与传送点的分布全压在右上一角。小地图的渲染核心是世界坐标到缩略图坐标的换算、视野框的绘制与标记的动态增删,解密源码里 gameStateWorld 的地图层提供了现成的参照。
---世界坐标转小地图坐标:比例 1:10
local MAPW, MAPH = 1000, 800
local MiniMap = { layer = nil, scale = 10 }
function MiniMap.toMini(wx, wy)
local mx = wx / MiniMap.scale
local my = MAPH / MiniMap.scale - wy / MiniMap.scale
return mx, my
end
function MiniMap.drawSelf(actor)
local mx, my = MiniMap.toMini(actor.x, actor.y)
if not MiniMap.selfMark then
MiniMap.selfMark = GUI:Text_Create(MiniMap.layer, "me", 0, 0, 12, "#FFD700", "▲")
end
GUI:Text_setPosition(MiniMap.selfMark, mx, my)
end
世界坐标除以缩放比例 10 落进 100 乘 80 的缩略区域,纵轴取反向匹配屏幕习惯——世界坐标向上增大而屏幕坐标向下增大,这步换反了标记就集体倒挂。自身标记创建一次后只改位置,避免每帧重建控件。
---注册地图标记消息:队友与 BOSS 位置
SL:RegisterLuaNetMsg("MAPMARK", function(data)
local marks = SL:JsonDecode(data)
if not marks or #marks > 50 then return end
for _, m in ipairs(marks) do
local mx, my = MiniMap.toMini(m.x, m.y)
MiniMap.put(m.kind, m.id, mx, my)
end
end)
-- 200 毫秒刷新一次视野框
SL:Schedule(0.2, function() MiniMap.refreshViewBox() end)
标记数据走前端网络注册通道,服务端每 200 毫秒推一帧队友与 BOSS 的聚合位置,单帧标记数上限 50,超限的低优先级标记丢弃。视野框按当前镜头的中心与尺寸绘制,玩家拖动镜头时视野框随之滑动,与世界的对应关系保持一致。解密源码的 actorManager 里同屏角色的遍历顺序可作对照,标记的层级在怪物之上、界面之下。
标记与真实位置的偏差抽样对比,偏差超过 1 个缩略格即为换算回归;刷新的帧耗时监控,超过 3 毫秒即优化控件复用。
纵轴方向曾经没取反,全服玩家的标记都在地图对角,两行代码的修复排查了一下午。标记控件曾经每帧重建,百人同屏时创建销毁的风暴让帧率腰斩,改为对象池复用后归零。队伍解散后队友标记残留,靠数据侧的清理消息兜底,界面层不做超时推断。
缩放比例与地图尺寸从配置读取,缩放支持滚轮调节 5 到 20 档位。标记按类型分层:BOSS 红色置顶、队友蓝色、传送点灰色,颜色的语义全服统一。小地图的点击即寻路:点击缩略图任意点,换算回世界坐标发起自动寻路,点击的命中半径放宽到 2 个缩略格。
本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 跨服远征分先锋、主力、后勤三队独立推进,三线全通合围BOSS。不同战力成员都有参与感。 策划要点与配置 …
实战应用:用在哪里 副本限时挑战加入超时血量惩罚:超时后BOSS攻击递增。上线后BOSS攻击叠到十倍秒杀全队。 事故还原与补…
实战应用:用在哪里 混沌麒麟召唤是全服高光时刻:暗幕聚合、裂缝展开、麒麟着陆三段演出各1.3秒。 三段式入场演出编排 围观镜…
实战应用:用在哪里 任务对话一闪而过玩家想回顾。回看接口把对话按节点存档,面板翻阅全部对话记录。 对话存档与查询渲染 当前章…
实战应用:用在哪里 服务器承载六十张地图,空闲地图白耗资源。按需激活,末人离开后六十秒休眠。 激活与休眠触发 休眠回收 验证…
实战应用:用在哪里 坐骑资质洗炼随机重滚五条属性,锁定满意的条目不再重滚,锁定越多消耗越大。 洗炼与锁定 锁定消耗递增 验证…