欢迎光临散文网 会员登陆 & 注册

【Terraria机制】飞镖机关与青绿压力垫板的结算

2019-01-04 22:09 作者:putianyi888  | 我要投稿

内容来源是Terraria电路群231355279的讨论和Terraria官方论坛上我和@DRKV 的讨论,原帖链接https://forums.terraria.org/index.php?threads/question-weird-mechanics-of-dart-traps-and-teal-pressure-plates.75145/

这里对原帖中的关键内容进行翻译。一些价值不大的内容会省略。

标题:【问题】飞镖机关与青绿压力垫板奇怪的机制

#1 我:

我和电路群里的人讨论了一下飞镖机关和青绿压力垫板的机制。我们有些分歧,我做了一些实验来证明或证伪我的观点。但是我们没有任何一个人可以解释这些实验结果。我现在在研究另一个东西,暂时没时间研究这个问题,所以我把我的实验发出来,看看有没有人能解释。

问题出自下面这个驱动:

原来的问题是:这些飞镖发射是否有间隔?

答案是没有。下面的截图说明所有的飞镖都是同一物理帧发射的。

也许飞镖直接生成在机关的前方,并且立刻触发了压力板?可能是对的,但是也有不对的时候。

我改变了飞镖的发射方向:

现在飞镖发射有明显的延迟了。

从上面的截图可以看出来向上发射的飞镖直接生成在机关之上,也许导致了这个延迟。

然后我缩短了机关和压力板的距离:

结果是:第一个向上射的飞镖可以触发压力板,但是第二个向下射的飞镖不可以。向上和向下的飞镖机关工作原理不同!

那么我只用向下的机关试试:

现在飞镖发射有延迟。但是这意味着向下的飞镖机关和水平的飞镖机关不一样吗?不是的。改变压力板的方向:

现在所有的飞镖都在同一物理帧发射了:

所以压力板的方向会影响到触发!

让我们单独看看向上发射的飞镖机关。下面的驱动无法生效:

但是下面的不仅生效,而且有延迟!

如果直接生成在压力板上的飞镖可以触发压力板,为什么第一个驱动会失效?

(注:本楼剩余内容是无效实验,故不翻译)

#2 DRKV:

我感觉我已经搞清楚了大多数的实验结果。我临时写了一个补丁,它可以暂停射弹的更新,从而我可以手动控制射弹的更新。(这应该不会影响实验结果的。)而且我还使用了一个Mod编辑工具去高亮射弹的碰撞箱。

首先,飞镖生成时相对机关有一个偏移量。这个偏移量根据机关的朝向各有不同。

这是在飞镖机关被激活后立刻发生的事,在任何的射弹刷新之前。你可以看到,向上发射的飞镖与众不同。我猜测这可能是由于舍入误差引起的。

另一个重要的事情是,飞镖刚生成时不会触发压力板。碰撞只会在刷新后触发。这就是压力板和机关之间必须空一格的原因。

在上面这种情况下,飞镖刚刚好碰到压力板。

这个例子很有趣。一开始时是这样的:

一次刷新之后变成了这样:

游戏是依次刷新各个射弹的。游戏按照Main.projectile数组的下标顺序遍历刷新射弹。所以我认为是这么回事:

  • 第一个飞镖刷新

  • 触发压力板

  • 电路运行,触发第二个机关,生成第二个飞镖

  • (第二个飞镖的下标比第一个飞镖下标大)

  • 第二个飞镖刷新

  • 触发下一个压力板

  • ……

我改变了飞镖的发射方向:

现在飞镖发射有明显的延迟了。

从上面的截图可以看出来向上发射的飞镖直接生成在机关之上,也许导致了这个延迟。


不是这样的。无论向上还是向下,飞镖触发压力板的时间相同。

它们初始的偏移量略有不同,但是在这个情况下不影响结果。

然后我缩短了机关和压力板的距离:

结果是:第一个向上射的飞镖可以触发压力板,但是第二个向下射的飞镖不可以。向上和向下的飞镖机关工作原理不同!

这种情况下偏移量的不同就很重要了。我的垃圾刷新调试器没法暂停碰撞过程,所以我没截到好的图。

注意观察第一次更新后飞镖的移动距离,我认为当飞镖向下发射时,飞镖会直接错过压力板,直接移动到了方块内,而当向上发射时,飞镖恰好与压力板的上一半碰撞。

那么我只用向下的机关试试:

现在飞镖发射有延迟。

没错。飞镖经过两次刷新才到达压力板。

但是这意味着向下的飞镖机关和水平的飞镖机关不一样吗?不是的。改变压力板的方向:

现在所有的飞镖都在同一物理帧发射了:

这和一开始的问题是一样的。一次刷新后的飞镖状态:

让我们单独看看向上发射的飞镖机关。下面的驱动无法生效:

我也不确定到底咋回事。

飞镖在两帧中都遇到了压力板,但是仍然没有触发。这可能是因为压力板的碰撞箱比贴图小。

但是下面的不仅生效,而且有延迟!

如果直接生成在压力板上的飞镖可以触发压力板,为什么第一个驱动会失效?

这个确实挺奇怪的。(下面的每张图之间仅间隔一次刷新)

你可能以为所有飞镖会同时发射,但是似乎一次只发射两个。这是全过程:

  • 第一个飞镖刷新

  • 触发压力板,触发下一个机关,下一个飞镖生成

  • (第二个飞镖的下标比第一个飞镖大)

  • 第一个飞镖被摧毁

  • 第二个飞镖刷新

  • 触发压力板,触发下一个机关,第三个飞镖生成

  • (现在射弹数组中第一个飞镖的位置空出来了,第三个飞镖被插入到这里)

  • 第二个飞镖摧毁

  • 后面没有需要刷新的射弹了,游戏去执行别的过程

  • 新的射弹刷新过程开始

  • 第三个飞镖刷新

  • ……

所以这是因为飞镖触发压力板和被摧毁都发生在同一次刷新中。

#3 是我提的一些问题,因为当时还没有完全理解DRKV的回复,这里省略

#4 DRKV:

我进一步研究了一下源码,根据Collision.SwitchTiles,青绿压力垫板只会在刷新后,当射弹的新位置与压力板碰撞箱相交,而旧的位置不相交时激活。

另外,似乎压力板的碰撞箱是10像素*16像素,所以事实上碰撞箱比贴图大,贴图只有8像素*16像素。

事实上我只是向MechScope里加了一个补丁,大致是这样的:

Harmony库会把这段代码插入到目标函数之前。(在这个情况下,目标函数是Projectile.Update)如果返回false,剩下的函数过程都会被跳过。SuspendableWireManager.doProjectile是一个静态变量,每次TModLoader的PostUpdate执行时我都把它置为false。按下热键时我把它置为true。

所以游戏会照常运行,但是会跳过射弹刷新,除非我按下热键。

一个非常有趣的实验是先生成一堆射弹,然后在第一个飞镖生成后立刻摧毁它们,这样的话在射弹数组的前面就会有一段空位,新的飞镖会插入在这个空位中,不会立刻刷新。

编辑:我把实验做了一下


#4 我:

我懂了。游戏在每个物理帧中以遍历射弹数组的方式刷新射弹。射弹刷新后可立刻触发压力板并插入电路过程,生成新的射弹。新的射弹会被插入到射弹数组中的第一个空位。如果这个空位在第一个射弹之前,那么直到下一物理帧才会刷新;如果空位在第一个射弹之后,那么在本次遍历中就会被刷新。

在那个奇怪的例子里,第一个飞镖在第三个飞镖生成前被摧毁,所以第三个飞镖被插入到了第一个飞镖的位置,到下一物理帧才会刷新。

#5 DRKV:

没错,就是这样。

【Terraria机制】飞镖机关与青绿压力垫板的结算的评论 (共 条)

分享到微博请遵守国家法律