我是大学新生,攻读计算机科学学位......过去几年我编写了大量的课程,但最近我对组织代码,设计模式,语言差异等方面的理论思考越来越深入.
我有一个Java类,所以我放弃了我的C++研究/开发,转而使用Java和JOGL(Java OpenGL).太棒了!但这不是重点.
我想制作一款小型角色扮演游戏,但这个问题确实适用于任何类型的游戏.如何以结构化的方式组织游戏对象,如模型 - 视图 - 控制器模式?它看起来是一个惊人的模式,使用非常广泛并且很有意义,但我无法弄清楚如何实现它.
例如,我需要跟踪一个GL对象以便绘制到屏幕上.我必须有实现MouseListener,MouseMotionListener,MouseWheelListener和KeyListener(或者一个类,一体化输入管理器)的类.我必须将我的游戏数据放在所有这些不同类可以访问和修改它的地方; 如果有人按下键盘上的按钮,输入管理类需要以某种方式执行键映射到的操作; 当需要绘制一个框架时,图形类需要找到一种方法来遍历所有不同的"事物"并将它们全部绘制出来.
我最大的问题是GUI; 它与哪里结合在一起?它类似于输入,但并不完全,它需要设置和获取实际游戏模拟中的数据......如果我决定尝试添加网络,那就更复杂了(类似于GUI )还需要访问大量数据进行修改和阅读...
哦,我只是困惑.我不知道如何以面向对象的方式将所有这些工作结合在一起......编写明显符合模式的东西很容易,但是当你发生的大量事情都与一个游戏循环相关时,相互修改和游戏数据等,...我甚至不知道.也许我只是让这个比实际更大.
还有其他人有这种感觉吗?请为我的情况提供一些清晰度,这样我就可以花更少的时间来担心并且不知道从哪里开始!
-Ricket
编辑:找到一个很好的图表,可以帮我解决这个问题...来源:(小心,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/
Edit3:另一篇很棒的文章! http://dewitters.koonsolo.com/gamemvc.html
它可能会帮助您将模型视为一种游戏API.如果从一开始就开始的游戏根本没有用户界面,你的游戏会被减少到什么程度呢?你提到你的想法是一个RPG,所以在这种情况下,你可以想象拥有玩家角色,他/她的库存,法术,能力,NPC,甚至地图和战斗规则都是模型的一部分.它就像大富翁的规则和部分,没有最终游戏如何显示或者用户如何与之交互的具体细节.它就像Quake一样,是一组抽象的3D物体,它通过一个水平线来计算交叉和碰撞,但是没有渲染,阴影或声音效果.
通过将所有这些放入模型中,游戏本身现在与UI无关.它可以连接到像Rogue游戏那样的ASCII文本界面,或者类似于Zork的命令行界面,或者基于Web或3D UI.根据游戏机制的不同,其中一些UI可能会非常合适,但它们都是可能的.
View图层是UI依赖图层.它反映了您使用的UI的具体选择,并将非常专注于该技术.它可能负责读取模型的状态并以3D,ASCII或图像和HTML为网页绘制它.它还负责显示玩家需要用来与游戏交互的任何控制机制.
Controller层是两者之间的粘合剂.它应该永远不会有任何实际的游戏逻辑,也不应该负责驱动View层.相反,它应该将在视图层中执行的操作(单击按钮,单击屏幕区域,操纵杆操作等)转换为对模型执行的操作.例如,丢弃一个项目,攻击一个NPC,无论如何.它还负责收集数据并进行任何转换或处理,以使View层更容易显示它.
现在,我上面描述的方式就好像有一个非常独特的事件序列驱动游戏,这可能只适用于网页游戏.那是因为那是我最近花的时间.在一个不是由用户的请求和服务器响应的游戏(例如在用户的机器上运行的游戏)中,您可能希望确保模型层很好地实现了Observer模式.例如,如果由于时间过去而在模型中发生操作,那么您可能不希望View层不断轮询模型以获取更新.相反,通过使用Observer模式,Model可以在发生模型对象时将其更改通知任何观察者.这可以反过来用于提示立即更新视图以反映更改.
然后,如果60秒的传球导致球员的基地发生了一些修复,那么基地可以进行修理,并立即通知任何附属于它的观察员基地已经更新.视图可以作为观察者附加,并注意它需要重新显示基础,因为它的状态已经改变.通知本身可能包含足够的信息来更新View,或者它可能需要转向并查询模型才能更新,但结果将是相同的.
你在那里相处.基本上,问自己一个问题"如果我必须改变程序的某些部分,哪些代码会改变?"
如果它在不改变基本数据的情况下改变它的外观,那么它就在视图中.如果是可以通过多种方式查看的数据,那就是模型.如果这是你玩的方式,那么它就是控制权.
因此,无论你是用两个刀片还是一个刀片绘制"斧头",它都是视图.如果你用斧头造成多少点伤害,那就是它的模型.如果是通过键入"s"或右键单击来摆动斧头,则可以控制它.
我觉得和你在一起我记得当我第一次发现MVC时,我试图把所有东西塞进去.我的确做了一个利用MVC模式的游戏.我后来发现的是,我所做的就是矫枉过正.我试图将我在MVC中制作的每个类都放入一个类别.
我建议的是四人一组阅读"设计模式".除了MVC之外,还有很多有用的模式.有时使用MVC没有任何意义.特别是对于游戏,我不确定MVC是否是一个好主意.原因是您不希望以多种不同的方式(视图)显示游戏对象,但是您想要为许多不同类型的游戏对象重用绘图代码.
对于我自己的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 };
这种方法的好处是你可以在几个精灵之间共享一个视图对象.因为通常会有很多例如怪物看起来相同,但是它们将是不同的位置并且可能表现不同.
所以行为我也会使用一个策略模式,它将是一个包含描述行为的代码的对象.这样我可以将相同的行为应用于不同位置的几个怪物.所以每一帧我都会调用update()函数来更新位置方向以及怪物做什么.
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的独立对象.这样我就可以在进行路径搜索算法时构建可能位置和方向的搜索树.然后我不想随身携带有关如何处理每个更新或如何绘制精灵的信息.