设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 2075|回复: 9
打印 上一主题 下一主题

[交流讨论] 事件执行方式的扩展(更新5、6)

[复制链接]

Lv6.析梦学徒

老鹰

梦石
40
星屑
34755
在线时间
6741 小时
注册时间
2012-5-26
帖子
3259

极短24评委极短23参与极短22参与极短21评委老司机慢点开短篇十吟唱者组别冠军开拓者剧作品鉴家

跳转到指定楼层
1
发表于 2022-6-23 00:09:48 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 百里_飞柳 于 2022-6-27 11:38 编辑

(写点没人看的东西)

在RM的游玩过程中,事件的编写可以说占据了一大半的时间。可视化的新建事件、高效全面的事件指令、直观的触发方式,充盈了整个游戏流程的血肉。

以下的插件脚本,如果链接失效,请直接前往我的GitHub仓库中的Event System目录下查找。
(毕竟我很可能会进行一些没啥用的重命名)(Gitee禁止了未登陆用户访问,就很怪)


0
先对默认设计的几种事件执行方式进行一些说明:

“按键触发”是最基础的方式,当玩家移动到事件面前,按下确定键(空格键)就能执行该事件,效果等同 event.start (比如 $game_map.events[1] 就是 1号事件 的 Game_Event对象),本质上是给该事件设置了一个flag,而在 $game_map 中有一个实时监测的事件解释器,当监测到有 flag 的事件时,就会把它的当前事件页的内容拉过来执行,也因此,当任一事件执行时,其它事件就没法再执行了(而玩家的按键移动也有判定,当存在事件执行时,不准移动)。

“玩家接触”“事件接触”的原理是一样的,只不过一个是在 $game_player 中判定,一个是在 Game_Event 中判定,具体的,在进行移动但失败时,如果面前一格是事件/玩家,那就给该事件/自身设置 flag,然后再由 $game_map 的事件解释器来后续执行。

“自动执行”就更简单了,每一帧都会给自己设置 flag,也就是说它在疯狂抢占 $game_map 的事件解释器,不留给其它事件机会,因此存在这类事件,且没有及时消除、关闭时,游戏就会和卡死了一样,根本无法操作。

“并行执行”就有一些特殊了,它会在事件生成时,同时给这个事件一个专属的事件解释器,确保了它能够顺利执行,不会抢占其它事件的执行资源。但要注意,一些公共资源(比如对话框)还是会抢占的。


1
特别的,在事件指令中的“公共事件”,它相当于把某个公共事件的全部内容拉了过来,全部执行完成后才会继续。这里有一个特别要注意的地方,公共事件中的事件指令“暂时消除事件”因为是依据事件ID,所以没有问题,还是消除了触发公共事件调用的原事件,但公共事件中的事件指令“中止事件处理”只能中止公共事件的执行,无法中止原事件,

“公共事件”是一个非常方便的设计,能够将重复的内容提取出来,就如同Ruby中的方法(可惜公共事件没法传入参数,只能自己约定全局变量),但是什么都写进公共事件的话,总觉得有点太臃肿,而且数量多了后,也有点不好整理和搜索。

注意到03都可以自由调用任意事件页来执行,怎么XP之后就删去了这个指令呢?

我写了一个这样的扩展:呼叫指定事件

不仅可以如同调用公共事件一样,调用任意地图中的任意事件的任意页,还可以在菜单等原本无法执行事件的地方,执行事件页(当然,功能有删减)。

在事件“脚本”中,编写 call_event(mid, eid, pid) 来执行指定的事件页,其中 mid 为地图ID,eid 为编辑器中的事件ID, pid 为事件页的序号(0时代表取符合出现条件的最大页)。

当然,这个调用和“公共事件”是一样的,其中指令的【本事件】都会变成当前事件。


2
在进行一些面向对象编程时,我发现“作为一个独立个体”的方式真的很直观,那么能不能用到事件上呢?

在利用C++的QT时,令人印象深刻的是GUI中的消息机制,其实也就是“客户端-服务端”的模式,“服务端”时刻刷新,查看是否有来自“客户端”的消息,如果有,就及时做出响应。

据此,我设计了这样一个插件:事件消息机制

将事件作为一个独立更新的个体,外界可以给它传入消息,然后它自己进行检索,看看自己是否能够响应这个消息(存在预先写好的对应内容),如果能,就处理一下。

具体的,对于一个事件 event ,可以给它传入一个 “被击退” 的消息,即 event.msg("被击退") ,随后,它会在自己的全部事件页中查找有没有 “被击退” 的标签,如果有,就会创建出一个并行执行的解释器,来执行 标签“被击退” 到 标签“END” 之间的指令。

依据这样的思想,就可以很容易实现各种互动,比如子弹击中敌人,本质上可以是开枪时,朝玩家前方检索事件,如果检索到了一个满足条件的事件(比如名称中含有“敌人”),就可以给这个事件发送一个 “被击中” 的消息,然后在这个事件里去处理后续效果。

当然,这个模式下还存在一个巨大的问题:需要能够进行事件检索,才能知道到底要给哪个事件发送消息,而这,只能依靠自己手动编写……

此外,每个事件都要在自己的事件页里编写执行内容,哪怕用公共事件之类的偷懒,也还是要编写标签,才能让事件知道自己可以响应,于是在以后需要修改时,会是地狱吧(确信

更关键的,没有参数,真的没有地方可以塞参数啊,事件没有只属于它自己的变量(就连扩展的独立变量,其实都是在一个全局变量里划分出一小块,依据地图id、事件id、变量id来检索……),使用事件指令时也没法方便调用自定义的参数。


3
在游玩各种新游时,我发现其中的NPC都会有不止一个功能选项,尽管在RM中可以利用选择框来进行设置,但额外的确定、切换、取消操作略显繁琐,而且在编辑器里套了一层选项后,再后续编写其它内容就有点臃肿了。

为此,我编写了一个简易的互动扩展UI:事件互动扩展

当玩家面对事件时,且已经是按下确定键就能触发的状态时,将会显示一个简易的指令UI,用于展示该事件的全部功能,以及按下确定键后将会执行的功能。此时,按下 SHIFT 键可以切换到下一个功能,而按下方向键,将正常移动走人,并自动关闭指令UI。

本质上还是将当前事件页利用标签对进行了划分,标签对的格式继承了“事件消息机制”。当默认中使用 event.start 来表示执行当前事件页时,该脚本中使用   event.start_ex(sym) 来执行指定的互动(其中 sym 为对应标签的字符串,比如之前说过的 "被击中"),当然,执行时效果是一样的,只是被执行指令的范围缩小了。

同时,也兼容了“呼叫指定事件”,使得它也能指定事件页中更小的范围了。

同时,也兼容了“事件消息机制”,因为标签对格式一样,也可以用 event.msg(sym) 来并行执行。


4
在进行地图上的简易ARPG的编写时,我发现,阻碍的有几个方面:一是技能的判定范围,即检索指定范围内的事件,二是敌人事件的编写,即如何处理敌人的攻击、受伤,甚至是特殊的动作。

关于技能判定范围,依然没有找到什么较好的方法,于是现在还是只能是yyds的圆心判定……

而关于敌人事件,之前在创作《弱水愿》时,我完全使用了“事件消息机制”和“事件警报机制”,最后果然被绕晕了,全是并行的判定,而且每个敌人都要写一遍整套的,如果不是有“事件拷贝”,可能就直接摆烂了。

在我继续更新这个脚本时:简易事件ARPG扩展

我尝试将事件个体进一步独立化,即执行的内容不再局限于自己预先编写的,也可以是别的事件编写好的,而这不同于“呼叫指定事件”的是,此处的执行必须要是并行的,因为不可能等着它判定完才能往玩家继续移动啊。

于是,对于一个事件 event,可以通过 event.run_event(params) 来让它为【本事件】,去并行执行指定的事件页,比如 $game_map.events[1].run_event({:mid => 1, :eid => 1}) 就是让 1号事件并行执行 1号地图1号事件的(符合出现条件的事件页的)内容。

这样做,就相当于把这些事件本应该写在它自己事件页里的内容,又提取了出来放到一个独立事件里,后续想要修改时也更加方便,而要制作特殊情况时,也可以在事件脚本里对当前事件进行判断。


5(2022.6.27)
上一节中提到了“事件警报机制”,它是一个给事件附加的实时判断,当满足编写的条件时(编写的Ruby脚本在被eval后返回true),将执行预先编写的Ruby脚本,也就相当于每个事件都自带了一个并行,只不过判定条件和执行内容都是依靠在注释中编写脚本。

但在实际使用的过程中,我发现了几个问题:每个事件的注释中都要重复写一大段脚本;如果想要的判定稍微复杂一点,在一个注释指令中甚至可能写不下,还是要在脚本中自己写全局方法,再在注释中调用;后续修改时很不方便,一大段文本没有换行没有高亮,属于是写完就扔不想再看的程度了。

于是我重新把它写成了:事件自动触发,同时废弃之前的警报机制。

比如是事件页开头的注释中编写 <自动 eval=玩家距离2 sym1=惊讶>,就是利用脚本中的 “玩家距离2” 所对应的预设脚本(具体功能是判定玩家与当前事件的距离是否小于等于2),当条件返回真时,就触发当前页的“惊讶”互动,如果没找到该互动,那就直接触发当前事件页。

在新插件中,统一把需要判定的Ruby脚本放置于了脚本的常量中,在事件注释中只需要指定该脚本的预设名称,这样做大幅简化了注释中的设置,但可惜不能传入参数(因为我丑陋的各种封装),同时满足判定条件时的执行内容变成了当前事件页,而如果使用了之前说的“事件消息机制”或者“事件互动扩展”,同样可以指定当前页中的对应标签对,并且引入了三个不同的执行时机:判定条件由不满足变成满足时、判定条件一直满足时、判定条件由满足变成不满足时,分别都可以设置独立的标签。

本质上其实是自造的一个自动执行,大概方便制作既要按键触发,又要自动触发的事件吧,但我也还没实际用过(心虚)


6(2022.6.27)
在不断使用“呼叫指定事件”时,我发现了一个关键的不足。在同时使用比如“事件互动扩展”时,不得不这样来设计:
标签:某个动作
脚本:call_event("eid=1, sym=某个动作")
标签:END

因为“事件互动扩展”只会读取标签指令,并不会关注你实际运行什么指令,也就导致了如果想用“呼叫指定事件”来偷懒,不得不再编写一组标签让它知道能够响应这个动作。

偷懒了,但没完全偷懒,如果中途修改了动作的名称,全部事件又要改一遍……
这真的不符合快乐做游戏的原则!

所以我给“呼叫指定事件”进行了一次小小的升级:现在可以通过事件注释,来把指定事件页的内容直接全部贴过来了!

比如编写事件注释: 事件页替换 | mid=1 eid=2 pid=3 ,就是把1号地图2号事件的第3页的全部内容放置到该注释位置,同时删去该注释,实际效果就和在该位置编写了这些事件指令一样,所以也就能保证那些读取注释、读取标签名的插件脚本都能正常使用了。


待续...

评分

参与人数 6星屑 +999 +5 收起 理由
WLian + 1 精品文章
zhangc + 1 精品文章
KB.Driver + 1 精品文章
cinderelmini + 1 塞糖
alexncf125 + 333 + 1 不明觉厉
VIPArcher + 666 精品文章

查看全部评分

Lv4.逐梦者

梦石
0
星屑
11180
在线时间
2066 小时
注册时间
2013-6-10
帖子
1516
2
发表于 2022-6-23 11:31:13 | 只看该作者
真乃精品之文章也!
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
994
在线时间
89 小时
注册时间
2022-3-19
帖子
59
3
发表于 2022-6-23 19:51:07 | 只看该作者
本帖最后由 tuifeiheihu 于 2022-6-24 11:46 编辑

我觉得呼叫指定事件很适合用于制作CG回想欸,那么似乎就存在一个问题了,呼叫整页事件的话,就会导致变量或者开关改变了,有没有办法跳过变量开关之类的操作不执行?或者只呼叫到指定的某一行?

捕获.PNG (4.66 KB, 下载次数: 32)

捕获.PNG

捕获1.PNG (4.7 KB, 下载次数: 36)

捕获1.PNG

捕获2.PNG (167.56 KB, 下载次数: 33)

捕获2.PNG

点评

搞定了,多谢指点!  发表于 2022-6-24 13:50
在呼叫指定事件的注释里有写,当同样使用了事件互动扩展时,可以增加一个参数sym  发表于 2022-6-24 13:38
我找到缺少的组件了,脚本可以正常使用了。但是用标签似乎只能划分当前事件的执行范围,要划分呼叫事件的执行范围该怎么操作呢?  发表于 2022-6-24 12:23
是我表述不准确了,应该说场景回想更准确。能用标签划分范围的话应该能解决问题了,谢谢大佬  发表于 2022-6-24 08:33
这个倒是和CG回看没有什么联系吧,cg就一个显示图片,有呼叫的功夫直接复制也行……不过再加上事件互动扩展,就可以执行指定标签对之间的内容了  发表于 2022-6-23 22:45
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
10
星屑
39597
在线时间
1920 小时
注册时间
2010-11-14
帖子
3320

R考场第七期纪念奖

4
发表于 2022-6-25 16:08:53 | 只看该作者
学习领教了。
之前还没系统地整理过触发事件的方式,这么一说就清楚了。
用头画头像,用脚写脚本
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
1
星屑
4506
在线时间
1151 小时
注册时间
2016-10-28
帖子
551

开拓者

5
发表于 2022-6-27 12:17:27 | 只看该作者
鹰佬牛逼!等我要填坑的时候再来仔细看【喂
用脑子来养鱼的杯子。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-30 00:49

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表