From ead6e596f702a4a2175139d7f26551e154fa8446 Mon Sep 17 00:00:00 2001 From: ckcz123 Date: Sat, 24 Jul 2021 19:54:36 +0800 Subject: [PATCH] =?UTF-8?q?=E8=83=8C=E6=99=AF=E9=9F=B3=E4=B9=90=E7=9A=84?= =?UTF-8?q?=E9=80=9F=E5=BA=A6=E5=92=8C=E9=9F=B3=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _docs/api.md | 15 ++++++-- _server/CodeMirror/defs.js | 8 ++--- _server/MotaAction.g4 | 38 ++++++++++++++++---- _server/MotaActionParser.js | 8 +++-- _server/editor_blocklyconfig.js | 1 + libs/control.js | 61 ++++++++++++++++++++++++++------- libs/core.js | 2 ++ libs/events.js | 13 +++++-- runtime.d.ts | 9 +++-- 9 files changed, 122 insertions(+), 33 deletions(-) diff --git a/_docs/api.md b/_docs/api.md index a7c27925..becdd230 100644 --- a/_docs/api.md +++ b/_docs/api.md @@ -478,8 +478,12 @@ playBgm: fn(bgm: string, startTime?: number) bgm: 背景音乐的文件名,支持全塔属性中映射前的中文名 startTime: 跳过前多少秒,不填则不跳过 -playSound: fn(sound: string) +playSound: fn(sound: string, pitch?: number, callback?: fn()) -> number 播放一个音效 +sound: 音效名;可以使用文件别名。 +pitch: 播放的音调;可选,如果设置则为30-300之间的数值;100为正常音调。 +callback: 可选,播放完毕后执行的回调函数。 +返回:一个数字,可用于core.stopSound的参数来只停止该音效。 registerAnimationFrame: fn(name: string, needPlaying: bool, func?: fn(timestamp: number)) 注册一个 animationFrame @@ -550,6 +554,11 @@ destX: 鼠标或手指的起拖点横坐标 destY: 鼠标或手指的起拖点纵坐标 stepPostfix: 拖动轨迹的数组表示,每项为一步的方向和目标点。 +setBgmSpeed: fn(speed: number, usePitch?: bool) +设置背景音乐的播放速度和音调 +speed: 播放速度,必须为30-300中间的值。100为正常速度。 +usePitch: 是否同时改变音调(部分设备可能不支持) + setBuff: fn(name: string, value: number) 设置主角某个属性的百分比修正倍率,初始值为1, 倍率存放在flag: '__'+name+'_buff__' 中 @@ -640,8 +649,8 @@ stopAutomaticRoute: fn() stopReplay: fn(force?: bool) 停止播放 -stopSound: fn() -停止所有SE +stopSound: fn(id?: number) +停止播放音效。如果未指定id则停止所有音效,否则只停止指定的音效。 syncLoad: fn() 从服务器加载存档 diff --git a/_server/CodeMirror/defs.js b/_server/CodeMirror/defs.js index dd4ee119..c69b4130 100644 --- a/_server/CodeMirror/defs.js +++ b/_server/CodeMirror/defs.js @@ -2189,12 +2189,12 @@ var terndefs_f6783a0a_522d_417e_8407_94c67b692e50 = [ "!type": "fn(name: string, value: ?)" }, "playSound": { - "!doc": "播放一个音效", - "!type": "fn(sound: string)" + "!doc": "播放一个音效
sound: 音效名;可以使用文件别名。
pitch: 播放的音调;可选,如果设置则为30-300之间的数值。
callback: 可选,播放完毕后执行的回调函数。
返回:一个数字,可用于core.stopSound的参数来只停止该音效。", + "!type": "fn(sound: string, pitch?: number, callback?: fn()) -> number" }, "stopSound": { - "!doc": "停止所有SE", - "!type": "fn()" + "!doc": "停止播放音效。如果未指定id则停止所有音效,否则只停止指定的音效。", + "!type": "fn(id?: number)" }, "addGameCanvasTranslate": { "!doc": "加减画布偏移", diff --git a/_server/MotaAction.g4 b/_server/MotaAction.g4 index 3b4ee833..c9d4605f 100644 --- a/_server/MotaAction.g4 +++ b/_server/MotaAction.g4 @@ -823,6 +823,7 @@ action | playSound_1_s | stopSound_s | setVolume_s + | setBgmSpeed_s | win_s | lose_s | restart_s @@ -2462,32 +2463,42 @@ return code; */; playSound_s - : '播放音效' EvalString '停止之前音效' Bool? Newline + : '播放音效' EvalString '停止之前音效' Bool? '音调' IntString? '等待播放完毕' Bool? Newline /* playSound_s tooltip : playSound: 播放音效 helpUrl : /_docs/#/instruction -default : ["item.mp3",false] +default : ["item.mp3",false,"",false] colour : this.soundColor allSounds : ['EvalString_0'] material : ["./project/sounds/", "EvalString_0"] +if (IntString_0) { + if (parseInt(IntString_0) < 30 || parseInt(IntString_0) > 300) throw '音调设置只能在30-300之间;100为正常音调。'; + IntString_0 = ', "pitch": ' + IntString_0; +} else IntString_0 = ''; Bool_0 = Bool_0 ? ', "stop": true' : ''; -var code = '{"type": "playSound", "name": "'+EvalString_0+'"'+Bool_0+'},\n'; +Bool_1 = Bool_1 ? ', "sync": true' : ''; +var code = '{"type": "playSound", "name": "'+EvalString_0+'"'+Bool_0+IntString_0+Bool_1+'},\n'; return code; */; playSound_1_s - : '播放系统音效' NameMap_List '停止之前音效' Bool? Newline + : '播放系统音效' NameMap_List '停止之前音效' Bool? '音调' IntString? '等待播放完毕' Bool? Newline /* playSound_1_s tooltip : playSound: 播放系统音效 helpUrl : /_docs/#/instruction -default : ["确认",false] +default : ["确认",false,"",false] colour : this.soundColor +if (IntString_0) { + if (parseInt(IntString_0) < 30 || parseInt(IntString_0) > 300) throw '音调设置只能在30-300之间;100为正常音调。'; + IntString_0 = ', "pitch": ' + IntString_0; +} else IntString_0 = ''; Bool_0 = Bool_0 ? ', "stop": true' : ''; -var code = '{"type": "playSound", "name": "'+NameMap_List_0+'"'+Bool_0+'},\n'; +Bool_1 = Bool_1 ? ', "sync": true' : ''; +var code = '{"type": "playSound", "name": "'+NameMap_List_0+'"'+Bool_0+IntString_0+Bool_1+'},\n'; return code; */; @@ -2518,6 +2529,21 @@ var code = '{"type": "setVolume", "value": '+Int_0+IntString_0+async+'},\n'; return code; */; +setBgmSpeed_s + : '设置背景音乐播放速度' Int '同时改变音调' Bool Newline + + +/* setBgmSpeed_s +tooltip : setSpeed: 设置背景音乐播放速度 +helpUrl : /_docs/#/instruction +default : [100, true] +colour : this.soundColor +if (Int_0 < 30 || Int_0 > 300) throw '速度只能设置只能在30-300之间;100为正常速度。'; +Bool_0 = Bool_0?', "pitch": true':''; +var code = '{"type": "setBgmSpeed", "value": '+Int_0+Bool_0+'},\n'; +return code; +*/; + win_s : '游戏胜利,结局' ':' EvalString? '不计入榜单' Bool '不结束游戏' Bool Newline diff --git a/_server/MotaActionParser.js b/_server/MotaActionParser.js index 7ba294f9..3b673eaa 100644 --- a/_server/MotaActionParser.js +++ b/_server/MotaActionParser.js @@ -642,10 +642,10 @@ ActionParser.prototype.parseAction = function() { var knownItems = MotaActionBlocks['NameMap_List'].options.map(function (one) {return one[1];}); if (knownItems.indexOf(data.name) >= 0) { this.next = MotaActionBlocks['playSound_1_s'].xmlText([ - data.name,data.stop,this.next]); + data.name,data.stop,data.pitch||"",data.sync,this.next]); } else { this.next = MotaActionBlocks['playSound_s'].xmlText([ - data.name,data.stop,this.next]); + data.name,data.stop,data.pitch||"",data.sync,this.next]); } break; case "playBgm": @@ -676,6 +676,10 @@ ActionParser.prototype.parseAction = function() { this.next = MotaActionBlocks['setVolume_s'].xmlText([ data.value, data.time, data.async||false, this.next]); break + case "setBgmSpeed": + this.next = MotaActionBlocks['setBgmSpeed_s'].xmlText([ + data.value, data.pitch||false, this.next]); + break; case "setValue": this.next = MotaActionBlocks['setValue_s'].xmlText([ this.expandIdBlock([data.name]), data["operator"]||'=', diff --git a/_server/editor_blocklyconfig.js b/_server/editor_blocklyconfig.js index fea6aaa9..2e9ab074 100644 --- a/_server/editor_blocklyconfig.js +++ b/_server/editor_blocklyconfig.js @@ -213,6 +213,7 @@ editor_blocklyconfig=(function(){ MotaActionBlocks['playSound_1_s'].xmlText(), MotaActionBlocks['stopSound_s'].xmlText(), MotaActionBlocks['setVolume_s'].xmlText(), + MotaActionBlocks['setBgmSpeed_s'].xmlText(), MotaActionBlocks['callBook_s'].xmlText(), MotaActionBlocks['callSave_s'].xmlText(), MotaActionBlocks['autoSave_s'].xmlText(), diff --git a/libs/control.js b/libs/control.js index 343404cd..f064cd1b 100644 --- a/libs/control.js +++ b/libs/control.js @@ -2695,6 +2695,25 @@ control.prototype._playBgm_play = function (bgm, startTime) { core.material.bgms[bgm].play(); core.musicStatus.playingBgm = bgm; core.musicStatus.lastBgm = bgm; + core.setBgmSpeed(100); +} + +///// 设置当前背景音乐的播放速度 ////// +control.prototype.setBgmSpeed = function (speed, usePitch) { + var bgm = core.musicStatus.playingBgm; + if (main.mode!='play' || !core.material.bgms[bgm]) return; + bgm = core.material.bgms[bgm]; + if (speed < 30 || speed > 300) return; + bgm.playbackRate = speed / 100; + core.musicStatus.bgmSpeed = speed; + + if (bgm.preservesPitch != null) { + if (bgm.__preservesPitch == null) bgm.__preservesPitch = bgm.preservesPitch; + if (usePitch == null) bgm.preservesPitch = bgm.__preservesPitch; + else if (usePitch) bgm.preservesPitch = false; + else bgm.preservesPitch = true; + core.musicStatus.bgmUsePitch = usePitch; + } } ////// 暂停背景音乐的播放 ////// @@ -2718,8 +2737,13 @@ control.prototype.pauseBgm = function () { control.prototype.resumeBgm = function (resumeTime) { if (main.mode!='play')return; try { + var speed = core.musicStatus.bgmSpeed; + var usePitch = core.musicStatus.bgmUsePitch; core.playBgm(core.musicStatus.playingBgm || core.musicStatus.lastBgm || main.startBgm, resumeTime ? core.musicStatus.pauseTime : 0); + if (resumeTime) { + core.setBgmSpeed(speed, usePitch); + } } catch (e) { console.log("无法恢复BGM"); @@ -2748,7 +2772,7 @@ control.prototype.triggerBgm = function () { } ////// 播放音频 ////// -control.prototype.playSound = function (sound) { +control.prototype.playSound = function (sound, pitch, callback) { sound = core.getMappedName(sound); if (main.mode!='play' || !core.musicStatus.soundStatus || !core.material.sounds[sound]) return; try { @@ -2757,16 +2781,22 @@ control.prototype.playSound = function (sound) { source.buffer = core.material.sounds[sound]; source.connect(core.musicStatus.gainNode); var id = setTimeout(null); + if (pitch && pitch >= 30 && pitch <= 300) { + source.playbackRate.setValueAtTime(pitch / 100, 0); + } source.onended = function () { delete core.musicStatus.playingSounds[id]; + if (callback) callback(); } + core.musicStatus.playingSounds[id] = source; if (source.start) source.start(0); else if (source.noteOn) source.noteOn(0); - core.musicStatus.playingSounds[id] = source; + return id; } else { core.material.sounds[sound].volume = core.musicStatus.userVolume; core.material.sounds[sound].play(); + if (callback) callback(); } } catch (e) { @@ -2776,18 +2806,23 @@ control.prototype.playSound = function (sound) { } ////// 停止所有音频 ////// -control.prototype.stopSound = function () { - for (var i in core.musicStatus.playingSounds) { - var source = core.musicStatus.playingSounds[i]; - try { - if (source.stop) source.stop(); - else if (source.noteOff) source.noteOff(); - } - catch (e) { - main.log(e); - } +control.prototype.stopSound = function (id) { + if (id == null) { + Object.keys(core.musicStatus.playingSounds).forEach(function (id) { + core.control.stopSound(id); + }); + return; } - core.musicStatus.playingSounds = {}; + var source = core.musicStatus.playingSounds[id]; + if (!source) return; + try { + if (source.stop) source.stop(); + else if (source.noteOff) source.noteOff(); + } + catch (e) { + main.log(e); + } + delete core.musicStatus.playingSounds[id]; } ////// 检查bgm状态 ////// diff --git a/libs/core.js b/libs/core.js index 11ee0a3a..4b31fc3e 100644 --- a/libs/core.js +++ b/libs/core.js @@ -64,6 +64,8 @@ function core() { 'playingSounds': {}, // 正在播放的SE 'userVolume': 1.0, // 用户音量 'designVolume': 1.0, //设计音量 + 'bgmSpeed': 100, // 背景音乐速度 + 'bgmUsePitch': null, // 是否同时修改音调 'cachedBgms': [], // 缓存BGM内容 'cachedBgmCount': 8, // 缓存的bgm数量 } diff --git a/libs/events.js b/libs/events.js index 5eed254f..6e0c2966 100644 --- a/libs/events.js +++ b/libs/events.js @@ -1722,8 +1722,12 @@ events.prototype._action_freeBgm = function (data, x, y, prefix) { events.prototype._action_playSound = function (data, x, y, prefix) { if (data.stop) core.stopSound(); - core.playSound(data.name); - core.doAction(); + if (data.sync) { + core.playSound(data.name, data.pitch, core.doAction); + } else { + core.playSound(data.name, data.pitch); + core.doAction(); + } } events.prototype._action_stopSound = function (data, x, y, prefix) { @@ -1737,6 +1741,11 @@ events.prototype._action_setVolume = function (data, x, y, prefix) { this.__action_doAsyncFunc(data.async, core.setVolume, data.value, data.time || 0); } +events.prototype._action_setBgmSpeed = function (data, x, y, prefix) { + core.setBgmSpeed(data.value, data.pitch || false); + core.doAction(); +} + events.prototype._action_setValue = function (data, x, y, prefix) { this.setValue(data.name, data.operator, data.value, prefix); if (!data.norefresh) { diff --git a/runtime.d.ts b/runtime.d.ts index 2ea4c36e..8f393565 100644 --- a/runtime.d.ts +++ b/runtime.d.ts @@ -774,6 +774,9 @@ declare class control { /** 恢复背景音乐的播放 */ resumeBgm(resumeTime?: number): void + /** 设置背景音乐的播放速度和音调 */ + setBgmSpeed(speed: number, usePitch?: bool): void + /** 设置音乐图标的显隐状态 */ setMusicBtn(): void @@ -781,10 +784,10 @@ declare class control { triggerBgm(): void /** 播放一个音效 */ - playSound(sound: string): void + playSound(sound: string, pitch?: number, callback?: () => any): number - /** 停止所有音频 */ - stopSound(): void + /** 停止(所有)音频 */ + stopSound(id?: number): void /** 检查bgm状态 */ checkBgm(): void