我正在尝试从零开始制作视频游戏,但是我对此确实很陌生,并且一直遇到基本问题。最重要的是,视频游戏如何存储屏幕外信息?我的意思是,程序如何知道接下来要在屏幕上显示什么?甚至,如果播放器更改了环境,下次将其加载到屏幕上时,该更改如何保留?
例如,在“新超级马里奥兄弟”中,如果您打了?阻止,然后离开屏幕,然后返回,它仍然保持点击状态。如何保存此信息,然后在玩家下次加载该块时执行该信息?为什么不重置呢?
我正在尝试从零开始制作视频游戏,但是我对此确实很陌生,并且一直遇到基本问题。最重要的是,视频游戏如何存储屏幕外信息?我的意思是,程序如何知道接下来要在屏幕上显示什么?甚至,如果播放器更改了环境,下次将其加载到屏幕上时,该更改如何保留?
例如,在“新超级马里奥兄弟”中,如果您打了?阻止,然后离开屏幕,然后返回,它仍然保持点击状态。如何保存此信息,然后在玩家下次加载该块时执行该信息?为什么不重置呢?
Answers:
您正在倒退。
您从游戏的逻辑状态开始,并对它进行建模。几乎可以肯定,整个世界的整个逻辑状态太多了,无法立即保存在内存中,因此您将其分解为可以独立加载和保存的较小部分。这些部分通常称为块。这些块可以构成一个连续的世界,但是它们也可以是单独的级别/实例。术语因类型和要使用的技术而异。
然后,加载感兴趣的那些部分,即播放器附近的块。距离太远的块将保存到磁盘/永久存储中,并从内存中卸载。
然后,作为最后一步,您确定实际可见的内容并创建视觉表示当前游戏状态并将其呈现在屏幕上。
当然,您将尝试不每次都重建整个视觉表示,而是将其缓存并重新使用(如果您已经构建了部件),但这是主要原理。
这对于任何具有输出的程序都适用。如果使用普通的GUI(例如文本编辑器)编写程序,则可能会对文档进行建模,然后GUI会确定文档的状态和可见部分并将其呈现到屏幕上。或适当地填写表格字段,否则。
主要要点是:考虑首先存储数据的位置和方式(可能以及如何表示数据)。几乎每个程序都必须处理数据存储。在极少数情况下,您不存储任何数据。
正如其他人所说的,您保留了地图(例如,以阵列形式)并将其可见部分绘制到屏幕上,而不要从屏幕上回读。
但是在某些较旧的系统中,您实际上会将数据置于屏幕之外。例如,对于320x200的显示器,将有400x300像素的视频内存,您将在其中定义一个视口(“从X = 10 Y = 30开始”)。因此,您可以通过调整寄存器来滚动屏幕。您无需花费移动字节所需的十万个周期,只需更改视频硬件开始读取字节的位置即可。
NES具有此功能,并结合了基于图块的系统:http : //wiki.nesdev.com/w/index.php/PPU_scrolling
NES永远不会在内存中构造完整映像,因为它没有足够的RAM。取而代之的是,有一个RAM阵列定义了两个屏幕范围的磁贴集。每种图块一个字节。视频硬件会查找图块和X / Y偏移坐标,以便确定在任何点上应显示哪个像素。
好吧,如果您问这样的问题,那么您将有一段漫长的路要走到可以创造游戏的地步。但是,成为您问题的核心,该程序可以将许多不同事物的状态保存在程序后端的变量中。让我们看几个例子。
Mario Brothers(或类似机构)会保存您所处级别的状态。这可能包括您死前已经走了多远(无论是否被击中)。在某种程度上更面向对象的意义上,游戏只是说“在这里成为障碍物”,并且存在障碍物。然后当您点击该块时,该块会更改其内部状态,说“我被击中”。这样的数据可以通过多种方式存储。
您的文字处理器将其数据保存在数据结构中。现在有许多这样的方法以及可以实现它们的许多方式,但是可能它使用某种形式的树。在树中,您至少有一个节点。在左侧之前添加的所有内容。之后添加的所有内容都将移至右侧。添加三个节点后,其中两个悬挂在中间节点上。通过在任何地方添加新片段,树可以变得更大,树也将自我重建。 或考虑您的敌人徘徊的射击游戏。他们每个人都有跟踪他们的位置,生活等的变量,因此当您缠绕一个时,它会记住它是受伤的。
所有这些都需要了解数据结构。它远远超出了您在屏幕上看到的内容。我建议阅读有关数组,列表,哈希(有时称为字典或映射)的文章,然后再回到您的问题上。
这里有一些很好的入门材料:
在某种程度上,这是3D渲染方式的函数。例如,OpenGL将自动在XY屏幕空间中剔除-1.0,+ 1.0范围之外的几何图形(Z更复杂,但相似)。剔除的几何图形永远不会产生碎片(大约像素),因此即使发送到系统进行渲染,也永远不会变成实际的图像。在任何情况下,都不可能在渲染窗口之外的空间中写入空间(如果一切正常运行)。
在某些情况下,仅依靠此行为作为优化就足够了。但是,您仍然必须将所有游戏数据传递到至少一个渲染阶段(顶点着色器),然后视频卡才能知道可见的内容。在诸如“天际”之类的东西中,这是不切实际的。您不仅必须通过渲染管道发送世界上的每个顶点,而且还必须将每个顶点加载到系统/视频内存中。即使有可能,效率也很低。
因此,许多游戏将利用基于CPU的清除功能。他们通常会实施某种LOD(详细程度)系统,其中资产的质量和存在会受到资产在给定背景下评估的重要性的影响。如果您距离一座山脉50英里,那么金字塔网格可能是一座可接受的近似山。如果您根本看不到它(例如被其他山脉阻挡),则无需加载它。有许多更复杂的方法可以实现此目的,我认为这些主题与该问题所要求的深度没有直接关系,但请参阅细分作为最常见示例之一。
真正的主旨是视觉效果只是游戏的产物。实际数据与大部分时间您所看到或未看到的内容没有任何直接关系,并且在到达将图片写入屏幕之前,数据会经过多个阶段过滤,以除去无关的信息。视引擎设计而定,视觉效果可能会与实际游戏逻辑极为脱节,只要有可能在同一款游戏中使用2D和3D接口即可。许多游戏引擎甚至有可能在没有输出的情况下运行。有时这是用来测试游戏AI。
但是,那会使事情变得复杂。在像马里奥游戏这样简单的事情中,即使关卡中的所有敌人都不可见,也不太可能计算出关卡中所有敌人的移动。在现代环境下,屏幕外发生的事情是一个认真考虑的实际问题。如果有多个NPC整个城市,当玩家被完全淘汰时,您将如何处理它们的行为-就像玩家在另一个城市中一样?您是否真的想在整个地图上计算数百个NPC的决策?答案通常是“否”,但是不这样做的确切方法可能会有所不同,并且可能会对游戏产生一些影响。
重要的是要注意,这就是现在的工作方式。考虑到当时的极端硬件限制,旧的Mario游戏本身可能以完全不同的方式编程(我无法确切地说出)。那时3D的概念还不存在。但是今天,几乎所有游戏,甚至是完全2D的游戏,都以某种形式使用3D渲染,即使他们不知道这样做也是如此。现代视频硬件首先使用3D,而2D渲染(至少在正确使用硬件的情况下)仅忽略了3D尺寸。