//============================================================================= // RPG Maker MZ - Scene_StaffRoll // // Copyright 2024 Panzer-IV. All rights reserved. // This source code or any portion thereof must not be // reproduced or used without licensed in any manner whatsoever. //============================================================================= /*: * @target MZ * @plugindesc スタッフロール画面プラグイン * @author 四号戦車 * @base PluginCommonBase * @base DebugSwitch * @base PluginUtils * @orderAfter PluginCommonBase * @orderAfter DebugSwitch * @orderAfter PluginUtils * * @param images * @text スタッフロール画像 * @desc スタッフロールの画像 * @type file[] * @dir img/system * @default [] * * @param bgm * @text BGM指定 * @desc BGMの指定です。 * @type file * @dir audio/bgm * @default * * @param event * @text 次のイベント * @desc スタッフロール終了後移動するイベントの指定です。 * @type common_event * @default 0 * * @param scrollWithMusic * @text BGM追従スクロール設定 * @desc BGMの終了とスクロールの終了を併せます。 * @type boolean * @default false * * @help Scene_StaffRoll.js * * Version: 0.0.1 * * スタッフロール画面 * * @command startStaffRoll * @text スタッフロール開始 * @desc スタッフロールを開始します。 */ (() => { "use strict"; //======================================================================== // プラグイン定義 //======================================================================== const pluginName = "Scene_StaffRoll"; const script = document.currentScript; const param = PluginManagerEx.createParameter(script); //======================================================================== // コアスクリプト変更部 (Scene_Boot) //======================================================================== const _Scene_Boot_prototype_onDatabaseLoaded = Scene_Boot.prototype.onDatabaseLoaded; Scene_Boot.prototype.onDatabaseLoaded = function() { _Scene_Boot_prototype_onDatabaseLoaded.apply(this, arguments); // preload param.images.forEach(image => { ImageManager.loadSystem(image); }); } //======================================================================== // 定数定義 (StaffRollState) //======================================================================== const StaffRollState = { NONE: 'none', READY: 'ready', RUNNING: 'running', ENDING: 'ending', END: 'end', }; const ENDING_WAIT = 60; const MOVE_IN_SKIP = 200; const MOVE_NORMAL = 4; //======================================================================== // クラス定義 (Scene_StaffRoll) //======================================================================== class Scene_StaffRoll extends Scene_Base { constructor() { super(); this.sprite = null; this.duration = 60 * 2; // 2 minutes this.currentY = 0; this.movePerFrame = 1; this._state = StaffRollState.NONE; this.endingCount = 0; this.imageHeight = Graphics.height; } create() { super.create(); this.sprite = new Sprite_Scrollable(Graphics.width, Graphics.height); let height = 0; param.images.forEach(image => { const sprite = new Sprite(ImageManager.loadSystem(image)); sprite.move((Graphics.width - sprite.width) / 2, height); this.sprite.addChild(sprite); height += sprite.height; }); this.imageHeight = height; this.sprite.enableInput(false); this.sprite.enableScrollX(false); this.sprite.move(0, 0); this.addChild(this.sprite); this.movePerFrame = this._calcMoveHeight() } start() { super.start(); if (!!param.bgm && param.bgm !== '') { const bgm = { name: param.bgm, volume: 100, pitch: 100, pan: 0, pos: 0, }; if (param.scrollWithMusic) { AudioManager.stopBgm(); AudioManager._bgmBuffer = AudioManager.createBuffer("bgm/", bgm.name); AudioManager.updateBgmParameters(bgm); const webAudio = AudioManager._bgmBuffer; const scene = this; const onBgmLoaded = () => { scene.duration = webAudio._totalTime; scene.movePerFrame = scene._calcMoveHeight() if (!AudioManager._meBuffer) { AudioManager._bgmBuffer.play(false, 0); } AudioManager.updateCurrentBgm(bgm, 0); scene.setState(StaffRollState.RUNNING); }; if (webAudio.isReady()) { onBgmLoaded.bind(this)(); } else { webAudio.addLoadListener(onBgmLoaded.bind(this)); } } else { AudioManager.playBgm(bgm, 0); this.setState(StaffRollState.RUNNING); } } else { this.setState(StaffRollState.RUNNING); } } update() { super.update(); if (!!this.sprite) { this.sprite.update(); } switch (this._state) { case StaffRollState.RUNNING: { if (Input.isPressed(InputClass.INPUT_CLASS_CTRL)) { this.currentY += MOVE_IN_SKIP; } else { this.currentY += this.movePerFrame; } const yEnd = Math.max(this.imageHeight - Graphics.height, 0); if (this.currentY > yEnd) { this.currentY = yEnd; } this.sprite.smoothScrollTo(0, this.currentY, 10); if (this.currentY >= yEnd) { AudioManager.fadeOutBgm(ENDING_WAIT); this.setState(StaffRollState.ENDING); } break; } case StaffRollState.ENDING: { this.endingCount++; if (this.endingCount > ENDING_WAIT) { this.setState(StaffRollState.END); AudioManager.stopBgm(); this.fadeOutAll(); this.popScene(); PluginUtils.fireCommonEvent(param.event); } break; } default: /* nothing to do */ break; } // switch } stop() { super.stop(); } setState(newState) { Logger.d(`Scene_StaffRole: setState old = ${this._state}, new = ${newState}`); this._state = newState; } _calcMoveHeight() { if (param.scrollWithMusic) { const bgmFrame = this.duration * 60; return this.imageHeight / bgmFrame; } else { return MOVE_NORMAL; } } }; //======================================================================== // プラグインコマンド //======================================================================== PluginManagerEx.registerCommand(script, 'startStaffRoll', args => { SceneManager._scene.fadeOutAll(); SceneManager.push(Scene_StaffRoll); }); })();