【RPG Maker MV插件编程】【实例教程2】制作一个启动画面

作者:Mandarava(鳗驼螺)
微博:@鳗驼螺pro

启动画面是游戏开始时,在进入标题画面前的一个显示画面,通常用于展示游戏开发商的Logo。RMMV自带一个官方启动画面插件 MadeWithMv,可以设定自己的启动图,一般来说,这个插件足够使用。本文介绍如何制作类似的一个启动画面插件。

首先,新建一个名为 MND_Splash.js 的文件放到 js/plugins 目录下,并在RMMV中安装该插件。

从哪里开始?

游戏在启动时,Scene_Boot 类用于初始化整个游戏,而 Scene_Boot.prototype.start 方法是场景开始时的处理方法。启动画面是游戏启动时的第一个“场景”,所以要创建启动画面,就应该在 start 方法中创建。来看一下 start 原始方法的实现:

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() 检测当前是否为进行战斗测试,如果是就进入战斗场景,比如在 数据库-敌群 界面进行战斗测试时;
  2. DataManager.isEventTest() 检测当前是否为事件测试,如果是则进入当前的游戏地图界面,比如在编辑事件时进行事件内容的测试时。
  3. 除此之外, else 部份就是正常启动游戏时要进入的场景的选择,可以在这里创建并进入我们的启动画面场景。

这里 SceneManager.goto(Scene_Title) 方法用于进入标题画面。从这里可以看出,RMMV在开始游戏时默认是直接进入标题画面的,所以很简单,只要将这里的 SceneManager.goto(Scene_Title) 改成进入我们的启动画面即可,如:SceneManager.goto(Scene_Splash)(假设我们的启动画面场景类叫做Scene_Splash),再由启动画面进入标题画面,为此就来创建我们的启动画面的场景类。

创建启动画面的场景类

要创建一个新的场景类,最简单的做法是改一个现有的场景类。场景类有很多,包括:Scene_BaseScene_BootScene_BattleScene_DebugScene_EquipScene_FileScene_GameEndScene_GameoverScene_ItemBaseScene_ItemScene_LoadScene_MapScene_MenuBaseScene_MenuScene_NameScene_OptionsScene_SaveScene_ShopScene_SkillScene_StatusScene_Title。分析一下这些场景类的实现,确定哪些方法需要,最后把我们要用到的方法拷贝到 MND_Splash.js 中,我们的场景类命名为:Scene_Splash。最后我们需要的方法包括以下几个:构建器部分、Scene_Splash.prototype.create 方法、Scene_Splash.prototype.start 方法、Scene_Splash.prototype.stop 方法、Scene_Splash.prototype.terminate 方法、Scene_Splash.prototype.update 方法等(当然除了构建器部分外,其它方法都是可选的)。下面就在Scene_Splash类中重写这些方法。

构建器部分

Scene_Base类是所有Scene类的基类,我们要创建的类Scene_Splash实际比较简单,所以只需要直接继承Scene_Base类就可以了。下面是Scene_Splash的构建器及初始化代码:

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方法

该方法是在场景创建时要执行的处理,在这里创建组件并将它们加入渲染队列中。所以,我们可以在这里添加要显示logo图片。假设我们的Logo图片放在 img/system/MyLogo.png,那么该方法的重写实现如下:

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);这个是调用基类(父类)的同名方法,因为我们这里是重写基类的该方法,你需要让基类中的操作也执行一下(除非你明确不想执行;即使现在基类的该方法没有执行任何操作,为了以后的兼容,比如官方在未来的某个版本添加了操作,也应该用调用基类的实现)。this.logo 就是用于显示我们的Logo图片的精灵对象,使用场景的 addChild() 方法可以将精灵加入到场景。在这里我们并没有为精灵设置显示座标,因为此时的Logo图片还没有加载完毕,读取到的图片尺寸高宽都是0,如果你需要根据图片的高宽为其定位,那么,这个定位处理应该放到 start 方法中去。

Scene_Splash.prototype.start方法

该方法是场景启动时要执行的处理。这里用 startFadeIn(duration, white) 方法让场景出现淡入效果。同时将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精灵的锚点设置到其正中心,再将其坐标设置到屏幕正中心,这样就能让精灵呈现在屏幕中心。

Scene_Splash.prototype.stop方法

该方法是场景停止时要执行的处理。这里用一个 fadeOutAll 淡出效果,淡出画面及所有背景音乐、音效。

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

Scene_Splash.prototype.terminate方法

该方法是在切换到其它场景时终止当前场景的处理。假如你在启动画面中添加了背景音乐,那么可以在这里终止背景音乐或音效的播放。

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

Scene_Splash.prototype.update方法

该方法是每帧运行一次的更新处理,可以在该方法中检测是否需要切换到其它场景、要切换到哪个场景等。(当然,如果你要实现动态logo,那么也可以在这里更新logo动画。)
  现在,我们想在启动画面停留90帧,90帧后自动切换到标题画面。那么代码如下:

Scene_Splash.prototype.update = function() {
    this._wait = this._wait || 0;//如果this._wait尚未定义,则定义并赋值为0;当然,这个_wait的定义代码最好放到构建器或create方法中进行
    if(this._wait>=0) {
        if (this._wait >= 90) {
            SceneManager.goto(Scene_Title);
            this._wait = -1;//让_wait=-1确保90帧后这段代码不会再被运行,否则会出现一直要goto却goto不了的情形
        } else {
            this._wait++;
        }
    }
    Scene_Base.prototype.update.call(this);
};

如果同时想在玩家点击启动画面或按下确定键后立即切换到标题画面而不用再等待完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() 用于检测玩家是否点击了屏幕,如果按下了确定键或点击了屏幕,则进入标题界面。

至此,一个启动画面的插件就完成了,完整代码如下:


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();
};

可以改进的地方:启动图的图片、等待时间这二项可以做成插件参数,以便可以自由设置。有关如何实现插件参数,请参考我的另一篇教程:【RPG Maker MV插件编程】【实例教程1】怎样编写一个插件?

by: Mandarava(鳗驼螺) 2017.06.14

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容