//+=======================================================================+ // Script: GameFocus // Version: 1.0.0 // Last Update: October 12th, 2015 // Author: Zalerinian //+=======================================================================+ var Imported = Imported || {}; var Zale = Zale || {}; Zale.GameFocus = Zale.GameFocus || {}; (function(){ if(Imported["MVCommons"] || Imported["PluginManagement"]){ var author = [{ email: "support@razelon.com", name: "Zalerinian", website: "http://www.razelon.com" }]; var v = PluginManager.register("GameFocus", "1.0.0", PluginManager.getBasicPlugin("GameFocus").description, author, "2015-10-12"); if(v === undefined) { throw new Error("Unable to load GameFocus due to mising dependencies!"); } else if (v === false){ PluginManager.printPlugin("GameFocus") throw new Error("Unable to load GameFocus due to registration failure! Is there another version running?"); } } else { Imported["GameFocus"] = "1.0.0"; console.log("Neither MVCommons nor PluginManagement are imported - Please install the MVCommons script to maintain an updated list of scripts in the project."); } }); /*: * @plugindesc Pauses the Audio and/or Video when the game loses focus. Has callbacks for onPause, whilePaused, and onResume. * @author Zalerinian * @param Pause Audio * @desc Pause the game audio when the window loses focus. * Default: true * @default true * * @param Pause Graphics * @desc Pause the game processing when the window loses focus. * Default: true * @default true * * @help * =========================================================================== * Introduction * =========================================================================== * * This plugin allows you to have the game pause the audio, video, or both * when the game is not the active window. In previous versions of RPG Maker, * the engine would pause the video and leave the audio running. This * aggrivated not only developers, who had carefully timed cutscenes that * relied on audio, but also players, who kept hearing the game's audio loop * while it was in the background. * * =========================================================================== * Usage - Game Developers * =========================================================================== * * For game developers, using this plugin is really easy! You just install it * in the Plugin Manager like you already have, and then you set which options * you want with the plugin. It can't get too much easier! * * =========================================================================== * Usage - Plugin Developers * =========================================================================== * * Integrating your plugin with GameFocus is also really easy! GameFocus * provides a callback system to let you run a function when the game first * losses focus, while the game is out of focus, and on resume, right before * everything starts back up. * * To demonstrate the callback system, GameFocus uses it itself for the * functions that pause and restart the game and audio! Please note that these * functions are always the first in the callback stack, and so your onPause * callbacks technically happen immediately after the game is paused, while * onResume will happen immediately after the game resumes. Because the game * sets up a callback on the browser's draw method first, it will complete a * single update before your onResume callback is called. * * =========================================================================== * Changing the music mid-pause * =========================================================================== * * While there is very little reason to modify the music that will be played * once the game is resumed, you can switch it from within whilePaused. In * order to change the BGM or BGS and not cause the music to start playing for * no apparent reason to the end user, change the value of the this._audio.bgm * and this._audio.bgs objects. The objects were obtained from the * AudioManager, and as such hold the same object it has. In most cases, all * you need to do is change the "name" field of the object and it will load * the new file in when it's ready. * */ /*:ja * @plugindesc ゲームがアクティブウィンドウでなくなった際に、 * オーディオかビデオ、もしくはその両方を一時停止します。 * @author Zalerinian * @param Pause Audio * @desc ウィンドウがアクティブでなくなった際、オーディオを停止します。 * Default: true * @default true * * @param Pause Graphics * @desc ウィンドウがアクティブでなくなった際、ビデオを停止します。 * Default: true * @default true * * @help * =========================================================================== * Introduction * =========================================================================== * * このプラグインは、ゲームがアクティブウィンドウでなくなった際に、 * オーディオかビデオ、もしくはその両方を一時停止します。 * 以前のRPGツクールのバージョンでは、 * エンジンはビデオのみを停止し、音楽を流し続けていました。 * これはカットシーンを入念に作り込んでいた開発者の悩みの種であり、 * バックグラウンド表示でBGMを聞き続けなければならない * プレイヤーにとっても、煩わしいものでした。 * * =========================================================================== * 使用方法 - ゲーム開発者向け * =========================================================================== * * ゲーム開発者向けの使用方法は非常に簡単です。 * GameFocusをプラグインマネージャーにインストールし、 * オプション選択をするだけで適用完了することができます! * * =========================================================================== * 使用方法 - プラグイン開発者向け * =========================================================================== * * GameFocusをあなたのプラグインと統合するのは、非常に簡単です。 * GameFocusは、ゲームフォーカスが外れた際、その最中とゲーム再開時に、 * 関数を実行するコールバックシステムを提供します。 * GameFocusはコールバックシステムそれ自身を、 * ゲーム/オーディオの停止・再開用の関数として用います。 * * GameFocusはonPause, whilePaused, onResumeのコールバックを提供します。 * これらの関数は常にコールバックスタックの上位に来るため、 * ゲームが一時停止されると即座に、onPauseコールバックが発生します。 * 同様に、ゲーム再開時にも即座にonRedumeのコールバックが発生します。 * 最初にブラウザの描画メソッド上にコールバックがセットされるため、 * onResumeが呼び出される前に、1つのアップデートが完了されます。 * * =========================================================================== * 中断時の音楽変更 * =========================================================================== * * ゲーム再開時に、音楽を変更する必要はあまりないかもしれませんが、 * WhilePaused内から音楽を切り替えることもできます。 * BGM/BGSを変更するには、"this._audio.bgm" と "this._audio.bgs" * オブジェクトの値を変更してください。 * これらのオブジェクトは AudioManagerから取得されています。 * オブジェクトの"name"フィールドを変更すれば、 * 準備ができ次第、新しいファイルが読み込まれます。 * */ function GameFocus() { throw new Error("GameFocus is a static class!"); } (function($) { // -------------------------------------------------------------------------- // // boolFunc(string str) // str: A string to be compared against true. // // This function will take the string and compare it to true, returning // true if the given string is also true, or false otherwise. // // Returns: // True when str is "true" // False otherwise // // -------------------------------------------------------------------------- function boolFunc(str) { return Function("return " + str + " === true")(); } var params = PluginManager.parameters("GameFocus"); Zale.GameFocus.PauseAudio = boolFunc(params["Pause Audio"]); Zale.GameFocus.PauseGraphics = boolFunc(params["Pause Graphics"]); $._callbacks = {onPause: [], whilePaused: [], onResume: []}; $._audio = {}; $._paused = { audio: false, graphics: false }; // -------------------------------------------------------------------------- // // GameFocus.registerCallback(string type, function cb) // type: Notes the type of callback being registered. Valid values are // onPause, whilePaused, and onResume // // cb: The function to call when the time comes. // // This function will add the given function to the list of functions to // call when it's call type is ready. onPause types are called right when // the game loses focus. whilePaused types only run while the game is // paused. onResume types run when the game first regains focus. // // Returns: // This function returns no value. // // -------------------------------------------------------------------------- $.registerCallback = function(type, cb) { if(typeof cb === 'function' && ["onPause", "whilePaused", "onResume"].contains(type)) { this._callbacks[type].push(cb); } } // -------------------------------------------------------------------------- // // GameFocus.removeCallback(string type, function cb) // type: The type of callback that was previously registered. Valis values // are onPause, whilePaused, and onResume. // // cb: The function to remove from the callback list. // // This function will remove the specified function from the list of // callbacks, preventing it from being called without being re-registered. // // Returns: // This function returns no value. // // -------------------------------------------------------------------------- $.removeCallback = function(type, cb) { if(typeof cb === 'function' && ["onPause", "whilePaused", "onResume"].contains(type)) { var index = this._callbacks.indexOf(cb); this._callbacks[type].splice(index, 1); } } // -------------------------------------------------------------------------- // // GameFocus.checkForFocus() // // This function is called when the game window redraws itself when the game // is paused. It will call the callbacks as needed, and request that it be // rerun at the next frame draw so as to continue checking for focus. // // You should NOT call this function yourself, or the onResume callbacks // will be called when they don't expect to be, possibly leading to // undefined behavior. // // Returns: // This function returns no value. // // -------------------------------------------------------------------------- function checkForFocus() { if(document.hasFocus()) { var cbs = GameFocus._callbacks.onResume; for(var i = 0; i < cbs.length; i++) { cbs[i].call(GameFocus); } } else { var cbs = GameFocus._callbacks.whilePaused; for(var i = 0; i < cbs.length; i++) { cbs[i].call(GameFocus); } window.requestAnimationFrame(checkForFocus); } } // -------------------------------------------------------------------------- // // Input._onLostFocus() // // This function was aliased from the Input class, and is used to call all // onPaused callbacks, and begin the inital checkForFocus call. // // Returns: // This function returns no value. // // -------------------------------------------------------------------------- Zale.GameFocus.Input_update_POJc32oincwoSn = Input.update; Input.update = function() { Zale.GameFocus.Input_update_POJc32oincwoSn.call(this); if(!document.hasFocus()){ var cbs = GameFocus._callbacks.onPause; for(var i = 0; i < cbs.length; i++) { cbs[i].call(GameFocus); } checkForFocus(); } } // -------------------------------------------------------------------------- // // SceneManager.start() // // This function reverts SceneManager.stop() by setting _stopped to false, // allowing the SceneManager to continue updating the game. // // Returns: // This function returns no value. // // -------------------------------------------------------------------------- SceneManager.start = function() { this._stopped = false; this.update(); } // -------------------------------------------------------------------------- // // GameFocus onPause Callback // // This function is a primary function in GameFocus, and is the first // callback in the onPause stack. It will check it's configuration, and stop // all audio and/or video if it needs to. // // Returns: // This function returns no value. // // -------------------------------------------------------------------------- $.registerCallback("onPause", function(){ if(Zale.GameFocus.PauseAudio) { this._paused.audio = true; this._audio.bgm = AudioManager.saveBgm(); this._audio.bgs = AudioManager.saveBgs(); AudioManager.stopMe(); AudioManager.stopSe(); if(AudioManager._bgmBuffer) { AudioManager._bgmBuffer.stop(); } if(AudioManager._bgsBuffer) { AudioManager._bgsBuffer.stop(); } } if(Zale.GameFocus.PauseGraphics) { this._paused.graphics = true; SceneManager.stop(); } }); // -------------------------------------------------------------------------- // // GameFocus onResume Callback // // This function is a primary function in GameFocus, and is the first // callback in the onResume stack. It checks it's configuration to see if // the audio or video was stopped earlier, and if it was, resumes it. If the // AudioManager detects that the stored audio is not the audio that was // playing at the pause, the new audio is played as normal. Otherwise, the // audio buffer is used to directly restart the audio. // // Returns: // This function returns no values. // // -------------------------------------------------------------------------- $.registerCallback("onResume", function() { if(this._paused.audio) { this._paused.audio = false; var bgm = this._audio.bgm; var bgs = this._audio.bgs; if(!AudioManager.isCurrentBgm(this._audio.bgm)) { AudioManager.playBgm(this._audio.bgm); } else if(AudioManager._bgmBuffer) { AudioManager._bgmBuffer.play(true, bgm.pos); } if(!AudioManager.isCurrentBgs(this._audio.bgs)) { AudioManager.playBgs(this._audio.bgs); } else if(AudioManager._bgsBuffer) { AudioManager._bgsBuffer.play(true, bgs.pos); } } if(this._paused.graphics) { this._paused.graphics = false; SceneManager.start(); } }); })(GameFocus);