在我们开始学习脚本之前,可能已经有很多同学知道了,MV是使用一种叫做JavaScript的脚本语言的。我们大概明白js可以实现很多事件无法完成的操作,也可以实现很多绚丽的场景效果。但是这些都是一些朦朦胧胧的感觉而已。我们在正式开始学习JavaScript(简称JS)之前,我想首先给各位大致介绍一下JS这门语言。同时说明一下,我们MV和JS究竟有什么关系?MV为什么需要js作为脚本?
什么是JS?一起来了解JS的历史吧!
JS,原名Javascript,最早是为了完成网页端的表单验证所被发明出来的,再后来,JavaScript被引入了ECMA,进行了一代代更新,诞生出了DOM、BOM、node等技术,在现在,JS已经变成了一个真正的世界级语言了。
什么?没看懂这段话?很正常,教科书一般都喜欢写这种绕口的定义,所以说大家看不懂高数书或者线代是很正常的,不是说你学不会,而是说学校的书根本就没打算好好教你!言归正传,我写这个的目的就是想说,在本文,坚决不会用这种枯燥、乏味的词语来讲解!!一切的一切都会尽可能的通俗易懂,毕竟对于一个游戏来说,乐趣是最重要的。一个游戏引擎的教程当然也要充满乐趣才行啦!
好,再次言归正传,JS为什么会被发明出来呢?在JS之前,已经拥有了横扫千军万马的C++,还有傲视群雄的Java,何必要再推出这么一个新生儿呢?
诸位请搬好小板凳,故事即将开始。
大家都有用过网站吧?在上网的时候,如果单纯浏览还好,如果要发帖或者评论什么的,往往会要求你进行登录或者注册。就以哔哩哔哩的注册为例:

你看,如果注册时,昵称不符合要求,那么浏览器就会告诉你昵称有问题。直到你把这些都改好之后,才可以点击注册的按钮。这个在现在看来可能是理所应当的设计了,但是在20年前的1995年,这种操作还无法实现。
当时的人们如果想要注册账号,首先需要点击这个注册按钮,然后数据会被传到服务器里面,然后服务器会分析这个昵称是否符合要求,如果不符合,那么服务器会发消息回去告知用户。
一般来说,服务器响应还是很快的,这个设计确实没有什么问题。但是如果服务器在很远的地方呢?或者网速不行呢?我为了注册一个账号,首先发送了一个账号过去,等了一分钟,网页才有了响应,告诉我我的账号格式有问题。然后我又得重新发一遍。如果网速再不行,传不过去,那么用户体验就会非常差。
所以JavaScript就被发明出来了。
JavaScript可以在浏览器里面直接分析你的账号数据是否符合要求,直到你完全修正后之后,才把数据发送过去。这样就可以极大提高用户体验了。
那么为什么非要叫JavaScript??它和java有什么关系?
答案是:没有关系!就跟雷锋和雷峰塔一样,就和老婆和老婆饼一样。仅仅是名字一样而已。
不过话又说回来,虽然两个语言没啥关系,但是这两个名字确确实实还是有关系的。
其实JavaScript诞生于浏览器大战的时代,这个浏览器大战在这里就不多讲了。如果同志们有兴趣,可以去看我的前端讲解。在1995年,布兰登·艾奇发明了JavaScript语言,但是他也不是兴趣使然,而是他工作的公司Netscape(网景)要求的。
其实啊,Netscape公司当初和发明java的sun公司私下关系密切,最开始Netscape打算用java作为网页端的语言的,但是因为这样会带来很多麻烦,所以不得不放弃了。但是Netscape贼心不死,便要求员工布兰登·艾奇发明一个专门服务于网页的语言,要求就是必须和java足够像。
但是这程序员写起代码来啊,思维就不收他自己控制了。布兰登·艾奇不愧是天才程序员,仅仅用了10天就把JavaScript设计完成了!结果,,,,,因为写的太快,很多地方设计的很不合理,而且最最重要的是,,这个语言和java根本就不像!!!!!!
布兰登·艾奇这下慌了,老板给的任务不能不完成啊!怎么办?没办法了,虽然语言不像,但是至少名字像吧。所以就给这个语言起名为了JavaScript。
如今啊,JavaScript已经不仅仅服务于网页端了,包括我们的RPGMakerMV的这个引擎都是JavaScript写的。可以说是非常非常全能的语言了。
RPGMV实际上是用一个叫做nw.js的框架所制作的,这个东西是一个非常非常强大的框架,微信也是用这个开发的。可以简单理解为,游戏引擎是专门来开发游戏的,而这种应用框架是专门用来写应用软件的。RPGMakerMV这个引擎软件就是用nw.js这个框架写的。而这个框架特点就是全面支持JavaScript。所以MV当然也全面支持JavaScript啦。
当然这个理由有点牵强,但是使用nw.js框架,使得RPGMV确实对JS有着完美的支持,我们何乐而不为呢?
RPGMV底层使用的是nw.js框架,同时还在使用PIXI动画框架,这个玩意也是用JavaScript来编写和操作的,我们之后也会学习到这个框架。
另外补充一下,现在nw.js也基本上被淘汰了,现在最主流的开发环境叫做electron ,连VSCode都是用这个开发的。
在我们开始学习之前,我还想给给位介绍一个新同学。因为本学期的课程毕竟还是太无聊啦,大家一个人学习很可能就坚持不下去啦。所以我专门请来了一个小姐姐和大家共同学习。在今后的脚本课程中,大家要好好相处哦~。
 
    
教程分为两个部分:第一个是比较有趣的主线课,第二个则是严肃严谨的支线课。主线课中讲授的内容比较简单,面向完全没有编程经验,或者是想系统学习的同学,而且有迷子同学作为陪伴。而支线课则是为主线课做的补充和进阶,而且主要面向已经有开发经验的同学。
之所以采用这种方法,我也是经过了一番思考。如果只是为了刻意营造简单的感觉,而对一些复杂语法避重就轻,只会让更多人懵逼。而如果只是为了严谨和复杂,那么真的还不如去看官方文档。所以采用了这种双线教学。我在这里想说明,支线内容不代表可以真的不看!而是说如果现在看不懂,可以暂时放着,等主线的经验足够高了,再来看也不迟。
支线内容将会在前面标注星号*。
在本课程中将会讲解js语法基础,基础API调用、不带插件指令的插件编写方法等内容。
不过呢,虽然一篇的文章不长,不过我不建议一口气看完哦!建议看的时候每次一个课时即可。
一个课时就是一个主线搭配对应支线这样来看。并且看完之后请务必亲自动手试试看!
虽然很枯燥,但是这个请务必仔细阅读。
下载VS Code
首先,我们需要下载一个叫做VS Code的编辑器,大概这个样子: 。这个玩意可以说是非常非常强大了,就算各位以后不继续开发RPGMV了,也强烈建议不要卸载它,以后迟早用得到的。
。这个玩意可以说是非常非常强大了,就算各位以后不继续开发RPGMV了,也强烈建议不要卸载它,以后迟早用得到的。
下载地址在这里:https://code.visualstudio.com/。点进去后,直接点”Download for Windows“即可。安装的话,就是一路点点点,没有什么难度。各位自行安装即可。
安装插件(请保证有网!)
在软件的左上角找到一个俄罗斯方块模样的图标,点进去之后,像我这样搜索”chinese“,下载中文插件。

然后再搜索live server,并安装。

安装node环境。(可选)
因为js脚本可以在node环境和web环境执行,我们为了方便起见直接使用浏览器学习,但是也可以自行下载node环境。
好,我们这节预备课就到这里。
下节课将会开始讲解js脚本的基础。
在学习JS之前,我想先考一考各位。事件指令我想各位都已经十分熟练了吧?那么在事件指令的第三页,右下角的两条指令是什么?忘记了?

没错就是脚本和插件指令!!!我们今天学习的脚本就需要写在里面。当然了实际上MV中可以写js脚本的地方有非常非常多,我们今天仅仅只学习这一种而已。
首先我们先来体验一下吧。
点击脚本事件,在里面写上这句代码。
xxxxxxxxxx11alert("hello world!");然后运行游戏。
就可以看到"hello world"的字样了。如果你成功运行出来了这句话,那么欢迎你进入JS的世界!我们即将开展这场JS的大冒险。
我们首先来学习一下js的基本类型,然后再学习一下三种流程控制的语句。。。。。
你以为我要这么讲?不! 我们还是直接通过游戏项目来学习吧!题材呢就选《勇者斗恶龙》吧。
不过我要说明一下,之后的内容很多其实都是可以用事件完成的,只不过本课是为了讲解JS脚本,所以尽可能用了脚本。实际上开发中,要尽可能使用事件指令。
那么在开发前,首先我们得要有一个剧本的开头:
很久很久以前,遥远的大蛇皮大陆上居住着善良的蛇人,还有可怕的恶龙。
每年,国王都会派遣大量的勇者去讨伐恶龙。
好,那么我们就先从这两句开始吧,首先当然是创建开场动画了。在事件指令中点击创建脚本的事件,然后把这个代码粘过去并执行。
xxxxxxxxxx11alert("很久很久以前,遥远的大蛇皮大陆上居住着善良的蛇人,还有可怕的恶龙。每年,国王都会派遣大量的勇者去讨伐恶龙。");怎么样,是否成功出现了这句话呢?
好,那么我们继续,,,

 
xxxxxxxxxx21var landName = "大蛇皮";2alert(`很久很久以前,遥远的${landName}大陆上居住着善良的蛇人,还有可怕的恶龙。每年,国王都会派遣大量的勇者去讨伐恶龙。`);再去粘贴过去试试看吧!效果是一样的。但是我们之后再次进行更改可就方便多了。
这就是变量的作用,变量就是一个可以储存数据的东西,里面不仅仅可以存放这种文字,也可以存放数字等其他类型,之后会经常看到的。
对于这个代码还有一个要注意的地方。不知道你发现了吗?两句话的颜色,在本教程里面是不一样的!实际上第一个代码用的是双引号来把句子包裹起来的,而第二个用的是反引号,反引号就是在TAB键上面那个东西和波浪号在一起。
用反引号包裹起来的语句就叫做模板字符串。只有模板字符串才能够使用变量。调用变量的语法就是${变量名}。
如果不适用模板字符串,那么也可以通过字符串拼接的方法实现同样的效果。
在两个字符串之间使用+号连接变量。比如:
xxxxxxxxxx21var landName="小蛇皮";2alert("很久很久以前,遥远的"+landName+"大陆上居住着善良的蛇人,还有可怕的恶龙。每年,国王都会派遣大量的勇者去讨伐恶龙。");
好了,我们继续开始MV的学习吧!
下面我们再增加一段剧情:
xxxxxxxxxx21var characterName = "大蛇人";2alert(`我们的勇者${characterName},他的传奇故事就发生在这里。`);再去粘过去试试看吧!

哈哈哈,迷子同学果然也发现了这个问题吗?
实际上alert这种弹窗虽然可以给玩家展示信息,但是表现的效果真的很差,尤其是在写游戏剧情的时候,要是通篇都是这种弹窗,实在是太low啦。
实际上这种弹窗一般都是警示或者是提示语出现的。比如说注册账号成功,会有一个弹窗告知注册成功;而注册失败同样也有弹窗。但是如果是描述剧情的话,用弹窗真的是不合时宜!
那么应该用什么呢?还记得在事件编辑器中是如何打印信息的吗?
是的,就是使用显示文字的事件指令,这应该是我们接触到的第一条事件指令了。
◆文本:无, 窗口, 底部
:文本:没错,我就是显示文字的事件指令!
实际上我们也能用代码来实现这个效果。
其实所有的事件指令都是可以用代码来实现的。MV官方把这些事件都封装成了各种代码,这些可以被我们使用的代码就叫API。
那么这些代码在哪里写呢?其中最常见的一个写法,就是通过脚本的事件指令,把代码直接写在里面。
我们现在就来试一试吧,把刚才的剧情改写成使用API的版本。
xxxxxxxxxx41var landName = "大蛇皮";2var characterName = "大蛇人";3$gameMessage.add(`很久很久以前,遥远的${landName}大陆上居住着善良的蛇人,还有可怕的恶龙。每年,国王都会派遣大量的勇者去讨伐恶龙。`);4$gameMessage.add(`我们的勇者${characterName},他的传奇故事就发生在这里。`);
效果如何呢?是否比alert强太多了呢?
但是我想,这时候你可能也发现了,,,,

这是怎末回事啊!为什么文字被遮挡住了一半?
实际上这个方法在调用的时候和使用事件是一样的。那就是不能超过那条虚线,在编辑器中我们可以看到虚线,在写代码的时候就只能根据自己的感觉来判断虚线位置了。

那你还记得在编辑器里面是怎么解决这个问题的吗?
对了就是使用回车键换行啊!
但是这时候又有一个问题,在编辑器里面,我们可以通过换行来解决一行显示不下的问题。在代码里面该如何换行呢?
这时候,我们可以通过一种叫做转义字符的东西来换行。换行的转义字符就是\n。我们把它写在代码里面看看效果吧。
xxxxxxxxxx41var landName="大蛇皮";2var characterName = "大蛇人";3$gameMessage.add(`很久很久以前,遥远的${landName}大陆上居住着善良的蛇人,\n还有可怕的恶龙。\n每年,国王都会派遣大量的勇者去讨伐恶龙。`);4$gameMessage.add(`我们的勇者${characterName},他的传奇故事就发生在这里。`);是不是已经成功换行了呢?像这种以反斜杠开头的字符就是转义字符。
这个东西我想你虽然可能用的不熟练,但是你绝对是见过哒。想起来了吗?MV中,在显示文字的事件指令中,如果鼠标长时间停留在文本里面,那么就会弹出一个窗口,里面就记录着MV中使用的各种转义字符。

不同的转义字符有着不同的含义,但是最常用的还是换行符:\n,在本次的学习中请务必记住换行符的用法。
不过要特别注意!如果在脚本代码中使用MV的转义字符,需要加两个反斜杠。例如:
xxxxxxxxxx11$gameMessage.add(`本游戏的货币单位:\\G`);
因为在代码中,反斜杠会默认修饰后面那个字符。比如说\n。如果真的想要打印\n该怎么办呢?,答案就是在前面再写一个反斜杠!这样子第一个反斜杠就会修饰第二个反斜杠,就不会影响到n了。而\\的意思就是打印一个\,所以就能打印出来\n了。
MV的这些转义字符并不是JS自带的!所以说,如果是在事件中写 \G, 实际上在MV内部,系统会把\G转化为货币单位;但是在写代码的时候,首先是编译器来处理代码,它会把\G解析为G,(反斜杠+字母,大部分都会直接解析为字母本身),然后再把结果交给MV处理,MV把代码拿到手里的时候,就只剩下G了。所以我们要写\\G,编译器会把这个解析为\G,然后MV再来解析成为货币单位。
${变量名}的格式来调用变量。脚本事件指令中,我们可以书写JS代码。$gameMessage.add()方法可以实现显示文字的事件指令,同时要注意没有换行的提示。\n的符号。这个叫做转义字符,MV中也提供了很多转义字符,要记得善于使用这些符号。
相信已经有很多同学之前已经了解过其他语言了,这些同学可能会有以下烦恼:
也就是说:
以上种种烦恼我大概是能够想象到的,不过不要着急,我们现在就来帮助这些同学快速入门js。而对于已经有js基础的同学,我建议你也还是再看看,权当查漏补缺啦。而对之前完全没有学过程序设计的同学,也不要害怕,我还是建议你看一遍比较好,毕竟如果真的想系统学习js,还是需要看看这些“教科书”比较好哒!
注释
js中的注释和其他语言一样,包括两种
xxxxxxxxxx61//单行注释2/*多3行注释*/4/*5*文档注释6**/
控制台输出
xxxxxxxxxx11console.log("hello world")
for循环
xxxxxxxxxx41//打印0到92for(let i=0;i<10;i++){3    console.log(i)4}
if语句
xxxxxxxxxx71if(flag){2  //语句3}else if(flag2){4 //语句25}else{6 //语句37}
函数定义与使用
注意,不需要在形参前面写声明符号
xxxxxxxxxx41function add(a,b){2  return a+b;3}4add(1+2);JS的函数,返回值默认是undefined。而且声明时不需要写形参类型和返回值类型。
类与对象(ES5)
实际上这个说法并不对,js中没有类,只有对象。但是为了大家尽快速成,可以简单理解为类。
xxxxxxxxxx81function Girl(name,age){2  this.name = name3  this.age = age4}5
6var maigo = new Girl("迷子",17); 7
8console.log(maigo.name,maigo.age);而且我没有写类的继承,这是因为类继承算是JS一个非常重要的语法知识,需要单独来讲。
分号问题
大家可能已经注意到了,我有时候写分号,有时候不写。那么到底是写还是不写????
实际上。无所谓。对,js对分号不作要求,所以写不写看自己。但是在MV中,还是建议都写上比较好,因为官方都写了。。。
js是一门动态类型的脚本语言。所谓的动态类型,就是说变量类型在声明的时候不需要指定数据类型。比如同样定义主角的名字,我们来看看以下几个语言的区别吧:
java
xxxxxxxxxx61public class HelloWorld {2    public static void main(String []args) {3        String characterName = "大蛇皮";4        System.out.println(characterName);5    }6}
C/C++(神)
xxxxxxxxxx91using namespace std;3
4int main()5{6   const char* characterName = "大蛇皮";7   cout << characterName;8   return 0;9}
python3
xxxxxxxxxx21characterName = "大蛇皮";2print(characterName);
matlab
xxxxxxxxxx11characterName = "大蛇皮"
lua
xxxxxxxxxx21characterName = "大蛇皮";2print(characterName);
c#
xxxxxxxxxx121using System;2namespace HelloWorldApplication3{4   class HelloWorld5   {6      static void Main(string[] args)7      {8         String characterName = "大蛇皮";9         Console.WriteLine(characterName);10      }11   }12}
typescript
xxxxxxxxxx21var characterName : string = "大蛇皮"2console.log(characterName)JavaScript
xxxxxxxxxx21var characterName = "大蛇皮"2console.log(characterName)
诸位能够猜到哪些是动态语言吗?对了,如果变量的声明前面没有string之类的类型标志,那么它就是动态语言。可以看到,不同的动态语言对于变量的声明也是不尽相同,像JavaScript还是需要用var来声明的,而python3、lua,他们甚至不需要给变量前写声明标志。
不过,不论怎么样写,他们的语言核心就是不需要写变量的类型,编译器会动态决定其类型,这也导致了其性能的下降。比如说C++分配一个int类型的变量,那么他的内存就是4byte。而js则很活跃,假设设置一个a=1,之后a的值还可以随时改变。可能下一秒a又变成了a=="hello",这在其他强类型语言里面是不允许的,但是js允许,所以编译器就不好给a直接分配内存了,它只能动态来推测a的类型,导致运行缓慢。
动态类型语言,不代表它没有数据类型。只是说不用在声明时标明类型罢了。
实际上js有8种数据类型:
| 类型 | 值 | 构造函数 | 
|---|---|---|
| null | null | 无 | 
| undefined | undefined | 无 | 
| string | "hello world" | Sting() | 
| number | 123 | Number() | 
| bigint [ES10] | 123n | BigInt() | 
| boolean | true false | Boolean() | 
| symbol [ES6] | 无 | |
| object | {} | Object() | 
正如各位所知的,都是一些很常见的数据类型。诸位可能不熟悉的类型就是bigint和symbol了,实际上bigint和C#中的decimal有点像。都是来对一些超级大的数进行运算时使用的,算是官方提供的一种大数运算的数据类型。
而symbol则是专门给某个对象设置唯一属性的,关于它我们之后会详细讲。
另外还要强调的一点是:null的数据类型在设计的时候有bug!(特性)
xxxxxxxxxx21typeof null //'object'2null instanceof Object //false
如果是之前学C++的同学,可能对typeof很熟悉,而学java的同学会对instanceof很熟悉。
其中typeof是意思是,看看这个null的数据类型是什么。结果答案是'object',那么之后我们又问编译器,那null是不是object的实例对象呢?答案却是false。
要知道,如果一个数据的类型是object,那么它必定是由Object构造的,但是null却是特例。这是当时设计上的一个bug,不够因为没有及时改正,现在已经来不及改了,成为了js的“特性”之一。
好,我们这次的内容就讲到这里,虽说大家想要急速入门,但是基础还是要打好的,诸位在进行下面的进阶之前,不妨看看主线剧情的内容吧!毕竟js的语法只是理论,具体怎样去用才是最重要的,而主线则更强调如何使用这些脚本。
第一课到此为止啦!大家请务必把课程里面的内容亲自试试!
好了,我们继续来创造我们的故事剧本吧。上次我们成功更改了角色的姓名,这次我们将要。。。
等一下啦!欸?又怎么了?为什么我的MV里面角色的姓名没有更改成功啊!欸?可是我们上节课不是已经验证过了吗?姓名确实是大蛇人啊?我是说游戏里面啦,就算对话里面,点击右键,在菜单栏里面,主角还是叫霍尔德啦!原来如此,你是说,就算我们说主角叫大蛇人,但是实际上游戏中主角的姓名还是霍尔德。实际上这个也很容易理解,就像$gameMessage.add一样,MV中所有的游戏数据都有自己的API。我们自己随便写的变量当然不可能影响游戏里面的数据啦,下面我们就来学习一下如何来更改角色的姓名吧!
还记得在事件中,我们使用哪个指令来更改角色姓名吗?
对了!就是更改姓名的事件指令。
◆更改名字:霍尔德, 更改姓名
这个API用起来略有点复杂,具体使用方法可以看下面:
xxxxxxxxxx21 var actor = $gameActors.actor(1) //获取第一个角色的信息(也就是主角)2 actor.setName("新名字");//把角色的名字设置为“新名字”
我们现在把之前的代码重新改写一下吧!
xxxxxxxxxx51var landName="大蛇皮";2var actor = $gameActors.actor(1) //获取第一个角色的信息(也就是主角)3actor.setName("大蛇人");//把角色的名字设置为“大蛇人”4$gameMessage.add(`很久很久以前,遥远的${landName}大陆上居住着善良的蛇人,\n还有可怕的恶龙。\n每年,国王都会派遣大量的勇者去讨伐恶龙。`);5$gameMessage.add(`我们的勇者\\N[1],他的传奇故事就发生在这里。`);
怎么样,是不是成功更改了呢?要注意到,代码里面有一个转义字符的使用,如果忘记了的话,请务必复习上一课的内容。
我们接着来完善剧情。
现在,再次把下面的剧情添加到上次的脚本后面吧!
xxxxxxxxxx951var villageName = "绵水镇"2$gameMessage.add(`每年的10月,是${villageName}猎奇鹿的日子。`);3$gameMessage.add(`而今年,收成似乎格外的好。这次出行,就足足猎到了两只。`);4$gameMessage.add(`按照以往的行情,这两只鹿,就能换到2000\\G。`);5$gameMessage.add(`当然了,除了今年老天爷的恩赐之外,\\N[1]也是村里面一等一的好手。`);6$gameMessage.add(`之前每年的猎鹿大赛上,他的成绩虽然不是年年第一,但也是名列前茅。`);7
8$gameMessage.add(`现在是正午12时。`);9$gameMessage.add(`他之所以敢这样断言,大概来源于他这么多年以来的生物钟吧。`);10$gameMessage.add(`上午7时,大公鸡晓时会准时叫他起床。`);11$gameMessage.add(`打开房门,一定能看到妹妹在饭桌前昏昏欲睡的的样子。`);12$gameMessage.add(`之后便是珍贵的早餐时间了。`)13$gameMessage.add(`新鲜的牛奶加上一小块粗麦馒头,有时还会有一小盘凉拌野菜。`)14$gameMessage.add(`简朴但是美味的食物,再加上母亲那唠叨但是温馨的家常话,这就是\\N[1]一家平静的早餐。`)15$gameMessage.add(`上午8点是工作的时间,自己猎鹿,妹妹和母亲学习纺织。父亲则去打理自家小小的麦田。`)16$gameMessage.add(`打猎会持续两天到三天,而妹妹和母亲每天正午都会在村口眺望自己,无论哪一天回来。`)17$gameMessage.add(`都能看到迎接自己的笑脸。`)18$gameMessage.add(`这样平静的日子已经不知道持续了多久,但是\\N[1]却没有半点厌倦,`);19$gameMessage.add(`他唯一的愿望就是这平静而幸福的日子能够再长一点。`);20
21//下一段剧情的转场22$gameMessage.add(`穿过一段悠长的迷木林,阳光开始渐渐的从叶间挤进\\N[1]身边。`);23$gameMessage.add(`“快到了”,\\N[1]压抑不住激动的心情。`);24$gameMessage.add(`“父亲看到这样的收成会怎样想?这笔钱足够给全家都换一身新衣了吧?”`);25$gameMessage.add(`“他不由加快了脚步。“`);26
27//转折28$gameMessage.add(`远远的,村中那棵古树已经依稀可见,但是,他的心脏却猛然抖了一下。`);29$gameMessage.add(`母亲和妹妹怎么不在??`);30$gameMessage.add(`是今天我回来的太早了吗?应该是吧,毕竟今天回来的时候跑的比较快。`);31$gameMessage.add(`虽然他的生物钟很确信现在就是正午,但是他还是说服自己不要去想。`);32$gameMessage.add(`刚才如飞的健步,现在却抖了起来,一股不祥的预感莫名袭来。`);33
34
35//发展36$gameMessage.add(`过于安静了,虽然镇子并不是什么富裕的村镇,但是正午还是热闹的。`);37$gameMessage.add(`而此刻,除了几家烟囱中缕缕的薄烟之外,镇子里竟然一个人都看不到。`);38$gameMessage.add(`整个村子死一般的宁静,唯一能听到的声音就只有他不止的心跳了。`);39$gameMessage.add(`到底是怎么了?`);40
41
42$gameMessage.add(`\\N[1]勉强拖着步子来到家门前。把猎物扔到门口,缓缓敲了敲门。`);43$gameMessage.add(`”进来吧。“一个尖细而慵懒的声音传了出来。`);44$gameMessage.add(`他认识这个声音,每年秋收之后,税收官就回来到镇中收税。`);45$gameMessage.add(`虽然\\N[1]也没有见过税收官几次,但是不知道为何,他对这尖锐的声音却异常的反感。`);46
47$gameMessage.add(`推开门,一股葡萄酒的香味扑鼻而来。`);48$gameMessage.add(`他不由看向桌子。桌子上摆满了家里平日里舍不得吃的腊肉和糖果。`);49$gameMessage.add(`还有那瓶家里已经传了50年的葡萄酒。`);50$gameMessage.add(`之前父亲还开过玩笑,要把这瓶酒传上100年,然后去城里卖掉,到时候家里可以再买上两瓶`);51$gameMessage.add(`然后过上几百年,说不定就能有钱搬到城里面,甚至买上个小官做做。`);52$gameMessage.add(`但是现在一切都随着这浓郁的酒香一起消散了。`);53
54$gameMessage.add(`父亲在桌子旁低着头站着,母亲则背着门在偷偷啜泣。`);55$gameMessage.add(`而在桌子旁坐着的当然就是税收官大人了。`);56$gameMessage.add(`你就是\\N[1]吧。`);57$gameMessage.add(`税收官把杯中的酒一饮而尽,缓缓开口。`);58$gameMessage.add(`他心中突然升起一阵无名火,但是仍然恭敬的低头回答。`);59$gameMessage.add(`是的,税收官大人。`);60$gameMessage.add(`虽然他没有抬头,但是还是能感受到税收官那肥硕的身体剧烈的颤抖了一下。`);61$gameMessage.add(`紧接着就是桌子上传来的巨响。`);62$gameMessage.add(`”蠢货,你难道不知道我现在被圣上临时授予了”集英使“的职位吗?“`);63$gameMessage.add(`\\N[1]浑身都渗出了冷汗。`);64$gameMessage.add(`妹妹的哭声也从卧室里面传出来。原来她躲在了卧室啊。`);65$gameMessage.add(`”也罢,念在你无知的份上,这次就不计较了。“`);66$gameMessage.add(`”多谢大人宽容大量,恭贺您高升。“`);67
68
69$gameMessage.add(`”嗯,那么说正事吧,“`);70$gameMessage.add(`”今年圣上要再次重启荣耀的猎龙活动,现在要招募勇者,每个村庄只有一个名额。“`);71$gameMessage.add(`而你们的村长把这个光荣的任务让给了你。`);72$gameMessage.add(`猎龙??这个活动10年前不就被取消了吗?怎么又要开始了`);73$gameMessage.add(`但是\\N[1]没有胆量把话问出来。`);74$gameMessage.add(`”那么,一个月内向你们的直辖市报道。明天早上就出发吧。“`);75$gameMessage.add(`说完,他把葡萄酒一饮而尽,”集英使“很快带着他的仆从们离开了村庄。`);76$gameMessage.add(`对了,路上你可得小心点,如果你路上出了点什么事,没有及时报道`);77$gameMessage.add(`明年你们村庄的税收就多交上2倍税收吧。`);78
79
80$gameMessage.add(`远眺着马车留下的灰烟,村庄里悄悄地传出几声开门的声音。`);81$gameMessage.add(`一家人围坐在桌前,门外是明媚的阳光,桌上是丰盛的午餐。但是气氛却沉重的喘不上气。`);82$gameMessage.add(`”我,我这两天猎到了两头奇鹿。“`);83$gameMessage.add(`父亲望了过来,挤出一丝微笑。”不愧是我儿子,好样的。好样的。“`);84$gameMessage.add(`”好了,开饭吧,这可是大丰收啊。父亲给葡萄酒瓶子里灌上稠酒。“`);85$gameMessage.add(`来,咱爷俩好久没有喝过了,今天来久违的庆祝一番吧!`);86$gameMessage.add(`\\N[1]已经想不起来那天是怎末度过的了。虽然大家对当勇者这件事缄默不提`);87$gameMessage.add(`但是半夜还是能看到母亲在缝制的身影。`);88
89$gameMessage.add(`第二天还是到来了。`);90$gameMessage.add(`父亲不知道从哪里搞来一把长刀,而母亲则拿来了一条厚重的围巾。`);91$gameMessage.add(`”快到深秋了,天冷,你平时多注意保。“`);92$gameMessage.add(`母亲话还没有就哭着紧紧的抱住了\\N[1]。`);93$gameMessage.add(`然后是妹妹,就连平日里性格厚重的父亲也落泪了。`);94$gameMessage.add(`但是分别的时候终究会来临。`);95$gameMessage.add(`就这样,我们的主角带着母亲连夜赶出来的围巾,带着父亲的长刀还有一大堆食物,踏上了成为勇者的道路。`);
好了,现在把这些粘过去吧。
欸?是不是报错了?这是怎末回事?我们不妨把这个事件拉到最下面看看,原来啊,这个脚本的命令过长了,编辑器接受不了这么多,所以有一部分代码被截掉了。一种解决方法就是,多开几个事件指令,比如下面这样,这样就可以防止代码被截掉:

另一种方法就是,我们能不能不在这里面写代码啊??????
这句话可能有点抽象,我再解释一下。
首先各位不觉得在MV这个白框框里面写代码实在是太痛苦了嘛。。。。目前的代码都是我写好的,你们只需要复制粘贴即可,那以后自己再要写代码可就没有这么轻松了。
还记得alert吗?alert是专门负责发送警示和提示消息的。实际上和alert一样,这个脚本的事件指令是专门处理简单短小的代码的。如果非要让它处理这种近百行的代码,真的是为难它了。
那么有没有什么地方可以让我们尽情写代码呢?对了,就是插件,虽然很多同学没有写过,但是总该见过吧。
MV中有三处可以编写代码:
我们之前已经学过了第一种,现在就来了解一下第二种吧!
首先打开VSCode,打开游戏所在的文件夹。
在根目录可以找到js文件夹,然后里面可以找到plugins文件夹。
在plugins文件夹中,我们新建一个Begin_story.js文件。
然后把下面的代码粘过去
xxxxxxxxxx901function storyBegin(){2    var villageName = "绵水镇"3    $gameMessage.add(`每年的10月,是${villageName}猎奇鹿的日子。`);4    $gameMessage.add(`而今年,收成似乎格外的好。这次出行,就足足猎到了两只。`);5    $gameMessage.add(`按照以往的行情,这两只鹿,就能换到2000\\G。`);6    $gameMessage.add(`当然了,除了今年老天爷的恩赐之外,\\N[1]也是村里面一等一的好手。`);7    $gameMessage.add(`之前每年的猎鹿大赛上,他的成绩虽然不是年年第一,但也是名列前茅。`);8    $gameMessage.add(`现在是正午12时。`);9    $gameMessage.add(`他之所以敢这样断言,大概来源于他这么多年以来的生物钟吧。`);10    $gameMessage.add(`上午7时,大公鸡晓时会准时叫他起床。`);11    $gameMessage.add(`打开房门,一定能看到妹妹在饭桌前昏昏欲睡的的样子。`);12    $gameMessage.add(`之后便是珍贵的早餐时间了。`)13    $gameMessage.add(`新鲜的牛奶加上一小块粗麦馒头,有时还会有一小盘凉拌野菜。`)14    $gameMessage.add(`简朴但是美味的食物,再加上母亲那唠叨但是温馨的家常话,这就是\\N[1]一家平静的早餐。`)15    $gameMessage.add(`上午8点是工作的时间,自己猎鹿,妹妹和母亲学习纺织。父亲则去打理自家小小的麦田。`)16    $gameMessage.add(`打猎会持续两天到三天,而妹妹和母亲每天正午都会在村口眺望自己,无论哪一天回来。`)17    $gameMessage.add(`都能看到迎接自己的笑脸。`)18    $gameMessage.add(`这样平静的日子已经不知道持续了多久,但是\\N[1]却没有半点厌倦,`);19    $gameMessage.add(`他唯一的愿望就是这平静而幸福的日子能够再长一点。`);20    21    //下一段剧情的转场22    $gameMessage.add(`穿过一段悠长的迷木林,阳光开始渐渐的从叶间挤进\\N[1]身边。`);23    $gameMessage.add(`“快到了”,\\N[1]压抑不住激动的心情。`);24    $gameMessage.add(`“父亲看到这样的收成会怎样想?这笔钱足够给全家都换一身新衣了吧?”`);25    $gameMessage.add(`“他不由加快了脚步。“`);26    27    //转折28    $gameMessage.add(`远远的,村中那棵古树已经依稀可见,但是,他的心脏却猛然抖了一下。`);29    $gameMessage.add(`母亲和妹妹怎么不在??`);30    $gameMessage.add(`是今天我回来的太早了吗?应该是吧,毕竟今天回来的时候跑的比较快。`);31    $gameMessage.add(`虽然他的生物钟很确信现在就是正午,但是他还是说服自己不要去想。`);32    $gameMessage.add(`刚才如飞的健步,现在却抖了起来,一股不祥的预感莫名袭来。`);33    34    35    //发展36    $gameMessage.add(`过于安静了,虽然镇子并不是什么富裕的村镇,但是正午还是热闹的。`);37    $gameMessage.add(`而此刻,除了几家烟囱中缕缕的薄烟之外,镇子里竟然一个人都看不到。`);38    $gameMessage.add(`整个村子死一般的宁静,唯一能听到的声音就只有他不止的心跳了。`);39    $gameMessage.add(`到底是怎么了?`);40    $gameMessage.add(`\\N[1]勉强拖着步子来到家门前。把猎物扔到门口,缓缓敲了敲门。`);41    $gameMessage.add(`”进来吧。“一个尖细而慵懒的声音传了出来。`);42    $gameMessage.add(`他认识这个声音,每年秋收之后,税收官就回来到镇中收税。`);43    $gameMessage.add(`虽然\\N[1]也没有见过税收官几次,但是不知道为何,他对这尖锐的声音却异常的反感。`);44    $gameMessage.add(`推开门,一股葡萄酒的香味扑鼻而来。`);45    $gameMessage.add(`他不由看向桌子。桌子上摆满了家里平日里舍不得吃的腊肉和糖果。`);46    $gameMessage.add(`还有那瓶家里已经传了50年的葡萄酒。`);47    $gameMessage.add(`之前父亲还开过玩笑,要把这瓶酒传上100年,然后去城里卖掉,到时候家里可以再买上两瓶`);48    $gameMessage.add(`然后过上几百年,说不定就能有钱搬到城里面,甚至买上个小官做做。`);49    $gameMessage.add(`但是现在一切都随着这浓郁的酒香一起消散了。`);50    51    $gameMessage.add(`父亲在桌子旁低着头站着,母亲则背着门在偷偷啜泣。`);52    $gameMessage.add(`而在桌子旁坐着的当然就是税收官大人了。`);53    $gameMessage.add(`你就是\\N[1]吧。`);54    $gameMessage.add(`税收官把杯中的酒一饮而尽,缓缓开口。`);55    $gameMessage.add(`他心中突然升起一阵无名火,但是仍然恭敬的低头回答。`);56    $gameMessage.add(`是的,税收官大人。`);57    $gameMessage.add(`虽然他没有抬头,但是还是能感受到税收官那肥硕的身体剧烈的颤抖了一下。`);58    $gameMessage.add(`紧接着就是桌子上传来的巨响。`);59    $gameMessage.add(`”蠢货,你难道不知道我现在被圣上临时授予了”集英使“的职位吗?“`);60    $gameMessage.add(`\\N[1]浑身都渗出了冷汗。`);61    $gameMessage.add(`妹妹的哭声也从卧室里面传出来。原来她躲在了卧室啊。`);62    $gameMessage.add(`”也罢,念在你无知的份上,这次就不计较了。“`);63    $gameMessage.add(`”多谢大人宽容大量,恭贺您高升。“`);64    $gameMessage.add(`”嗯,那么说正事吧,“`);65    $gameMessage.add(`”今年圣上要再次重启荣耀的猎龙活动,现在要招募勇者,每个村庄只有一个名额。“`);66    $gameMessage.add(`而你们的村长把这个光荣的任务让给了你。`);67    $gameMessage.add(`猎龙??这个活动10年前不就被取消了吗?怎么又要开始了`);68    $gameMessage.add(`但是\\N[1]没有胆量把话问出来。`);69    $gameMessage.add(`”那么,一个月内向你们的直辖市报道。明天早上就出发吧。“`);70    $gameMessage.add(`说完,他把葡萄酒一饮而尽,”集英使“很快带着他的仆从们离开了村庄。`);71    $gameMessage.add(`对了,路上你可得小心点,如果你路上出了点什么事,没有及时报道`);72    $gameMessage.add(`每年你们村庄的税收就多交上2倍税收吧。`);73    74    $gameMessage.add(`远眺着马车留下的灰烟,村庄里悄悄地传出几声开门的声音。`);75    $gameMessage.add(`一家人围坐在桌前,门外是明媚的阳光,桌上是丰盛的午餐。但是气氛却沉重的喘不上气。`);76    $gameMessage.add(`”我,我这两天猎到了两头奇鹿。“`);77    $gameMessage.add(`父亲望了过来,挤出一丝微笑。”不愧是我儿子,好样的。好样的。“`);78    $gameMessage.add(`”好了,开饭吧,这可是大丰收啊。父亲给葡萄酒瓶子里灌上稠酒。“`);79    $gameMessage.add(`来,咱爷俩好久没有喝过了,今天来久违的庆祝一番吧!`);80    $gameMessage.add(`\\N[1]已经想不起来那天是怎末度过的了。虽然大家对当勇者这件事缄默不提`);81    $gameMessage.add(`但是半夜还是能看到母亲在缝制的身影。`);82    83    $gameMessage.add(`第二天还是到来了。`);84    $gameMessage.add(`父亲不知道从哪里搞来一把长刀,而母亲则拿来了一条厚重的围巾。`);85    $gameMessage.add(`”快到深秋了,天冷,你平时多注意保。“`);86    $gameMessage.add(`母亲话还没有就哭着紧紧的抱住了\\N[1]。`);87    $gameMessage.add(`然后是妹妹,就连平日里性格厚重的父亲也落泪了。`);88    $gameMessage.add(`但是分别的时候终究会来临。`);89    $gameMessage.add(`就这样,我们的主角带着母亲连夜赶出来的围巾,带着父亲的长刀还有一大堆食物,踏上了成为勇者的道路。`);90}把之前事件指令中的代码都删掉
写上
xxxxxxxxxx11storyBegin();在插件中把这个插件打开

要注意,这次我们就不要在MV中运行游戏了,我们可以打开根目录下的index.html文件,对其右键选择open with live server

然后游戏就可以在网页中运行了。怎么样,这下是不是就能正常运行了呢?

这个东西啊,叫做函数,是插件编写中最最最重要的东西。我们下面会讲解的,不过在讲解之前我们还是先讲讲插件吧。
刚刚,我们就已经成功编写了一个插件了,有什么想法吗?
没错,相比于在脚本中直接写代码,编写插件可以说是好处多多
但是插件也不是没有缺点,插件往往被封装在一个函数中来使用的。
那么函数是什么?不要着急,我们马上就要学到。
如果累了的话休息一下也可以哟。
函数是js语法中非常非常重要的一个东西,语法上结构如下:
xxxxxxxxxx31function 函数名(参数1,参数2,,,,){2    return 返回值;3}函数一般用于代码的封装。封装、继承、多态是咱们面向对象语言最重要的三个知识。我们今天就来看看封装的知识吧!
就如刚才的例子,如果你的代码太多了,放到事件编辑器里面会显得非常臃肿,所以放到插件里面,以插件的形式调用就显得非常简洁了。而写在插件里面的代码必须封装到函数里面,这个原因比较复杂,有兴趣的同学可以看看下节课的内容,这个是作为支线课程的,
另一方面,如果你的代码比较短,但是要经常被用到,这时候,你是不是会想到些什么呢?是的!就是使用公共事件。公共事件就是用来封装代码的一种机制。
光说的话,实在不容易理解,我们不妨把这个做入游戏中看看吧!
刚刚说到主角离开了家乡踏上了成为勇者的道路,但是这路上要是光赶路也太无聊了。按照通常的做法,男主路上肯定会遇到很多野怪,那么有了野怪就要有战斗,有了战斗就要有战斗系统。
我们这次不会写出完整的战斗系统,仅仅是简单的打个草稿。
首先,我们不妨在地图上添加几个怪物。然后在每个怪物的身上都挂载一个脚本:
xxxxxxxxxx11  $gameMessage.add(`\\N[1]遇到了怪物!开始战斗!`);
唔,,,就算是草稿也太简陋了吧。说的也是呢战斗可以分为进入战斗、战斗处理。战斗结果三部分
我们把剩下的几个部分也加上去吧!
现在,再次把脚本更改为:
xxxxxxxxxx31$gameMessage.add(`\\N[1]遇到了怪物!开始战斗!`);2$gameMessage.add(`战斗中`);3$gameMessage.add(`战斗胜利!获得奖励!`);
怎么样?是不是觉得有点麻烦啦?如果今后还要对战斗系统进行什么修改,又得把所有怪物的脚本都再次进行替换。
这个情况我们是不是有些似曾相识呢?
没错!我们第一次接触变量的时候也是这种情况。更改主角名字时,我们希望只用更改一处就可以了,而不想对所有语句一个个修改。所以使用了变量。只有变量存储着真正的值,剩下的代码都是引用这个值而已。
函数也是一样的,只不过函数存放的不是字符串或者数字。它里面储存的就是代码!
如果某个代码需要被多次使用,那么最好把它封装成一个函数。这样以后修改它的时候就可以“牵一发而动全身”,不至于“遍地开花”。
所以我们就不妨把刚才的战斗代码封装一下。
xxxxxxxxxx51function battle(){2    $gameMessage.add(`\\N[1]遇到了怪物!开始战斗!`);3    $gameMessage.add(`战斗中`);4    $gameMessage.add(`战斗胜利!获得奖励!`);5}
现在再次调用它试试看吧!
现在我们如果需要修改战斗的内容,只需要修改函数里面的代码即可,大大的提高了代码的灵活性。
而这种把很多语句封装到一起的操作,我们是不是在哪里见过呢?没错,就是公共事件!
实际上
看到这里,想必一些大佬已经试过了吧,为什么非要封装成函数?如果不封装又怎么样?
答案想必各位也知道了吧,那就是:没有反应。
为什么呢?这就得来谈谈MV的生命周期了。
学习unity的同学都知道,unity的代码都是和生命周期息息相关的。比如事件唤醒的Awake、以帧数更新的的Update、控制物理操作,以赫兹更新的FixedUpdate,各司其职。
但是MV真的非常非常离谱,官方没有公开生命周期图。其实也不是不能够理解,因为MV的代码基本上都是写在插件里面的,根本就不需要担心生命周期的问题。但是这也会造成很多问题,比如莫名其妙的BUG出现了,但是又不知道为什么。
如果能知道生命周期就好了,肯定有同学这么想吧!我其实也很想知道,所以,我自己从源码的调用关系中,推导了一下MV的生命周期,这个准确性实在不敢保证。因为我技术也是非常非常废物,所以如果有错误,希望大佬门不吝赐教。
不过MV的生命周期非常复杂,一口气肯定是说不清楚的,我在这里只是简单说明一下插件的执行顺序。
首先不封装函数直接运行代码的结果各位已经看到了吧?为了防止有的同志没有试过,我把结果先贴出来:

是的,居然报错了!而且错误非常诡异,“不能从null身上读取属性。”也就是说,在执行这条命令的时候,gameMessage对象根本就没有诞生!所以才会出现这个bug。
为了理解这个bug,我们需要知道两个事情,
我首先回答第一点:
插件是在main.js被运行时就调用了。还记得刚才我是不是说过,在index.html中右键可以打开游戏。而这个html就是游戏运行时访问的第一个文件。
写过前端的同志都知道,index.html在前端就相当于main函数的地位,而一进入这个“main函数”,就可以看到里面有一个body。就是这个body加载了MV的各个源代码。
xxxxxxxxxx221<body style="background-color: black">2    3    <script type="text/javascript" src="js/libs/pixi.js"></script>4    <script type="text/javascript" src="js/libs/pixi-tilemap.js"></script>5    <script type="text/javascript" src="js/libs/pixi-picture.js"></script>6    <script type="text/javascript" src="js/libs/fpsmeter.js"></script>7    <script type="text/javascript" src="js/libs/lz-string.js"></script>8    <script type="text/javascript" src="js/libs/iphone-inline-video.browser.js"></script>9    10    11    <script type="text/javascript" src="js/rpg_core.js"></script>12    <script type="text/javascript" src="js/rpg_managers.js"></script>13    <script type="text/javascript" src="js/rpg_objects.js"></script>14    <script type="text/javascript" src="js/rpg_scenes.js"></script>15    <script type="text/javascript" src="js/rpg_sprites.js"></script>16    <script type="text/javascript" src="js/rpg_windows.js"></script>17    18    19    20    <script type="text/javascript" src="js/plugins.js"></script>21    <script type="text/javascript" src="js/main.js"></script>22</body>在里面可以看到许多的.js文件。
前面6个(我已经给你分好组了)是MV的库文件,也就是比较底层的文件,相当于<stdio><iostream>之类的,没事不要去改。
之后6个,都是游戏的各个功能,包括人物的数据、窗体的绘制、战斗的数值计算等等。游戏的运行基本上就是靠的这些,我们今后主要的学习内容就是这些js文件。
plugins.js就是当前MV中所有加载的插件。这个和插件管理器是一一对应的。
最后面这个main.js,就是我们今天要学习的。它负责的功能只有两个:
看到了吗?
首先是加载插件,然后才是开始游戏。
也就是说当我们这些语句被写入内存的时候,游戏还没有开始。
然后来回答第二个吧,这个gameMessage是什么时候诞生的?
答案就是:在游戏加载之后被new出来!
我们可以简单看一下执行顺序
xxxxxxxxxx1381//首先,全局的场景启动,加载游戏的各个画面2SceneManager.run(Scene_Boot);3
4//在SceneManager.run方法中可以看到有一个goto方法5SceneManager.run = function(sceneClass) {6    try {7        this.initialize();8        this.goto(sceneClass);9        this.requestUpdate();10    } catch (e) {11        this.catchException(e);12    }13};14
15//在goto方法中,Scene_Boot类第一次被实例化16SceneManager.goto = function(sceneClass) {17    if (sceneClass) {18        this._nextScene = new sceneClass();19    }20    if (this._scene) {21        this._scene.stop();22    }23};24
25//然后回到上面去,进入requestUpdate,在这里就可以看到一个库函数requestAnimationFrame,这个玩意是web自带的底层函数,这个已经很底层了不再赘述,我只能介绍一下这个函数的功能,这个函数的作用定期执行回调函数——SceneManager.update方法。26SceneManager.requestUpdate = function() {27    if (!this._stopped) {28        requestAnimationFrame(this.update.bind(this));29    }30};31
32//然后在回调函数中,我们可以看到有一个updateMain33SceneManager.update = function() {34    try {35        this.tickStart();36        if (Utils.isMobileSafari()) {37            this.updateInputData();38        }39        this.updateManagers();40        this.updateMain();//这个就是主更新函数41        this.tickEnd();42    } catch (e) {43        this.catchException(e);44    }45};46
47//进入updateMain,可以看到有一个updateScene48//而且我要特别强调一点,changeScene方法可以在场景切换的时候把this._scene 赋值为 this._nextScene;49SceneManager.updateMain = function() {50    if (Utils.isMobileSafari()) {51        this.changeScene();52        this.updateScene();53    } else {54        var newTime = this._getTimeInMsWithoutMobileSafari();55        var fTime = (newTime - this._currentTime) / 1000;56        if (fTime > 0.25) fTime = 0.25;57        this._currentTime = newTime;58        this._accumulator += fTime;59        while (this._accumulator >= this._deltaTime) {60            this.updateInputData();61            this.changeScene();62            this.updateScene();63            this._accumulator -= this._deltaTime;64        }65    }66    this.renderScene();67    this.requestUpdate();68};69
70
71//然后可以在updateScene看到一个 this._scene.start();72//看到这个是不是有感觉了?我刚才之所以强调changeScene方法,就是因为它会把之前的Scene_Boot设为当前的场景。73//然后执行Scene_Boot的start方法。74SceneManager.updateScene = function() {75    if (this._scene) {76        if (!this._sceneStarted && this._scene.isReady()) {77            this._scene.start();78            this._sceneStarted = true;79            this.onSceneStart();80        }81        if (this.isCurrentSceneStarted()) {82            this._scene.update();83        }84    }85};86
87
88//下面就是重点了!!89//在Scene_Boot中,有一个setupNewGame方法。90//这个方法就是真正启动游戏的方法了。91Scene_Boot.prototype.start = function() {92    Scene_Base.prototype.start.call(this);93    SoundManager.preloadImportantSounds();94    if (DataManager.isBattleTest()) {95        DataManager.setupBattleTest();96        SceneManager.goto(Scene_Battle);97    } else if (DataManager.isEventTest()) {98        DataManager.setupEventTest();99        SceneManager.goto(Scene_Map);100    } else {101        this.checkPlayerLocation();102        DataManager.setupNewGame();//我在这里!!103        SceneManager.goto(Scene_Title);104        Window_TitleCommand.initCommandPosition();105    }106    this.updateDocumentTitle();107};108
109
110
111//进入其中,我们可以看到有一个createGameObjects方法,112//顾名思义,这个方法就是创建游戏对象的113DataManager.setupNewGame = function() {114    this.createGameObjects();115    this.selectSavefileForNewGame();116    $gameParty.setupStartingMembers();117    $gamePlayer.reserveTransfer($dataSystem.startMapId,118        $dataSystem.startX, $dataSystem.startY);119    Graphics.frameCount = 0;120};121
122
123//然后就是旅途的终点了,可以看到,我们可爱的$gameMessage就在这里诞生了。124DataManager.createGameObjects = function() {125    $gameTemp          = new Game_Temp();126    $gameSystem        = new Game_System();127    $gameScreen        = new Game_Screen();128    $gameTimer         = new Game_Timer();129    $gameMessage       = new Game_Message();130    $gameSwitches      = new Game_Switches();131    $gameVariables     = new Game_Variables();132    $gameSelfSwitches  = new Game_SelfSwitches();133    $gameActors        = new Game_Actors();134    $gameParty         = new Game_Party();135    $gameTroop         = new Game_Troop();136    $gameMap           = new Game_Map();137    $gamePlayer        = new Game_Player();138};所以说,插件的加载比游戏对象要早,当然会显示错误啦!!!
怎么样?是不是有些绕呢?没有关系,本文的主题本来就是js入门,现在看不懂是很正常哒!之后会有专门的进阶课哒!
况且。。。。。。

好了,今天的课程就到这里啦!大家辛苦喽!!!
今天我们学习函数。虽然各位没有见过函数,但是各位之前可能已经不知不觉学习了函数的思想了。数据库中的公共事件就是非常典型的函数思想。
首先我们来谈一谈,为什么需要函数?人类总是一种爱干净爱整洁的生物。不仅生活中我们爱进行收纳整理,在程序开发中,我们也喜欢干净整洁的代码。而函数就是包装代码的收纳袋。如果你写的代码过长,过于复杂,那么一定要把它封装成一个函数。
函数的第二种用法其实就是公共事件了。如果有一个功能被频繁的使用,那么把它封装成函数可以说是再合适不过的了。我们今天就来学习一下函数的这个用法。
上回说到啊,这个大蛇人同志呢,应征入伍踏上了勇者之旅。但是这勇者哪有那么好当,一路上的艰辛自不用说,但是我们最关心的部分想必就是路上,和各种野怪的战斗了吧。(毕竟都拿了村里最好的刀)
那么在进行下面的游戏之前,我们得先把战斗系统设计一下。因为是脚本教学,我们就不采用自带的战斗系统了,我们将采用魔塔的那种简易的战斗系统。
我们设计这些什么什么系统之前,千万要记住,不要急着动手写代码,而是要先把你的系统脑补好。
首先,我们先来分析一下战斗的流程:
第一个可以直接使用事件的确定键来解决,而在进行第二步之前,我们得先设计一下主角的各种数值。
xxxxxxxxxx121var character_dex = 5;2var character_hp = 20;3var character_mp = 15;4var character_atk = 5;5var character_def = 7;6
7
8var enemy_dex = 3;9var enemy_hp = 10;10var enemy_mp = 15;11var enemy_atk = 3;12var enemy_def = 4;
这几句意思很简单,就是给玩家和敌人设置了各个属性。
但是下面就遇到了问题,第三步要求我们判断玩家和敌人的敏捷谁更高,如果玩家更高,那么玩家攻击。如果敌人更高,那么敌人攻击。
那这个如果和判断到底是怎么实现的呢?
我们之前接触到的代码都是一次执行完的,只要写上去就能运行,但是实际开发中怎么可能都这么一帆风顺呢?现在我们就可以请出我们今天的新语法了——if语句。
xxxxxxxxxx51if (character_dex>enemy_dex){2    console.log("玩家攻击!")3}else{4    console.log("敌人攻击!")5}实际上这个代码还是很显而易见的。在代码中判断如果的语法就是if。if character_dex大于enemy_dex,那么玩家攻击。else,除开之外的情况下,执行敌人攻击语句。非常的直观。
不过要注意的是,if语句的判断条件需要写在括号里面,else则不需要写括号。因为else是if之外的所有条件。
如果我是女孩,我就穿小裙子。要是我不是的话我就穿裤子。
可以看到我后一句话没有再次假设,要是我是男孩的话,,,而是直接说了要是我不是。因为else是除开if之外的情况,可以自己推导出来,所以不需要再写条件。
不过我们的战斗当然不能这么简单的写console啦,我们需要确确实实地把hp扣除掉。下面我们就来详细写一下战斗的过程吧。
xxxxxxxxxx51if (character_dex>enemy_dex){2    enemy_hp = enemy_hp - character_atk;3}else{4    character_hp = character_hp - enemy_atk;5}
好啦,现在我们去MV中试一下吧!
在js中函数是一等公民,重要性可想而知,