- 注册时间
- 2004-11-1
- 最后登录
- 2018-4-24
版主
  
- 积分
- 548
|
只是节译,机翻效果,也就是看看大意罢了。
原作者:Rasmus Christian Kaae
2.0 在引擎核心中应用Model-View-Control
引擎的核心应该处理游戏中的所有任务。也就是说可以处理用户的输入,处理其他用户的可能的输入(网络游戏),处理游戏事件,当然还包括处理声音和图形输出。为了这个目的,我将使用一个Model-View-Control设计模式的衍生模式。这个模式将把引擎分成三个重要的部分。Model-View-Control 对GUI程序特别有用。因为它提供了一定程度的模块化,使得它可以转化一个已有的实现到别的图形驱动。例如,现有一个游戏引擎可能是用最新的DirectX SDK实现的,那么可以就把它移植到OpenGL。因为所有关于游戏引擎对DirectX的调用代码都在View类中。这使得移植变得容易一些——虽然只有View类须要改造。更多关于Model-View-Control构架信息,你可以在http://ootips.org/mvc-pattern.html和http://compsci.about.com/cs/mvcpattern/index.htm找到。
2.1 Model
Model模块是这个构架的一部分,用来包含所有的游戏结构。
例如,3D游擎的结构就放在这个类中。还有行为模式,也就是当给出一个用户输入后,将怎么去作的信息也存放在这里。作为构架的一部分,Model和View、Control模块没有任何关系。也就是说Model模块完全可以单独用在另外一个环境中。
2.2 View
View模块包含所有涉及输出给用户的东西,如声音播放和图形显示。例如,在这里实现OpengGL和DirectX驱动。View模块和model模块相关,View模块能把Model 模块的当前状态显示给用户。
2.3 Control
Control模块是这个构架中最根本的部分。当它被初始化后,它将分配一个View和Model的实例,并等待用户的输入。用户输入被解析然后传去Model模块处理,很快View会反映出Model的当前状态。
2.4 例子代码
下面的代码是伪代码,不能通过编译。
/*InputBlock 包含用户的当前输入*/
class InputBlock{
// todo : 加入有趣的变量和显示用户输入的函数
};
/* Model模块*/
class Model {
public:
Engine3D *m_engine;
Sound *m_sound;
Model();
UpdateControl(InputBlock *input) {
// todo : 对当前输入的反应
}
};
/* ViewVisual是各具体驱动实现的接口类 */
class ViewVisual {
public:
ViewVisual() {
}
virtual void Update(Model *model)=0; //纯虚函数处理当前Model的变化
}
/* ViewVisualOpenGL是ViewVisual接口的实现*/
class ViewVisualOpenGL {
public:
ViewVisualOpenGL(){
// todo : 初始化
}
void Update(Model *model) { // 显示Model的当前状态
// todo : 用model->m_engine 画图
}
};
/* ViewAudio是各声音驱动实现的接口类 */
class ViewAudio {
public:
ViewAudio() {
// todo: 初始化
}
virtual void Update(Model *model)=0; // 纯虚函数处理当前Model的改变
};
/* ViewAudioDirectSound是ViewAudio的实现,用DirectSound播放声音 */
class ViewAudioDirectSound {
public:
ViewAudioDirectSound() {
// todo : 初始化
}
void Update(Model *model) { // todo : 用model->m_sound播放当前声音
}
};
/* View类连接图形和声音驱动*/
class View {
protected:
ViewVisual *m_visual;
ViewAudio *m_audio;
public:
View(Model *model, ViewVisual *visual, ViewAudio *audio) {
m_model=model;
m_visual=visual;
m_audio=audio;
}
void Update() {
m_visual->Update(m_model);
m_audio->Update(m_model);
}
};
/* Control is the class that handles input from the user and starts the output */
class Control {
enum {
ESCAPE_IS_PRESSED,
USER_INPUT
};
private:
View *m_view;
Model *m_model;
public:
Control() {
m_model = new Model();
m_view = new View(m_model, new ViewVisualOpenGL(),
new ViewAudioDirectSound());
}
~Control() {
delete m_model;
delete m_view;
}
InputBlock Input(int which) {
switch (which) {
case USER_EXIT :
if (escape_is_pressed)
return new InputBlock(ESCAPE_IS_PRESSED);
break;
case USER_INPUT :
if (user_has_made_an_input)
return new InputBlock(the_new_input_info);
break;
}
}
void Run() {
while (!Input(USER_EXIT)) {
if (Input(USER_INPUT))
m_model->UpdateControl(Input(USER_INPUT));
m_view->Update();
}
}
};
/* 调用框架的主函数*/
void Main(int argc, char **argv) {
Control *control = new Control();
control->Run();
delete control;
}
2.4.1 代码解说
上面的代码最终将创建一个控制器。这个控制器然后创建一个OpenGL驱动,一个DirectSound驱动,和一个Model。在创建结束后,主程序调用控制器的Run()函数。这个成员函数把它自己放在一个循环中,直到用户按下退出按钮。在用户退出前,程序将根据用户的输入更新Model和View。当一个输入信息给出时。这个输入被解析并传到Model中处理。当输入处理结束后,控制器将调用View来更新显示。结束时,退出代码将清理资源。
2.5 一个图形化的示意
CONTROL
↓ ↓
MODEL VIEW
上面的箭头代表了这个model-view-control结构中的联系. Control模块和Model、View都有联系。而View从Model中检索信息。这些关系可以根据实际需求而改变。我喜欢上面的那种联系,这给了每个模块足够的独立性。当然,给Model和View到Control间加上一条通信线路也是个不错的主意,可以让它们通报突发错误! 正在玩crysis呢,被叫出来修改完毕 -_-! |
|