• 【泡泡堂】格子管理等


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

      

  • 相关阅读:
    Flume将A服务器上的日志采集到B服务器上展示
    flume1.8的安装及环境配置
    springboot实现控制层返回二维码,扫描后打开PDF文件
    Eureka添加security验证后客户端无法注册报错
    Elasticsearch系统学习(八)-partial update
    Elasticsearch系统学习(七)-ES并发控制
    Elasticsearch系统学习(六)-document元数据及基本操作
    Elasticsearch系统学习(五)-分布式架构及shard容错原理
    Elasticsearch系统学习(四)-简单查询及聚合函数
    Elasticsearch系统学习(三)-document基本操作
  • 原文地址:https://www.cnblogs.com/cocotang/p/10825682.html
Copyright © 2020-2023  润新知