什么是旧游戏的"侧滚动黑客"?

Kos*_*Kos 15 graphics 2d demoscene

我听说旧的街机侧滚动游戏使用特定的编程黑客来实现高性能的侧滚动.

据我所知,多年前这些机器的功能还不足以像现在这样完成每一帧的整个屏幕重绘.有些技术,例如脏矩形,可以在背景静止且只有精灵移动时最小化重绘所需的屏幕区域.

上述方法仅在背景不变时才起作用(因此大多数屏幕像素保持静止).

垂直滚动游戏,比如老式的射击游戏,由于滚动,背景会改变每一帧,因此有点困难.然而,人们可以利用像素被馈送到显示器的方式(逐行).我想可以使用更大的缓冲区并将数据指针移动到每一帧"向下"一些线条,这样它将从另一个位置开始重绘,从而给人一种平滑滚动的印象.仍然只需要重绘精灵(以及屏幕边缘的一些背景),这是一个严重的优化.

然而,对于侧滚动游戏来说,事情并不那么简单明了.尽管如此,我知道某个人,在过去的某个地方,虽然有一个优化(有一些限制)允许旧机器水平滚动背景而不是每帧重绘它.

IIRC它被用于许多旧游戏,主要是80年代的节拍,以及demoscene制作

你能描述一下这种技术并为其作者命名吗?

Dan*_*röm 11

我为好老的C64编写了游戏.基本上有两件事需要注意:

  1. 这些游戏不使用位图图形,而是使用"重新映射"字符字体,这意味着8x8像素的块实际上只是一个字节.

  2. 接下来要注意的是,有硬件支持将整个屏幕移动七个像素.请注意,这并没有以任何方式影响任何图形 - 它只是使发送到电视的所有内容都有点移位.

因此2)可以真正平滑滚动7像素.然后你移动了每个角色 - 整个屏幕只有1000个字节,计算机可以处理,同时你将滚动寄存器移回7个像素.8 - 7 = 1意味着它看起来像你滚动了另一个像素......然后它就这样继续了.所以1)和2)结合起来做出了真实流畅滚动的错觉!

在那之后,第三件事发挥作用:光栅中断.这意味着当电视/显示器即将开始在指定位置绘制扫描线时,CPU会收到中断.这种技术可以创建分屏,这样您就不需要滚动整个屏幕而不是我的第一个描述.

更详细的说明:即使你不想要分屏,光栅中断仍然非常重要:因为它和今天一样重要(但今天框架会隐藏这一点)来更新在合适的时间屏幕.当电视/显示器在可见区域的任何地方进行更新时修改"滚动寄存器"将导致称为"撕裂"的效果 - 您清楚地注意到屏幕的两个部分是彼此同步的一个像素.

还有什么可说的?嗯,使用重新映射的字符集的技术可以很容易地做一些动画.例如,通过不断改变在屏幕上表示它们的"字符"的外观,可以使输送机和齿轮和东西动画化.因此,跨越整个屏幕宽度的传送带看起来就像通过改变字符映射中的单个字节一样在任何地方旋转.


3Da*_*ave 8

我使用两种不同的方法在90年代做了类似的事情.

第一个涉及"窗口化",这是由VESA SVGA标准支持的.有些卡正确实现了它.基本上,如果您的帧缓冲区/视频RAM大于可显示区域,则可以绘制一个大位图,并为要显示的区域内的窗口提供系统坐标.通过更改这些坐标,您可以滚动而无需重新填充帧缓冲区.

另一种方法依赖于操纵BLT方法,用于将完成的帧放入帧缓冲区.将页面模糊到与屏幕大小相同的帧缓冲区非常简单有效.

我发现这个旧的286汇编程序代码(在一个运行的 17岁软盘上!)将64000字节(320x200)屏幕从屏幕外页面复制到视频缓冲区:

  Procedure flip; assembler;
    { This copies the entire screen at "source" to destination }
    asm
      push    ds
      mov     ax, [Dest]
      mov     es, ax
      mov     ax, [Source]
      mov     ds, ax
      xor     si, si
      xor     di, di
      mov     cx, 32000
      rep     movsw
      pop     ds
    end;
Run Code Online (Sandbox Code Playgroud)

所述rep movsw移动CX字(其中一个字是在这种情况下两个字节).这非常有效,因为它基本上是一条指令,告诉CPU尽可能快地移动整个事物.

但是,如果你有一个更大的缓冲区(例如,侧面滚动条的1024*200),你可以很容易地使用嵌套循环,并且每个循环复制一行像素.例如,在1024像素宽的缓冲区中,您可以复制字节:

start          count            
0+left         320
1024+left      320 
...
255*1024+left  320
Run Code Online (Sandbox Code Playgroud)

这里left是X,你想在(画面左侧)开始大背景图像中的坐标.

当然,在16位模式下,需要一些魔法和段指针操作(ES,DS)来获得大于64KB的缓冲区(实际上,多个相邻的64k缓冲区),但它工作得很好.

对于这个问题可能有更好的解决方案(今天肯定会有更好的解决方案),但它对我有用.