嵌套渲染循环是不是一种糟糕的做法
Is it bad practice to have nested render loops?
我正在将一个游戏从Ruby移植到C++。有一个主渲染循环,用于更新和绘制内容。现在让我们假设在游戏中,你想在另一个屏幕上选择一个项目。原始代码中的方法是执行Item item = getItemFromMenu();
getItemFromMenu
是一个打开菜单并有自己的更新/渲染循环的函数,这意味着在播放器打开另一个屏幕的整个过程中,您处于嵌套的渲染循环中。我觉得这是一个糟糕的方法,但我不知道为什么。另一方面,它非常方便,因为我只需调用一个函数就可以打开菜单,因此代码是本地化的。你知道这是不是一个糟糕的设计吗?我犹豫要不要把它发布到gamedev上,但由于这主要是一个设计问题,我把它发布在这里
编辑:一些伪代码给你一个想法:
代码主要部分的常见循环:
while(open) {
UpdateGame();
DrawGame();
}
现在在UpdateGame()中,我会做一些类似的事情:
if(keyPressed == "I") {
Item& item = getItemFromInventory();
}
和getItemFromInventory()
:
while(true) {
UpdateInventory();
if(item_selected) return item;
DrawInventory();
}
处理这样的事情的一个好方法是用类似InvalidateInventory()
的东西替换DrawInventory()
调用,这将标记库存的当前图形状态为过时,并请求在下一帧渲染期间重新绘制它(这将在主循环到达DrawGame()
后很快发生)。
通过这种方式,您可以继续运行主循环,但屏幕上只有被视为需要重新绘制的部分是无效的,在正常游戏过程中,您可以将您的(2/3)D环境作为正常处理部分无效,但在库存中,您始终可以仅将库存资产标记为需要重新画出,这将开销降至最低。
如果您使用标志来指示当前游戏状态,那么内部循环的另一部分UpdateInventory()
可以是UpdateGame()
的一部分,例如:
UpdateGame()
{
switch(gameState)
{
case INVENTORY:
UpdateInventory();
break;
case MAIN:
default:
UpdateMain();
break;
}
}
如果你真的想,你也可以把它应用于绘图:
DrawGame()
{
switch(gameState)
{
case INVENTORY:
DrawInventory();
break;
case MAIN:
default:
DrawMain();
break;
}
}
但我认为绘图应该被封装,你应该告诉它需要绘制屏幕的哪个部分,而不是游戏的哪个单独区域。
使用嵌套渲染循环创建的内容在功能上是一个状态机(就像大多数游戏渲染循环一样)。嵌套循环的问题是,很多时候你会想在嵌套循环中做与外循环相同的事情(处理输入、处理IO、更新调试信息等)。
我发现最好有一个渲染循环,并使用有限状态机(FSM)来表示您的实际状态。你的州可能看起来像:
- 主菜单状态
- 选项菜单状态
- 库存状态
- 世界视图状态
您可以连接状态之间的转换以在它们之间移动。玩家点击按钮可能会触发转换,该转换可以播放动画或其他内容,然后移动到新状态。有了FSM,你的循环可能看起来像:
while (!LeaveGame()) {
input = GetInput();
timeInfo = GetTimeInfo();
StateMachine.UpdateCurrentState(input, timeInfo);
StateMachine.Draw();
}
一个完整的FSM对于一个小型游戏来说可能有点重量级,所以你可以尝试使用一堆游戏状态的简化状态机。每次用户执行转换到新状态的操作时,都会将状态推送到堆栈上。同样,当他们离开一个状态时,你会将其弹出。通常只有堆栈的顶部会接收输入,堆栈上的其他项目可能会/可能不会绘制(取决于你的偏好)。这是一种常见的方法,根据你与谁交谈有一些优点和缺点。
最简单的选择是只抛出一个switch语句来选择要使用的渲染函数(类似于darvids0n的答案)。如果你正在写一款街机克隆游戏或一款小型益智游戏,那就太好了。
- 有没有一种方法可以使用弗洛伊德-沃歇尔算法给出最短路径,其中存在负权重循环而不允许重叠边缘?
- 是否有一种方法可以在运行时停止循环重复一次不止一次
- 我想不出一种方法来使我的代码循环
- 有没有一种方法可以关闭C++和Rust编译中的循环优化
- 有没有一种方法可以访问for循环块之外的变量
- 在"for"循环条件下使用 "ternary operation" 是一种好的做法吗?
- C++-使用循环的另一种方法
- 构造长循环语句是一种好的做法吗
- 有没有一种方法可以在变量之间循环?(C++)
- 嵌套渲染循环是不是一种糟糕的做法
- 思考一种不同的方式来运行win32事件循环没有WndProc
- 从套接字接收消息的无限循环内ussleep的另一种方式
- 一种分配和初始化数组的方法,比普通的循环和设置更快
- 这在多大程度上是一种不好的做法?(循环依赖)
- 我需要以一种可以从循环调用构造函数的方式组织我的类
- 一种更有效的处理循环内列表参数的方法
- 一种涉及比较函子的循环依赖关系
- 有没有一种方法可以在没有while循环的情况下在计算机之间传输数据?c++
- 有没有一种方法可以在for循环中将多个变量推回到一个向量中
- 有没有一种方法可以简化这个c++整数循环数组?