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

Project1

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

[交流讨论] 关于Drill移动镜头插件 解决事件抖动问题的尝试

[复制链接]

Lv4.逐梦者

梦石
0
星屑
6939
在线时间
638 小时
注册时间
2012-7-29
帖子
173
跳转到指定楼层
1
发表于 2020-3-11 06:54:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 开关关 于 2020-3-24 11:06 编辑

曾用标题:关于Drill移动镜头插件 解决事件贴图出现像素偏移的常试

标题:关于Drill移动镜头插件 解决事件抖动问题的尝试

 @Drill_up 大佬你好,我想请你看一眼这个帖子。这是关于你写的移动镜头插件插件的讨论。

原插件连接:https://rpg.blue/thread-409713-1-2.html


  最近听说Drill大佬的移动镜头插件更新了,赶紧在自己的游戏里装上了最新版(v1.6)。

  以前的版本有事件贴图出现像素偏移的问题,像我这种建筑物元件不够事件来凑的,就会十分不爽。玩家移动时,NPC都会发抖抽搐,充当建筑物的事件也会开始地震似的摇晃,观感十分差。不知道大家用这款插件时有没有遇到这个问题?

  看代码,新版本似乎解决了一些问题。上面有注释的这行代码规定,当镜头与目的地距离不足1像素时,瞬间补齐剩余距离;下面这行有注释的代码规定,镜头移动速度不足1/4像素时补足到1/4。

此处有折叠的代码1

  现在已经比原来好多了。但是,还是有轻微的事件贴图出现像素偏移的问题。可以看到,不论是移动的过程中,还是移动的最后,都有轻微的卡顿。

此处有折叠的动图1

  由于低分辨率的限制,镜头移动有卡顿是无法避免的。我现在想要做的,是仅通过修改这个插件,使事件贴图尽量与地图贴图同步移动。

  我假设不同步的原因是镜头在移动的时候,地图贴图和事件贴图对于位置为小数的显示的理解有所不同。其中一个认为不足1像素就忽略小数,另一个认为要四舍五入(还可能是不足1像素补加到1),这样在不同时刻地图和事件的贴图就产生了最多1像素的位移差。我称呼会引起这个问题的小数为“歧义小数”。未安装移动镜头插件时,镜头的移动时匀速的,只会有整数的位移,因此不会呈现出这个问题。可以说,最大的问题其实在于自带的代码不合理。但是我看了自带的代码,发现里面各种对象互相引用,错综复杂,我不太懂代码,怕改了自带代码会炸,所以决定只改插件。

  我的第一个打算是把最小速度(1/4像素)改成最小速度为1像素,这样可以保证避免四舍五入不同导致的移动像素数不一致造成的事件贴图抖动问题。

此处有折叠的代码2

此处有折叠的动图2

  这时我注意到,即将停下的镜头移动末端确实没有问题了,但是在移动的过程中依然有问题。我猜测是移动过程中产生了“歧义小数”。所以应该把平时的移动也给它附加上最小移动1像素的限制。

  我以前也在v1.4上干过这件事,当时是用的土法,直接对speed先/48然后向上取整再*48,也能解决这个问题。但是那样由于每次刷新时,只要移动,都会移动至少1像素,这就导致原来有的丝滑感没了。因此,我需要换个思路。

  丝滑感的来源是经过算法算出的每次刷新移动距离,也就是随丝滑函数变化而变化的速度。我的修改应该仅降低speed的精度,而不应该影响speed的整体变化曲线。用声波来类比形容的话就是变成方波但不要变调。

  我的思路是,定义两个全局变量“镜头移动助手”,代表镜头移动量的计算过程值。这个值存储起来,以后一直使用。每当镜头需要移动,移动的量就加(右下加,左上减)在偏移缓存上,然后取镜头移动助手四舍五入后的值作为speed,最后对镜头移动助手减去speed。镜头移动助手剩下没有给speed的量会加到下次的移动中。

  开始。

  我在359行的初始化中加入三个变量,其中两个是镜头移动助手,还有一个是最小速度。

此处有折叠的代码3

  然后改一改镜头移动相关的代码……

此处有折叠的代码4

  测试,确实丝滑,但是发现镜头左移或上移后会差一个像素,于是对它作了一些修改。我回过头看尚未修改的代码,发现每次移动至少1像素是原作者故意为之,于是又给加了回去。下面是目前确定的样子。

此处有折叠的代码5

  然后在原本的632行,“容器 - 切换地图时”中加入两行。我的理解是场景移动时执行这些代码,于是在这里插入了镜头移动助手的初始化。

此处有折叠的代码6

  运行!

此处有折叠的动图3

  感觉还行,事件贴图出现像素偏移的问题不明显了。如果这个图看不出来,可以再看下面这张图。

此处有折叠的动图6、7

  效果是不是比原来好一些?尽管测试中还是会时不时发生事件贴图出现像素偏移,但是已经在我个人的接受范围内了。

  总结一下,我的方法核心思路是把移动小数个像素的镜头改成移动整数个像素。其中有两个细节,一个是为了保持原有速度曲线,加了个“镜头移动助手”来记录原本的移动;另一个是为了避免精度产生的误差,人为制造了更大的差。



  谢谢大家耐心看完。我这代码逻辑挺乱的,但愿没有提升你们的血压。我希望能抛转引玉,请问各位大佬有什么解决方法吗?


补充:做gif的时候发现,从gif上根本看不出多大差别。把源码放上来就可以方便体验交流,但是源码是Drill大佬原创的,我修改后放出来,有二次发布的嫌疑。如果Drill大佬真的看到这个帖子,我就向他询问能不能在这里放修改后的源码。







评分

参与人数 1+1 收起 理由
白嫩白嫩的 + 1 精品文章

查看全部评分

Lv5.捕梦者

梦石
0
星屑
28005
在线时间
271 小时
注册时间
2018-7-27
帖子
323
2
发表于 2020-3-11 10:14:26 | 只看该作者

厉害了,写那么长的文字,是个细心的大佬。
支持。
量子妹: 只要你愿意开始,什么时候出发都不晚。
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
540
在线时间
330 小时
注册时间
2010-8-16
帖子
21
3
发表于 2020-3-11 10:38:44 | 只看该作者
tql!是大佬~两位都是大佬
似乎移动量还是会部分出现1像素的偏移.....
感觉...还是有哪里没同步上,似乎是停下来那一瞬间...
郁闷ing......
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
0
星屑
28005
在线时间
271 小时
注册时间
2018-7-27
帖子
323
4
发表于 2020-3-11 12:11:49 | 只看该作者
本帖最后由 Drill_up 于 2020-3-11 12:13 编辑

首先,感谢你提供的思路。


我把你的代码优化了一下,其实这个部分本来我没打算深入的……因为我当时的目标,是为了镜头暂停后,所有像素一定归位到标准位置。过程稍微监督一下就好。
你这里实际上是提供了像素补正值,使得每次移动都是 相对 标准的像素值,移动后就不会出现抖动的情况。
实际上,rmmv这个函数的公式扭转了很多次,估计你也被“tileHeight()”给弄头晕了吧。
JAVASCRIPT 代码复制
  1. if (y2 > this.centerY()){
  2.                 var distance = Math.abs(y2 - this.centerY());
  3.                 var pixel_distance = distance * $gameMap.tileHeight() ;                                                                                //像素距离
  4.                 var pixel_speed = Math.min(pixel_distance/speedRatio_y,$gameSystem._drill_LCa_speedMax);        //像素速度
  5.                 if( pixel_speed < 0.25 ){ pixel_speed = 0.25; }                                                                                                //像素最小速度(1/4像素)
  6.  
  7.                 if( pixel_distance < pixel_speed ){                                                //最小收敛间距
  8.                         $gameTemp._drill_LCa_pixel_fix_y = 0;                                //(镜头停止移动后,所有像素必须吻合归位)
  9.                         $gameMap.scrollDown( distance );                                        //
  10.                 }else{                                                       
  11.                         pixel_speed += $gameTemp._drill_LCa_pixel_fix_y;                                                        //速度小数位补正
  12.                         $gameTemp._drill_LCa_pixel_fix_y = pixel_speed - Math.round(pixel_speed);        //补正值
  13.                         pixel_speed = Math.round(pixel_speed);                                                                                //设置速度为固定像素速度
  14.                         $gameMap.scrollDown( pixel_speed/$gameMap.tileHeight() );                                        //
  15.                 }
  16.  
  17.     }

总的来说,镜头需要解决的问题有两个:
1.镜头暂停移动后,所有像素一定归位到标准位置。
2.每次移动时,需要防止事件出现抖动。
但是,rmmv和js本身的局限性,给我们的思路造成了一些局限:
1. distance 是 1/$gameMap.tileHeight()  的像素值,写代码时经常被绕晕。
2. 所有编程语言,频繁使用除号,一定会造成精度丢失。(比如你有时候会看到0.9999999999999999992的值,而不是整数)
3. 镜头移动每次都是固定的像素值,小数位后的精度会丢失。事件的位置和镜头的不匹配,造成抖动。
你的思路解决了问题3.
考虑到问题1,我这里将速度和距离转成了 var  pixel_distance 和 var  pixel_speed 像素单位。因为像素单位也可能是小数,像素单位后面的小数位,才是需要的补正值。
考虑到问题2,也就是你图中最后,镜头停止了,但是事件偏偏多出了1像素的缝隙。
这个是编程语言除法的缺陷,这里直接用"$gameMap.scrollDown( distance );",也就是为什么我之前需要强调的最小收敛间距


图中大多数地方都没有出现问题,但是在坐标(51,13)的位置,移动过程中还是出现了缝隙,不过没有抖动,而且镜头暂停后,缝隙被收敛了。
基本问题已经被解决。
量子妹: 只要你愿意开始,什么时候出发都不晚。
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
540
在线时间
330 小时
注册时间
2010-8-16
帖子
21
5
发表于 2020-3-11 12:36:55 | 只看该作者
钻头牛逼(破音)
辛苦了~
郁闷ing......
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
6939
在线时间
638 小时
注册时间
2012-7-29
帖子
173
6
 楼主| 发表于 2020-3-12 16:19:52 | 只看该作者
本帖最后由 开关关 于 2020-3-12 16:30 编辑
Drill_up 发表于 2020-3-11 12:11
首先,感谢你提供的思路。


大佬回复我了啊啊!谢谢你愿意深究这个问题。优化的代码太棒了,解决了很多问题。

我猜问题2并不是不能解决,如果精度丢失会导致显示有偏移,那就说明自带的Game_Map一定有问题。Game_Map里面记录坐标的变量的基本单位都是1格,而不是1像素,没办法避免精度问题。假如能重写Game_Map类,以1像素作为基本单位,就可以解决问题,还能实现一些其他效果。但是又怕牵扯到其他的类,不太敢动Game_Map。

总之谢谢大佬,我会使用大佬的代码并继续寻找更好的解决之道。

我还有一个疑问,请问为什么像素最小速度是1/4像素?

点评

因为1/8太小,1/2太大,必须要是2的倍数(*ˉ﹃ˉ)  发表于 2020-3-18 11:03
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
6939
在线时间
638 小时
注册时间
2012-7-29
帖子
173
7
 楼主| 发表于 2020-3-12 16:36:18 | 只看该作者
kuaile412 发表于 2020-3-11 10:38
tql!是大佬~两位都是大佬
似乎移动量还是会部分出现1像素的偏移.....
感觉...还是有哪里没同步上,似乎是 ...

这个1像素的偏移看来是赖在这里不走了。_(:з」∠)_

除了改Game_Map类,我想不到还有什么办法能彻底解决这个问题......
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
6939
在线时间
638 小时
注册时间
2012-7-29
帖子
173
8
 楼主| 发表于 2020-3-16 01:49:42 | 只看该作者
本帖最后由 开关关 于 2020-3-19 03:22 编辑
Drill_up 发表于 2020-3-11 12:11
首先,感谢你提供的思路。

  几天前拜读了Drill_up大佬的代码,认为大佬的代码比我的逻辑通顺了很多,也更加合理。于是我套用了大佬的代码,但是发现抖动现象反而又出现了。

此处有直接套用的大佬的代码

此处有三张动图

  总觉得大佬的代码缺了什么东西。_(:з」∠)_

  抖动和移动时偏移的现象出现频率较高。因为除法必然出现的误差可能偏大可能偏小,我在之前修改的代码中加入了“允许误差”(叫做“手动增加误差”更合适),让计算结果必然偏大。具体实现就是每次移动时加入一个不影响整体的小值,但是这个小值会使整体不容易出现歧义。这个步骤让镜头移动的像素更加可控,有可能消除歧义。加入以后,抖动的问题得到很大缓解,几乎不出现了,而且移动时偏移的出现频率也得到降低。

  移动结束后还会偏移一个像素现象的出现频率比较中等。我猜测大佬设计每次最少移动1/4像素,就是为了既能避免镜头移动多了偏移一整个像素,又能在镜头移动少半个像素时给予补齐。但是测试表明,有时出现一个像素的偏移时,y2和this.centerY()的值竟然是相等的,这样这个错误就十分狡猾地绕过了大佬设置的矫正程序。于是我加了个镜头移动停止后的矫正程序,一旦x2,y2分别与this.centerX(),this.centerY()相等,就对$gameMap._displayX,$gameMap._displayY取四舍五入的整数,对坐标进行矫正。

此处有再次修改的代码

  最终运行的效果终于跟此楼引用的楼层(4楼)里面那个效果图一样了。经测试这些改动与镜头墙功能不冲突,与看向事件功能未知。但是测试过程中一直没离开出生点太远,如果有积少成多的错误,暂时还看不出来。

  最后再次感谢Drill_up大佬的指引。
回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
0
星屑
28005
在线时间
271 小时
注册时间
2018-7-27
帖子
323
9
发表于 2020-3-18 11:08:24 | 只看该作者
本帖最后由 Drill_up 于 2020-3-18 12:17 编辑

(´⊙ω⊙`) 镜头bug是我的代码造成的问题,我给你代码的时候,提供了分段的思路,
但是我没有注意到分段的pixel_speed在进入分段时判断的值不一样,因为round了。也就出现了镜头墙的bug。
你其实不需要绕路那么多,我原先那段代码的三行换一下位置就可以了,你可以试试看。
速度变低之后,镜头一定要收敛,且镜头收敛之后一定静止,只要确保这一点,镜头墙、看向镜头位置就都不会出问题。


===================================================================================
测试了一下,发现第一次收敛还是比较重要的,第一次收敛是为了防止1像素的突出,第二次收敛是为了避免镜头bug。
JAVASCRIPT 代码复制
  1. if (y2 > this.centerY()){
  2.                 var distance = Math.abs(y2 - this.centerY());
  3.                 var pixel_distance = distance * $gameMap.tileHeight() ;                                                                                //像素距离
  4.                 var pixel_speed = Math.min(pixel_distance/speedRatio_y,$gameSystem._drill_LCa_speedMax);        //像素速度
  5.                 if( pixel_speed < 0.25 ){ pixel_speed = 0.25; }                                                                                                //像素最小速度(1/4像素)
  6.  
  7.                 if( pixel_distance < pixel_speed ){                                                        //第一次收敛(最小收敛间距)
  8.                         $gameTemp._drill_LCa_pixel_fix_y = 0;                                        //(镜头停止移动后,所有像素必须吻合归位)
  9.                         $gameMap.scrollDown( distance );                                                //
  10.                 }else{                                                       
  11.                         pixel_speed += $gameTemp._drill_LCa_pixel_fix_y;                                                        //速度小数位补正
  12.                         $gameTemp._drill_LCa_pixel_fix_y = pixel_speed - Math.round(pixel_speed);        //补正值
  13.                         pixel_speed = Math.round(pixel_speed);                                                                                //设置速度为固定像素速度
  14.  
  15.                         if( pixel_distance < pixel_speed ){                                                //第二次收敛(round镜头墙bug)
  16.                                 $gameTemp._drill_LCa_pixel_fix_y = 0;                                //
  17.                                 $gameMap.scrollDown( distance );                                        //
  18.                         }else{
  19.                                 $gameMap.scrollDown( pixel_speed/$gameMap.tileHeight() );       
  20.                         }
  21.                 }   
  22.     }



另外,脚本我也贴出来了,你如果可以,麻烦测测会不会有其他bug。

Drill_LayerCamera.rar

11.27 KB, 下载次数: 63

量子妹: 只要你愿意开始,什么时候出发都不晚。
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
6939
在线时间
638 小时
注册时间
2012-7-29
帖子
173
10
 楼主| 发表于 2020-3-18 14:52:26 | 只看该作者
本帖最后由 开关关 于 2020-3-19 03:24 编辑
Drill_up 发表于 2020-3-18 11:08
(´⊙ω⊙`) 镜头bug是我的代码造成的问题,我给你代码的时候,提供了分段的思路,
但是我没有注意到分段的 ...


恍然大悟!pixel_speed在参与判断之后又被round了,所以镜头每次移动才都有偏移!

谢谢大佬,我下载脚本试试看。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-4-26 14:13

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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