From e82a6165322e858cbc7a9be69b43a11b0b745dc0 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 8 Oct 2024 20:14:07 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=BF=BD=E9=80=90=E6=88=98=E5=88=9D?= =?UTF-8?q?=E6=AD=A5=E9=87=8D=E7=BD=AE=E5=AE=8C=E6=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/libs/control.js | 4 ++ public/project/floors/MT16.js | 14 +++--- public/project/functions.js | 24 +++-------- src/core/audio/bgm.ts | 22 ++++++++++ src/core/render/camera.ts | 18 +++++++- src/core/render/preset/viewport.ts | 3 +- src/plugin/chase/chase.ts | 23 ++++++++++ src/plugin/chase/chase1.ts | 69 +++++++++++++++++++++--------- src/plugin/chase/index.ts | 31 ++++++++++++-- 9 files changed, 155 insertions(+), 53 deletions(-) diff --git a/public/libs/control.js b/public/libs/control.js index aed20fe..596d39c 100644 --- a/public/libs/control.js +++ b/public/libs/control.js @@ -2412,6 +2412,10 @@ control.prototype._doSL_load_afterGet = function (id, data) { core.myconfirm('此存档可能存在风险,你想要播放录像么?', _replay); return; } + // 追逐战 + Mota.r(() => { + Mota.Plugin.require('chase_r').end(false); + }); core.ui.closePanel(); core.loadData(data, function () { core.removeFlag('__fromLoad__'); diff --git a/public/project/floors/MT16.js b/public/project/floors/MT16.js index 7f89fe2..625d448 100644 --- a/public/project/floors/MT16.js +++ b/public/project/floors/MT16.js @@ -144,6 +144,10 @@ main.floors.MT16= "type": "forbidSave", "forbid": true }, + { + "type": "function", + "function": "function(){\nconst controller = Mota.Plugin.require('chase_r').initChase(0);\ncontroller.initAudio(false);\n}" + }, { "type": "show", "loc": [ @@ -154,11 +158,6 @@ main.floors.MT16= ], "floorId": "MT14" }, - { - "type": "playBgm", - "name": "escape.mp3", - "keep": true - }, { "type": "animate", "name": "amazed" @@ -400,10 +399,7 @@ main.floors.MT16= }, { "type": "function", - "function": "function(){\nMota.Plugin.require('chase_r').startChase(0);\n}" - }, - { - "type": "autoSave" + "function": "function(){\nMota.Plugin.require('chase_r').start(false);\n}" } ], "2,23": [ diff --git a/public/project/functions.js b/public/project/functions.js index bcb353b..92152dd 100644 --- a/public/project/functions.js +++ b/public/project/functions.js @@ -122,8 +122,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { const { checkLoopMap } = Mota.Plugin.require('loopMap_g'); - flags.floorChanging = true; - // ---------- 此时还没有进行切换,当前floorId还是原来的 ---------- // var currentId = core.status.floorId || null; // 获得当前的floorId,可能为null var fromLoad = core.hasFlag('__fromLoad__'); // 是否是读档造成的切换 @@ -189,13 +187,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { // 转换楼层结束的事件;此函数会在整个楼层切换完全结束后再执行 // floorId是切换到的楼层 - if (flags.onChase) { - flags.chaseTime ??= {}; - flags.chaseTime[floorId] = Date.now(); - } - - flags.floorChanging = false; - // 如果是读档,则进行检查(是否需要恢复事件) if (core.hasFlag('__fromLoad__')) { core.events.recoverEvents(core.getFlag('__events__')); @@ -282,10 +273,6 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { }, loadData: function (data, callback) { // 读档操作;从存储中读取了内容后的行为 - if (window.flags && flags.onChase) { - flags.chase.end(); - flags.onChase = true; - } // 重置游戏和路线 core.resetGame( data.hero, @@ -348,12 +335,13 @@ var functions_d6ad677b_427a_4623_b50f_a445a3b0ef8a = { core.removeFlag('__fromLoad__'); if (callback) callback(); - if (flags.onChase) { - Mota.Plugin.require('chase_r').startChase(flags.chaseIndex); - if (flags.chaseIndex === 1) { - core.playBgm('escape.mp3', 43.5); + Mota.r(() => { + if (flags.onChase) { + const chase = Mota.Plugin.require('chase_r'); + const controller = chase.initChase(0); + controller.start(true); } - } + }); }); }, updateStatusBar: function () { diff --git a/src/core/audio/bgm.ts b/src/core/audio/bgm.ts index 3af1357..c969c0a 100644 --- a/src/core/audio/bgm.ts +++ b/src/core/audio/bgm.ts @@ -37,6 +37,22 @@ export class BgmController private transitionData: Map = new Map(); + private canChange: boolean = true; + + /** + * 屏蔽音乐修改 + */ + blockChange() { + this.canChange = false; + } + + /** + * 取消屏蔽音乐修改 + */ + unblockChange() { + this.canChange = true; + } + /** * 添加一个bgm * @param uri bgm的`uri`,由于bgm是一类资源,因此`uri`为`bgms.xxx`的形式 @@ -67,6 +83,7 @@ export class BgmController * @param when 切换至的歌从什么时候开始播放,默认-1,表示不改变,整数表示设置为目标值 */ changeTo(id: BgmIds, when: number = -1, noStack: boolean = false) { + if (!this.canChange) return; if (id === this.now) return this.resume(); let prevent = false; const preventDefault = () => { @@ -98,6 +115,7 @@ export class BgmController * @param transition 是否使用渐变效果,默认使用 */ pause(transition: boolean = true) { + if (!this.canChange) return; if (!this.now) return; let prevent = false; const preventDefault = () => { @@ -120,6 +138,7 @@ export class BgmController * @param transition 是否使用渐变效果,默认使用 */ resume(transition: boolean = true) { + if (!this.canChange) return; if (!this.now) return; let prevent = false; const preventDefault = () => { @@ -147,6 +166,7 @@ export class BgmController * @param when 从bgm的何时开始播放 */ play(id: BgmIds, when: number = 0, noStack: boolean = false) { + if (!this.canChange) return; if (id === this.now) return; let prevent = false; const preventDefault = () => { @@ -184,6 +204,7 @@ export class BgmController * 撤销当前播放,改为播放前一个bgm */ undo(transition: boolean = true, when: number = 0) { + if (!this.canChange) return; if (this.stack.length === 0) return; else { const to = this.stack.pop()!; @@ -200,6 +221,7 @@ export class BgmController * 取消上一次的撤销,改为播放上一次撤销的bgm */ redo(transition: boolean = true, when: number = 0) { + if (!this.canChange) return; if (this.redoStack.length === 0) return; else { const to = this.redoStack.pop()!; diff --git a/src/core/render/camera.ts b/src/core/render/camera.ts index 024b06c..82d6a2f 100644 --- a/src/core/render/camera.ts +++ b/src/core/render/camera.ts @@ -44,6 +44,8 @@ export class Camera extends EventEmitter { /** 是否需要更新视角 */ private needUpdate: boolean = false; + /** 是否启用摄像机 */ + private enabled: boolean = true; /** 变换操作列表,因为矩阵乘法跟顺序有关,因此需要把各个操作拆分成列表进行 */ protected operation: CameraOperation[] = []; @@ -84,7 +86,7 @@ export class Camera extends EventEmitter { } private tick = () => { - if (!this.needUpdate) return; + if (!this.needUpdate || !this.enabled) return; const trans = this.transform; trans.reset(); for (const o of this.operation) { @@ -100,6 +102,20 @@ export class Camera extends EventEmitter { this.needUpdate = false; }; + /** + * 禁用这个摄像机 + */ + disable() { + this.enabled = false; + } + + /** + * 启用这个摄像机 + */ + enable() { + this.enabled = true; + } + /** * 在下一帧进行强制更新 */ diff --git a/src/core/render/preset/viewport.ts b/src/core/render/preset/viewport.ts index a577da6..515ceb3 100644 --- a/src/core/render/preset/viewport.ts +++ b/src/core/render/preset/viewport.ts @@ -1,9 +1,8 @@ import { logger } from '@/core/common/logger'; import { HeroRenderer } from './hero'; import { ILayerGroupRenderExtends, LayerGroup } from './layer'; -import { Transform } from '../transform'; import { LayerGroupFloorBinder } from './floor'; -import { hyper, inverseTrigo, power, TimingFn, trigo } from 'mutate-animate'; +import { hyper, TimingFn } from 'mutate-animate'; import { RenderAdapter } from '../adapter'; export class FloorViewport implements ILayerGroupRenderExtends { diff --git a/src/plugin/chase/chase.ts b/src/plugin/chase/chase.ts index a0793cc..c57b62a 100644 --- a/src/plugin/chase/chase.ts +++ b/src/plugin/chase/chase.ts @@ -8,6 +8,29 @@ import { disableViewport, enableViewport } from '@/core/render/utils'; import type { HeroMover, MoveStep } from '@/game/state/move'; import EventEmitter from 'eventemitter3'; +export interface IChaseController { + /** 本次追逐战实例 */ + readonly chase: Chase; + + /** + * 开始这个追逐战 + * @param fromSave 是否是从存档开始 + */ + start(fromSave: boolean): void; + + /** + * 结束这个追逐战 + * @param success 是否逃脱成功 + */ + end(success: boolean): void; + + /** + * 初始化这次追逐战的音频 + * @param fromSave 是否从存档开始 + */ + initAudio(fromSave: boolean): void; +} + export interface ChaseData { path: Partial>; camera: Partial>; diff --git a/src/plugin/chase/chase1.ts b/src/plugin/chase/chase1.ts index 4c8f815..7efaf3c 100644 --- a/src/plugin/chase/chase1.ts +++ b/src/plugin/chase/chase1.ts @@ -1,23 +1,12 @@ -import { - Animation, - bezier, - hyper, - linear, - power, - shake, - sleep -} from 'mutate-animate'; -import { Chase, ChaseData } from './chase'; +import { Animation, hyper, linear, power, sleep } from 'mutate-animate'; +import { Chase, ChaseData, IChaseController } from './chase'; import { completeAchievement } from '../ui/achievement'; -import { - Camera, - CameraAnimation, - CameraRotate, - CameraScale -} from '@/core/render/camera'; +import { Camera, CameraAnimation, CameraScale } from '@/core/render/camera'; import { LayerGroup } from '@/core/render/preset/layer'; import { MotaRenderer } from '@/core/render/render'; import { Sprite } from '@/core/render/sprite'; +import { AudioPlayer } from '@/core/audio/audio'; +import { bgm } from '@/core/audio/bgm'; const path: Partial> = { MT16: [ @@ -115,15 +104,16 @@ let back: Sprite | undefined; /** * 初始化并开始这个追逐战 */ -export function initChase() { +export function initChase(): IChaseController { const ani = new Animation(); const render = MotaRenderer.get('render-main')!; const layer = render.getElementById('layer-main')! as LayerGroup; - const camera = Camera.for(layer); + const camera = new Camera(layer); camera.clearOperation(); camera.transform = layer.camera; + camera.disable(); const animation16 = new CameraAnimation(camera); const animation15 = new CameraAnimation(camera); const animation14 = new CameraAnimation(camera); @@ -199,6 +189,8 @@ export function initChase() { camera.destroy(); back?.destroy(); back = void 0; + core.removeFlag('onChase'); + core.removeFlag('chaseId'); }); judgeFail1(chase, ani, camera); @@ -210,8 +202,45 @@ export function initChase() { Mota.Plugin.require('chase_g').chaseInit1(); - chase.start(); - wolfMove(chase); + const controller: IChaseController = { + chase, + start(fromSave) { + core.setFlag('onChase', true); + core.setFlag('chaseId', 1); + core.autosave(); + chase.start(); + camera.enable(); + wolfMove(chase); + if (fromSave) { + initFromSave(chase); + } + }, + end(success) { + chase.end(success); + }, + initAudio(fromSave) { + if (fromSave) initFromSave(chase); + else initAudio(chase); + } + }; + return controller; +} + +function initAudio(chase: Chase) { + playAudio(0, chase); +} + +function initFromSave(chase: Chase) { + playAudio(43.5, chase); +} + +function playAudio(from: number, chase: Chase) { + bgm.changeTo('escape.mp3', from); + bgm.blockChange(); + chase.on('end', () => { + bgm.unblockChange(); + bgm.undo(); + }); } // function chaseShake(chase: Chase) { diff --git a/src/plugin/chase/index.ts b/src/plugin/chase/index.ts index 2797c5f..b036a5e 100644 --- a/src/plugin/chase/index.ts +++ b/src/plugin/chase/index.ts @@ -1,9 +1,34 @@ +import { IChaseController } from './chase'; import { initChase as init1 } from './chase1'; -const chaseIndexes: Record void> = { +let nowChase: IChaseController | undefined; + +const chaseIndexes: Record IChaseController> = { 0: init1 }; -export function startChase(index: number) { - chaseIndexes[index](); +export function getNow() { + return nowChase; +} + +export function initChase(index: number) { + nowChase?.end(false); + const controller = chaseIndexes[index](); + nowChase = controller; + controller.chase.on('end', () => { + nowChase = void 0; + }); + return nowChase; +} + +export function start(fromSave: boolean) { + nowChase?.start(fromSave); +} + +export function end(success: boolean) { + nowChase?.end(success); +} + +export function initAudio(fromSave: boolean) { + nowChase?.initAudio(fromSave); }