TCG Splash Screen Plugin - Orthographic
Today concludes my junior year at Santa Susana High School. It's been a half all right, I'm looking forward to my senior year next year. In other news, Orthographic has been approved as my senior project. This week I made a new RPG Maker MV plugin for Orthographic. I made a splash screen plugin, so that devs can put their company name before the title screen of their game. So far, I have 3 parameters. The first one is the text that appears, the second one is the length of the splash screen in seconds, and the last is an option determines whether or not the splash screen will be skipped if there's already a save file. The top of the plugin looks like this:
/*: * * @plugindesc Displays a Splash Screen before the title screen * * @author José Rodriguez-Rivas * * @param Splash Text * @desc Text to be drawn in the splash screen. * @default Lorem Ipsum Presents * * @param Splash length * @desc Amount of time, in seconds, that the splash screen will last * @default 5 * * @param Skip if File Exists * @desc Determines whether to skip if a file exists * @default false * * @help * Displays the text provided in the plugin parameter before going to the title screen. * Uses, but does not alias Scene_Boot.prototype.start */
I retrieve them with the following code:
var parameters = PluginManager.parameters('TCGSplashScreen'); var splashText = String(parameters['Splash Text']); var numSeconds = Number(parameters['Splash length']); var fileSkip = String(parameters['Skip if File Exists']).toLowerCase() === 'true';
Next I use everything that a scene needs to function in RPG Maker
Scene_TCG_Splash.prototype = Object.create(Scene_Base.prototype); Scene_TCG_Splash.prototype.constructor = Scene_TCG_Splash; Scene_TCG_Splash.prototype.initialize = function() { Scene_Base.prototype.initialize.call(this); }; Scene_TCG_Splash.prototype.terminate = function() { Scene_Base.prototype.terminate.call(this); SceneManager.snapForBackground(); };
I added my own code to the start method, that fades in the screen.
Scene_TCG_Splash.prototype.start = function() { Scene_Base.prototype.start.call(this); SceneManager.clearStack(); this.startFadeIn(this.fadeSpeed(), false); };
And I add a couple of variables to the create method.
Scene_TCG_Splash.prototype.create = function() { Scene_Base.prototype.create.call(this); this.createForeground(); this._numFrames = 0; this._done = false; };
In the createForground method, I create a sprite, add it to the scene, and draw the text. The method looks like this:
Scene_TCG_Splash.prototype.createForeground = function() { this._splashSprite = new Sprite(new Bitmap(Graphics.width, Graphics.height)); this.addChild(this._splashSprite); this.drawSplashText(); }
In the drawSplashText method, I calculate where the text goes on the screen and draw it with the splashSprite I created in the createForground method. The method looks like this:
Scene_TCG_Splash.prototype.drawSplashText = function() { var x = 20; var y = Graphics.height / 2.45; var maxWidth = Graphics.width - x * 2; var text = splashText; this._splashSprite.bitmap.outlineColor = 'black'; this._splashSprite.bitmap.outlineWidth = 8; this._splashSprite.bitmap.fontSize = 72; this._splashSprite.bitmap.drawText(text, x, y, maxWidth, 48, 'center'); }
In the update method, I check whether the player has clicked, or typed the action button or cancel button. I also use a variable that I increment every frame for timing. RPG Maker MV runs at a set 60 frames per second, so every second is 60 frames. When the amount of frames modulo 60 is zero, that means a second has passed, and the amount of frames divided by 60 is the number of seconds that has passed. The method looks like this:
Scene_TCG_Splash.prototype.update = function() { Scene_Base.prototype.update.call(this); if(!this._done) { if(TouchInput.isTriggered() || Input.isTriggered('ok') || Input.isTriggered('escape')) { this.gotoTitle(); } } if(!this._done) { this._numFrames++; if(this._numFrames % 60 == 0 && (this._numFrames / 60 == numSeconds)) { this.gotoTitle(); } } };
In the gotoTitle method, the screen fades out, and the done boolean is set to true, to ensure that the method isn't run twice, and it changes the scene to the title screen. I had to modify the Scene_Boot.start method without aliasing because I need to change what the method does, not add to it. What I change is when the method was supposed to go the the screen title. If the dev wants to skip the splash screen when there is a save file and there is a save file, it goes directly to the title scene, otherwise it goes to the splash scene. The method looks like this:
Scene_Boot.prototype.start = function() { Scene_Base.prototype.start.call(this); SoundManager.preloadImportantSounds(); if (DataManager.isBattleTest()) { DataManager.setupBattleTest(); SceneManager.goto(Scene_Battle); } else if (DataManager.isEventTest()) { DataManager.setupEventTest(); SceneManager.goto(Scene_Map); } else { this.checkPlayerLocation(); DataManager.setupNewGame(); if(fileSkip && DataManager.isAnySavefileExists()) { SceneManager.goto(Scene_Title); } else { SceneManager.goto(Scene_TCG_Splash); } Window_TitleCommand.initCommandPosition(); } this.updateDocumentTitle(); };
This means that other plugins that use this method might not be able to work, which is why I included that in the help file. The full plugin looks like this:
/*: * * @plugindesc Displays a Splash Screen before the title screen * * @author José Rodriguez-Rivas * * @param Splash Text * @desc Text to be drawn in the splash screen. * @default Lorem Ipsum Presents * * @param Splash length * @desc Amount of time, in seconds, that the splash screen will last * @default 5 * * @param Skip if File Exists * @desc Determines whether to skip if a file exists * @default false * * @help * Displays the text provided in the plugin parameter before going to the title screen. * Uses, but does not alias Scene_Boot.prototype.start */ (function() { var parameters = PluginManager.parameters('TCGSplashScreen'); var splashText = String(parameters['Splash Text']); var numSeconds = Number(parameters['Splash length']); var fileSkip = String(parameters['Skip if File Exists']).toLowerCase() === 'true'; function Scene_TCG_Splash() { this.initialize.apply(this, arguments); } Scene_TCG_Splash.prototype = Object.create(Scene_Base.prototype); Scene_TCG_Splash.prototype.constructor = Scene_TCG_Splash; Scene_TCG_Splash.prototype.initialize = function() { Scene_Base.prototype.initialize.call(this); }; Scene_TCG_Splash.prototype.create = function() { Scene_Base.prototype.create.call(this); this.createForeground(); this._numFrames = 0; this._done = false; }; Scene_TCG_Splash.prototype.start = function() { Scene_Base.prototype.start.call(this); SceneManager.clearStack(); this.startFadeIn(this.fadeSpeed(), false); }; Scene_TCG_Splash.prototype.update = function() { Scene_Base.prototype.update.call(this); if(!this._done) { if(TouchInput.isTriggered() || Input.isTriggered('ok') || Input.isTriggered('escape')) { this.gotoTitle(); } } if(!this._done) { this._numFrames++; if(this._numFrames % 60 == 0 && (this._numFrames / 60 == numSeconds)) { this.gotoTitle(); } } }; Scene_TCG_Splash.prototype.gotoTitle = function() { this.fadeOutAll(); this._done = true; SceneManager.goto(Scene_Title); } Scene_TCG_Splash.prototype.terminate = function() { Scene_Base.prototype.terminate.call(this); SceneManager.snapForBackground(); }; Scene_TCG_Splash.prototype.createForeground = function() { this._splashSprite = new Sprite(new Bitmap(Graphics.width, Graphics.height)); this.addChild(this._splashSprite); this.drawSplashText(); } Scene_TCG_Splash.prototype.drawSplashText = function() { var x = 20; var y = Graphics.height / 2.45; var maxWidth = Graphics.width - x * 2; var text = splashText; this._splashSprite.bitmap.outlineColor = 'black'; this._splashSprite.bitmap.outlineWidth = 8; this._splashSprite.bitmap.fontSize = 72; this._splashSprite.bitmap.drawText(text, x, y, maxWidth, 48, 'center'); } Scene_Boot.prototype.start = function() { Scene_Base.prototype.start.call(this); SoundManager.preloadImportantSounds(); if (DataManager.isBattleTest()) { DataManager.setupBattleTest(); SceneManager.goto(Scene_Battle); } else if (DataManager.isEventTest()) { DataManager.setupEventTest(); SceneManager.goto(Scene_Map); } else { this.checkPlayerLocation(); DataManager.setupNewGame(); if(fileSkip && DataManager.isAnySavefileExists()) { SceneManager.goto(Scene_Title); } else { SceneManager.goto(Scene_TCG_Splash); } Window_TitleCommand.initCommandPosition(); } this.updateDocumentTitle(); }; })();
I did not stream this because I was in a class while I worked on it. I hope to be able to stream a lot over the summer and get far in the development of this game.
-José Rodriguez-Rivas