<1>很多人都玩过炸弹人或者泡泡堂,之前做了这个玩法,记录一下关键实现
<2>直接上Lua代码
1.维护每个格子上的物体 比如:BUFF类,宝箱,草箱,木箱,铁箱,炸弹,小怪...
用一个结构维护一个格子31*31=961,进入场景创建,离开释放掉
每个结构里面声明一张map缓存格子里面所有的物体 <物体类型,map<物体uid,true>>
2.计算炸弹爆炸所影响的格子(长宽不等的十字形)
炸弹有一个威力等级Force,计算规则为 Force*2+1 = 同一轴上所影响的格子
但是碰到铁箱子是无法穿透的,所有这个爆炸的十字形可能是长宽不等的
BombermanMgr = { }
local _isInit = false
local rowNum = 31
local colNum = 31
local cellSize = 2
-- -22 30 对应 -21.945 29.925 要么场景做偏移 要么起始X Y做偏移 -0.055 0.075
-- 场景做偏移
local startX = -31
local startY = -31
local function create_self_param(self)
if _isInit == ture then
return
end
-- 导入依赖的文件
-- 初始化
self:__init_self_param()
end
local function create(self)
create_self_param(self)
end
-- 初始化成员
function BombermanMgr:__init_self_param()
self.boxPool = nil --缓存961格子信息 BoxData
self.dropPool = { } --缓存掉落物 entity
self.memberPool = { } --玩家信息 PPTMemberData
self.rankPool = { }--玩家信息 PPTMemberRankData
self.rankMap = { }--玩家排名 PPTMemberRankData
self.skillPool = nil --玩家技能信息
self.mainRoleId = 0
--排行数据
self.todayReqTime = -1 --上次拉取时间
self.yestodayReqTime = -1 --上次拉取时间
self.todayLst = { } --今天数据
self.yestodayLst = { }--昨天数据
self.todayMine = nil --自己今天
self.yestodayMine = nil --自己昨天
self.myRespawnRoleId = nil --出生点模型
self.followId = -1 --跟随id
self.lastAlertTime = -1--上次弹出提示时间
self.bombEffectTimeMap = { }--格子爆炸特效上次释放时间
self.audioTimeMap = { }--音效上次播放时间
--self.combineLst = ListLong() --需要合并的对象
self.combineRoot = nil --合并根节点
self.combineNum = 0
--无需清理
self.infoHandler = nil
self.rankRewardLst = nil
end
function BombermanMgr:getMainPlayerId()
return self.mainRoleId
end
function BombermanMgr:getMaxIndex()
return rowNum*colNum
end
--技能信息
--新实体协议下发 初始化技能 根据实体中的宠物id获取充能次数...
function BombermanMgr:initSkill(petId)
self.skillPool = { }
local pptCfg = BombermanUtils:getPetConfigById(petId)
if not pptCfg then
Logger:logError("没有读取到PptPetConfig id ",petId)
return
end
local boomData = PPTSkillData(PPTSkillType.boom,PPTBombForceIcon[1],BombermanConst.bombCooldown,pptCfg.bomCharge)
self.skillPool[PPTSkillType.boom] = boomData
local speedData = PPTSkillData(PPTSkillType.speed,BombermanConst.speedIcon,BombermanConst.speedCooldown,pptCfg.speedRune)
self.skillPool[PPTSkillType.speed] = speedData
local superData = PPTSkillData(PPTSkillType.super,BombermanConst.superIcon,BombermanConst.superCooldown,pptCfg.snvincibleRune)
self.skillPool[PPTSkillType.super] = superData
local hpData = PPTSkillData(PPTSkillType.hp,BombermanConst.hpIcon,BombermanConst.hpCooldown,pptCfg.life)
self.skillPool[PPTSkillType.hp] = hpData
end
function BombermanMgr:getSkillLst()
return self.skillPool
end
--计数数据更新
function BombermanMgr:updateSkill(skillType,count,force)
local dt = self.skillPool[skillType]
if dt then
if force then
dt:setForceLevel(force)
end
if count then
dt:onCountChange(count)
end
end
end
function BombermanMgr:addSkillCount(skillType)
local dt = self.skillPool[skillType]
if dt then
dt:addChargeNum(1)
end
end
--配置静态盒子
--2次for循环 中间少了的固定格子写死
function BombermanMgr:initBox()
self.boxPool = { }
--把固定格子创建出来
local ignore = { }
ignore[419] = true
ignore[479] = true
ignore[481] = true
ignore[483] = true
ignore[543] = true
for i = 1,15 do
local num = 31+2*i
for k = 1,15 do
local num2 = num+31*(k-1)*2
if ignore[num2] == nil then
local data = BoxData(BoxType.metalBox,MathUtils:getUniqueID())
self.boxPool[num2] = data
end
end
end
--创建剩余的格子 默认为空格子
for i = 1,rowNum*colNum do
if self.boxPool[i] == nil then
local data = BoxData(BoxType.emptyBox,MathUtils:getUniqueID())
self.boxPool[i] = data
end
end
end
--隐射一个实体类型
local entityMap = { }
entityMap[BoxType.bombBox] = LBoxHinderBombEntity
local function getClass(type)
local class = entityMap[type]
if class == nil then
class = LBoxHinderEntity
end
return class
end
--创建静态实体
function BombermanMgr:createBox(msg)
local index = msg.gridId
local id = msg.livingId
local btype = msg.type
local masterId = msg.playerId
local modelId = BoxType2Model[btype]
if btype == BoxType.bombBox then
modelId = masterId<=0 and BombermanConst.bossBombModelId or modelId
--音效:炸弹创建
if masterId*10 == self:getMainPlayerId() then
self:playAudio(BombermanConst.bombCastAudioId, nil)
end
end
local pos = self:getBoxCenterPos(index)
--data
local roleData = LRoleData(id, RoleType.BoxHinder, true)
roleData:changeAttr(RoleAttr.SkinId,modelId)
roleData:changeAttr(RoleAttr.Fight,index)
roleData:changeAttr(RoleAttr.Exp,btype)
roleData:changeAttr(RoleAttr.MasterId,masterId)
--roleData:changeAttr(RoleAttr.MountId,msg.blood)
--roleData:changeAttr(RoleAttr.MagicWeaponId,msg.maxBlood)
roleData:changeAttr(RoleAttr.isActive,true)
roleData:changeAttr(RoleAttr.InitPosition, pos)
roleData:setFull()
roleData:attach()
--创建
if StaticEntityMgr:getRoleData(id) ~= nil then
return
end
local class = getClass(btype)
local staticEntity = class(id, RoleType.BoxHinder, roleData , nil)
if staticEntity then
if self.boxPool[index] then
self.boxPool[index]:addType(btype,id)
end
StaticEntityMgr:addRoleData(roleData)
StaticEntityMgr:addRole(staticEntity)
staticEntity:create()
end
end
--移除触发器实体
function BombermanMgr:removeBox(msg)
local id = msg.livingId
local index = msg.gridId
local btype = msg.type
if self.boxPool[index] then
self.boxPool[index]:removeType(btype,id)
end
StaticEntityMgr:removeRole(id)
StaticEntityMgr:removeRoleData(id)
--移除的盒子需要有特效 则播放特效
self:playEffect(btype,index)
end
--有的盒子销毁需要播放特效
function BombermanMgr:playEffect(btype,idx)
if BoxType2ExplodeEffect[btype] ~= nil then
local pos = self:getBoxCenterPos(idx)
EffectMgr:createEffect(BoxType2ExplodeEffect[btype], pos, nil)
end
--宝箱移除 播放音效
if btype == BoxType.treasureBox then
self:playAudio(BombermanConst.openTreasureAudioId, nil)
end
end
--协议更新盒子
function BombermanMgr:updateBox(msg)
if self.boxPool == nil then
self:initBox()
end
local index = msg.gridId
local btype = msg.type
local uid = msg.livingId
local isAdd = msg.blood > 0 --不再使用状态字段 blood就可以标记这个状态了
if self.boxPool[index] then
if isAdd then
self:createBox(msg)
self.boxPool[index]:addType(btype,uid)
else
self:removeBox(msg)
self.boxPool[index]:removeType(btype,uid)
end
end
end
--怪物移动
--在格子上添加移除
function BombermanMgr:simpleAddType(index,btype,uid)
local boxData = self:getBoxData(index)
if boxData then
boxData:addType(btype,uid)
end
end
function BombermanMgr:simpleRemoveType(index,btype,uid)
local boxData = self:getBoxData(index)
if boxData then
boxData:removeType(btype,uid)
end
end
--是否可以移动到目标位置
function BombermanMgr:canMoveTo(nowIndex,targetPos)
local index = self:getCellIndex(targetPos)
--如果玩家在当前格子 可以移动
if index == nowIndex then
return true
end
--没有找到格子 无法移动
if self.boxPool[index] == nil then
return true
end
--最后返回目标格子没有阻挡物
return not self.boxPool[index]:getIsHinder()
end
function BombermanMgr:canMoveToByPos(nowPos,targetPos)
local index = self:getCellIndex(nowPos)
return self:canMoveTo(index,targetPos)
end
--炸弹爆炸所有格子
--服务器推 爆炸点 炸弹等级 客户端计算出在哪些格子实例化炸弹
function BombermanMgr:getExplodeIndexs(index,level)
local lst = { }
local dirMap = { }--4个方向的数量
dirMap.top = 0
dirMap.bottom = 0
dirMap.left = 0
dirMap.right = 0
lst[1] = index
local row = self:getIndexRow(index)
--local col = self:getIndexCol(index)
local boxData = self:getBoxData(index)
if boxData == nil then
return lst
end
local unlockTop = true
local unlockBottom = true
local unlockLeft = true
local unlockRight = true
for i = 1,level do
local top = index-rowNum*i
local bottom = index+rowNum*i
local left = index-i
local right = index+i
--验证是否合理
--top不能<=0 bottom不能>31 left right 验证同一行既可
--公共条件 有的(铁格子)无需放炸弹 被铁格子挡住了 也无法继续延伸释放炸弹
if unlockTop and top > 0 then
unlockTop,canAdd = self:canPlaceExplode(top,level)
if unlockTop then
dirMap.top = dirMap.top + 1
end
if canAdd then
table.insert(lst,top)
end
end
if unlockBottom and bottom <= rowNum*colNum then
unlockBottom,canAdd = self:canPlaceExplode(bottom,level)
if unlockBottom then
dirMap.bottom = dirMap.bottom + 1
end
if canAdd then
table.insert(lst,bottom)
end
end
--left right
if unlockLeft and self:getIndexRow(left) == row then
unlockLeft,canAdd = self:canPlaceExplode(left,level)
if unlockLeft then
dirMap.left = dirMap.left + 1
end
if canAdd then
table.insert(lst,left)
end
end
if unlockRight and self:getIndexRow(right) == row then
unlockRight,canAdd = self:canPlaceExplode(right,level)
if unlockRight then
dirMap.right = dirMap.right + 1
end
if canAdd then
table.insert(lst,right)
end
end
end
return lst,dirMap
end
--格子是否可以放置炸弹爆炸物
--return 1是否被阻挡 2是否可以爆炸
function BombermanMgr:canPlaceExplode(index,level)
local boxData = self:getBoxData(index)
if boxData == nil then
return true,true
end
if boxData:hasType(BoxType.metalBox) then
return false,false
elseif boxData:hasType(BoxType.grassBox) then
return false,true--level>=3
elseif boxData:hasType(BoxType.woodBox) then
return false,true--level>=1
end
return true,true
--return not boxData:hasType(BoxType.metalBox) and not boxData:hasType(BoxType.grassBox) and not boxData:hasType(BoxType.woodBox)
end
--根据index获取行列
function BombermanMgr:getIndexRow(index)
return math.ceil(index/rowNum)
end
function BombermanMgr:getIndexCol(index)
local col = index%rowNum
return col == 0 and rowNum or col
end
--获取格子数据
function BombermanMgr:getBoxData(index)
return self.boxPool[index]
end
--根据位置获取格子index
function BombermanMgr:getCellIndex(pos)
local x = pos.x
local y = pos.z
local rowIndex = math.ceil((x - startX)/cellSize)
local colIndex = math.ceil((y - startY)/cellSize)
return (colIndex-1)*rowNum+rowIndex
end
--获取格子对应的坐标(取格子中心)
function BombermanMgr:getBoxCenterPos(index)
local row = self:getIndexRow(index)
local col = self:getIndexCol(index)
local x = startX+(col-1)*cellSize+(cellSize/2) --x是递加
local y = startY+(row-1)*cellSize+(cellSize/2) --y是递加
return Vector3(x,0,y)
end
--获取当前格子九宫格
function BombermanMgr:getSudokuBoxs(index)
local lst = self:getRoundIndex(index)
local boxLst = { }
for k,v in pairs(lst) do
local data = self:getBoxData(k)
if data then
table.insert(boxLst,data)
end
end
return boxLst
end
--获取格子周围所有格子
function BombermanMgr:getRoundIndex(index)
local lst = {}
--top 没有上 r1r2r3 --bottom没有下 r6r7r8 --left没有左r1r4r6 --right没有右r3r5r8
local isTop = index<=rowNum
local isBottom = index > (colNum-1)*rowNum
local isLeft = index%rowNum == 1
local isRight = index%rowNum == 0
local filter = {}
local r1 = index - rowNum - 1
local r2 = index - rowNum
local r3 = index - rowNum + 1
local r4 = index - 1
local r5 = index + 1
local r6 = index + rowNum - 1
local r7 = index + rowNum
local r8 = index + rowNum + 1
if isTop then
filter[r1] = true
filter[r2] = true
filter[r3] = true
end
if isBottom then
filter[r6] = true
filter[r7] = true
filter[r8] = true
end
if isLeft then
filter[r1] = true
filter[r4] = true
filter[r6] = true
end
if isRight then
filter[r3] = true
filter[r5] = true
filter[r8] = true
end
local result = {r1,r2,r3,r4,r5,r6,r7,r8}
for i =1,#result do
if filter[result[i]] == nil then
lst[result[i]] = true
end
end
lst[index] = true
return lst
end
function BombermanMgr:isVaildMove(nowIndex,targetPos)
local index = self:getCellIndex(targetPos)
return index == nowIndex+1 or index == nowIndex-1 or index == nowIndex+rowNum*1 or index == nowIndex+rowNum-1
end
--动态修改层级
--如果玩家当前格子有阻碍物
--设置当前阻碍物为role层 不与玩家发生碰撞
--在玩家更换格子之后 把层级设置回来
function BombermanMgr:changeLayer(index,layerName)
local boxData = self:getBoxData(index)
if boxData and boxData:getIsHinder() then
for k,v in pairs(BoxHinderType) do
local map = boxData:getTypeLst(k)
if map then
for m,n in pairs(map) do --m = uid n = true
if n == true then
EntityUtils:changeStaticRoleLayer(m, LayerMask.NameToLayer(layerName))
end
end
end
end
end
end
--阻碍物加载完成
function BombermanMgr:checkLayer(hinderIndex,uid)
local playerIndex = -1
local role = EntityMgr:getRole(self:getMainPlayerId())
if role then
playerIndex = role:getCellIndex()
end
if hinderIndex == playerIndex then
--self:changeLayer(hinderIndex,'Role')
EntityUtils:changeStaticRoleLayer(uid, LayerMask.NameToLayer('Role'))
end
end
-------------------------------以下缓存玩家信息---------------------------------
function BombermanMgr:addInfoListener(handler)
self.infoHandler = handler--不需要清理
end
function BombermanMgr:invokeInfoHandler()
if self.infoHandler then
self.infoHandler()
end
end
--PPTMemberData (uid,name,serverName,job,transferJob)
function BombermanMgr:addMember(id,msg)
if self.memberPool[id] == nil then
local dt = PPTMemberData(id,msg.nick_name,msg.serverName,msg.tempId,msg.lifeCount)
self.memberPool[id] = dt
self:invokeInfoHandler()
end
end
function BombermanMgr:updateMemberHp(id,hp)
local dt = self.memberPool[id]
if dt then
dt:setHp(hp)
end
self:invokeInfoHandler()
end
function BombermanMgr:getMemberLst()
return self.memberPool
end
--rankPool
function BombermanMgr:addRank(id,msg)
if self.rankMap[id] == nil then
local dt = PPTMemberRankData(id,msg.nick_name,msg.serverName)
table.insert(self.rankPool,dt) --lst 排序
self.rankMap[id] = dt --map 快速查找
self:invokeInfoHandler()
end
end
function BombermanMgr:updateRank(id,score)
local dt = self.rankMap[id]
if dt then
dt:setScore(score)
end
table.sort(self.rankPool,function(m,n) return m:getScore()>n:getScore() end)
self:invokeInfoHandler()
end
function BombermanMgr:getRankLst()
return self.rankPool
end
function BombermanMgr:getScore(id)
return self.rankMap[id] and self.rankMap[id]:getScore() or 0
end
--以下排行榜相关 PPTRankData:__init(id,rank,nickName,score)
function BombermanMgr:addTodayLst(msg)
self.todayLst = { }
local lst = msg.allReports
if lst and #lst>0 then
for i = 1,#lst do
local rsp = lst[i]
local dt = PPTRankData(rsp.livingId,rsp.rank,rsp.nickName,rsp.toalScore)
table.insert(self.todayLst,dt)
end
end
table.sort(self.todayLst,function(m,n) return m:getRank()<n:getRank() end)
local rsp = msg.meInfos
self.todayMine = PPTRankData(rsp.livingId,rsp.rank,rsp.nickName,rsp.toalScore)
end
function BombermanMgr:addYesTodayLst(msg)
self.yestodayLst = { }
local lst = msg.allReports
if lst and #lst>0 then
for i = 1,#lst do
local rsp = lst[i]
local dt = PPTRankData(rsp.livingId,rsp.rank,rsp.nickName,rsp.toalScore)
table.insert(self.yestodayLst,dt)
end
end
table.sort(self.yestodayLst,function(m,n) return m:getRank()<n:getRank() end)
local rsp = msg.meInfos
self.yestodayMine = PPTRankData(rsp.livingId,rsp.rank,rsp.nickName,rsp.toalScore)
end
function BombermanMgr:getTodayLst()
return self.todayLst,self.todayMine
end
function BombermanMgr:getYesTodayLst()
return self.yestodayLst,self.yestodayMine
end
function BombermanMgr:canReqToday()
return TimerMgr:getServerTime() - self.todayReqTime > 60*1000--60S才能拉取
end
function BombermanMgr:canReqYesToday()
return TimerMgr:getServerTime() - self.yestodayReqTime > 60*1000--60S才能拉取
end
function BombermanMgr:resetReqToday()
self.todayReqTime = TimerMgr:getServerTime()
end
function BombermanMgr:resetReqYesToday()
self.yestodayReqTime = TimerMgr:getServerTime()
end
function BombermanMgr:getRankRewards()
if self.rankRewardLst == nil then
self.rankRewardLst = {}
local list = RewardConfigMgr:getRewardConfigList(RewardType.PPTAllRank)
if list then
for i = 1, #list do
local data = DemonAwardData(list[i])
self.rankRewardLst[#self.rankRewardLst + 1] = data
end
else
Logger:logError("can not find RewardConfig type =", RewardType.PPTAllRank)
end
end
return self.rankRewardLst
end
--出生点模型 BombermanConst.myRespawnModeltId
function BombermanMgr:checkMyRespawnModel(idx)
if not self.myRespawnRoleId then
local pos = self:getBoxCenterPos(idx)
--data
self.myRespawnRoleId = MathUtils:getUniqueID()
local roleData = LRoleData(self.myRespawnRoleId, RoleType.BoxHinder, true)
roleData:changeAttr(RoleAttr.SkinId,BombermanConst.myRespawnModeltId)
roleData:changeAttr(RoleAttr.isActive,true)
roleData:changeAttr(RoleAttr.InitPosition, pos)
roleData:setFull()
roleData:attach()
--创建
local staticEntity = LBoxHinderEntity(self.myRespawnRoleId, RoleType.BoxHinder, roleData , nil)
if staticEntity then
StaticEntityMgr:addRoleData(roleData)
StaticEntityMgr:addRole(staticEntity)
staticEntity:create()
end
end
end
--是否可以释放
function BombermanMgr:canCastBomb(isAlert)
local role = EntityMgr:getRole(self:getMainPlayerId())
if role then
local roleIndex = role:getCellIndex()
local boxData = self:getBoxData(roleIndex)
if boxData and boxData:hasType(BoxType.bombBox) then
if isAlert then
--1000ms才能弹出1次提示
if TimerMgr:getServerTime() - self.lastAlertTime > 800 then
self.lastAlertTime = TimerMgr:getServerTime()
UIUtils:floatAlertByKey(BombermanLang.thisBoxHasBombStr)
end
end
return false
end
end
return true
end
function BombermanMgr:isFollowPlayer(id)
return id == self.followId
end
--格子是否可以实例化爆炸特效
function BombermanMgr:canPlayCellEffect(index,time)
if not self.bombEffectTimeMap[index] or time - self.bombEffectTimeMap[index] > 500 then
self.bombEffectTimeMap[index] = time
return true
end
return false
end
--接口 index1是否在index2的 14*14范围内 用于播放音效
function BombermanMgr:indexIn14Range(mine,target)
local mineRow = self:getIndexRow(mine)
local mineCol = self:getIndexCol(mine)
local tarRow = self:getIndexRow(target)
local tarCol = self:getIndexCol(target)
return math.abs(tarRow-mineRow) <= 7 and math.abs(tarCol-mineCol) <= 7
end
--封装一层 音效播放
function BombermanMgr:playAudio(audioId, callBack)
if audioId and audioId > 0 and self:canPlayAudioTime(audioId) then
AudioMgr:playAudio(audioId, callBack)
end
end
function BombermanMgr:canPlayAudioTime(audioId)
local time = TimerMgr:getServerTime()
local mill = AudioIdMinMill[audioId] and AudioIdMinMill[audioId] or 0
if not self.audioTimeMap[audioId] or time - self.audioTimeMap[audioId] > mill then
self.audioTimeMap[audioId] = time
return true
end
return false
end
--合并
function BombermanMgr:addStaticId(id)
--table.insert(self.combineLst,id)
self.combineLst:Add(id)
if self.combineLst.Count>=1 then
--combine
EntityUtils:combineStatic(self.combineLst)
self.combineLst:Clear()
end
end
---[[
function BombermanMgr:addToStatic(id)
if self.combineRoot == nil or not Helper:goIsHas(self.combineRoot) then
self.combineRoot = GameObject("combineRoot")
end
EntityUtils:setStaticParent(id,self.combineRoot)
self.combineNum = self.combineNum + 1
if self.combineNum >= 15 then
if self.combineRoot ~= nil and Helper:goIsHas(self.combineRoot) then
--Logger:logError("combineRoot")
StaticBatchingUtility.Combine(self.combineRoot)
self.combineNum = 0
end
end
end
--]]
-- 清理数据
function BombermanMgr:clearSelf()
self.boxPool = nil
self.mainRoleId = 0
self.dropPool = { } --缓存掉落物 BUFF
self.memberPool = { } --玩家信息 PPTMemberData
self.rankPool = { }--玩家信息 PPTMemberRankData
self.rankMap = { }--玩家排名 PPTMemberRankData
self.todayReqTime = -1 --上次拉取时间
self.yestodayReqTime = -1 --上次拉取时间
self.todayLst = { } --今天数据
self.yestodayLst = { }--昨天数据
self.todayMine = nil --自己今天
self.yestodayMine = nil --自己昨天
self.myRespawnRoleId = nil --出生点模型
self.followId = -1 --跟随id
self.lastAlertTime = -1--上次弹出提示时间
self.bombEffectTimeMap = { }--格子爆炸特效上次释放时间
self.audioTimeMap = { }--音效上次播放时间
--self.combineLst = ListLong()
self.combineNum = 0
end
---------以下段落实现一些需要的定义方法-------end-------------------------
-- 自动初始化
create(BombermanMgr)
<3>代码备注
--[[
实体创建:
5,6号协议主角还是会创建(进入不会推)
在进入这个场景的时候,创建完毕炸弹人实体(继承LRole),相机进行跟随
同时关闭所有原先RootUI,摇杆重新创建一个新的(复用预设,class重写),技能UI也做新的(全部重写) 头像 任务UI都重做
位置同步:
客户端A摇杆拖动开始同步 停止移动也同步一次
客户端A每次预测当前方向0.1秒位置,预测位置发送给服务器,服务器进行广播
客户端A每次移动都检测是否碰撞到阻挡格子
客户端B接到同步协议,进行插值移动
怪物位置同步:
服务器每次推送怪物目标格子
客户端把每个格子位置加入到怪物的目标位置列表
客户端进行平滑插值 速度会根据列表中的个数进行加速度
碰撞器:
碰撞器使用Unity自带碰撞
如果玩家卡到格子里面 那么格子里面的物体碰撞层都会设置成不与玩家碰撞
触发器:
不适用Unity触发器 在Lua这边维护触发
主角每次改变格子 都会检测触发(检测当前格子和九宫格,盒子生成也需要与玩家所在格子检测)
BUFF:
buff存在于实体身上(对应关系备注在BombermanConst)
buff服务器只告诉结束时间戳 客户端自己维护BUFF结束 无法使用之前的buff组件
实体获取buff起定时器 每100ms检查buff是否结束 使用setCountDown定时器会有后台运行的问题(后台运行定时器暂停)
主角buff定时器每次都抛出消息给UI
技能:
技能分为3中类型 1炸弹(可以充能) 2符文(使用一层少一层) 3血量(死亡一次少一次)
技能数据都存在于实体身上(对应关系备注在BombermanConst)
1炸弹充能 有最大充能次数(会动态更改)
2符文
3血量
其他:
1.进入PPT场景主动拉取所有信息(不然会出现还没加载完场景 协议来了创建实体 实体又马上被销毁)
2.进入PPT场景 服务器还是会推其他玩家的6号协议(服务器通用处理) 客户端PPT玩家实体的id = id*10 取实体的 更新实体都需要*10
3.玩家实体创建协议与怪物实体创建协议不同(怪物实体用的是Box协议 客户端转实体)
--]]