【RPG Maker MV插件編程】【實例教程2】制作一個啟動畫面

作者:Mandarava(鰻駝螺)
微博:@鰻駝螺pro

啟動畫面是游戲開始時,在進入標(biāo)題畫面前的一個顯示畫面,通常用于展示游戲開發(fā)商的Logo。RMMV自帶一個官方啟動畫面插件 MadeWithMv,可以設(shè)定自己的啟動圖,一般來說,這個插件足夠使用。本文介紹如何制作類似的一個啟動畫面插件。

首先,新建一個名為 MND_Splash.js 的文件放到 js/plugins 目錄下,并在RMMV中安裝該插件。

從哪里開始?

游戲在啟動時,Scene_Boot 類用于初始化整個游戲,而 Scene_Boot.prototype.start 方法是場景開始時的處理方法。啟動畫面是游戲啟動時的第一個“場景”,所以要創(chuàng)建啟動畫面,就應(yīng)該在 start 方法中創(chuàng)建。來看一下 start 原始方法的實現(xiàn):

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();
        SceneManager.goto(Scene_Title);
        Window_TitleCommand.initCommandPosition();
    }
    this.updateDocumentTitle();
};
  1. DataManager.isBattleTest() 檢測當(dāng)前是否為進行戰(zhàn)斗測試,如果是就進入戰(zhàn)斗場景,比如在 數(shù)據(jù)庫-敵群 界面進行戰(zhàn)斗測試時;
  2. DataManager.isEventTest() 檢測當(dāng)前是否為事件測試,如果是則進入當(dāng)前的游戲地圖界面,比如在編輯事件時進行事件內(nèi)容的測試時。
  3. 除此之外, else 部份就是正常啟動游戲時要進入的場景的選擇,可以在這里創(chuàng)建并進入我們的啟動畫面場景。

這里 SceneManager.goto(Scene_Title) 方法用于進入標(biāo)題畫面。從這里可以看出,RMMV在開始游戲時默認是直接進入標(biāo)題畫面的,所以很簡單,只要將這里的 SceneManager.goto(Scene_Title) 改成進入我們的啟動畫面即可,如:SceneManager.goto(Scene_Splash)(假設(shè)我們的啟動畫面場景類叫做Scene_Splash),再由啟動畫面進入標(biāo)題畫面,為此就來創(chuàng)建我們的啟動畫面的場景類。

創(chuàng)建啟動畫面的場景類

要創(chuàng)建一個新的場景類,最簡單的做法是改一個現(xiàn)有的場景類。場景類有很多,包括:Scene_BaseScene_BootScene_BattleScene_DebugScene_EquipScene_FileScene_GameEndScene_GameoverScene_ItemBaseScene_ItemScene_LoadScene_MapScene_MenuBaseScene_MenuScene_NameScene_OptionsScene_SaveScene_ShopScene_SkillScene_StatusScene_Title。分析一下這些場景類的實現(xiàn),確定哪些方法需要,最后把我們要用到的方法拷貝到 MND_Splash.js 中,我們的場景類命名為:Scene_Splash。最后我們需要的方法包括以下幾個:構(gòu)建器部分、Scene_Splash.prototype.create 方法、Scene_Splash.prototype.start 方法、Scene_Splash.prototype.stop 方法、Scene_Splash.prototype.terminate 方法、Scene_Splash.prototype.update 方法等(當(dāng)然除了構(gòu)建器部分外,其它方法都是可選的)。下面就在Scene_Splash類中重寫這些方法。

構(gòu)建器部分

Scene_Base類是所有Scene類的基類,我們要創(chuàng)建的類Scene_Splash實際比較簡單,所以只需要直接繼承Scene_Base類就可以了。下面是Scene_Splash的構(gòu)建器及初始化代碼:

function Scene_Splash() {
    this.initialize.apply(this, arguments);
}

Scene_Splash.prototype = Object.create(Scene_Base.prototype);
Scene_Splash.prototype.constructor = Scene_Splash;

Scene_Splash.prototype.initialize = function() {
    Scene_Base.prototype.initialize.call(this);
};

Scene_Splash.prototype.create方法

該方法是在場景創(chuàng)建時要執(zhí)行的處理,在這里創(chuàng)建組件并將它們加入渲染隊列中。所以,我們可以在這里添加要顯示logo圖片。假設(shè)我們的Logo圖片放在 img/system/MyLogo.png,那么該方法的重寫實現(xiàn)如下:

Scene_Splash.prototype.create = function() {
    Scene_Base.prototype.create.call(this);

    this.logo=new Sprite();
    this.logo.bitmap=ImageManager.loadSystem("MyLogo");    
    this.addChild(this.logo);
};

Scene_Base.prototype.create.call(this);這個是調(diào)用基類(父類)的同名方法,因為我們這里是重寫基類的該方法,你需要讓基類中的操作也執(zhí)行一下(除非你明確不想執(zhí)行;即使現(xiàn)在基類的該方法沒有執(zhí)行任何操作,為了以后的兼容,比如官方在未來的某個版本添加了操作,也應(yīng)該用調(diào)用基類的實現(xiàn))。this.logo 就是用于顯示我們的Logo圖片的精靈對象,使用場景的 addChild() 方法可以將精靈加入到場景。在這里我們并沒有為精靈設(shè)置顯示座標(biāo),因為此時的Logo圖片還沒有加載完畢,讀取到的圖片尺寸高寬都是0,如果你需要根據(jù)圖片的高寬為其定位,那么,這個定位處理應(yīng)該放到 start 方法中去。

Scene_Splash.prototype.start方法

該方法是場景啟動時要執(zhí)行的處理。這里用 startFadeIn(duration, white) 方法讓場景出現(xiàn)淡入效果。同時將logo圖片顯示到場景正中間。

Scene_Splash.prototype.start = function() {
    Scene_Base.prototype.start.call(this);
    this.startFadeIn(this.slowFadeSpeed(), false);

    //將this.logo定位到場景的正中(由于沒有使用logo的尺寸來定位,所以下面這段代碼放到 create 方法中也是沒問題的)
    this.logo.anchor.x=0.5;
    this.logo.anchor.y=0.5;
    this.logo.x=Graphics.width/2;
    this.logo.y=Graphics.height/2;
};

Graphics.widthGraphics.height 用于獲取游戲屏幕的寬高尺寸。這里將logo精靈的錨點設(shè)置到其正中心,再將其坐標(biāo)設(shè)置到屏幕正中心,這樣就能讓精靈呈現(xiàn)在屏幕中心。

Scene_Splash.prototype.stop方法

該方法是場景停止時要執(zhí)行的處理。這里用一個 fadeOutAll 淡出效果,淡出畫面及所有背景音樂、音效。

Scene_Splash.prototype.stop = function() {
    Scene_Base.prototype.stop.call(this);
    this.fadeOutAll();
};

Scene_Splash.prototype.terminate方法

該方法是在切換到其它場景時終止當(dāng)前場景的處理。假如你在啟動畫面中添加了背景音樂,那么可以在這里終止背景音樂或音效的播放。

Scene_Splash.prototype.terminate = function() {
    Scene_Base.prototype.terminate.call(this);
    AudioManager.stopAll();
};

Scene_Splash.prototype.update方法

該方法是每幀運行一次的更新處理,可以在該方法中檢測是否需要切換到其它場景、要切換到哪個場景等。(當(dāng)然,如果你要實現(xiàn)動態(tài)logo,那么也可以在這里更新logo動畫。)
  現(xiàn)在,我們想在啟動畫面停留90幀,90幀后自動切換到標(biāo)題畫面。那么代碼如下:

Scene_Splash.prototype.update = function() {
    this._wait = this._wait || 0;//如果this._wait尚未定義,則定義并賦值為0;當(dāng)然,這個_wait的定義代碼最好放到構(gòu)建器或create方法中進行
    if(this._wait>=0) {
        if (this._wait >= 90) {
            SceneManager.goto(Scene_Title);
            this._wait = -1;//讓_wait=-1確保90幀后這段代碼不會再被運行,否則會出現(xiàn)一直要goto卻goto不了的情形
        } else {
            this._wait++;
        }
    }
    Scene_Base.prototype.update.call(this);
};

如果同時想在玩家點擊啟動畫面或按下確定鍵后立即切換到標(biāo)題畫面而不用再等待完90幀,可以改為以下代碼:

Scene_Splash.prototype.update = function() {
    if (this.isActive() && !this.isBusy() && (Input.isTriggered('ok') || TouchInput.isTriggered())) {//新增
        SceneManager.goto(Scene_Title);
        return;
    }
    
    if (this._wait == undefined) { this._wait = 0; }
    if (this._wait >= 0) {
        if (this._wait >= 90) {
            SceneManager.goto(Scene_Title);
            this._wait = -1
        } else {
            this._wait++;
        }
    }
    Scene_Base.prototype.update.call(this);
};

Input.isTriggered('ok') 用于檢測玩家是否按下了確定鍵,TouchInput.isTriggered() 用于檢測玩家是否點擊了屏幕,如果按下了確定鍵或點擊了屏幕,則進入標(biāo)題界面。

至此,一個啟動畫面的插件就完成了,完整代碼如下:


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();
        SceneManager.goto(Scene_Splash);
        Window_TitleCommand.initCommandPosition();
    }
    this.updateDocumentTitle();
};

function Scene_Splash() {
    this.initialize.apply(this, arguments);
}

Scene_Splash.prototype = Object.create(Scene_Base.prototype);
Scene_Splash.prototype.constructor = Scene_Splash;

Scene_Splash.prototype.initialize = function() {
    Scene_Base.prototype.initialize.call(this);
};

Scene_Splash.prototype.create = function() {
    Scene_Base.prototype.create.call(this);

    this._wait = 0;
    this.logo=new Sprite();
    this.logo.bitmap=ImageManager.loadSystem("MyLogo");
    this.addChild(this.logo);
};

Scene_Splash.prototype.start = function() {
    Scene_Base.prototype.start.call(this);
    this.startFadeIn(this.slowFadeSpeed(), false);

    this.logo.anchor.x=0.5;
    this.logo.anchor.y=0.5;
    this.logo.x=Graphics.width/2;
    this.logo.y=Graphics.height/2;
};

Scene_Splash.prototype.update = function() {
    if (this.isActive() && !this.isBusy() && (Input.isTriggered('ok') || TouchInput.isTriggered())) {
        SceneManager.goto(Scene_Title);
        return;
    }

    this._wait = this._wait || 0;
    if (this._wait >= 0) {
        if (this._wait >= 90) {
            SceneManager.goto(Scene_Title);
            this._wait = -1
        } else {
            this._wait++;
        }
    }
    Scene_Base.prototype.update.call(this);
};

Scene_Splash.prototype.stop = function() {
    Scene_Base.prototype.stop.call(this);
    this.fadeOutAll();
};

Scene_Splash.prototype.terminate = function() {
    Scene_Base.prototype.terminate.call(this);
    AudioManager.stopAll();
};

可以改進的地方:啟動圖的圖片、等待時間這二項可以做成插件參數(shù),以便可以自由設(shè)置。有關(guān)如何實現(xiàn)插件參數(shù),請參考我的另一篇教程:【RPG Maker MV插件編程】【實例教程1】怎樣編寫一個插件?

by: Mandarava(鰻駝螺) 2017.06.14

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容