我正在制作不是基于图块的2D街头霸王般的游戏。通常人们建议将实体提供给渲染它们的渲染器,而不是渲染它们自己,但是看起来反函数更好,
为什么一个比另一个更好?
谢谢
我正在制作不是基于图块的2D街头霸王般的游戏。通常人们建议将实体提供给渲染它们的渲染器,而不是渲染它们自己,但是看起来反函数更好,
为什么一个比另一个更好?
谢谢
Answers:
有两个注意事项:
正如您所提到的,每个精灵都必须“提示”要使用的位图,但是如果实体必须渲染自己的话。那是什么“提示”?如果每个小精灵都引用了不同的位图,小精灵表等,那么您可能最终会使用比必要更多的内存,或者在管理该内存时遇到麻烦。单独的渲染器的优点是您只有一个类负责任何资产管理。也就是说,在类似SF2的格斗游戏中,您可能只有两个Sprite;)
正如其他地方提到的,每当要更改图形API时,都必须更改所有精灵的代码。
如果不参考某些图形上下文,则很少执行渲染。因此,要么有一个表示此概念的全局变量,要么每个子画面都有一个与render(GraphicalContext ctx)的接口。这混合了图形API和游戏逻辑(有些人会觉得这些逻辑不明确),并可能导致编译问题。
我个人发现,将渲染与单个实体分开是朝着将您的游戏视为完全不需要图形的系统方向迈出的有趣的第一步。我的意思是,当您不进行渲染时,您会意识到很多游戏玩法都是在“非图形世界”中发生的,其中实体的坐标,内部状态等很重要。这为自动化测试,更多解耦的系统等打开了大门。
总而言之,我倾向于使用由单独的类进行渲染的系统。这并不意味着您的子画面不能具有“图形相关”的某些属性(动画名称,动画帧,高度x宽度,子画面ID等...),如果这会使渲染器更容易编写或更有效。
而且我不知道这是否适用于3D(其中网格的概念以及您将使用的坐标变量可能与3D API绑定;而x,y,h,w几乎与任何2D无关API)。
希望这会有所帮助。
您希望渲染系统控制何时绘制的内容。取而代之的是,精灵控制着渲染,您会在效率方面的大量提高和灵活性上变得松懈。我认为将渲染系统置于控制之下会产生更简洁的代码。
集中渲染的一些优点:
我在游戏中实现此方法的方式是让游戏对象注册要使用渲染系统绘制的精灵。当对象不再需要绘制对象时,它将取消注册精灵,或将其标记为不活动。
所有这些。如果更容易让您的游戏对象通过各种方式呈现自己,请按照这种方式进行。与拥有完善的体系结构相比,取得进展并获得某些事物/东西要重要得多。
免责声明:您的问题并没有提供太多细节,因此我在回答时遵循的是一般原则。如果我误解了您的使用或“渲染”,请原谅。
我通常使用外部对象在场景中渲染各种角色,作为封装场景级别属性和方法的方法,这些属性和方法位于各个“角色对象”之外。场景中的对象应仅包含内部方法和属性;他们应该只知道自己是什么,做什么。据推测,它们将受到游戏中其他对象以及用户输入的影响。这将影响它们在屏幕上的呈现方式/是否呈现。例如,“导演对象”可以转换“ w”按键以跳转,然后告诉演员对象.jump()。这种导演级逻辑还可以告诉演员完全进入或退出场景。
干杯,大卫
如果有一天您想将游戏移植到其他分辨率(例如iPhone和朋友),该怎么办?因此,关于渲染更改的全局属性,如何轻松地更新代码?
我使用的是基于观察者的设计。创建要渲染的类的实例时,指向它的指针存储在中央Renderer类中。您打电话的时候RenderFrame()
,渲染器已经具有渲染所需的所有现有对象,并访问了它们的属性来执行此操作。类本身根本不知道将要渲染它们。这个API很好,干净而且易于使用。
通常,总是与维护和扩展代码有多容易有关。明天您会发现您不喜欢当前使用的图形API,并且想要切换。您现在是否必须遍历所有对象类并更改所有内容,还是只需要在项目的一个中心点更改代码?
这取决于调用render()时对象实际在做什么。只要它们将方法调用包装在您的图形引擎周围,就可以了,因为仍然会给出逻辑<->图形区别。
例如,如果您的render()方法基本上是便捷方法,并且看起来像这样:
void MyClass::render(const Graphics &g)
{
g.draw(this);
}
要么
void MyClass::render()
{
mySprite->render();
}
要么
void MyClass::render()
{
mySprite->UseShader(thatshader);
mySprite->render();
}
或接近那个,我认为这不是一个问题。