在较早的游戏中逐渐消失。需要一些帮助来弄清楚算法是如何得出的


12

抱歉,这个问题有点深奥,但我还是想不起来!

我正在研究街机游戏DoDonPachi(以及许多其他较旧的游戏)中使用的淡入淡出算法:

在此处输入图片说明

我写了一个python脚本来挑选一些像素,并在淡入淡出的过程中跟踪它们。这是结果的代表性示例。每组的第一行是起始颜色值,而随后的每一行是当前帧的颜色值和前一帧的颜色值之间的差。

Starting Value: (132, 66, 189)
Frame 1:    [9, 9, 8]
Frame 2:    [8, 8, 8]
Frame 3:    [8, 8, 8]
Frame 4:    [8, 8, 9]
Frame 5:    [9, 9, 8]
Frame 6:    [8, 8, 8]
Frame 7:    [8, 8, 8]
Frame 8:    [8, 8, 9]
Frame 9:    [9, 0, 8]
Frame 10:   [8, 0, 8]
Frame 11:   [8, 0, 8]
Frame 12:   [8, 0, 9]
Frame 13:   [9, 0, 8]
Frame 14:   [8, 0, 8]
Frame 15:   [8, 0, 8]
Frame 16:   [8, 0, 9]
Frame 17:   [0, 0, 8]
Frame 18:   [0, 0, 8]
Frame 19:   [0, 0, 8]
Frame 20:   [0, 0, 9]
Frame 21:   [0, 0, 8]
Frame 22:   [0, 0, 8]
Frame 23:   [0, 0, 8]
Frame 24:   [0, 0, 0]
Frame 25:   [0, 0, 0]
Frame 26:   [0, 0, 0]
Frame 27:   [0, 0, 0]
Frame 28:   [0, 0, 0]
Frame 29:   [0, 0, 0]

Starting Value: (132, 0, 0)
Frame 1:    [9, 0, 0]
Frame 2:    [8, 0, 0]
Frame 3:    [8, 0, 0]
Frame 4:    [8, 0, 0]
Frame 5:    [9, 0, 0]
Frame 6:    [8, 0, 0]
Frame 7:    [8, 0, 0]
Frame 8:    [8, 0, 0]
Frame 9:    [9, 0, 0]
Frame 10:   [8, 0, 0]
Frame 11:   [8, 0, 0]
Frame 12:   [8, 0, 0]
Frame 13:   [9, 0, 0]
Frame 14:   [8, 0, 0]
Frame 15:   [8, 0, 0]
Frame 16:   [8, 0, 0]
Frame 17:   [0, 0, 0]
Frame 18:   [0, 0, 0]
Frame 19:   [0, 0, 0]
Frame 20:   [0, 0, 0]
Frame 21:   [0, 0, 0]
Frame 22:   [0, 0, 0]
Frame 23:   [0, 0, 0]
Frame 24:   [0, 0, 0]
Frame 25:   [0, 0, 0]
Frame 26:   [0, 0, 0]
Frame 27:   [0, 0, 0]
Frame 28:   [0, 0, 0]
Frame 29:   [0, 0, 0]

Starting Value: (165, 156, 222)
Frame 1:    [9, 8, 8]
Frame 2:    [8, 8, 8]
Frame 3:    [8, 8, 8]
Frame 4:    [8, 9, 9]
Frame 5:    [9, 8, 8]
Frame 6:    [8, 8, 8]
Frame 7:    [8, 8, 8]
Frame 8:    [8, 9, 9]
Frame 9:    [9, 8, 8]
Frame 10:   [8, 8, 8]
Frame 11:   [8, 8, 8]
Frame 12:   [8, 9, 9]
Frame 13:   [9, 8, 8]
Frame 14:   [8, 8, 8]
Frame 15:   [8, 8, 8]
Frame 16:   [8, 9, 9]
Frame 17:   [9, 8, 8]
Frame 18:   [8, 8, 8]
Frame 19:   [8, 8, 8]
Frame 20:   [8, 0, 9]
Frame 21:   [0, 0, 8]
Frame 22:   [0, 0, 8]
Frame 23:   [0, 0, 8]
Frame 24:   [0, 0, 9]
Frame 25:   [0, 0, 8]
Frame 26:   [0, 0, 8]
Frame 27:   [0, 0, 8]
Frame 28:   [0, 0, 0]
Frame 29:   [0, 0, 0]

Starting Value: (156, 90, 206)
Frame 1:    [8, 8, 8]
Frame 2:    [8, 8, 9]
Frame 3:    [8, 8, 8]
Frame 4:    [9, 9, 8]
Frame 5:    [8, 8, 8]
Frame 6:    [8, 8, 9]
Frame 7:    [8, 8, 8]
Frame 8:    [9, 9, 8]
Frame 9:    [8, 8, 8]
Frame 10:   [8, 8, 9]
Frame 11:   [8, 8, 8]
Frame 12:   [9, 0, 8]
Frame 13:   [8, 0, 8]
Frame 14:   [8, 0, 9]
Frame 15:   [8, 0, 8]
Frame 16:   [9, 0, 8]
Frame 17:   [8, 0, 8]
Frame 18:   [8, 0, 9]
Frame 19:   [8, 0, 8]
Frame 20:   [0, 0, 8]
Frame 21:   [0, 0, 8]
Frame 22:   [0, 0, 9]
Frame 23:   [0, 0, 8]
Frame 24:   [0, 0, 8]
Frame 25:   [0, 0, 8]
Frame 26:   [0, 0, 0]
Frame 27:   [0, 0, 0]
Frame 28:   [0, 0, 0]
Frame 29:   [0, 0, 0]

如您所见,从每个帧的每个颜色分量中减去8或9。此外,即使每个颜色分量的起始减去值都不相同,数字9也会始终出现在数字8之后的三帧。还要注意,每个颜色分量达到0(即黑色)的差为8或9,而不是任意的余数。这意味着8,8,8,9的减法值循环永不中断!(编写此算法可能是为了确保淡入淡出的最后一帧与其他帧一样平滑。)

现在,这使我感到困惑。根据我的计算,如果您逆转此过程-即以8、8、8、9周期进行相加,以找出29帧中的所有可能组合,则只会得到52个唯一数字。但是碰巧的是,每个颜色分量都是该集合的成员!这意味着要么专门为该渐变算法选择颜色(不太可能),要么渐变算法是围绕游戏的调色板设计的。但是到底有人会发现,如果您采用8,8,8,9,适当地改变周期,并不断从调色板中的每个颜色分量中减去数字,最终每种颜色将达到0? !我必须缺少一些数学技巧。它是什么?


2
为什么不只是玩alpha?这就是淡入/淡出动画的方式。
DogDog 2012年

我并不是试图在自己的代码中复制算法,而是试图弄清楚它是如何派生的。
Archagon

我感觉就是您所说的,颜色是根据序列8、8、8、9挑选的。给定顺序,他们可以从52 * 52 * 52颜色中进行选择。有趣的是,如果从0开始并添加序列8,8,8,9,您将获得255。这使他们可以使用黑白。
路易斯·埃斯特拉达

@Apoc:淡出的样式明显不同于alpha淡入。看到每个颜色值如何下降固定的数字(数字模式)而不是其初始值的百分比?这意味着在某些情况下,您可能更喜欢使用它而不是更常用的方法。例如复古风格。
2012年

Answers:


20

实际上,在8-8-8-9模式后面有一个简单的逻辑。如果仅使用32个强度级别(每个组件5位),但想要在每个组件8位的显示器上渲染,则自然会出现。

考虑一下您是否具有5位强度级别,并希望将其扩展到8位。最简单的操作是左移并保持低三位为零。麻烦的是,那么它并不会一直到纯白色。您可以达到的最高强度级别是11111000,即248。因此,您没有使用8位显示屏的整个强度范围。

确实,您想要做的是像这样的计算intensity8 = round(intensity5 * 255.0 / 31.0),以将[0,31]范围重新缩放为[0,255]。但是,有一个巧妙的技巧可以在不进行任何浮点运算或除法的情况下完成此操作:将低三位设置为等于高三位。也就是说,要将强度从5位转换为8位

intensity8 = (intensity5 << 3) | (intensity5 >> 2);

然后,强度11111将映射到11111111(31映射到255),中间结果也将变得理智,例如10000-> 10000100(16-> 132)。

这组数字正是您所拥有的。以第一个示例的红色部分为例,您具有:

132    10000100
123    01111011
115    01110011
107    01101011
 99    01100011
 90    01011010
 82    01010010
 74    01001010

请注意,低三位始终等于高三位。当位0和位3同时翻转时,发生9的差。

我不确定为什么在这种情况下会使用5位强度级别;也许那是街机硬件的极限?值得注意的是,5位RGB值为15位,非常适合16位字。无论如何,这解释了奇怪的8-8-8-9模式。


1
每个像素16位被称为“高色”。(这就是我所记得的一切)en.wikipedia.org/wiki/High_color
拖船

1
在快速浏览Wikipedia之后,Sega Saturn(en.wikipedia.org/wiki/Sega_Saturn#Video)提到了15位彩色显示模式,以及GameBoy Advance(en.wikipedia.org/wiki/Game_Boy_Advance
拖船

1
那太好了!现在一切都说得通了。谢谢!
Archagon

游戏必须具有16位颜色,并且美术师可能想以牺牲透明度为代价,从游戏中挤出更多颜色,从而提供RGBA 5551配色方案。
Archagon

0

您应该查看模式13h或256调色板褪色。那时,您拥有这么多的颜色,而您所做的却使整个调色板变得混乱,因为您无法计算出其中没有的新颜色。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.