├── README.md └── game.js /README.md: -------------------------------------------------------------------------------- 1 | ## 使用小游戏api下载压缩包并解压到客户端缓存的例子 2 | 3 | 在laya 1.7中测试 4 | 可以保持原本资源加载模式不变,测试真机可以离线加载所有资源 5 | 在微信开发工具中offline模式会读取资源失败,这个问题可能是开发工具offline模式不能重定向的原因 6 | 有需求的或许可以通过修改laya.wxmini.js文件修复 7 | 8 | 这样做本身目的就是扔掉laya.wxmini.js的那一套缓存方案... 9 | 首先atlas等除了声音和图片以外的资源并不能正常的缓存后读取(即使通过手动调用downloadfile缓存 10 | 而且laya的声音播放api无法在小游戏切回时继续播放,所以我的项目使用了小游戏的音频api,这样laya.wxmini.js将无法缓存声音素材 11 | 12 | 综合以上原因,扔掉laya自带的缓存方案,手动创建一个缓存系统并管理。顺便统一了缓存系统,不管直接通过小游戏或laya的api都可以调用到缓存文件 13 | 14 | 另外这样也一定程度简化了版本管理..不需要在用IDE的发布功能附加hash了 15 | 16 | 但这样有个问题是项目不能在浏览器环境调试了..可以用gulp等工具实时合并,直接扔掉ide在微信开发工具中调试 17 | 18 | > https://ldc.layabox.com/doc/?nav=zh-js-5-0-5 19 | https://developers.weixin.qq.com/minigame/dev/tutorial/ability/file-system.html 20 | https://github.com/witcat/gulpLayaairWxDemo 21 | -------------------------------------------------------------------------------- /game.js: -------------------------------------------------------------------------------- 1 | function boot() { 2 | //游戏初始化 3 | Laya.MiniAdpter.init() 4 | //关闭Laya的小游戏自动缓存 5 | Laya.MiniAdpter.autoCacheFile = false 6 | Laya.init(750, Laya.Browser.clientHeight * 2, Laya.WebGL); 7 | //设置cdn地址 8 | let baseURL = 'https://res.xxx.com/' 9 | //设置一个本地用户文件缓存目录 10 | //https://developers.weixin.qq.com/minigame/dev/tutorial/ability/file-system.html 11 | let cacheURL = wx.env.USER_DATA_PATH + '/cache/' 12 | //设置一个资源包的版本号,可以写死也可以联网热更新 13 | let bundleVer = '180826' 14 | // 组装资源包路径 15 | let bundleURI = wx.env.USER_DATA_PATH + '/bundle' + bundleVer + '.zip' 16 | //挂载对象 17 | Laya.ext = {} 18 | //手动资源分组 19 | Laya.ext.assetsGroup = { 20 | mode: 'interface', 21 | common: [ 22 | 'res/atlas/a.atlas', 23 | ], 24 | interface: [ 25 | 'res/atlas/b.atlas', 26 | ], 27 | game: [ 28 | 'res/atlas/c.atlas', 29 | ] 30 | } 31 | Laya.ext.sounds = { 32 | common: [ 33 | 'change', 34 | 'decide', 35 | ], 36 | interface: [ 37 | 'close', 38 | ], 39 | game: [ 40 | '808-bounce', 41 | ] 42 | } 43 | 44 | //因为laya的声音api无法在微信切出并返回时继续播放 45 | //声音全部使用小游戏api接管 46 | //https://developers.weixin.qq.com/minigame/dev/tutorial/ability/audio.html 47 | Laya.ext.wxSound = { 48 | soundCache: { 49 | common: {}, 50 | interface: {}, 51 | game: {}, 52 | mp: [] 53 | }, 54 | preloadSounds(groupName) { 55 | let group = Laya.ext.sounds[groupName] 56 | let cache = this.soundCache[groupName] 57 | for (let i = 0; i < group.length; i++) { 58 | let sound = wx.createInnerAudioContext() 59 | sound.src = cacheURL + 'sound/' + group[i] + '.mp3' 60 | sound.volume = 1 61 | sound.autoplay = false 62 | cache[group[i]] = sound 63 | } 64 | }, 65 | destroySounds(group) { 66 | let cache = this.soundCache[group] 67 | for (let i in cache) { 68 | cache[i].destroy() 69 | } 70 | this.soundCache[group] = {} 71 | }, 72 | playSound(group, name) { 73 | let sound = this.soundCache[group][name] 74 | sound.seek(0) 75 | sound.play() 76 | }, 77 | playMusic(group, name) { 78 | let sound = this.soundCache[group][name] 79 | sound.seek(0) 80 | sound.loop = true 81 | sound.volume = 0.6 82 | 83 | function playBgm() { 84 | sound.play() 85 | } 86 | sound.cb = playBgm 87 | wx.onShow(playBgm) 88 | sound.play() 89 | } 90 | } 91 | Laya.ext.wxSound.preloadSounds('common') 92 | Laya.ext.wxSound.preloadSounds('interface') 93 | 94 | //跟随4m代码包一起发布的资源文件 95 | let nativeResources = [ 96 | 'res/atlas/local.atlas' 97 | ] 98 | Laya.loader.load(nativeResources, Laya.Handler.create(this, async () => { 99 | //本地资源加载后创建一个资源加载等待页面 100 | let initialPage = new Laya.InitialPage() 101 | //资源包缓存主逻辑 102 | //https://developers.weixin.qq.com/minigame/dev/document/file/wx.getFileSystemManager.html 103 | let clientBundleVer = wx.getStorageSync('bundleVer') 104 | if (clientBundleVer == bundleVer) { 105 | console.log('素材包版本匹配'); 106 | } else { 107 | let fs = wx.getFileSystemManager() 108 | let isCached = await new Promise((rs, rj) => { 109 | fs.access({ 110 | path: bundleURI, 111 | success(evt) { 112 | console.log('素材包已下载') 113 | rs(true) 114 | }, 115 | fail(evt) { 116 | console.log('素材包不存在') 117 | rs(false) 118 | } 119 | }) 120 | }) 121 | if (!isCached) { 122 | console.log('素材包已开始下载') 123 | await new Promise((rs, rj) => { 124 | wx.downloadFile({ 125 | url: baseURL + 'zip/bundle' + bundleVer + '.zip', 126 | filePath: bundleURI, 127 | success(evt) { 128 | console.log('素材包下载完毕') 129 | rs() 130 | }, 131 | fail(evt) { 132 | console.log('素材包下载取消') 133 | rj() 134 | } 135 | }) 136 | }) 137 | } 138 | let isDirExists = await new Promise((rs, rj) => { 139 | fs.access({ 140 | path: cacheURL, 141 | success(evt) { 142 | console.log('缓存目录已存在') 143 | rs(true) 144 | }, 145 | fail(evt) { 146 | console.log('缓存目录不存在') 147 | rs(false) 148 | } 149 | }) 150 | }) 151 | if (isDirExists) { 152 | console.log('删除旧的缓存文件') 153 | function cleanDir(target) { 154 | return new Promise(async(rs,rj)=>{ 155 | let list = fs.readdirSync(target) 156 | for (let i = 0; i < list.length; i++) { 157 | if (list[i].includes('.')) { 158 | await new Promise((rs, rj) => { 159 | fs.unlink({ 160 | filePath: target + list[i], 161 | complete() { 162 | rs() 163 | } 164 | }) 165 | }) 166 | } else { 167 | await cleanDir(target + list[i] + '/') 168 | } 169 | } 170 | fs.rmdirSync(target) 171 | rs() 172 | }) 173 | } 174 | await cleanDir(cacheURL) 175 | } 176 | 177 | console.log('缓存目录已新建') 178 | fs.mkdirSync(cacheURL) 179 | await new Promise((rs, rj) => { 180 | fs.unzip({ 181 | zipFilePath: bundleURI, 182 | targetPath: cacheURL, 183 | success() { 184 | console.log('资源包解压缩完毕') 185 | rs() 186 | }, 187 | fail(err) { 188 | rj(err) 189 | } 190 | }) 191 | }) 192 | fs.unlink({ 193 | filePath: bundleURI 194 | }) 195 | wx.setStorageSync('bundleVer', bundleVer) 196 | } 197 | //此时修改basePath为本地的缓存路径 198 | //这时所有文件将从本地读取,这样做原因是laya.wxmini.js无法自动缓存除声音图片外的文件, 199 | //即使使用downloadfile缓存也无法通过loader加载 200 | //如果用微信本身的api播放声音,声音当然就无法自动缓存了。通过使用上述缓存方案可以统一缓存系统,两者api可以同时调用缓存的文件 201 | //总之就是在LayaLoader加载之前将素材转移到客户端,这样不用修改laya本身的文件,也解决了诸多问题 202 | Laya.URL.basePath = cacheURL 203 | Laya.loader.load(resources, Laya.Handler.create(this, () => { 204 | //后续游戏逻辑 205 | })) 206 | })) 207 | } 208 | boot() 209 | --------------------------------------------------------------------------------