基于RPGMakerMV的JavaScript基础-5

第五章        js对象实力装逼

第一节        任务系统

话说rpg游戏里面很重要的一个系统就是任务系统。但是在RPG Maker MV当中,并没有现成的任务系统来给我们使用。


虽然我们可以将事件,变量和开关联合使用来达到“任务”的效果,但是这终究是不太方便。所以,我们就来做一个任务系统,将上面的功能封装起来,方便我们的使用,毕竟有一个显式的“任务”比一堆不明所以的开关和变量更加符合我们的思维方式,不是吗?


另外,我们顺便学习一下js的面向对象编(zhuang)程(bi)。


第二节        需求分析

简而言之,我们的任务系统到底需要什么?


要炫酷的动画提示,还要跟着提示音效,还要与众不同的界面效果。


这些都不对!!!


需求分析,应当把最核心的功能给分析出来,我们制作的时候,也应当这样,先做好基本的功能,然后以此为框架,逐步完善。


至于炫酷的动画……那是什么鬼?



好了,有了这个共识,我们会发现,程序只剩下数据和功能,连输入输出的界面都不需要考虑了。这样的话,问题就简单多了。


开始分析。


我们的任务系统是基于原版MV系统的,不是基于其他大神的插件系统的。当然,我们的原则是,尽量不修改原文件,尽量不修改系统对象。



任务系统:当然是像其他游戏一样的。有各种任务,还需要实时监测任务完成的条件,对任务的状态进行管理。


任务:要有编号,名字,描述,当前所处的状态,以及各种条件下触发的动作等等。


任务数据库:用于存放静态的预定义好的任务。


第三节        对象和原型链简介

一个js对象,应该像下面一样创建:


  1. var cat=function(){
  2. }
复制代码

没错,这就是一个函数,不过js里面的函数可和别的语言的函数不同,它可以用来当做对象/类使用。


当然,在es6的新标准里,我们可以用语法糖class,从而制作像(只是看上去)其他语言里面的类一样的东西。


我们通过new来创建一个对象的副本,并且在同时运行function内的代码,这样的函数就叫做构造器。


定义在function体里面的变量,只能在function里面使用,如果外面要调用的话是不行的。那么我们该如何在外面调用呢?


js提供了原型链这种神奇的东西。简而言之,定义在原型链上的变量都是可以被继承下去的,并且可以在外面调用。通过一个简单的“.”,我们就可以访问原型链上的东西了。就像下面这样,我们可以在原型链上定义新的对象(函数也可以看做对象)。


  1. var Cat=function(){
  2.         var m=258;//在构造器内部。
  3.         this.mm=123;//不在原型链上,可以访问。
  4. }
  5. Cat.prototype.mmm=456;//在原型链上,一旦修改,全部会变。
  6. var cat1=new Cat();//创建新Cat对象,事实上是创建了对原型链的引用。
  7. var cat2=new Cat();//创建新Cat对象

  8. alert(cat1.m);//不可以访问
  9. alert(cat1.mm)//可以访问
  10. alert(cat1.mmm)//可以访问

  11. cat2.mm=5;
  12. alert(cat1.mm);//仍然是123
  13. cat2.mmm=3;
  14. alert(cat1.mmm);//也变成了3

复制代码

我们也可以在外面使用prototype来访问原型链,像下面这样定义一个函数。


  1. Cat.prototype.Say=function(){
  2.         return “Miao Miao Miao…”;
  3. }
复制代码

但是要注意的是,从同一个Cat上new出来的所有对象,它们的原型链是共享的,也就是说,只要在任意一个对象上改变了原型链的值,那么就会影响所有的对象。如下:


  1. cat1.mm=567;
  2. alert(cat2.mm);//结果也是567
复制代码

这种特性方便了继承,但是也造成了一些不便,所以我们一般只在原型链上放共同的特性,以及不会变化的函数。


那么如果我们想要创造每个对象可以取不同的值的属性,该怎么办呢?看下面的代码:


  1. var Dog=function(){
  2.         this.name=”The Dog Haven’t Name”;
  3. }
  4. Dog.prototype.getName=function(){
  5.         return this.name;
  6. };
  7. Dog.prototype.setName=function(value){
  8.         this.name=value;
  9. };
复制代码

像这样,定义在原型链上的函数里面的内容,是可以访问构造器里面定义的变量的(像上面的name),这样我们就可以为不同的Dog设置不同的name了,使用的时候只需要通过两个函数getName和setName,而这两个函数对所有的Dog来讲只有一份。



这只是一种简单的封装方法,也是js原生支持的一种方法,关于如何用js实现面向对象的各种特性,可以专门百度,有很多更好的办法。不过在这里,我们的方法就够了。


第四节        任务和管理者

简单明白了原型链之后,我们就可以正式开始了,首先,要定义一个Task对象,这应该是所有的任务对象的原型(与类相似的)。任务要有各种各样的属性和方法。


我们像下面的图5-1这样定义一个Task,注意,仍然按我的风格,放进命名空间里面装逼~~~


需要说明的是,id,title之类的属性都是各不相同的,所以应当放在构造器中定义,而且后面的几个函数也一样,分别对应着各种情况下要自动响应的动作。在我们的设计中每个Task通过定义各自的这些动作来完成自动的处理。


 
图5-1

那么后面当然还要在原型链上定义对上面的属性和方法的操作了,否则在外边是访问不到的。具体的内容可以看附件中的实际插件的脚本。



然后,我们就该定义一个管理者了——Manager。为什么非要管理者呢?难道你不觉得这样的分层设计更加的明(ke)白(yi)可(zhuang)靠(bi)吗?


这个Manager就简单多了,只需要一个任务列表(数组),用来储存我们生成的具体的Task对象。还有一些方法,用来把对任务列表的操作封装起来。调用的时候更加简单明白。定义如图5-2。
好吧,我的起名水平和封装水平一样,但是这不要紧。毕竟大致已经够我使用了。


 
图5-2
第五节        静态设定——一个不是json的json表

好吧,我们难道非得把数据写在事件里?每次都要new一个?还有,任务是事件,但是任务信息可以算是数据了,写在动态生成的地方真的好吗?


基于以上及其他原因考虑,我们将要把所有已经设计好的任务,放在一个json表里面,这样就可以方便我们设计和管理已经制作好的任务了。


但是,个人风格,为了写注释,我不用json文件,而是改写成js,把它和插件一起加载。这样除了使用的时候麻烦一些,倒也不错。


此外,我们还要在Manager里面专门定义一个函数,用来读取json(暂时仍然这么叫吧)的信息,并且转换成我们真正的Task并存在Manager的任务列表里面。这就是loadTaskFile函数的功能了。


Tasks,这个json一样的列表,关于他的具体内容可以参看附件中的文件。毕竟东西有点多,而且里面也是加了比较详细的注释的。


但是,这个loadTaskFile函数,我们还是可以在这里分析一下的,如图5-3。


 
图5-3

先将任务列表清空,然后来一个循环遍历Tasks这个(伪?)json。每次都创建一个新的Task,然后根据Tasks里面的值来设定这个新的Task对应的值(这一部分功能被放到了createByData函数里面)。最后把新的Task放进任务列表里面。然后执行一些操作:将state设置为Unrecive,将avaliable设置为true,执行自己定义的init函数。事实上就相当于进行了初始化。


同样的,自己定义的begin会在开始任务的时候执行,ifFinish会在判定任务是否完成时当做判据(返回值),end会在任务结束时执行。当然这些都要自己进行设计。


第六节        是监视者还是窗口

好了,一切设计的都很完美,但是关键的一点仍然没有进行——如何对变量进行管理?让任务达到条件自动改变状态,自动执行动作。这些都需要一个监视者,每时每刻都在执行这一任务——判定任务所处的状态。这实际上是要并行完成的,但是,我们考虑到窗口的事件模型的话。我们可以用一种比较“简单”的方法来完成这件事情——画一个窗口,然后在窗口的update里面添加上相关的判定部分,顺便还能显示一些我们所需要的信息。(这些都不重要,真的,没有任务窗口,不显示任务信息难道就是没有任务了?)


如图5-4,我们就这样完成了一个任务系统。


 
图5-4
第七节        把我的变量存起来

等等,我要存档的话,任务会不会白做了?


显然是的,因为这些代码都是每次开启游戏都会执行一遍的。也就是说,目前为止你并不能保存下来任何东西。


那该怎么办呢?


别着急,我的独门(?)秘(pian)诀(fang)即将登场。


 
图5-5
如图5-5,我们重写了两个MV的方法,DataManger的saveGame和loadGame,从而让游戏在读档和存档的时候执行我们所要干的事情~~~如图5-6所示。

在保存前,我们遍历了manager的任务列表,并且把每个任务的variables带着名字存到了一个新的空对象里面。


然后,我们使用JSON.stringify函数,将一个js对象变成了一个字符串。这样,就可以把它放进某个MV的变量(在事件窗口用到的那种)中去了。


接下来在保存,那就是实打实的被保存起来了。


下次读取的时候,只要把这个字符串上的值用JSON.parse函数还原回来就好了,这简直是太机智了。


这种方法需要付出一个MV变量槽,以及重写存档读档的函数。用不用自己决定吧。


最后的效果gif,如图5-7。
 
图5-6 

图5-7

具体这个插件如何使用,还要再细看附件中的示例和代码。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【实例教程1】怎样编写一个插件? 1. 插件的注释与定义参数 2. 读取插件参数 3. 插件指令的实现 【实例教程2】制作一个启动画面 1. 从哪里开始? 2. 创建启动画面的场景类 【实例教程3】玩转菜单初级篇 1. 给各个菜单界面添加背景 2. 让背景滚动起来 3. 在主菜单界面增加自定义菜单:改名 4. 在主菜单界面移除菜单命令 5. 在主菜单界面增加一个自定义窗口 【实例教程4】玩转标题画面 1. 美化游戏标题 2. 让背景动起来 3. 自定义标题菜单 4. 美化菜单 【实例教程5】制作小游戏:坦克大战(上) 1. 游戏结构及流程介绍 2. 相关素材资源的下载和使用 3. 基础知识:音效的播放 4. 基础知识:精灵表的切帧 5. 基础知识:使用MV中的动画 6. Scene_TankWarTitle类解析 7. Sprite_Bullet类解析 8. Sprite_Explode类解析 9. Sprite_Tank类解析 10. Sprite_Enemy类解析 11. Scene_TankWar类解析 12. Scene_TankWarGameOver类解析 【实例教程6】存档的加密解密与保护 1. 找出MV存档和读档的方式 2. 制作MV存档的修改器 3. 如何保护存档? 4. 制作一个存档保护插件 【实例教程7】制作一个传送插件 1. 传送插件的主要功能 2. 将自定义数据保存到存档中 3. meta数据的使用 4. 使用地图备注登记传送点 5. 在插件中解析并记录传送点 6. 使用地图备注登记多个传送点并在插件中记录 7. 制作传送点选取窗口显示传送点数据 8. 将物品或技能标记为传送物品、传送技能 9. 显示传送动画实现传送功能 10. 禁止使用传送道具或传送技能 11. 实现插件命令

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值