1

好的。从本质上讲,我在尝试对 NES 硬件做出自己的解释,这样我就可以制作出理想情况下类似于 NES 游戏外观的游戏。我目前不知道如何调整如何将游戏场绘制到视频内存(后缓冲区)。

后备缓冲器

NES 对 nametable 或 backbuffer 有限制。在我的示例中,后备缓冲区大小为 256x240 像素,即一个屏幕的大小。如果我把它画到电视上,它会完美地填满屏幕。现在,如果我以 X=5 的偏移量将其绘制到屏幕上,整个图像将被移动并环绕屏幕。

例如.....

ORIGINAL, NO OFFSET:                      DRAWN WITH OFFSET OF X=5:
ABCDEFGHIJK                               GHIJKABCDEF

DRAWN WITH OFFSET OF X=-5:
FGHIJKABCDE

屏幕被分成每个 8x8 像素的正方形,总共 32x30 行和列。(256x240 像素)。偏移量以像素表示 - 而不是列;所以理论上,我可以将屏幕偏移 5 个像素,每列将向右移动 5 个像素。

关卡设计

我的阶段由屏幕组成,包含以 16x15 行和列表示的数据,每行和列由 16x16 像素组成。这是为了模拟有多少 NES 游戏存储了关卡数据 - 每个图块都包含有关每个 8x8 块中应该包含什么的信息。

例如:

AA
BC     with A,B,C,D representing what 8x8 graphic should go where

关卡设计也以此为代表,每个数字代表不同的屏幕并且 - 无意义,为空。

-----
-123-
---4-
--54-
-----

角色放置 这很容易。我已经知道如何根据角色的绝对定位来确定我的角色所在的表、行和列。我还可以确定屏幕内的相对位置。

有了这个信息,我可以很容易地找出字符的左侧和右侧有哪些列,如果有的话(如果字符在屏幕 1 的左侧,则左侧不再有水平)

所以这里是问题 DUN DUN DUN 我如何将我的关卡绘制到屏幕上,以便它们从一个滚动到下一个。一次绘制一个全屏相对容易,当角色到达边缘时,只需翻转到另一个屏幕。

但是,我在概念上遇到的问题是我需要将关卡数据“流式传输”到屏幕上。也就是说,假设角色向右移动了 24 个像素。BG也需要移动。

所以,我需要将后台缓冲区的滚动调整 24 像素。然而,单独滚动会导致屏幕覆盖,从而影响关卡的旧部分。因此,在滚动时,我需要确保将关卡的新部分绘制到后台缓冲区。但在我这样做之前,我需要弄清楚需要先绘制哪些图块。如果这个人向左移动了 24 个像素,我需要在后台缓冲区上重新绘制图块并相应地更改偏移量。

并且我们不要忘记,如果角色向右移动并且没有要绘制的关卡数据,则不应该有偏移,而是角色更靠近屏幕的一侧(而不是通过X 轴)。

基本上,我现在脑子里只有很多不同的数字和价值观——试图把我的脑袋围绕着许多概念,它们导致我的大脑变得粘稠。有人对我如何解决这个问题有任何看法吗?

编辑:使用 VB.Net。C# 也适用(我在两者中都编程)

4

2 回答 2

3

NES 的做法是使用 4 个名称表,每个 256x240。当您从屏幕上滚动一个时,相邻的一个会滚动。要获得大于 512x480 的“世界”,您需要在屏幕外的位置更新名称表。

通常,磁带在 ROM 中有一个包含所有级别数据的巨大表格,并会使用 1 或 2 个 RAM 变量来跟踪整体位置。然后当游戏滚动时,它会更新 RAM 变量,使用这些变量来查找关卡数据表并将新的关卡数据复制到名称表的屏幕外部分。

所以实际上你的后台缓冲区应该是 512x480,你只显示它的 256x240 部分。

您是否查看过任何具有大型滚动世界的 NES 游戏的反汇编?我认为银河战士的部分拆卸在某处......

...是的,在romhacking.net上找到了一些文档

银河战士拆卸;没有真正得到很好的评论,但稍加努力就应该不难弄清楚。

另一个评论更好的反汇编。

编辑:在上面发布的第二次反汇编中,查看 MetroidGameEnginePage.txt 中的“SetupRoom”例程和“DrawRoom”例程;标签 LEB4D 处的例程还显示了在一种情况下如何更新名称表。另请查看“GetNameTable”例程上方的大量注释。通常,在整个文档中搜索“名称表”会得到更多信息。

编辑 编辑:也在 romhacking.net;SMB的内存映射可能很有用。

于 2010-06-23T17:00:51.203 回答
0

我会设置一个图像控件网格并从数据库中加载关卡,该数据库存储每张图片相对于关卡的列和行。一旦代表游戏角色的图像在屏幕右侧足够远(您必须将其位置存储在某些模块级变量中),您将加载下一列图像(同时将所有其他图像移至左并删除第一列)。

于 2010-06-23T00:58:09.677 回答