你怎么能组织一个游戏的代码,以适应MVC模式?
我是一个大学新生,为我的计算机科学学位…我已经编程了很多年,但最近我已经越来越多的关于组织代码,devise模式,语言差异等理论的想法。
我有一个Java类,所以我放弃了我的C ++研究和开发,并转移到Java和JOGL(Java OpenGL)。 太棒了! 但是那不是重点。
我想做一个小angular色扮演游戏,但是这个问题真的适用于任何types的游戏。 如何以结构化的方式组织游戏对象,如模型 – 视图 – 控制器模式? 它看起来是一个了不起的模式,使用非常广泛,并且有很大的意义,但是我很难弄清楚如何实现它。
例如,我需要跟踪一个GL对象来绘制到屏幕上。 我必须有实现MouseListener,MouseMotionListener,MouseWheelListener和KeyListener(或一个类,一个全function于一身的inputpipe理器)的类。 而且我必须把我的游戏数据放在一个所有这些不同的类可以访问和修改的地方。 如果有人按下键盘上的button,inputpipe理类需要以某种方式执行键映射到的动作; 当一个框架需要绘制时,graphics类需要find一种方法来循环所有不同的“事物”,并把它们全部绘制出来。
而我最大的问题,GUI; 它在哪里结合在一起? 这就像input,但不是完全一样,它需要从实际的游戏模拟中设置和获取数据片段,而且更复杂的是如果我决定尝试添加networking,那么(类似于GUI )也需要访问大量的数据进行修改和阅读…
哦,我只是困惑。 我不知道如何以面向对象的方式将所有这些工作结合在一起。写出明显符合模式的东西是很容易的,但是当你有大量的事情发生在一个游戏循环上时,相互修改和游戏数据等……我什至不知道了。 也许我只是把这个做得比实际更大。
有没有其他人有这种感觉? 请提供一些清晰的我的情况,所以我可以花更less的时间担心,不知道从哪里开始!
-Ricket
编辑:find一个很好的图,可能会帮助我把这一切都…出处:(当心,PS文件!) http://www.tucs.fi/publications/attachment.php?fname=TR553.ps.gz
http://img10.imageshack.us/img10/6278/mvcdiagramgamesbl5.png
编辑2:我也喜欢这个人如何计划他的MVC游戏的解释: http : //interactivesection.wordpress.com/2007/11/19/dum-de-dum-drum-my-first-mvc-game-development/
编辑3:另一个伟大的文章! http://dewitters.koonsolo.com/gamemvc.html
这可能会帮助你将Model看作一种游戏API。 如果游戏从一开始就没有UI,那么你的游戏会减less多less? 你提到你所想到的是一个RPG游戏,所以在这种情况下,你可以想象玩家angular色,他/她的库存,法术,能力,NPC,甚至地图和作战规则等都是模型的一部分。 这就像大富翁的规则和片断,没有最终游戏如何显示或用户如何与之交互的细节。 这就像雷神(Quake)一样,是一个三维物体的抽象集合,通过交点和碰撞等计算而不是渲染,阴影或声音效果。
通过把所有这些放到模型中,游戏本身现在是UI不可知论的。 它可以挂在一个像Rogue游戏那样的ASCII文本界面,或者一个类似于Zork的命令行界面,或者一个基于Web的或者3D UI。 根据游戏机制,其中一些用户界面可能会非常糟糕,但它们都是可能的。
视图图层是UI依赖层。 它反映了您所使用的用户界面的具体select,并将非常专注于该技术。 它可能负责读取模型的状态,并以3D,ASCII或图像和HTML为网页进行绘制。 它还负责显示玩家需要用来与游戏交互的任何控制机制。
Controller层是两者之间的粘合剂。 它不应该有任何实际的游戏逻辑,也不应该负责驱动视图层。 相反,它应该将视图层中的操作(点击button,点击屏幕区域,操纵杆动作等等)转换为在模型上采取的操作。 例如,放下物品,攻击NPC,不pipe。 它还负责收集数据并进行任何转换或处理,以便View层显示它。
现在,我上面描述的方式好像有一个非常独特的事件序列驱动游戏,可能只是真正适合网页游戏。 那是因为这是我最近花费的时间。 在不受用户请求驱动的游戏和服务器响应(例如在用户机器上运行的游戏)的情况下,您可能需要确保Model层很好地实现了Observer模式。 例如,如果操作发生在模型中,因为时间正在传递,那么您可能不希望View层不断地轮询Model更新。 相反,通过使用Observer模式,Model可以在模型对象发生变化时通知任何观察者对其进行更改。 这反过来可以用来立即更新视图以反映更改。
然后如果60秒传球造成了球员基地的一些维修,基地可以进行维修,并立即通知任何附属的观察员基地已经更新。 视图可以作为观察者附加,并注意它需要重新显示基础,因为它的状态已经改变。 通知本身可能包含足够的信息来更新视图,或者它可能需要转换并查阅模型以更新,但结果将是相同的。
你在那里。 基本上,问自己一个问题:“如果我必须改变程序的某些部分,哪个代码会改变?
如果在不改变基本数据的情况下改变它的样子,那么它就在视图中。 如果是可以以多种方式查看的数据,那就是模型。 如果这是你如何玩,那就是控制。
所以如果是用两个刀片或者一个刀片绘制一个“斧头”,这是视图。 如果用斧头造成的伤害是多less,那就是模型。 如果是通过input“s”或右击来摆动斧头,那就是控制。
我记得当我第一次发现MVC的时候,我想要把所有东西塞进它里面。 我确实做了一个利用MVC模式的游戏。 我后来发现的是,我所做的是过度的。 我试图将MVC中的每一个类都归入一个类别。
我build议的是由四人帮阅读“devise模式”。 除了MVC,还有很多有用的模式。 有时使用MVC根本没有任何意义。 特别是对于游戏,我不确定MVC是不是一个好主意。 原因是你不想以许多不同的方式(视图)显示一个游戏对象,但是你想要为许多不同types的游戏对象重用一个绘图代码。
对于我自己的2D游戏引擎,我非常积极地使用了战略模式。 游戏对象,就像玩家和我称之为雪碧的怪物一样。 我让精灵的绘图被一个策略模式处理。 那是当我调用sprite.draw()我会做这样的事情:
class Sprite { void draw() { this.view.draw(this.currentPosition, this.currentOrientation); } Point currentPosition; // Current position of this sprite double currentOrientation; // Facing angle of sprite };
这种方法的好处是你可以在几个精灵之间共享一个视图对象。 因为通常会有很多例如怪物看起来相同,但是会有不同的位置,可能会有不同的performance。
所以行为我也会使用一个战略模式,这将是一个包含代码描述行为的对象。 这样我就可以将同样的行为应用到不同位置的几个怪物。 所以每一帧我都会调用update()函数来更新位置方向和怪物的function。
class Sprite { void setUpdateAction(Action action) { this.updateAction = action; } void update(double start_time, double delta_time) { this.prevPosition = position(); advance(delta_time); // Advance to next position based on current speed and orientation this.updateAction.execute(this, start_time, delta_time); } Action updateAction; };
这有很多的变化。 在我目前的实现中,我甚至将currentPosition , speed , orientation和advance()分隔到一个名为MotionState的独立对象中。 这样我就可以在做pathsearchalgorithm的时候build立一个可能的位置和方向的search树。 然后,我不想随身携带有关如何更新每个更新或如何绘制精灵的信息。
集中用户交互逻辑的MVC概念是游戏开发的一个很好的模型。
我已经做了一些Flash游戏开发的工作。 这是一篇关于Flash中的对象池的文章。 这个概念是跨平台的,可能会给你一些想法。
你一直关心所有的事情是对的。 根据您的游戏devise,您的游戏循环可以有很多要处理。 这是你将学习所有肮脏的优化技巧,往往是艰难的方式:)
有很多方法来组织你的代码 – 一个选项可能是作为一个单例编写一个GameManager类。 所有的游戏对象都会绑定到pipe理和用户交互。 GameManager处理所有用户input并将消息分派到其对象池。 您可以使用接口来定义游戏对象和GameManager之间的通用通信模式。
就性能优化而言,线程非常强大。 asynchronous操作可以确保你不会浪费那些宝贵的周期。
所有的监听器和处理器都需要进入Controller类,屏幕上的对象的状态(例如位置,颜色等)应该是你的Model类的一部分,任何在屏幕上绘制东西的代码都将成为风景。
我认为MVC的方式就像MDUC一样
模型
显示
用户input控制器
该模型包含域模型对象
显示屏幕上显示域模型对象的当前状态和行为。
用户input控制器处理所有的用户input。
它的模式完全一样,但名称只是稍微更具描述性,所以我发现模式的每个部分都有更清晰的责任,所以模式的含义更加令人难忘。
一旦看到从显示中分离数据和模型操作,从用户的input中,可以更容易地看到在自己的代码中分组的内容。