View在创建实体时接收事件,获取指向接口的指针:这样,View只能使用接口方法(即请求信息来执行绘图),并且不能更改对象状态。 View有自己的onw类(EnemyView,BulletView,ExplosionView),它们拥有指向接口的指针。 (还涉及一个事件基础模式,以便模型可以通知View关于实体更改,因为纯查询方法是不可修复的,但我不会在这里讨论它。)
*模型类使用编译时组件方法:它们使用boost :: fusion库来存储不同的状态组件,如PositionComponent,HealthComponent等。
目前View并不知道基于组件的设计,只知道模型视图部分:获取敌人的位置,它调用Enemy :: get_xy()方法。实现接口的EnemyModel将此调用转发给PositionComponent并返回结果。
由于子弹也有位置,我也必须将get_xy方法添加到Bullet。 BulletModel然后使用与EnemyModel类相同的实现(即它转发调用)。
这个approch然后导致有很多重复的代码:接口有很多类似的方法和*模型类充满了前向方法。
所以我基本上有两个选择:
1)公开基于组件的设计,以便每个组件都有一个接口:View可以使用该接口直接查询组件。它使视图和模型保持分离,仅在组件级别而不是实体级别。
2)放弃模型视图部分并进行基于纯组件的设计:视图只是一个组件(RenderableComponent部分),它基本上可以完全访问游戏引擎。
根据您的经验,哪种方法最好?
答案 0 :(得分:1)
MVC 对于游戏来说并不容易,因为当游戏变得更大(包括菜单,敌人,关卡,GUI ......)和过渡时,它就会崩溃。
组件或实体系统非常适合游戏。
作为一个更简单的案例,您可以考虑使用 HMVC 。您仍然会遇到转换问题,但至少您的代码将以更干净的方式组合在一起。您可能希望坦克的代码(渲染和逻辑)靠近在一起。
答案 1 :(得分:1)
我会给我两分钱。从您描述的问题来看,在我看来,您需要一个抽象类来执行所有类中常见的操作(例如get_xy
,它应该适用于子弹,敌人,爆炸,等等。)。这个类是一个执行基本咕噜声工作的游戏实体。如果需要,继承类可以覆盖它。
这个抽象类应该是所有接口的核心(幸运的是,你在C ++中,类,抽象类和接口之间没有物理差异)。因此,Views将了解特定接口,并且仍然具有通用实体方法。
我有设计的经验法则 - 如果多个类具有相同的数据成员或方法,它应该是它们继承的单个类。
无论如何,暴露Model类的内部结构并不是一个好主意。说你想用其他东西取代助力?您必须重新编写整个程序,而不仅仅是相关部分。
答案 2 :(得分:1)
已经有专门为基于代理的系统设计的表示架构,例如Presentation-Abstraction-Control。设计这样一个系统的困难之处在于,你最终会在代理商之间进行硬连线协作。
您可以执行此操作,但不要使用OO继承来为消息传递层次结构建模。你会后悔的。如果你考虑一下,你真的对使用OO继承关系不感兴趣,因为定义的接口实际上只是对象可以响应的“函数记录”。在这种情况下,您最好正式建模通信协议。
如果您有任何疑问,请询问 - 这不是一个明显的解决方案,容易出错。