音频资源加入cdn方案
This commit is contained in:
parent
0c7df8acd1
commit
a00361d157
|
|
@ -139,96 +139,35 @@
|
||||||
"__id__": 2
|
"__id__": 2
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"audioGameBgm0": {
|
"main_bgm": null,
|
||||||
"__uuid__": "75b4f368-70b5-452d-9afd-ca7a6f1e2e60"
|
"xiaochu": null,
|
||||||
},
|
"hit": null,
|
||||||
"xiaochu": {
|
"down": null,
|
||||||
"__uuid__": "8d67c864-c7f4-4305-8b3b-2d66eb69e349"
|
"win": null,
|
||||||
},
|
"anniu_Big": null,
|
||||||
"hit": {
|
"anniu_little": null,
|
||||||
"__uuid__": "7575a6bd-a21d-491e-aad2-e40a189683e9"
|
"tanchuang": null,
|
||||||
},
|
"zhuan1": null,
|
||||||
"down": {
|
"zhuan2": null,
|
||||||
"__uuid__": "ec293610-1767-46e8-b6b6-4a9a79ef2233"
|
"adhesive": null,
|
||||||
},
|
"freezeBlock": null,
|
||||||
"fangxiang": null,
|
"freezeDoor": null,
|
||||||
"build": null,
|
"hammer": null,
|
||||||
"win": {
|
"lockBlock1": null,
|
||||||
"__uuid__": "9f2906df-601d-4dfa-a561-31745b62c9dd"
|
"lockBlock2": null,
|
||||||
},
|
"lockDoor": null,
|
||||||
"lose": null,
|
"magic1": null,
|
||||||
"anniu_Big": {
|
"magic2": null,
|
||||||
"__uuid__": "7362cac7-12b5-4704-af6d-5b110c5e9fcf"
|
"simpleColor": null,
|
||||||
},
|
"stacking": null,
|
||||||
"anniu_little": {
|
"starBlock": null,
|
||||||
"__uuid__": "a5518b0f-7ed3-46f0-aa78-93f02f4579cc"
|
"timePause1": null,
|
||||||
},
|
"timePause2": null,
|
||||||
"tanchuang": {
|
"hit1": null,
|
||||||
"__uuid__": "1301aea4-4351-40d8-b4c4-e428613b3681"
|
"hit2": null,
|
||||||
},
|
"hit3": null,
|
||||||
"zhuan1": {
|
"hit4": null,
|
||||||
"__uuid__": "e4d2f16e-7663-4ee5-a479-06ae0eae91d5"
|
"hit5": null,
|
||||||
},
|
|
||||||
"zhuan2": {
|
|
||||||
"__uuid__": "998a24bd-ffa0-4f96-bc39-a9789f42bd9b"
|
|
||||||
},
|
|
||||||
"adhesive": {
|
|
||||||
"__uuid__": "e0f2c22c-d8dd-4dad-9fa2-7b73d15a5518"
|
|
||||||
},
|
|
||||||
"freezeBlock": {
|
|
||||||
"__uuid__": "9a056601-12c6-45dd-abde-a847d6f15247"
|
|
||||||
},
|
|
||||||
"freezeDoor": {
|
|
||||||
"__uuid__": "20367986-5fa0-4558-9c73-861dc7bc1293"
|
|
||||||
},
|
|
||||||
"hammer": {
|
|
||||||
"__uuid__": "a25b43cf-deba-4061-a5da-e87aa343269d"
|
|
||||||
},
|
|
||||||
"lockBlock1": {
|
|
||||||
"__uuid__": "227cb730-4de8-41e2-93d1-f9e8cfdffd11"
|
|
||||||
},
|
|
||||||
"lockBlock2": {
|
|
||||||
"__uuid__": "2cfcd2ad-bb5d-47c0-be0a-3a8135d89c1f"
|
|
||||||
},
|
|
||||||
"lockDoor": {
|
|
||||||
"__uuid__": "25ca59d5-b522-472d-83e4-de16fd1cdd5c"
|
|
||||||
},
|
|
||||||
"magic1": {
|
|
||||||
"__uuid__": "b8ec297a-cc2d-4a82-ac2c-345db075ce84"
|
|
||||||
},
|
|
||||||
"magic2": {
|
|
||||||
"__uuid__": "e09b4699-ba82-4ac8-9894-d8b88640d041"
|
|
||||||
},
|
|
||||||
"simpleColor": {
|
|
||||||
"__uuid__": "6f213771-d0ef-45ba-b87d-e878f291886b"
|
|
||||||
},
|
|
||||||
"stacking": {
|
|
||||||
"__uuid__": "2c418573-4beb-49f8-bafe-6a9ae7906195"
|
|
||||||
},
|
|
||||||
"starBlock": {
|
|
||||||
"__uuid__": "643d1ba5-fd6f-45ab-928e-c271afddbcef"
|
|
||||||
},
|
|
||||||
"timePause1": {
|
|
||||||
"__uuid__": "f5c8c01d-aa75-4518-a7c6-82599ad31e58"
|
|
||||||
},
|
|
||||||
"timePause2": {
|
|
||||||
"__uuid__": "37c7f2a9-e0d2-4f3e-9ed6-1ad2ef1862c0"
|
|
||||||
},
|
|
||||||
"hit1": {
|
|
||||||
"__uuid__": "e16fd77e-9bbb-4bd1-b149-e1dd5a409c8f"
|
|
||||||
},
|
|
||||||
"hit2": {
|
|
||||||
"__uuid__": "bab2f84c-f988-4355-8fc7-2c55a09cc089"
|
|
||||||
},
|
|
||||||
"hit3": {
|
|
||||||
"__uuid__": "e06aa433-8f1d-4787-8e6d-7fe6a29ca6f5"
|
|
||||||
},
|
|
||||||
"hit4": {
|
|
||||||
"__uuid__": "ed4cf450-ae51-46ce-997a-50dd75d9a519"
|
|
||||||
},
|
|
||||||
"hit5": {
|
|
||||||
"__uuid__": "b27d353c-e4fe-46de-b7c9-75d2b96363d3"
|
|
||||||
},
|
|
||||||
"_id": "24lN1LYRdNia3ZOiLsINIp"
|
"_id": "24lN1LYRdNia3ZOiLsINIp"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1418,6 +1418,7 @@ export default class Block extends cc.Component {
|
||||||
this.node.removeFromParent();
|
this.node.removeFromParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const deadCheckVersion = MapConroler._instance.nextDeadCheckVersion();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (MapConroler._instance) {
|
if (MapConroler._instance) {
|
||||||
if (MapConroler._instance.blockNum != 0 && (MapConroler._instance.openWall.length > 0 ||
|
if (MapConroler._instance.blockNum != 0 && (MapConroler._instance.openWall.length > 0 ||
|
||||||
|
|
@ -1426,10 +1427,7 @@ export default class Block extends cc.Component {
|
||||||
|| MapConroler._instance.change_colorBlock == true || MapConroler._instance.jump_state != null || MapConroler._instance.buttonWall.length > 0)
|
|| MapConroler._instance.change_colorBlock == true || MapConroler._instance.jump_state != null || MapConroler._instance.buttonWall.length > 0)
|
||||||
&& !MapConroler._instance.gameOver && !MapConroler._instance.gameWin) {
|
&& !MapConroler._instance.gameOver && !MapConroler._instance.gameWin) {
|
||||||
|
|
||||||
let gameover = MapConroler._instance.predict_End(true);
|
MapConroler._instance.requestPredictEndCheck(deadCheckVersion);
|
||||||
if (gameover == false) {
|
|
||||||
MapConroler._instance.failReason();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 1200);
|
}, 1200);
|
||||||
|
|
@ -2058,6 +2056,7 @@ export default class Block extends cc.Component {
|
||||||
this.node.removeFromParent();
|
this.node.removeFromParent();
|
||||||
}
|
}
|
||||||
MapConroler._instance.checkColor(colorTemp, true, this.node);
|
MapConroler._instance.checkColor(colorTemp, true, this.node);
|
||||||
|
const deadCheckVersion = MapConroler._instance.nextDeadCheckVersion();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (MapConroler._instance) {
|
if (MapConroler._instance) {
|
||||||
if (MapConroler._instance.blockNum != 0 && (MapConroler._instance.openWall.length > 0 ||
|
if (MapConroler._instance.blockNum != 0 && (MapConroler._instance.openWall.length > 0 ||
|
||||||
|
|
@ -2065,10 +2064,7 @@ export default class Block extends cc.Component {
|
||||||
MapConroler._instance.blockLock == true
|
MapConroler._instance.blockLock == true
|
||||||
|| MapConroler._instance.change_colorBlock == true || MapConroler._instance.jump_state != null || MapConroler._instance.buttonWall.length > 0)
|
|| MapConroler._instance.change_colorBlock == true || MapConroler._instance.jump_state != null || MapConroler._instance.buttonWall.length > 0)
|
||||||
&& !MapConroler._instance.gameOver && !MapConroler._instance.gameWin) {
|
&& !MapConroler._instance.gameOver && !MapConroler._instance.gameWin) {
|
||||||
let gameover = MapConroler._instance.predict_End(true);
|
MapConroler._instance.requestPredictEndCheck(deadCheckVersion);
|
||||||
if (gameover == false) {
|
|
||||||
MapConroler._instance.failReason();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 900);
|
}, 900);
|
||||||
|
|
@ -2270,6 +2266,7 @@ export default class Block extends cc.Component {
|
||||||
}
|
}
|
||||||
MapConroler._instance.checkColor(colorTemp, true, this.node);
|
MapConroler._instance.checkColor(colorTemp, true, this.node);
|
||||||
|
|
||||||
|
const deadCheckVersion = MapConroler._instance.nextDeadCheckVersion();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (MapConroler._instance) {
|
if (MapConroler._instance) {
|
||||||
if (MapConroler._instance.blockNum != 0 && (MapConroler._instance.openWall.length > 0 ||
|
if (MapConroler._instance.blockNum != 0 && (MapConroler._instance.openWall.length > 0 ||
|
||||||
|
|
@ -2277,10 +2274,7 @@ export default class Block extends cc.Component {
|
||||||
MapConroler._instance.blockLock == true
|
MapConroler._instance.blockLock == true
|
||||||
|| MapConroler._instance.change_colorBlock == true || MapConroler._instance.jump_state != null || MapConroler._instance.buttonWall.length > 0)
|
|| MapConroler._instance.change_colorBlock == true || MapConroler._instance.jump_state != null || MapConroler._instance.buttonWall.length > 0)
|
||||||
&& !MapConroler._instance.gameOver && !MapConroler._instance.gameWin) {
|
&& !MapConroler._instance.gameOver && !MapConroler._instance.gameWin) {
|
||||||
let gameover = MapConroler._instance.predict_End(true);
|
MapConroler._instance.requestPredictEndCheck(deadCheckVersion);
|
||||||
if (gameover == false) {
|
|
||||||
MapConroler._instance.failReason();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 1200);
|
}, 1200);
|
||||||
|
|
|
||||||
|
|
@ -158,12 +158,14 @@ export default class GameManager extends cc.Component {
|
||||||
|
|
||||||
}
|
}
|
||||||
onHide() {
|
onHide() {
|
||||||
cc.audioEngine.stopMusic();
|
// 只暂停游戏逻辑,不要 stopMusic —— 微信小游戏 InnerAudioContext 的 resumeMusic 经常失效
|
||||||
|
// 用 pauseAll,回前台时用 resumeAll 续播,保证退回 HomeScene 时音乐不被中断/丢失
|
||||||
|
cc.audioEngine.pauseAll();
|
||||||
cc.game.pause();
|
cc.game.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
cc.audioEngine.resumeMusic();
|
cc.audioEngine.resumeAll();
|
||||||
cc.game.resume();
|
cc.game.resume();
|
||||||
}
|
}
|
||||||
//#region 给加载好的墙壁资源排序
|
//#region 给加载好的墙壁资源排序
|
||||||
|
|
@ -204,18 +206,19 @@ export default class GameManager extends cc.Component {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('加载 shop 失败:', err);
|
console.error('加载 shop 失败:', err);
|
||||||
} else {
|
} else {
|
||||||
// 加载成功后进入 HomeScene
|
|
||||||
cc.assetManager.loadBundle('music', (err, bundle) => {
|
|
||||||
if (err) {
|
|
||||||
console.error('加载 music bundle 失败:', err);
|
|
||||||
// 加载失败时仍尝试进入 HomeScene
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
cc.director.loadScene("HomeScene");
|
cc.director.loadScene("HomeScene");
|
||||||
}, 300);
|
// 加载成功后进入 HomeScene
|
||||||
|
// cc.assetManager.loadBundle('music', (err, bundle) => {
|
||||||
|
// if (err) {
|
||||||
|
// console.error('加载 music bundle 失败:', err);
|
||||||
|
// // 加载失败时仍尝试进入 HomeScene
|
||||||
|
// } else {
|
||||||
|
// }
|
||||||
|
// setTimeout(() => {
|
||||||
|
|
||||||
});
|
// }, 300);
|
||||||
|
|
||||||
|
// });
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ export default class JiaZai extends cc.Component {
|
||||||
if (cc.fx.GameConfig.GM_INFO.openid) {
|
if (cc.fx.GameConfig.GM_INFO.openid) {
|
||||||
if (cc.fx.GameConfig.GM_INFO.openid == "orm8I7N10NSQdAhN4LP04n8UP56I") {
|
if (cc.fx.GameConfig.GM_INFO.openid == "orm8I7N10NSQdAhN4LP04n8UP56I") {
|
||||||
this.node.getChildByName("Load").getChildByName("New EditBox").active = true;
|
this.node.getChildByName("Load").getChildByName("New EditBox").active = true;
|
||||||
cc.fx.GameTool.changeCoin(9999);
|
// cc.fx.GameTool.changeCoin(9999);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -411,7 +411,7 @@ export default class JiaZai extends cc.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
//console.log("音乐开关", cc.fx.GameConfig.GM_INFO.musicOpen);
|
//console.log("音乐开关", cc.fx.GameConfig.GM_INFO.musicOpen);
|
||||||
AudioManager._instance.playMusicGame();
|
// AudioManager._instance.playMusicGame();
|
||||||
// 从房间出来判断是否弹出通行证
|
// 从房间出来判断是否弹出通行证
|
||||||
this.popUpPassCheck();
|
this.popUpPassCheck();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,8 @@ export default class MapConroler extends cc.Component {
|
||||||
new_mode: number = 0;
|
new_mode: number = 0;
|
||||||
new_item: number = 0;
|
new_item: number = 0;
|
||||||
autoNextAfterNewMode: boolean = false;
|
autoNextAfterNewMode: boolean = false;
|
||||||
|
deadCheckVersion: number = 0;
|
||||||
|
deadCheckConfirmDelay: number = 450;
|
||||||
mapWidth: number = 0;
|
mapWidth: number = 0;
|
||||||
mapHeight: number = 0;
|
mapHeight: number = 0;
|
||||||
wallNum: number = 0;
|
wallNum: number = 0;
|
||||||
|
|
@ -5899,6 +5901,45 @@ export default class MapConroler extends cc.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
//提前判断游戏结束
|
//提前判断游戏结束
|
||||||
|
nextDeadCheckVersion() {
|
||||||
|
this.deadCheckVersion += 1;
|
||||||
|
return this.deadCheckVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
canRunPredictEndCheck() {
|
||||||
|
return this.blockNum != 0 && (this.openWall.length > 0 ||
|
||||||
|
this.revolving_state != 0 || this.longAndShortWall.length > 0 ||
|
||||||
|
this.blockLock == true || this.change_colorBlock == true ||
|
||||||
|
this.jump_state != null || this.buttonWall.length > 0)
|
||||||
|
&& !this.gameOver && !this.gameWin;
|
||||||
|
}
|
||||||
|
|
||||||
|
requestPredictEndCheck(version: number) {
|
||||||
|
if (version != this.deadCheckVersion || !this.canRunPredictEndCheck()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let gameover = this.predict_End(true);
|
||||||
|
if (gameover != false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.openWall.length > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (version != this.deadCheckVersion || !this.canRunPredictEndCheck()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let confirmGameover = this.predict_End(true);
|
||||||
|
if (confirmGameover == false) {
|
||||||
|
this.failReason();
|
||||||
|
}
|
||||||
|
}, this.deadCheckConfirmDelay);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.failReason();
|
||||||
|
}
|
||||||
|
|
||||||
predict_End(type) {
|
predict_End(type) {
|
||||||
//return true;
|
//return true;
|
||||||
// console.log("提前判断游戏结束");
|
// console.log("提前判断游戏结束");
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ export class GameConfig {
|
||||||
vibrateOpen: true, //震动
|
vibrateOpen: true, //震动
|
||||||
coinnum: 0, //每局的金币数
|
coinnum: 0, //每局的金币数
|
||||||
paid_user: false, //是否是付费用户
|
paid_user: false, //是否是付费用户
|
||||||
version: "1.9.94", //版本号
|
version: "1.9.95", //版本号
|
||||||
shushu_DistinctId: "", //数数访客ID
|
shushu_DistinctId: "", //数数访客ID
|
||||||
shushu_AccountId: "", //数数账号ID
|
shushu_AccountId: "", //数数账号ID
|
||||||
uid: "", //用户和后端唯一id
|
uid: "", //用户和后端唯一id
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,41 @@ const { ccclass, property } = cc._decorator;
|
||||||
@ccclass
|
@ccclass
|
||||||
export default class AudioManager extends cc.Component {
|
export default class AudioManager extends cc.Component {
|
||||||
static _instance: any;
|
static _instance: any;
|
||||||
//背景音乐
|
// 远程音频 CDN 基础地址
|
||||||
@property(cc.AudioClip)
|
// public CDN_AUDIO_BASE: string = "https://pay.nika4games.com/remote/music/";
|
||||||
audioGameBgm0: cc.AudioClip = null;
|
|
||||||
|
|
||||||
|
public CDN_AUDIO_BASE: string = "https://cdn.pay.nika4games.com/remote/music/";
|
||||||
|
|
||||||
|
// 本地缓存的 AudioClip(按需懒加载)
|
||||||
|
private audioCache: { [key: string]: cc.AudioClip } = {};
|
||||||
|
// 远程 URL 映射表
|
||||||
|
private audioUrlMap: { [key: string]: string } = {};
|
||||||
|
// 本地持久化缓存目录(微信小游戏)
|
||||||
|
private localCacheDir: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取本地缓存目录
|
||||||
|
* 微信小游戏使用 USER_DATA_PATH 下的 audio_cache 子目录
|
||||||
|
*/
|
||||||
|
getLocalCacheDir(): string {
|
||||||
|
if (this.localCacheDir) return this.localCacheDir;
|
||||||
|
// @ts-ignore
|
||||||
|
if (typeof wx !== 'undefined' && wx.env && wx.env.USER_DATA_PATH) {
|
||||||
|
// @ts-ignore
|
||||||
|
this.localCacheDir = wx.env.USER_DATA_PATH + '/audio_cache/';
|
||||||
|
}
|
||||||
|
return this.localCacheDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取本地缓存文件路径
|
||||||
|
*/
|
||||||
|
getLocalCachePath(name: string): string {
|
||||||
|
return this.getLocalCacheDir() + name + '.mp3';
|
||||||
|
}
|
||||||
|
// 背景音乐
|
||||||
|
@property(cc.AudioClip)
|
||||||
|
main_bgm: cc.AudioClip = null;
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
xiaochu: cc.AudioClip = null;
|
xiaochu: cc.AudioClip = null;
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
|
|
@ -15,14 +46,8 @@ export default class AudioManager extends cc.Component {
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
down: cc.AudioClip = null;
|
down: cc.AudioClip = null;
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
fangxiang: cc.AudioClip = null;
|
|
||||||
@property(cc.AudioClip)
|
|
||||||
build: cc.AudioClip = null;
|
|
||||||
@property(cc.AudioClip)
|
|
||||||
win: cc.AudioClip = null;
|
win: cc.AudioClip = null;
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
lose: cc.AudioClip = null;
|
|
||||||
@property(cc.AudioClip)
|
|
||||||
anniu_Big: cc.AudioClip = null;
|
anniu_Big: cc.AudioClip = null;
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
anniu_little: cc.AudioClip = null;
|
anniu_little: cc.AudioClip = null;
|
||||||
|
|
@ -32,8 +57,6 @@ export default class AudioManager extends cc.Component {
|
||||||
zhuan1: cc.AudioClip = null;
|
zhuan1: cc.AudioClip = null;
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
zhuan2: cc.AudioClip = null;
|
zhuan2: cc.AudioClip = null;
|
||||||
|
|
||||||
|
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
adhesive: cc.AudioClip = null;
|
adhesive: cc.AudioClip = null;
|
||||||
@property(cc.AudioClip)
|
@property(cc.AudioClip)
|
||||||
|
|
@ -112,6 +135,257 @@ export default class AudioManager extends cc.Component {
|
||||||
|
|
||||||
this.mMusicSwitch = 1;
|
this.mMusicSwitch = 1;
|
||||||
this.mEffectSwitch = 1;
|
this.mEffectSwitch = 1;
|
||||||
|
|
||||||
|
// 初始化远程音频 URL 映射
|
||||||
|
this.initAudioUrlMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化远程音频 URL 映射表
|
||||||
|
* 将所有音频文件路径映射到 CDN 完整 URL
|
||||||
|
*/
|
||||||
|
initAudioUrlMap() {
|
||||||
|
const base = this.CDN_AUDIO_BASE;
|
||||||
|
// 音效列表
|
||||||
|
const names = [
|
||||||
|
'main_bgm', 'xiaochu', 'hit', 'down', 'win',
|
||||||
|
'anniu_Big', 'anniu_little', 'tanchuang', 'zhuan1', 'zhuan2',
|
||||||
|
'adhesive', 'freezeBlock', 'freezeDoor', 'hammer',
|
||||||
|
'lockBlock1', 'lockBlock2', 'lockDoor',
|
||||||
|
'magic1', 'magic2', 'simpleColor', 'stacking',
|
||||||
|
'starBlock', 'timePause1', 'timePause2',
|
||||||
|
'hit1', 'hit2', 'hit3', 'hit4', 'hit5'
|
||||||
|
];
|
||||||
|
names.forEach((name) => {
|
||||||
|
this.audioUrlMap[name] = base + name + '.mp3';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据名称获取远程音频 URL
|
||||||
|
*/
|
||||||
|
getRemoteUrl(name: string): string {
|
||||||
|
if (name == null || name == "null") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return this.audioUrlMap[name] || (this.CDN_AUDIO_BASE + name + '.mp3');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载远程音频
|
||||||
|
* 优先从缓存获取,没有则从 CDN 下载
|
||||||
|
*/
|
||||||
|
loadRemoteAudio(name: string, callback?: (clip: cc.AudioClip) => void) {
|
||||||
|
// 1. 已有缓存直接返回
|
||||||
|
if (this.audioCache[name]) {
|
||||||
|
callback && callback(this.audioCache[name]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 本地有 @property 注入的 AudioClip,优先使用
|
||||||
|
if (this[name] instanceof cc.AudioClip) {
|
||||||
|
this.audioCache[name] = this[name];
|
||||||
|
callback && callback(this[name]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 从远程 CDN 加载
|
||||||
|
const url = this.getRemoteUrl(name);
|
||||||
|
// console.log('远程加载音频:', name, url);
|
||||||
|
if (url == null || url == "") {
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 微信小游戏:先查本地缓存,没有再下载
|
||||||
|
if (cc.sys.platform === cc.sys.WECHAT_GAME) {
|
||||||
|
// @ts-ignore
|
||||||
|
if (typeof wx !== 'undefined' && wx.downloadFile) {
|
||||||
|
this.loadRemoteAudioWithCache(name, url, callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 其他平台直接 loadRemote
|
||||||
|
cc.assetManager.loadRemote(url, (err, audioClip: cc.AudioClip) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('远程音频加载失败:', name, err);
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.audioCache[name] = audioClip;
|
||||||
|
callback && callback(audioClip);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小游戏:优先从本地缓存加载音频,没有则下载并保存到本地
|
||||||
|
* 缓存路径: wx.env.USER_DATA_PATH/audio_cache/<name>.mp3
|
||||||
|
* 微信本地缓存总上限 50MB,超出 saveFile 会失败但不影响本次播放
|
||||||
|
*/
|
||||||
|
loadRemoteAudioWithCache(name: string, url: string, callback?: (clip: cc.AudioClip) => void) {
|
||||||
|
const localPath = this.getLocalCachePath(name);
|
||||||
|
if (!localPath) {
|
||||||
|
// 拿不到本地路径,回退到直接下载
|
||||||
|
this.downloadAndCacheAudio(name, url, '', callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
const fs = wx.getFileSystemManager();
|
||||||
|
|
||||||
|
// 确保缓存目录存在(递归创建)
|
||||||
|
try {
|
||||||
|
fs.mkdirSync(this.getLocalCacheDir(), true);
|
||||||
|
} catch (e) {
|
||||||
|
// 目录已存在或其他错误,忽略
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 检查本地缓存文件是否存在
|
||||||
|
fs.access({
|
||||||
|
path: localPath,
|
||||||
|
success: () => {
|
||||||
|
// 本地缓存命中,直接从本地路径加载
|
||||||
|
// console.log('____________音频本地缓存命中:', name, localPath);
|
||||||
|
cc.assetManager.loadRemote(localPath, (err, audioClip: cc.AudioClip) => {
|
||||||
|
if (err) {
|
||||||
|
//console.log('____________本地缓存加载失败,重新下载:', name, err);
|
||||||
|
// 加载失败,删除坏文件并重新下载
|
||||||
|
try { fs.unlinkSync(localPath); } catch (e) { }
|
||||||
|
this.downloadAndCacheAudio(name, url, localPath, callback);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.audioCache[name] = audioClip;
|
||||||
|
//console.log('____________本地缓存加载成功:', name, this.audioCache);
|
||||||
|
callback && callback(audioClip);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
// 本地缓存未命中,从 CDN 下载
|
||||||
|
//console.log('____________本地缓存未命中,下载音频:', name, url);
|
||||||
|
this.downloadAndCacheAudio(name, url, localPath, callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 下载音频,保存到本地后再从本地路径加载(避免 loadRemote 与 saveFile 竞争)
|
||||||
|
* 关键:wx.saveFile 是移动 temp 文件,而 cc.assetManager.loadRemote 是异步读,
|
||||||
|
* 如果先 loadRemote(tempPath) 再 saveFile,引擎真正读 temp 时文件已被移走 → 500。
|
||||||
|
* 正确顺序:saveFile 落盘 → loadRemote(本地路径)
|
||||||
|
* @param localPath 本地保存路径,为空时只下载不缓存
|
||||||
|
*/
|
||||||
|
downloadAndCacheAudio(name: string, url: string, localPath: string, callback?: (clip: cc.AudioClip) => void) {
|
||||||
|
// @ts-ignore
|
||||||
|
const fs = wx.getFileSystemManager();
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
wx.downloadFile({
|
||||||
|
url: url,
|
||||||
|
success: (res: any) => {
|
||||||
|
if (res.statusCode !== 200) {
|
||||||
|
//console.error('____________下载音频失败:', name, res.statusCode);
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tempFilePath = res.tempFilePath;
|
||||||
|
|
||||||
|
if (!localPath) {
|
||||||
|
// 不需要缓存,直接从 temp 加载
|
||||||
|
cc.assetManager.loadRemote(tempFilePath, (err, audioClip: cc.AudioClip) => {
|
||||||
|
if (err) {
|
||||||
|
//console.error('____________远程音频加载失败:', name, err);
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.audioCache[name] = audioClip;
|
||||||
|
callback && callback(audioClip);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 先 saveFile 落盘到本地缓存,再从稳定的本地路径 loadRemote
|
||||||
|
fs.saveFile({
|
||||||
|
tempFilePath: tempFilePath,
|
||||||
|
filePath: localPath,
|
||||||
|
success: (saveRes: any) => {
|
||||||
|
const savedPath = saveRes.savedFilePath || localPath;
|
||||||
|
//console.log('____________音频已缓存到本地:', name, savedPath);
|
||||||
|
cc.assetManager.loadRemote(savedPath, (err, audioClip: cc.AudioClip) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('____________本地缓存加载失败:', name, err);
|
||||||
|
try { fs.unlinkSync(savedPath); } catch (e) { }
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//console.log('____________远程音频加载成功:', name);
|
||||||
|
this.audioCache[name] = audioClip;
|
||||||
|
callback && callback(audioClip);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (saveErr: any) => {
|
||||||
|
// saveFile 失败(50MB 超出 / temp 已被清理等),回退到 temp 直接加载
|
||||||
|
//console.log('____________saveFile 失败,回退到 temp 直接加载:', name, saveErr);
|
||||||
|
cc.assetManager.loadRemote(tempFilePath, (err, audioClip: cc.AudioClip) => {
|
||||||
|
if (err) {
|
||||||
|
//console.error('____________远程音频加载失败:', name, err);
|
||||||
|
callback && callback(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.audioCache[name] = audioClip;
|
||||||
|
callback && callback(audioClip);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: (err: any) => {
|
||||||
|
//console.error('____________downloadFile 失败:', name, err);
|
||||||
|
callback && callback(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有音频本地缓存(调试/换包用)
|
||||||
|
*/
|
||||||
|
clearLocalAudioCache(onComplete?: () => void) {
|
||||||
|
if (!(cc.sys.platform === cc.sys.WECHAT_GAME)) {
|
||||||
|
onComplete && onComplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
const fs = wx.getFileSystemManager();
|
||||||
|
const dir = this.getLocalCacheDir();
|
||||||
|
if (!dir) {
|
||||||
|
onComplete && onComplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs.readdir({
|
||||||
|
dirPath: dir,
|
||||||
|
success: (res: any) => {
|
||||||
|
const files: string[] = res.files || [];
|
||||||
|
let removed = 0;
|
||||||
|
if (files.length === 0) {
|
||||||
|
onComplete && onComplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
files.forEach((file) => {
|
||||||
|
const filePath = dir + file;
|
||||||
|
fs.unlink({
|
||||||
|
filePath: filePath,
|
||||||
|
success: () => {
|
||||||
|
removed++;
|
||||||
|
if (removed === files.length) onComplete && onComplete();
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
removed++;
|
||||||
|
if (removed === files.length) onComplete && onComplete();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
onComplete && onComplete();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
play(audioSource, loop, callback, isBgMusic) {
|
play(audioSource, loop, callback, isBgMusic) {
|
||||||
// if (isBgMusic && !this.mMusicSwitch) return;
|
// if (isBgMusic && !this.mMusicSwitch) return;
|
||||||
|
|
@ -165,13 +439,65 @@ export default class AudioManager extends cc.Component {
|
||||||
preload() {
|
preload() {
|
||||||
if (!(cc.sys.platform === cc.sys.WECHAT_GAME || cc.sys.platform === cc.sys.BYTEDANCE_GAME)) { return; }
|
if (!(cc.sys.platform === cc.sys.WECHAT_GAME || cc.sys.platform === cc.sys.BYTEDANCE_GAME)) { return; }
|
||||||
|
|
||||||
var musics = [
|
// 预加载所有音频
|
||||||
this.audioGameBgm0,
|
const allSounds = Object.keys(this.audioUrlMap);
|
||||||
];
|
console.log('AudioManager 开始预加载所有音频,共', allSounds.length, '个');
|
||||||
musics.forEach(function (path) {
|
this.preloadAudios(
|
||||||
})
|
allSounds,
|
||||||
// console.log("音乐开关", cc.fx.GameConfig.GM_INFO.musicOpen);
|
(loaded, total) => {
|
||||||
// this.playMusicGame();
|
// console.log('音频预加载进度:', loaded, '/', total);
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
console.log('所有音频预加载完成');
|
||||||
|
},
|
||||||
|
// 单条加载完成回调:main_bgm 特殊处理
|
||||||
|
(name, clip) => {
|
||||||
|
if (name === 'main_bgm' && clip) {
|
||||||
|
// main_bgm 加载完成后,如果音乐开关是打开的,自动播放
|
||||||
|
if (cc.fx.GameConfig.GM_INFO && cc.fx.GameConfig.GM_INFO.musicOpen) {
|
||||||
|
console.log('main_bgm 加载完成,音乐开关已开启,自动播放');
|
||||||
|
this.playMusic('main_bgm', null, true);
|
||||||
|
} else {
|
||||||
|
console.log('main_bgm 加载完成,但音乐开关未开启');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预加载指定的音频列表
|
||||||
|
* @param names 音频名称数组
|
||||||
|
* @param onProgress 进度回调 (loaded, total)
|
||||||
|
* @param onComplete 完成回调
|
||||||
|
*/
|
||||||
|
preloadAudios(
|
||||||
|
names: string[],
|
||||||
|
onProgress?: (loaded: number, total: number) => void,
|
||||||
|
onComplete?: () => void,
|
||||||
|
onItemLoaded?: (name: string, clip: cc.AudioClip) => void
|
||||||
|
) {
|
||||||
|
if (!names || names.length === 0) {
|
||||||
|
onComplete && onComplete();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let loaded = 0;
|
||||||
|
const total = names.length;
|
||||||
|
const onOneLoaded = (name: string, clip: cc.AudioClip) => {
|
||||||
|
loaded++;
|
||||||
|
onItemLoaded && onItemLoaded(name, clip);
|
||||||
|
onProgress && onProgress(loaded, total);
|
||||||
|
if (loaded === total) onComplete && onComplete();
|
||||||
|
};
|
||||||
|
names.forEach((name) => {
|
||||||
|
if (this[name] instanceof cc.AudioClip || this.audioCache[name]) {
|
||||||
|
onOneLoaded(name, this[name] || this.audioCache[name]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.loadRemoteAudio(name, (clip) => {
|
||||||
|
onOneLoaded(name, clip);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getAudioMusicSwitch() {
|
getAudioMusicSwitch() {
|
||||||
|
|
@ -217,30 +543,96 @@ export default class AudioManager extends cc.Component {
|
||||||
if (!cc.fx.GameConfig.GM_INFO.effectOpen) {
|
if (!cc.fx.GameConfig.GM_INFO.effectOpen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this[name])
|
// 1. 本地有 AudioClip 直接播放
|
||||||
|
if (this[name] instanceof cc.AudioClip) {
|
||||||
|
// console.log('____________本地有音频成功:', name);
|
||||||
return this.play(this[name], false, callback, this.mEffectSwitch);
|
return this.play(this[name], false, callback, this.mEffectSwitch);
|
||||||
}
|
}
|
||||||
|
// 2. 缓存中有已加载的 AudioClip
|
||||||
|
if (this.audioCache[name]) {
|
||||||
|
// console.log('____________缓存音频加载成功:', name, this.audioCache);
|
||||||
|
return this.play(this.audioCache[name], false, callback, this.mEffectSwitch);
|
||||||
|
}
|
||||||
|
// console.log('____________最终走远程加载:', name);
|
||||||
|
// 3. 远程加载
|
||||||
|
this.loadRemoteAudio(name, (clip) => {
|
||||||
|
if (clip) {
|
||||||
|
// console.log('____________远程音频加载成功:', name);
|
||||||
|
this.play(clip, false, callback, this.mEffectSwitch);
|
||||||
|
} else {
|
||||||
|
console.log('音效播放失败:', name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
playMusic(key, callback, loop) {
|
playMusic(key, callback, loop) {
|
||||||
// console.log("音频开关________________________________________");
|
console.log("音频开关________________________________________", cc.fx.GameConfig.GM_INFO.musicOpen);
|
||||||
if (!cc.fx.GameConfig.GM_INFO.musicOpen) {
|
if (!cc.fx.GameConfig.GM_INFO.musicOpen) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
loop = typeof loop == 'undefined' || loop ? true : false;
|
loop = typeof loop == 'undefined' || loop ? true : false;
|
||||||
this.stopMusic();
|
|
||||||
this.mMusicKey = this.play(key, loop, callback, true);
|
|
||||||
|
|
||||||
|
// 如果请求播放的就是当前已在播放的音乐,跳过 stop+restart,避免打断
|
||||||
|
const targetName = (key instanceof cc.AudioClip) ? key.name : key;
|
||||||
|
if (this.mMusicKey != null && this.mMusicKey === targetName
|
||||||
|
&& cc.audioEngine.isMusicPlaying && cc.audioEngine.isMusicPlaying()) {
|
||||||
|
console.log("当前已在播放的音乐,跳过 stop+restart,避免打断");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this.stopMusic();
|
||||||
|
|
||||||
|
// key 可能是 AudioClip 实例,也可能是字符串名称
|
||||||
|
if (key instanceof cc.AudioClip) {
|
||||||
|
this.mMusicKey = this.play(key, loop, callback, true);
|
||||||
|
console.log("开始播放音乐", key.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字符串名称:尝试从缓存或远程加载
|
||||||
|
const name = key;
|
||||||
|
console.log("开始播放音乐的名称", name);
|
||||||
|
const playFromCache = () => {
|
||||||
|
console.log("从缓存播放音乐", name);
|
||||||
|
if (this.audioCache[name]) {
|
||||||
|
this.mMusicKey = this.play(this.audioCache[name], loop, callback, true);
|
||||||
|
} else {
|
||||||
|
console.log('背景音乐播放失败:', name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (this.audioCache[name]) {
|
||||||
|
console.log("从缓存播放音乐", name);
|
||||||
|
playFromCache();
|
||||||
|
} else {
|
||||||
|
this.loadRemoteAudio(name, (clip) => {
|
||||||
|
console.log("从远程加载音乐", name, clip);
|
||||||
|
if (clip) {
|
||||||
|
this.mMusicKey = this.play(clip, loop, callback, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 游戏背景音乐
|
* 游戏背景音乐
|
||||||
|
* 仅当音乐开关开启、且当前没有在播放 main_bgm 时才真正播放
|
||||||
|
* 避免从 GameScene 退回 HomeScene 时被打断重启
|
||||||
*/
|
*/
|
||||||
playMusicGame() {
|
playMusicGame() {
|
||||||
this.stopMusic();
|
|
||||||
this.playMusic(this.audioGameBgm0, {}, true);
|
if (!cc.fx.GameConfig.GM_INFO.musicOpen) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 已经在播背景音乐(musicId 不为 -1)就不再打断
|
||||||
|
if (this.mMusicKey != null && this.mMusicKey !== undefined && cc.audioEngine.isMusicPlaying && cc.audioEngine.isMusicPlaying()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("开始播放音乐");
|
||||||
|
this.playMusic('main_bgm', null, true);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 停止背景音乐播放
|
* 停止背景音乐播放
|
||||||
*/
|
*/
|
||||||
stopMusic() {
|
stopMusic() {
|
||||||
|
console.log("无论什么原因——————————————暂停了背景音乐播放", this.mMusicKey);
|
||||||
// cc.wwx.OutPut.log('stopMusic audio effect wx: ' + this.mMusicKey);
|
// cc.wwx.OutPut.log('stopMusic audio effect wx: ' + this.mMusicKey);
|
||||||
cc.audioEngine.stopAll();
|
cc.audioEngine.stopAll();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,11 +21,11 @@
|
||||||
"trimThreshold": 1,
|
"trimThreshold": 1,
|
||||||
"rotated": false,
|
"rotated": false,
|
||||||
"offsetX": 0,
|
"offsetX": 0,
|
||||||
"offsetY": 0,
|
"offsetY": 0.5,
|
||||||
"trimX": 0,
|
"trimX": 0,
|
||||||
"trimY": 0,
|
"trimY": 0,
|
||||||
"width": 175,
|
"width": 175,
|
||||||
"height": 190,
|
"height": 189,
|
||||||
"rawWidth": 175,
|
"rawWidth": 175,
|
||||||
"rawHeight": 190,
|
"rawHeight": 190,
|
||||||
"borderTop": 0,
|
"borderTop": 0,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"ver": "1.1.3",
|
"ver": "1.1.3",
|
||||||
"uuid": "6ebfe2d9-539a-4853-8b16-fca5c89cf2ce",
|
"uuid": "6ebfe2d9-539a-4853-8b16-fca5c89cf2ce",
|
||||||
"importer": "folder",
|
"importer": "folder",
|
||||||
"isBundle": true,
|
"isBundle": false,
|
||||||
"bundleName": "music",
|
"bundleName": "music",
|
||||||
"priority": 9,
|
"priority": 9,
|
||||||
"compressionType": {
|
"compressionType": {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"appid": "wxdd145ced49158a1e",
|
"appid": "wxdd145ced49158a1e",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"separate_engine": true,
|
"separate_engine": true,
|
||||||
"REMOTE_SERVER_ROOT": "",
|
"REMOTE_SERVER_ROOT": "https://cdn.pay.nika4games.com/",
|
||||||
"subContext": "SubContextView",
|
"subContext": "SubContextView",
|
||||||
"startSceneAssetBundle": true
|
"startSceneAssetBundle": true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user