--[[
背包系统主模块
主要功能:
- 管理背包界面布局
- 处理多页签切换
- 物品格子初始化
- 货币数量更新
平台适配说明:
- 支持Win32和移动端双平台不同布局
- 通过isWin32参数区分平台配置
]]
Bag = {}
function Bag.Init(isWin32)
-- 平台相关布局配置参数
-- _ScrollHeight: 滚动容器总高度
-- _PWidth/_PHeight: 容器可见区域尺寸
-- _IWidth/_IHeight: 单个物品格子尺寸
-- _Row/_Col: 行列数(Win32采用12x10布局,移动端8x5布局)
Bag._ScrollHeight = isWin32 and 214 or 320
Bag._PWidth = isWin32 and 338 or 500
Bag._PHeight = isWin32 and 214 or 320
Bag._IWidth = isWin32 and 30 or 62.5
Bag._IHeight = isWin32 and 30 or 64
Bag._Row = isWin32 and 10 or 5
Bag._Col = isWin32 and 12 or 8
Bag._PerPageNum = isWin32 and 120 or 40 -- 每页容量 = 行数 x 列数
Bag._defaultNum = isWin32 and 120 or 40 -- 默认每页格子数
Bag._MaxPage = isWin32 and 1 or 3 -- 最大支持页数
Bag._codeInitGrid = false -- 是否用代码生成格子(当UI预制件中无格子时启用)
-- 状态控制变量
Bag._changeStoreMode = false -- 切换存储模式标志
Bag._bagPage = isWin32 and 1 or 3 -- 当前开放的页数
Bag._selPage = 0 -- 当前选中页签索引
Bag._openNum = 126 -- 当前开放的格子总数(从服务器获取)
-- 资源路径配置
Bag._lockImg = isWin32 and "res/image/bag_ui/pc/lock.png" or "res/image/bag_ui/mobile/lock.png"
Bag._baiTanImg = isWin32 and "res/public/word_bqzy_09_1.png" or "res/public/word_bqzy_09.png"
Bag._bagPageBtns = {} -- 页签按钮缓存表
end
--[[
主入口函数
@param page: 初始显示页数(可选)
]]
function Bag.main(page)
local parent = GUI:Attach_Parent()
local isWin32 = SL:GetMetaValue("WINPLAYMODE")
-- 加载平台对应的UI预制件
GUI:LoadExport(parent, isWin32 and "bag/bag_panel_win32" or "bag/bag_panel")
-- 初始化UI引用和代理
Bag._ui = GUI:ui_delegate(parent)
Bag._UI_ScrollView = Bag._ui["ScrollView_items"]
Bag.Init(isWin32) -- 初始化配置参数
-- 界面定位适配
GUI:setPositionY(Bag._ui["Panel_1"], isWin32 and SL:GetMetaValue("PC_POS_Y") or SL:GetMetaValue("SCREEN_HEIGHT") / 2)
-- 设置界面拖动和浮起功能
GUI:Win_SetDrag(parent, Bag._ui["Image_bg"])
GUI:Win_SetZPanel(parent, Bag._ui["Image_bg"])
-- 关闭按钮事件
GUI:addOnClickEvent(Bag._ui["Button_close"], function()
SL:CloseBagUI()
end)
-- 存入英雄背包按钮逻辑
local Button_store_hero_bag = Bag._ui["Button_store_hero_bag"]
GUI:addOnClickEvent(Button_store_hero_bag, function()
local changeStoreMode = not Bag._changeStoreMode
-- 切换前验证英雄状态
if changeStoreMode then
if not SL:GetMetaValue("HERO_IS_ACTIVE") then
return SL:ShowSystemTips("英雄还未激活")
end
if not SL:GetMetaValue("HERO_IS_ALIVE") then
return SL:ShowSystemTips("英雄还未召唤")
end
end
Bag._changeStoreMode = changeStoreMode
GUI:Button_setGrey(Button_store_hero_bag, changeStoreMode)
end)
GUI:setVisible(Button_store_hero_bag, SL:GetMetaValue("USEHERO"))
Bag.InitPage() -- 初始化页签
Bag.PageTo(page or 1) -- 跳转到指定页
Bag.OnUpdateGold() -- 初始化货币显示
Bag.RegisterEvent() -- 注册事件监听
-- 设置页签层级
GUI:setLocalZOrder(Bag._ui.Button_page1, 4)
GUI:setLocalZOrder(Bag._ui.Button_page2, 3)
GUI:setLocalZOrder(Bag._ui.Button_page3, 2)
end
--[[
初始化页签按钮
根据开放页数动态显示/隐藏页签按钮
]]
function Bag.InitPage()
-- 计算实际需要显示的页数
Bag._bagPage = math.ceil(Bag._openNum / Bag._PerPageNum)
Bag._bagPage = math.max(Bag._bagPage, 1)
Bag._bagPage = math.min(Bag._bagPage, Bag._MaxPage)
-- 遍历初始化所有页签按钮
for i = 1, Bag._MaxPage do
local pageBtn = Bag._ui["Button_page" .. i]
GUI:setVisible(pageBtn, false)
if Bag._bagPage ~= 1 and i <= Bag._bagPage then
GUI:setVisible(pageBtn, true)
GUI:setTag(pageBtn, i) -- 用tag存储页索引
Bag._bagPageBtns[i] = pageBtn
-- 页签点击事件
GUI:addOnClickEvent(GUI:getChildByName(pageBtn, "TouchSize"), function()
if Bag._selPage == i then return end
Bag.PageTo(i)
if Bag.UpdateItems then
Bag.UpdateItems() -- 刷新物品显示
end
end)
end
end
end
--[[
跳转到指定页签
@param page: 目标页数(1-based)
]]
function Bag.PageTo(page)
if Bag._selPage == page then return end
SL:SetMetaValue("BAG_PAGE_CUR", page)
Bag._selPage = page
Bag.SetPageBtnStatus() -- 更新按钮状态
end
-- 更新页签按钮的选中状态
function Bag.SetPageBtnStatus()
for i = 1, Bag._bagPage do
local btnPage = Bag._bagPageBtns[i]
if btnPage then
local isPress = i == Bag._selPage
-- 通过ZOrder和纹理切换实现选中效果
GUI:setLocalZOrder(btnPage, isPress and Bag._bagPage + 1 or GUI:getTag(btnPage))
GUI:Button_loadTextureNormal(btnPage,
isPress and "res/image/bag_ui/mobile/p" .. i .. "_light.png"
or "res/image/bag_ui/mobile/p" .. i .. "_gray.png")
end
end
end
-- 初始化背包格子线(当_codeInitGrid为true时调用)
function Bag.InitGird()
local index = 0
-- 绘制垂直和水平格子线
for i = 1, Bag._Row + 1 do
for j = 1, Bag._Col + 1 do
local x = (j-1) * Bag._IWidth
local y = Bag._ScrollHeight - (i-1) * Bag._IHeight
-- 绘制垂直线(旋转90度的图片)
if i <= Bag._Row then
local pGird1 = GUI:Image_Create(Bag._UI_ScrollView, "Grid_1_" .. index, x, y, "res/public/bag_gezi.png")
GUI:setAnchorPoint(pGird1, 0, j == 1 and 0 or 1) -- 首列底部对齐,其他顶部对齐
GUI:setRotation(pGird1, 90)
index = index + 1
end
-- 绘制水平线
if j <= Bag._Col then
local pGird2 = GUI:Image_Create(Bag._UI_ScrollView, "Grid_2_" .. index, x, y, "res/public/bag_gezi.png")
GUI:setAnchorPoint(pGird2, 0, i == 1 and 1 or 0) -- 首行顶部对齐,其他底部对齐
index = index + 1
end
end
end
end
--[[
重置初始化参数(根据游戏数据动态调整)
从GAME_DATA.bag_row_col获取行列配置,格式:"列数|行数"
]]
function Bag.ResetInitData()
local isWinMode = SL:GetMetaValue("WINPLAYMODE")
local bag_row_col = SL:GetMetaValue("GAME_DATA", "bag_row_col_max")
if isWinMode and bag_row_col then
local slices = string.split(bag_row_col, "|")
-- 覆盖默认行列配置
Bag._Row = tonumber(slices[2]) or 5
Bag._Col = tonumber(slices[1]) or 8
Bag._PerPageNum = Bag._Row * Bag._Col
-- 当自定义容量大于默认时隐藏页签
if Bag._PerPageNum > Bag._defaultNum then
for i = 1, Bag._MaxPage do
GUI:setVisible(Bag._ui["Button_page"..i], false)
end
end
end
-- 重新计算容器尺寸
local pSize = GUI:getContentSize(Bag._UI_ScrollView)
GUI:ScrollView_setInnerContainerSize(Bag._UI_ScrollView, pSize)
Bag._ScrollHeight = pSize.height
Bag._PWidth = pSize.width
Bag._PHeight = pSize.height
Bag._IWidth = Bag._PWidth / Bag._Col -- 重新计算格子宽度
Bag._IHeight = Bag._PHeight / Bag._Row -- 重新计算格子高度
-- 按需生成格子线
if Bag._codeInitGrid then
Bag.InitGird()
end
end
--[[
货币更新处理
@param data: 事件数据(可选),当指定时只更新对应货币
]]
function Bag.OnUpdateGold(data)
-- 货币类型配置表
local currencyTypes = {
{id = 1, uiKey = "Text_goldNum"}, -- 金币
{id = 2, uiKey = "Text_gamegoldNum"}, -- 元宝
{id = 4, uiKey = "Text_b_gamegoldNum"}, -- 绑定元宝
{id = 7, uiKey = "Text_gamegirdNum"}, -- 代币
{id = 8, uiKey = "Text_b_gamegirdNum"}, -- 绑定代币
}
local function updateCurrency(id, uiElement)
local amount = SL:GetMetaValue("ITEM_COUNT", id) or 0
if Bag._ui[uiElement] then
GUI:Text_setString(Bag._ui[uiElement], amount)
end
end
if not data then
-- 全量更新所有货币
for _, currency in ipairs(currencyTypes) do
updateCurrency(currency.id, currency.uiKey)
end
else
-- 增量更新指定货币
for _, currency in ipairs(currencyTypes) do
if data.id == currency.id then
updateCurrency(currency.id, currency.uiKey)
break
end
end
end
end
-- 事件拦截函数(供业务层扩展)
function Bag.IsCanSingle(data) return true end -- 是否允许单击
function Bag.IsCanDouble(data) return true end -- 是否允许双击
-- 关闭事件处理
function Bag.OnClose(winID)
if winID == "BagLayerGUI" then
Bag.UnRegisterEvent()
end
end
-- 事件注册/注销
function Bag.RegisterEvent()
SL:RegisterLUAEvent(LUA_EVENT_MONEYCHANGE, "Bag", Bag.OnUpdateGold)
SL:RegisterLUAEvent(LUA_EVENT_CLOSEWIN, "Bag", Bag.OnClose)
end
function Bag.UnRegisterEvent()
SL:UnRegisterLUAEvent(LUA_EVENT_MONEYCHANGE, "Bag")
SL:UnRegisterLUAEvent(LUA_EVENT_CLOSEWIN, "Bag")
end