Model view controller 俄罗斯方块和漂亮的图形

Model view controller 俄罗斯方块和漂亮的图形,model-view-controller,graphics,encapsulation,Model View Controller,Graphics,Encapsulation,假设你正在制作一个俄罗斯方块游戏。作为一个合适的程序员,您的视图逻辑在一边,业务逻辑在另一边;可能是MVC的全面升级 当模型发送其更新()时,视图会按预期重新绘制自身 但是。。。如果要添加(例如)动画以使线消失,您将如何在视图中实现该操作 做任何你想做的假设——除了“一切都被正确封装”之外。大多数游戏都会执行一个循环,不断地以尽可能快的速度重新绘制游戏的视图,而不是等待模型状态的更改,然后刷新视图 如果您喜欢模型视图模式,那么视图在从模型中删除某些类型的对象后,继续绘制这些对象,并在几毫秒内将其

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

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

但是。。。如果要添加(例如)动画以使线消失,您将如何在视图中实现该操作


做任何你想做的假设——除了“一切都被正确封装”之外。

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


如果您喜欢模型视图模式,那么视图在从模型中删除某些类型的对象后,继续绘制这些对象,并在几毫秒内将其淡出可能会很好。就我个人而言,即使没有更新块位置,我也会尽可能频繁地分开绘制屏幕。所以我会在某个地方有一个循环,其中有一个的“更新”和一个的“渲染”部分。Update按照逻辑进行击球,该逻辑执行或不执行任何位置更新和/或方块移除。渲染将球播放到图形部分,图形部分将在块应位于的位置绘制块

现在,如果有要删除的行,逻辑知道并可以标记要删除的行。我在这里假设,每一块都由4个单独的块组成,这些块中的任何一个都是一个单独的对象。现在,当该块设置了“die”标志时,您可以使用一些渲染部分使该块消失(比如说,爆炸500毫秒)。在该时间之后,可以放置对象并且上面的块a线落下。为什么是500毫秒?当然,你应该使用基于时间的移动,因为这样可以在不同的电脑上保持相同的游戏速度


顺便说一句,已经有所谓的游戏引擎提供了这样一个更新渲染循环。例如XNA,如果您使用.NET行。您也可以编写自己的引擎,但请注意,这不是一项容易的任务,而且非常耗时。我做过一次,不希望它是一个像源引擎一样的引擎;-)

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

我自己也经常想知道这一点

我自己的想法是这样的:

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

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

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

  • 无更改:此特定块的状态相同
  • 从“下降”变为“锁定”:状态为“锁定”(通过下降块)
  • 从“锁定”更改为“移除”:状态为“移除”(通过行完成)
  • 从“下降”到“移除”:状态为“移除”,但旧状态为“下降”

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

控制器显然是用户交互的中心点。当它们发出键盘命令时,控制器将解释它们,并进行适当的状态调整。然而,有时游戏会进入一个与特定事件相一致的状态…例如,用现在应该移除的块填充一条线

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