slave-thistle/www/js/plugins/Gamefocus.js
2025-05-26 09:44:24 -05:00

381 lines
16 KiB
JavaScript

//+=======================================================================+
// 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);