开发者生态
morning
一个很棒的老式游戏编程技巧 (2013)
摘要
A long time ago, when I was a college undergrad, I spent some time working on computer video games. This was in the 8-bit PC era, when the gaming hardware was almost impossibly slow by today’s standar...
the
was
had
some
that
game
things
time
crazy
been
2026-11-11
1 阅读
约6分钟阅读
palsecam
字号:
很久以前,当我还是一名大学本科生时,我花了一些时间研究电脑视频游戏。那是在 8 位 PC 时代,当时的游戏硬件以今天的标准来看几乎慢得不可思议。那么,当你得知过去的游戏程序员做了各种疯狂的事情来让他们的游戏以可玩的速度运行时,你可能不会感到惊讶。疯狂,疯狂的事情。这是一个关于其中一件事情的故事。虽然我已尽力回忆重要细节,但我可能还是记错了一些事情。如果我有的话,请原谅我。那是很久以前的事了。 (注意:这篇文章包含一些作为内联数据 URL 的小图像,一些提要阅读器显然不能很好地处理这些图像。如果您在提要中看不到这些图像,请点击查看原始文章以查看它们。)更新 2013 年 12 月 16 日:Hacker News 和 Proggit 以及博客上有很多关于此故事的精彩评论。谢谢大家分享!设置 我的一位朋友是一位才华横溢的程序员,他即将完成一款新游戏。不知何故,他相当忠实地挤进了一台 1980 年代的 PC,这是一款当时在街机厅流行的图形令人印象深刻的投币游戏。唯一的问题是他的游戏版本无法玩。它太慢了,而且断断续续的动作破坏了玩家的沉浸感。毕竟这是一款横向卷轴游戏。我的朋友一直在开发这款游戏,同时还修满了大学课程,他开始显得有点疲惫。他担心自己错过了一些简单的优化,所以让我看一下代码。我做到了。但没有简单的优化方法。代码很紧凑。放眼望去,我能想到的事情他都已经做了。循环已经展开。不必要的平局已被消除。所有浪费的证据都消失了。并且,有了他们,我们希望能够轻松解决问题。但是硬修复呢?疯狂的修复?嗯,这总是有可能的。然而,在开始讨论这些疯狂的事情之前,我应该回顾并解释一下图形硬件当时的工作原理。当时的图形硬件是如何工作的 下面是简单的版本:图形硬件不支持千斤顶深蹲。在相关的 PC 上,如果您想在屏幕上绘制某些内容,您必须自己逐字节地进行操作。没有纹理映射器,没有位块传输。只是字节。您必须自己移动的字节。乐趣。我朋友的游戏大部分时间都花在重绘背景上。 (再次强调:横向卷轴游戏。)对于每一帧,它都必须绘制几乎一个屏幕的背景图块,并根据玩家的位置进行移动。如果我没记错的话,每个图块都是 28 x 28 像素。每个像素都是 16 种颜色中的一种,需要半个字节来表示。因此,图块在内存中表示为 28 个连续行,每行 14 字节。前 14 个字节表示第一行,第二个 14 字节表示第二行,依此类推。然而,屏幕的宽度为 320 像素,高度为 240 像素。然后,在内存中,屏幕缓冲区被布局为 240 个连续的行,每行 160 字节。因此,当将地址 X 处的图块复制到从地址 Y 开始的屏幕缓冲区位置时,您必须复制 28 行。要复制每一行,您必须复制 14 个字节。幸运的是,这款游戏的处理器是 6809,它有一些 16 位索引寄存器和令人愉快的“自动增量”寻址模式(有点像在 C 语言中将后缀 ++ 运算符应用于指针)。这意味着您可以一次复制 4 个像素,同时同时推进 X 和 Y 寄存器:LDU ,X++ ;从源图块 STU 中读取 2 字节字(= 4 像素),Y++ ;将其写入屏幕缓冲区要复制整行,您必须执行七次,因此您可以将这些行夹在 7 计数循环中: LDB #7 ;剩余单词 <- 以单词为单位的平铺宽度 @LOOP LDU ,X++ ;从源图块 STU 中读取 2 字节字(= 4 像素),Y++ ;将其写入屏幕缓冲区 DECB ;减少剩余字数 BNE @LOOP ;当单词保留时循环 当您完成复制行时,您需要前进目标指针 Y,以便它指向您将绘制到屏幕缓冲区中的下一行的起始地址。由于屏幕缓冲区有 160 字节宽,而图块只有 14 字节宽,这意味着您必须将它们的差异添加到 Y 中:LEAY 160-14,Y 并且,就像这样,您已将一行复制到屏幕上。这是一个。要复制完整的图块,您需要执行相同的操作 28 次。因此,您又将该代码夹在 28 计数循环中。将它们放在一起,并为重要的数字命名,您最终可能会得到这样的子例程:;;;重要常数 SCRW = 160 ;屏幕缓冲区宽度(以字节为单位)(= 320 4 位像素) TILW = 14 ;背景图块宽度(以字节为单位)(= 28 4 位像素) TILH = 28 ;背景平铺行高度 WOFF = SCRW - TILW ; s-b 从一个图块行末尾到下一个 COPYTILE 开始的偏移量 ;;; ;;;将 28x28 背景图块复制到屏幕缓冲区中。 ;;;参数:;;; X = 背景图块的起始地址;;; Y = 屏幕缓冲区中目标的起始地址;;; LDA#TILH;雷姆
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱