俄罗斯方块和漂亮的图形

时间:2009-05-21 10:20:24

标签: model-view-controller graphics encapsulation

假设您正在构建俄罗斯方块游戏。作为任何合适的程序员,您的视图逻辑在一边,而您的业务逻辑在另一边;可能是一个全面的MVC。

当模型发送其update()时,视图会按预期重绘自身。

但是......如果你想添加动画来消除一条线,你会如何在视图中实现它?

做出你想要的任何假设 - 除了“一切都被正确封装”。

5 个答案:

答案 0 :(得分:4)

就个人而言,即使没有更新块位置,我也会尽可能经常分开画面。所以我会在某个地方设置一个带有“更新”“渲染”部分的循环。更新将球传递给逻辑,该逻辑执行或不执行任何位置更新和/或块移除。渲染将球传递到图形部分,绘制出应该存在的块。

现在,如果有要擦除的行,则逻辑知道并可以标记要删除的行。我假设每个部分由4个单独的块组成,这些块中的任何一个都是单个对象。现在当这个块具有“die” - 标志集时,你可以使用一些渲染部分来消除该块(比方说,500ms来爆炸)。在此之后,可以布置物体并且上面的线块下降。为什么500ms?好吧,你绝对应该使用基于时间的动作,因为这样可以在不同的计算机上保持相同的游戏速度。

Btw,已经有所谓的游戏引擎提供了这样的更新渲染循环。例如XNA,如果你去.NET行。您也可以编写自己的引擎,但要注意,这不是一件容易的事,而且非常耗时。我这样做过一次并且不要指望它像源引擎那样引擎; - )

答案 1 :(得分:2)

大多数游戏都会执行循环,以便尽可能快地重新绘制游戏视图,而不是等待模型状态的更改,然后刷新视图。

如果你喜欢模型视图模式,那么它可能适用于视图在从模型中删除它们之后继续绘制某些类型的对象,并在几毫秒内淡出它们。

答案 2 :(得分:1)

另一种方法是将类MVC与差异执行相结合 - “视图”是所呈现内容的模型,但绘图代码将“视图”创建的事件流与先前渲染的流进行比较。因此,如果在一个流中有一条线,而下一条线没有,则绘图代码可以为差异设置动画。这允许将绘图从视图中抽象出来。 MVC中的“视图”通常是一个小部件的集合,而不是直接绘制显示的东西,所以最终你最终得到嵌套的MVC层次结构:应用程序是MVC(数据模型,视图对象,app控制器),其中view对象有一组小部件,每个小部件都是MVC(小部件状态(例如按下按钮),外观和工具包绑定,工具箱事件的映射 - >小部件状态)。

答案 3 :(得分:1)

我自己经常想到这一点。

我自己的想法一直都是这样的:

1)视图给出了块的状态(形状,yada-yada),但有额外的“过渡”数据:

2)必须删除一行的事实是在状态中编码的,不在视图中计算。

3)视图现在知道如何绘制过渡:

  • 无变化:此特定区块的状态相同
  • 从“下降”变为“已锁定”:状态为“锁定”(通过丢弃块)
  • 从“锁定”更改为“删除”:状态被“删除”(通过行完成)
  • 从“下降”变为“删除”:状态被“删除”,但旧状态“正在下降”

答案 4 :(得分:1)

将游戏视为MVC很有意思。这是我从未采取的一个观点(出于某些奇怪的原因),但绝对是一个很有意义的有趣的观点。假设您使用MVC实现了您的俄罗斯方块游戏,我认为在您的控制器和您的视图之间的通信方面,您可能需要考虑两件事:有状态,有事件。

您的控制器显然是用户交互的中心点。当他们发出键盘命令时,您的控制器将解释它们,并进行适当的状态调整。但是,有时候游戏会进入与特定事件重合的状态......比如用现在应该删除的块填充一行。

Scoregraphic为您奠定了坚实的基础。您的视图应以固定周期运行,以保持计算机之间的一致速度。但是除了更新屏幕以呈现新状态之外,它还应该有一个事件队列,它可以执行动画响应。在俄罗斯方块中填充行的情况下,您的控制器可以发出强类型事件对象,这些对象从某种基本事件类型派生到视图事件队列中,然后视图可以使用它来执行适当的动画响应。