2012-01-16 51 views
1

我正在将一款游戏从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(); 
} 
+1

我一直挣扎在VB.NET应用了类似的事实是,在渲染循环,以保持GUI从冻结和崩溃和死亡,但也避免了污秽样-的“进度窗口”执行'DoEvents'引入线程。这意味着我的进度窗口中只有一个会一次更新。我并不介意,而且它可以避免线程。但它感觉恶心。我离开它现在... – 2012-01-16 22:23:49

+0

一个坏事,我可以用这个看到的是在你有这样的游戏循环,取决于它是如何做的所有的地方可能重复的代码。 – Xeo 2012-01-16 23:04:14

+0

你可以显示你想要的伪代码吗? – 2012-01-16 23:08:32

回答

2

来处理这样的事情将是取代DrawInventory()调用的东西,如InvalidateInventory(),这将标志着库存过时的当前的图形状态,并要求其到下一帧渲染时重绘的一个好办法(当主循环到达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; 
    } 
} 

但我认为图形应该被封装,你应该告诉它的屏幕的哪一部分,而不是该游戏的单独的区域,需要绘制。

0

你用你的嵌套渲染循环创建的功能是一个状态机(因为大多数游戏渲染循环往往是)。嵌套循环的问题在于,你需要多次在嵌套循环中完成与外循环相同的操作(处理输入,处理IO,更新调试信息等)。

我发现最好有一个渲染循环,并使用有限状态机(FSM)来表示您的实际状态。你的国家可能是这样的:

  • 主菜单状态
  • 选项菜单状态
  • 库存状态
  • 世界视图状态

您挂钩状态之间的转换在它们之间移动。玩家点击一个按钮可能触发可以播放动画的转换,否则转到新的状态。随着FSM你的循环可能看起来像:

while (!LeaveGame()) { 
    input = GetInput(); 
    timeInfo = GetTimeInfo(); 

    StateMachine.UpdateCurrentState(input, timeInfo); 
    StateMachine.Draw(); 
} 

一个完整的FSM可以是一个小游戏,有点重量级的,所以你可以使用游戏状态的堆栈尝试简化状态机。每当用户执行一个操作以转换到新状态时,您都会将状态推入堆栈。同样,当他们离开一个状态时,你会弹出它。只有堆叠的顶部通常会接收输入,并且堆叠上的其他物品可能/不可能绘制(取决于您的偏好)。这是一种常见的方法,取决于你与谁交谈,有一些好处和坏处。

所有最简单的选择是仅抛出一个switch语句中挑选要使用的渲染功能(类似于darvids0n的答案)。如果你正在编写一款街机克隆版或者一款小型益智游戏,那就太好了。