【泡泡堂】格子管理等

<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协议 客户端转实体)
--]]

  

原文地址:https://www.cnblogs.com/cocotang/p/10825682.html

时间: 2024-11-25 13:24:01

【泡泡堂】格子管理等的相关文章

BZOJ 1034: [ZJOI2008]泡泡堂BNB( 贪心 )

贪心...用最弱的赢最弱的,用最强的赢最强的,否则用最弱的和最强的比... (贴个官方题解:将双方的选手均按从强到弱排序,然后第一次扫描尽可能用当前剩下的选手中能赢对手当前最强选手中最弱的一个去赢得胜利,若无法做到,则暂时不考虑给对方最强的选手匹配对手.第二遍扫描使用同样策略去获取尽量多的平局.最后剩下的选手任意匹配就能获得最多的分数) -------------------------------------------------------------------- #include<cs

ZJOI2008泡泡堂BNB

1034: [ZJOI2008]泡泡堂BNB Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1305  Solved: 676[Submit][Status] Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组委会提交一份参赛选手的名单,决定了选手上场的顺序,一经确定,不得修改.比赛中

1034: [ZJOI2008]泡泡堂BNB

题目描述: 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组委会提交一份参赛选手的名单,决定了选手上场的顺序,一经确定,不得修改.比赛中,双方的一号选手,二号选手--,n号选手捉对厮杀,共进行n场比赛.每胜一场比赛得2分,平一场得1分,输一场不得分.最终将双方的单场得分相加得出总分,总分高的队伍晋级(总分相同抽签决定).作为浙江队的领队,你已经在事先将各省

BZOJ [ZJOI2008]泡泡堂BNB 贪心

[ZJOI2008]泡泡堂BNB Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1034 Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组委会提交一份参赛选手的名单,决定了选手上场的顺序,一经确定

[BZOJ 1034] [ZJOI 2008] 泡泡堂BNB

1034: [ZJOI2008]泡泡堂BNB Time Limit: 10 SecMemory Limit: 162 MB Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组委会提交一份参赛选手的名单,决定了选手上场的顺序,一经确定,不得修改.比赛中,双方的一号选手,二号选手……,n号选手捉对厮杀,共进行n场比赛.每胜一场比赛得2分,

【BZOJ1034】省队选手不务正业打泡泡堂(我也不知道是啥算法)

1034: [ZJOI2008]泡泡堂BNB Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表 队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组委会提交一份 参赛选手的名单,决定了选手上场的顺序,一经确定,不得修改.比赛中,双方的一号选手,二号选手……,n号 选手捉对厮杀,共进行n场比赛.每胜一场比赛得2分,平一场得1分,输一场不得分.最终将双方的单场得分相加 得出总分,总分高的

【140811】泡泡堂游戏单机版完整源码(ASL引擎)

此源码模拟了盛大公司的同名游戏泡泡堂,演示了ASL引擎的使用方法.支持支持小龟.大物体.飞碟等坐骑.动画物体,猫头鹰,支持草丛.帐篷.冰窟等隐藏物体,支持各种主要道具. 本游戏可以实现单双人对战. 游戏截图: 源码下载地址:点击下载 [140811]泡泡堂游戏单机版完整源码(ASL引擎)

bzoj 1034: [ZJOI2008]泡泡堂BNB 貪心

1034: [ZJOI2008]泡泡堂BNB Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1398  Solved: 727[Submit][Status] Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组委会提交一份参赛选手的名单,决定了选手上场的顺序,一经确定,不得修改.比赛中

[Bzoj1034][ZJOJ2008]泡泡堂BNB(贪心)

1034: [ZJOI2008]泡泡堂BNB Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3482  Solved: 1776[Submit][Status][Discuss] Description 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏泡泡堂.每一场比赛前,对阵双方的教练向组委会提交一份参赛选手的名单,决定了选手上场的顺序,一经确