背包是玩家操作密度最高的界面:拖拽换位、跨页挪动、拖出即丢弃,每个手势都要顺手。背包网格的拖拽实现要点是命中检测、拖影跟随与落点的两种语义——落在格子上是交换,落在页签上是翻页携带。
---背包网格:40 格逐格创建
function BagUI.build(page)
for i = 1, 40 do
local idx = (page - 1) * 40 + i
local box = GUI:ItemBox_Create(BagUI.node, "cell_" .. idx,
10 + ((i - 1) % 8) * 46, 10 + math.floor((i - 1) / 8) * 46)
GUI:addOnClickEvent(box, function()
BagUI.onCellTap(idx)
end)
BagUI.cells[idx] = box
end
end
---点击选中与拖拽起手的区分
function BagUI.onCellTap(idx)
if BagUI.dragFrom and BagUI.dragFrom ~= idx then
BagUI.swap(BagUI.dragFrom, idx)
else
BagUI.dragFrom = idx
SL:ShowSystemTips("已选中,再点另一格交换")
end
end
40 格按 8 列 5 行排布,GUI:ItemBox_Create 逐格创建物品格子控件。拖拽的手势在触屏上不好判定,点选交换的两段式操作是等价替代:点第一格选中,点第二格完成交换。拖影与点选并存,端上游走拖拽、移动端点选,同一套交换语义。
---跨页交换:拖到页签即翻页携带
function BagUI.swap(fromIdx, toIdx)
local fromPage = BagUI.pageOf(fromIdx)
local toPage = BagUI.pageOf(toIdx)
if fromPage ~= toPage then
SL:ShowSystemTips("跨页请先翻页再整理")
return
end
SL:SendNetMsg(MSGID.BAG_SWAP, fromIdx, toIdx, 0, "")
BagUI.render(fromIdx, BagUI.itemOf(fromIdx))
BagUI.render(toIdx, BagUI.itemOf(toIdx))
end
交换请求发给服务器裁决,客户端先本地换显再按服务器回包校正,拖拽的跟手感与数据的一致性两头兼顾。非法落点(丢弃区、锁定格)在客户端预先拦截,SL:ShowSystemTips 给出原因提示。装备上身的快捷操作走同一套交换通道:把裁决之杖从背包格拖到装备位,本质是一次特殊的目标格交换。
交换请求的客户端预演与服务器裁决的不一致率监控,超过 1% 说明预演规则与服务器不同步;拖拽误触率的埋点统计,误触进丢弃区的操作弹二次确认。
格子坐标曾经按 6 列排布写死,换 8 列皮肤后整屏错位,行列数进皮肤配置。跨页交换曾经直接执行,服务器因页签校验拒绝后客户端显示错乱,跨页的预拦截统一收口。点选态没有超时释放,选中一小时后误触另一格完成了一次无意识交换,选中态 10 秒自动释放。
网格的行列数与格子尺寸从皮肤配置读取,主题换肤不动逻辑。交换的快捷键支持:选中后按方向键移动物品,键盘玩家的整理效率翻倍。物品的 Tooltip 在长按 300 毫秒时弹出,与拖拽起手的时间阈值错开。
本文由 996 技术组基于 996 引擎官方知识库与浮生梦老师课程体系整理。团队长期从事传奇类引擎 Lua 后端逻辑、客户端界面与商业版本交付,内容以官方知识库与真实项目为出处,按版本持续修订。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
实战应用:用在哪里 行会等级是行会玩法的地基:建筑上限、商店货架、活动资格全部挂在等级上。行会经验与等级成长框架把升级路径做…
实战应用:用在哪里 行会走过两年,第一次拿下沙巴克、第一位满级成员、最强的一次攻防战,这些瞬间散落在聊天记录里无人记得。行会…
实战应用:用在哪里 两服合服时允许玩家自由抢注重名角色,结果原服老玩家“至尊战神”的名字被另一服新号抢先注册,老玩家两年的社…
实战应用:用在哪里 热门行会一天几十份入会申请,逐条点开看效率极低还容易漏人。行会申请列表把申请铺成可批量操作的清单:每行显…
实战应用:用在哪里 炼狱回廊是高端玩家的试炼场:十层回廊逐层深入,每下一层全属性递减百分之五,越往深处怪物越强、自己越弱,奖…
实战应用:用在哪里 本服押镖产出稳定但缺乏刺激,高战玩家押镖像散步。跨服镖局把押运拉到跨服边境:路线穿越两服交界的无主之地,…