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

Project1

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

[交流讨论] 歪门邪道事件心得[1]:为什么我的事件标题手感不好

[复制链接]

Lv5.捕梦者 (版主)

梦石
28
星屑
10170
在线时间
4673 小时
注册时间
2011-8-22
帖子
1279

开拓者

跳转到指定楼层
1
发表于 2018-4-7 11:01:16 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

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

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

x
本帖最后由 ⑨姐姐 于 2018-9-12 16:36 编辑

一直想开这个坑,今天终于开了。这一系列会专注于一些比较边缘地带的知识,它们经常被作者们当做“玄学”,或者被不屑一顾。但是,每个现象都是有它的道理的,深入了解下去,就能对RM的运作方式更加熟悉,制作出更符合心意的游戏效果。
这系列面向的是有一定事件基础的制作者们,并没有脚本水平的要求(完全不会也没关系)。另一方面,也许写了很长时间脚本但对RM的默认内容关注不多的,也能从中得到一些有用的东西吧。

欢迎反馈关于内容深浅以及描述方式等等的各种问题,也欢迎提供各种大家在RM中的“玄学”以及一直当做习惯却难以理解的地方,在以后的几期中也可以把这些作为主题的。
-------------------------------------------------------------

一天,埃里克百无聊赖地在海洋上行走(不要问他是如何做到的)。


他觉得,是时候开始游戏了。“开始游戏”……就是说需要个游戏标题:



用图片当做三个按钮,然后用并行事件判断当前的选项和图片的透明度,像这样——





可是,埃里克发现了一个问题:按左右键的时候,不是每次都成功的,有时候按了但是毫无反应。
“为什么我的事件标题手感不好呢?明明所有地方都写对了。”

“你遇到问题总是愁眉苦脸,这可不是勇者该有的样子呢。”娜塔莉不知什么时候出现在这里。


“我猜,按键没反应,是不是RM内部的按键输入时好时坏?”

“不可能。”娜塔莉否定了埃里克的猜想,“如果RM的输入真的有问题,为什么其他菜单的窗口都那么流畅呢?”

“难道是很多人说的,事件的效率天生不如脚本,用事件就会卡顿?呜呜呜,我要去学脚本……”

“给我打起精神来你这白毛!你忘了事件的背后就是脚本在运行吗?这两者又有什么区别呢。”

“事件的背后就是脚本?”

“一看你就没有好好听大贤者的讲课。来,我们打开脚本编辑器,找到Game_Interpreter。46行。”

RUBY 代码复制
  1. #--------------------------------------------------------------------------
  2. # * Event Setup
  3. #--------------------------------------------------------------------------
  4. def setup(list, event_id = 0)
  5.   clear
  6.   @map_id = $game_map.map_id
  7.   @event_id = event_id
  8.   @list = list
  9.   create_fiber
  10. end

在埃里克疑惑的目光中,娜塔莉解释道:“你看,这个setup,就是把事件的内容放入脚本中去执行了。list是事件列表,event_id是事件编号。所以我们编辑的每一个事件,其实都会丢到脚本里去执行的。既然这样,为什么要说事件速度慢呢?根本就是无稽之谈。”

埃里克还是没有完全搞懂:“我还记得一些脚本,这种等于号的都只是把一个值放到另一个变量里的操作,比如a=2就是把a变成2。就算我生成了好多个变量,但它们也只是数据倒来倒去而已,事件放进去以后,怎么执行呢?”

“事件执行的奥秘,就在create_fiber里了。”

娜塔莉一遍说着,一遍顺着脚本往下追溯:

RUBY 代码复制
  1. #--------------------------------------------------------------------------
  2. # * Create Fiber
  3. #--------------------------------------------------------------------------
  4. def create_fiber
  5.   @fiber = Fiber.new { run } if @list
  6. end

RUBY 代码复制
  1. #--------------------------------------------------------------------------
  2. [font=&quot]# * Execute[/font]
  3. #--------------------------------------------------------------------------
  4. def run
  5.   wait_for_message
  6.   while @list[@index] do
  7.     execute_command
  8.     @index += 1
  9.   end
  10.   Fiber.yield
  11.   @fiber = nil
  12. end



“埃里克,你看这个run,不就是执行事件的过程吗。execute_command的意思是执行一条事件指令,@index += 1的意思是把事件执行的位置往下移一格。你可以想象,你用铅笔指着一条事件,执行完以后再执行下一条事件的感觉。”

埃里克反而更疑惑了:“从这里看来,我上面写的事件应该是一点问题也没有啊,怎么可能按键失效呢。除非事件没有正常执行,没能通过条件分歧判断到我的按键,才会出现失效的情况吧。”

娜塔莉沉思片刻,两眼突然放出了光芒,把埃里克吓了一跳:“我明白了,你的事件确实没问题,问题出在事件结束的时候。埃里克,我考你一个问题,从上面的run当中,你能看出事件结束的时候会发生什么吗?”

“事件结束的时候,@index就超过事件列表的长度了,所以@list[index]就拿不到事件的内容,这时候while……”

“答对了,while @list[index]的循环就会正常退出,事件也就结束了。接下来呢?”

“接下来……Fiber.yield,这是什么意思呢?”

娜塔莉把代码翻到了Game_Interpreter的236行:

RUBY 代码复制
  1. #--------------------------------------------------------------------------
  2. # * Wait
  3. #--------------------------------------------------------------------------
  4. def wait(duration)
  5.   duration.times { Fiber.yield }
  6. end

“这里duration.times就是重复duration那么多次的操作。你看,一个叫做wait的东西,重复了那么多次的Fiber.yield,还不能猜出Fiber.yield是做什么的?”

埃里克恍然大悟:“wait我知道,就是事件里的等待。用N次某个操作组成了等待N帧,那某个操作就是‘等待1帧’了吧。”

娜塔莉点点头:“在这里确实可以理解成等待1帧。准确地说,是暂时退出Fiber上下文,去执行其他内容,等到1帧以后再来继续执行这个Fiber。”[如果想要了解关于Fiber更多的知识,可以看这篇文章的介绍]

“你还是别讲Fiber啊上下文什么的了,我暂且理解成等待1帧没错吧,那为什么是这里会导致出问题呢?”

“并行事件只要在地图上,它就会循环重启执行,这一点你作为事件党,应该很了解吧。”[如果想要了解它的原理,可以参考Game_Event脚本,一直拉到最后就能看到的def update]

“那是当然,我埃里克再怎么说,也是游戏制作勇者啊。”

“可是你发现了吗,你用来判断按键的并行事件,其实不是和游戏帧率一样,每秒60次,而是每秒30次。”

“每秒30次……也就是实际上一次并行事件占用了2帧吗。是不是因为,当到达下一帧的时候原本并行事件该重启了,结果却因为上面多等待了一帧,结果没有重启?这等待的一帧,就是我的键盘‘失灵’的时机?”

“你终于明白了。”娜塔莉笑道,“实际上你每次按键,都是在赌随机数啊。赌你按键的时刻是不是恰好落在执行事件的一帧上。假如落到了等待的一帧,那就没反应啦。所以快改脚本吧。”

“不行,不行。我作为勇者,怎么能认输呢,我偏要用事件的方式,把这个问题解决了。”

“这回你倒是说对了,说不定有什么其他人的脚本,会利用到这条特性呢。那就看看你能用事件搞出什么花样吧。”

只过了片刻,埃里克就找到了解决问题的办法:




果然,这样处理以后,按键就完全流畅了。

那么今天的课后习题就是,为什么这样处理以后按键流畅了呢?上面提到的“多出的一帧”去哪儿了呢?

用到的工程: DeviantEventTutorial1.zip (1.33 MB, 下载次数: 297)

正确答案

评分

参与人数 12+12 收起 理由
indio + 1 精品文章
多啦A户 + 1 精品文章
水野·迪尔 + 1 精品文章
鑫晴 + 1 精品文章
人民卫戍部队 + 1 精品文章
Mayaru + 1 塞糖
Kim_Shyuen + 1 精品文章
W.Q.C. + 1 精品文章
2256538860 + 1 精品文章
迷糊的安安 + 1 终于知道喂什么了

查看全部评分

Lv3.寻梦者

梦石
0
星屑
4863
在线时间
485 小时
注册时间
2018-6-18
帖子
613
19
发表于 2022-2-11 17:55:34 | 只看该作者
我感觉这么做就是为了优化游戏的运行吧。
这个引擎原本方向就是做简单的游戏吧。
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
330
在线时间
17 小时
注册时间
2022-1-1
帖子
45
18
发表于 2022-2-3 21:33:22 | 只看该作者
好家伙翻译到第一个次我就懂了问题的答案(小白 看不懂7楼
每次运行后需要等待1帧才能运行下一次
要修复这个bug需要改代码
爷不会代码
爷加个循环
循环一次不用等待1帧
所以就不会吞按键了XD
LLLLLLLLLLLLLLohy吖
回复 支持 反对

使用道具 举报

Lv3.寻梦者 (暗夜天使)

精灵族の天使

梦石
0
星屑
1702
在线时间
3038 小时
注册时间
2007-3-16
帖子
33731

开拓者贵宾

17
发表于 2020-12-9 09:32:30 | 只看该作者
本帖最后由 精灵使者 于 2020-12-9 09:53 编辑

等待帧是个好东西,其实事件也可以等待帧(选择“等待”选项)
如果我记得没错的话,渐变画面需要等待相应的帧数,以及运行脚本后至少要等待1帧
如果是纯事件标题的话就可以用等待帧微调手感
一般的情况下我基本上是使用“事件陷阱”来保证选项成功触发
简单的说,和原版一样,使用变量来控制你的选项,然后按回车后根据变量触发打开的事件,应该是这样的。
事件菜单可以做到很多东西,例如LOGO和开头CG之类的。
顺便,还有一个重要的事。
第一个选项下的“移动图片”后面还要有个“1帧”对吧。
你那三个1帧需要3帧来完成这个动作
所以后面一定要至少等待3帧来保证图片正常的显示完成。
“脚本不会考虑执行图片处理的等待帧”
是这里出了问题
移动图片,更改色调等图片操作,都需要等待帧。
选择项中间也要必须插1帧,这样的话才能正确的反映输入情况,因为循环执行起来似乎整个游戏都停止工作了(?)
“有的时候跑得太快也不是啥好事”
所以写脚本的时候也会加入@wait_count或者是Graphics.sleep来控制脚本速度
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (暗夜天使)

梦石
18
星屑
12732
在线时间
2104 小时
注册时间
2012-12-12
帖子
559
16
发表于 2020-12-9 00:05:41 | 只看该作者
今天才发现!!学到了!

葱兔の游戏列表 (´・ω・`)
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
384
在线时间
29 小时
注册时间
2018-6-1
帖子
42
15
发表于 2018-6-9 12:56:32 | 只看该作者
未执行完啊!我明白了——“因为事件没有结束,所以就跳过了多出的一帧”

点评

是的。  发表于 2018-6-9 13:27
我本是仅有两片叶子的花,可黑暗的不公使我拥有荆棘
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
384
在线时间
29 小时
注册时间
2018-6-1
帖子
42
14
发表于 2018-6-7 20:01:55 | 只看该作者
双叶荆棘 发表于 2018-6-1 21:24
【作业】多加了wait,还有其他事件

其实这里面的原理……是加的脚本一定会控制时间什么的

点评

如果遇到不理解的地方也没问题,可以提出来的,我们再讨论……  发表于 2018-6-7 21:45
建议看一下7楼老鹰的答案吧,写得比较详细~  发表于 2018-6-7 21:44
我本是仅有两片叶子的花,可黑暗的不公使我拥有荆棘
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
384
在线时间
29 小时
注册时间
2018-6-1
帖子
42
13
发表于 2018-6-1 21:24:25 | 只看该作者
【作业】多加了wait,还有其他事件

点评

可以继续深入思考一下后面的原理~  发表于 2018-6-1 22:35
我本是仅有两片叶子的花,可黑暗的不公使我拥有荆棘
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2338
在线时间
275 小时
注册时间
2017-7-25
帖子
163
12
发表于 2018-4-11 18:38:35 | 只看该作者
RM确实有很多操作是直接设置体验dio差,但是中间加个等待一帧就手感贼6了,大概是因为等待一帧从某种角度避免了6楼说的毛病?

点评

如果你遇到了什么现象欢迎投稿,我会开一期来讲解的~  发表于 2018-4-11 18:49
其实要看具体情况,原因也不好一概而论。有的时候可能等待1帧给了地图刷新的机会,让地图上能即时地显示出你要显示的东西。  发表于 2018-4-11 18:48
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
28
星屑
10170
在线时间
4673 小时
注册时间
2011-8-22
帖子
1279

开拓者

11
 楼主| 发表于 2018-4-11 07:44:11 | 只看该作者
本帖最后由 ⑨姐姐 于 2018-4-11 07:54 编辑
Mayaru 发表于 2018-4-11 05:20
(哇!瞧我发现了什么!一个野生的九姐姐教程!青蛙味嘎嘣脆,蛋白质是触手的五倍x)
感谢教程~大概理解了 ...


for也是可以的,用法是 for [variable] in [range],比如
RUBY 代码复制
  1. for i in 1 .. 5
  2.   p i
  3. end

就能输出1、2、3、4、5。其中 1 .. 5 表示一个range。

上面的@index表示的是“当前执行事件的过程中正执行到的序号”。@list是事件列表,所以@list[@index]就是从@list中取出当前执行的那一条事件了。while @list[@index],只要当@index不超出@list的范围就能一直循环下去。它的初始值是@list的第一条,应该就是0了。

评分

参与人数 1+1 收起 理由
Mayaru + 1 感谢解答!

查看全部评分

回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2025-7-29 04:02

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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