--local MainSceneConfig = require "res.scripts.configs.MainSceneConfig" -- 暂时添加一个临时配置文件 --require "res.scripts.scenes.MainScene" -- 加载事件 OnLoadingStart = "OnLoadingStart"; OnLoadingProcess = "OnLoadingProcess"; OnLoadingEnd = "OnLoadingEnd"; -- 加载类型 SOUNDTYPE = "sounds"; TEXTURETYPE = "textures"; ATLASTYPE = "atlas"; ANIMATIONTYPE = "animations"; EFFECTTYPE = "effects"; -- 加载控制逻辑 local LoadingController = class("LoadingController", Behavior); function LoadingController:ctor(sceneName) LoadingController.super.ctor(self); -- 定义成员变量 self.progress = 0; -- 加载进度 self.totalLoadingNum = 0; --加载总数数量 self.curLoadingNum = 0; -- 当前加载数量 self.loadingConfig = ""; -- 资源配置文件 self.log = nil; -- 加载界面log self.btmLabel = nil; --进度显示标签 self.uiLayout = nil; -- 加载界面布局 self.uiLayer = nil; -- 加载界面层 self.curScene = nil; -- 上一个场景 self.nextScene = nil; -- 下一个场景 self.config = res[sceneName];-- 配置文件 self.curSceneName = sceneName; self.isLoaded = false; -- 随机抽取一只怪物 local animKeys = table.keys(res.animations); if #animKeys > 0 then local index = math.random(1, #animKeys); self.animName = tostring(animKeys[index]); self.loadingxml = res.animations[self.animName]; self.loadingplist = string.gsub(self.loadingxml, ".xml", ".plist") self.loadingpng = string.gsub (self.loadingxml, ".xml", ".png") end end function LoadingController:run( ) self.curScene = SceneM.getRunningScene(); self.nextScene = nil; -- 1.ui层 self.uiLayer = ObjectFactory.newLayer(); self.uiLayer:setColor(ccc3(0, 0, 0)); -- 2.创建构成加载场景的元素 self.btmLabel = ObjectFactory.newBMFontLabel({text = "Loading 0%", font = res.fonts.UIFont,}) self.btmLabel:setPosition(ccp(Screen.cx, Screen.cy - 80)); self.uiLayer:addChild(self.btmLabel); if self.loadingxml then CCArmatureDataManager:sharedArmatureDataManager():addArmatureFileInfoAsync(self.loadingpng, self.loadingplist, self.loadingxml, function ( ) if self.isLoaded then return; end local lion = ObjectFactory.newArmature(self.animName); lion:setPosition(ccp(Screen.cx,Screen.cy)); lion:addParent(self.uiLayer); lion:getComponent("Animation"):play("run", WrapMode.Loop); end) end -- 3. 添加到场景 SceneM.dontDestroy(self.uiLayer); -- 4. 关掉触摸消息 CCDirector:sharedDirector():getTouchDispatcher():setDispatchEvents(false); -- 5. 关掉动作管理 CCDirector:sharedDirector():getActionManager():removeAllActions(); -- 6. 退出当前场景 if self.curScene then self.curScene:setVisible(false); end -- 7. 重新初始化管理类 SceneM.uiLayers = {}; -- 8.延迟清除当前资源,并且加载下一个场景资源 performWithDelay(function ( ) self:cleanup(); self:startLoading(self.config); end, 0.01) -- 9. 回收lua内存 collectgarbage("collect") end function LoadingController:startLoading(theloadingconfig) if theloadingconfig == nil then self.isLoaded = true; -- 切换场景 self.nextScene = ObjectFactory.newScene(self.curSceneName); SceneM.curScene = self.nextScene; self.nextScene:addComponent(self.curSceneName,SceneM.getSceneController(self.curSceneName)); -- 关闭加载层 SceneM.destroy(self.uiLayer); -- 开启触摸消息 CCDirector:sharedDirector():getTouchDispatcher():setDispatchEvents(true); -- 记录配置文件路径 SceneM.lastSceneName = self.curSceneName; -- 切换到新场景 SceneM.replaceScene(self.nextScene, "crossfade", 0.2, Screen.COLOR_WHITE); return; end print ("start loading") self.loadingConfig = theloadingconfig; local resTypes = {"sounds","textures","atlas","animations","effects"} local curIndex = 1; -- 1.开始当前场景加载资源 self.curLoadingNum = 0 local totalNum = 0 local function loopRes( t , resType) if self.curLoadingNum > self.totalLoadingNum then return; end if t == nil then curIndex = curIndex + 1; local resType = resTypes[curIndex]; print("加载类型:",resType); print("加载:",theloadingconfig[resType]); loopRes(theloadingconfig[resType], resType); return; end local keys = table.keys(t); totalNum = totalNum + #keys; local tempIndex = 1; local function loadRes( ) self.curLoadingNum = self.curLoadingNum + 1; if self.curLoadingNum > self.totalLoadingNum then return; end --print("====",self.curLoadingNum , totalNum) if self.curLoadingNum > totalNum then tempIndex = 1; curIndex = curIndex + 1; local resType = resTypes[curIndex]; self.curLoadingNum = self.curLoadingNum - 1; loopRes(theloadingconfig[resType], resType); return; end local key = keys[tempIndex]; local value = t[key]; tempIndex = tempIndex + 1; if (tolua.type(value) == "table") then loopRes( value ); elseif (tolua.type(value) == "string") then if resType == SOUNDTYPE then -- 1.异步声音加载 --print("加载声音:", value); Audio.preloadEffect(value); performWithDelay(function ( ) loadRes(); end, CCDirector:sharedDirector():deltaTime()) end if resType == TEXTURETYPE then -- 2.异步纹理加载 --print("加载纹理:", value); CCTextureCache:sharedTextureCache():addImageAsync(value, function ( ) self:CheckedResLoaded(); -- 检测下是否加载完毕 performWithDelay(function ( ) loadRes(); end, CCDirector:sharedDirector():deltaTime()) end); end if resType == ATLASTYPE then -- 2.异步纹理加载 local png = string.gsub(value, ".plist", ".png") --print("加载图集:",png); CCTextureCache:sharedTextureCache():addImageAsync(png, function ( ) -- 添加plist 到 CCSpriteFrameCache CCSpriteFrameCache:sharedSpriteFrameCache():addSpriteFramesWithFile(value) self:CheckedResLoaded(); -- 检测下是否加载完毕 performWithDelay(function ( ) loadRes(); end, CCDirector:sharedDirector():deltaTime()) end); end if resType == ANIMATIONTYPE or resType == EFFECTTYPE then --3.异步动画加载 local plist = string.gsub(value, ".xml", ".plist") local png = string.gsub (value, ".xml", ".png") --print("加载骨骼动画:",png, plist, value); CCArmatureDataManager:sharedArmatureDataManager():addArmatureFileInfoAsync(png, plist, value, function ( ) self:CheckedResLoaded(); -- 检测下是否加载完毕 performWithDelay(function ( ) loadRes(); end, CCDirector:sharedDirector():deltaTime()) end) end end end loadRes(); end -- 计算加载的资源总数 local function size( config ) return #table.keys(config.textures) + #table.keys(config.sounds) + #table.keys(config.fonts) + #table.keys(config.animations) + #table.keys(config.atlas) + #table.keys(config.effects); end self.totalLoadingNum = size(theloadingconfig); -- 加载场景资源 local resType = resTypes[curIndex]; print("加载类型:",resType); print("加载:",theloadingconfig[resType]); loopRes(theloadingconfig[resType], resType); end -- 检测是否加载完毕 function LoadingController:CheckedResLoaded( ) if self.curLoadingNum <= self.totalLoadingNum then -- 1.更新当前进度 local percent = math.modf(self.curLoadingNum * 100 / self.totalLoadingNum) self.btmLabel:setString(string.format("Loading %s%%", percent)); end -- 2.检测下是否加载完毕 if (self.curLoadingNum == self.totalLoadingNum) then local function onComplete(event) print ("loading res finished!") self.isLoaded = true; -- 切换场景 self.nextScene = ObjectFactory.newScene(self.curSceneName); SceneM.curScene = self.nextScene; self.nextScene:addComponent(self.curSceneName,SceneM.getSceneController(self.curSceneName)); -- 关闭加载层 SceneM.destroy(self.uiLayer); -- 开启触摸消息 CCDirector:sharedDirector():getTouchDispatcher():setDispatchEvents(true); -- 记录配置文件路径 SceneM.lastSceneName = self.curSceneName; -- 切换到新场景 SceneM.replaceScene(self.nextScene, "crossfade", 0.2, Screen.COLOR_WHITE); end -- 等待一帧 不然最后一次无法绘制 performWithDelay(onComplete, CCDirector:sharedDirector():deltaTime() * 2); end end -- 清理资源 function LoadingController:cleanup( ) CCDirector:sharedDirector():getActionManager():removeAllActions(); -- 获得上一个场景配置,根据配置删除 if SceneM.lastSceneName then local lastConfig = res[SceneM.lastSceneName]; local function removeRes( t , resType) if t == nil or type(t) ~= "table" then return; end for key, value in pairs(t) do if (tolua.type(value) == "table") then loopRes( value ); elseif (tolua.type(value) == "string") then if resType == SOUNDTYPE then -- 1.删除声音 Audio.unloadSound(value); end if resType == TEXTURETYPE then -- 2.删除纹理 CCTextureCache:sharedTextureCache():removeTextureForKey(value); end if resType == ATLASTYPE then -- 3.删除plist纹理 CCSpriteFrameCache:sharedSpriteFrameCache():removeSpriteFramesFromFile(value); value = string.gsub(value, ".plist", ".png"); CCTextureCache:sharedTextureCache():removeTextureForKey(value); end if resType == ANIMATIONTYPE then -- 4.删除动画 print("删除骨骼动画资源:",value); value = string.gsub(value, ".xml", ".png"); CCTextureCache:sharedTextureCache():removeTextureForKey(value); value = string.gsub(value, ".png", ".plist"); CCSpriteFrameCache:sharedSpriteFrameCache():removeSpriteFramesFromFile(value); --CCArmatureDataManager:purge(); end end end end removeRes(lastConfig.sounds, SOUNDTYPE); --删除声音资源 removeRes(lastConfig.textures, TEXTURETYPE); --删除纹理资源 removeRes(lastConfig.atlas, ATLASTYPE); --删除图集资源 removeRes(lastConfig.animations, ANIMATIONTYPE); --删除动画资源 removeRes(lastConfig.effects, ANIMATIONTYPE); --删除动画资源 -- 移除临时动态公共资源 if ResM.tempPathCache then removeRes(ResM.tempPathCache.sounds, SOUNDTYPE); --删除声音资源 removeRes(ResM.tempPathCache.textures, TEXTURETYPE); --删除纹理资源 removeRes(ResM.tempPathCache.atlas, ATLASTYPE); --删除图集资源 removeRes(ResM.tempPathCache.animations, ANIMATIONTYPE); --删除动画资源 end ResM.init(); CCTextureCache:sharedTextureCache():dumpCachedTextureInfo(); end -- CCSpriteFrameCache:purgeSharedSpriteFrameCache(); -- CCTextureCache:sharedTextureCache():removeAllTextures(); -- CCArmatureDataManager:purge(); end return LoadingController;