• About
    • Resume
A Game Developer also plays some guitar

Tag Archives: Framework

Game Framework的两种实现方式

April 24, 2011 2:11 pm / Leave a Comment / Benny Chen

一年多前,曾经写过一篇关于Game Engine Framework的文章,当时基本上是为了巩固并加深对framework的理解。最近又做了一些关于framework的工作,对于framework的实现方式又有了些新的认识。虽然我现在做的已经完全不是game了,不过方式对于game也同样适用。

这篇文章主要希望通过一些示例性的C++代码介绍game framework的两种实现方式。首先,我还是搬出一年多前的那篇文章里的game流程图,以下的一些代码也主要基于这张图实现。对于图的细节在这里不再赘述,可以再去翻看之前的那篇文章。

FoC of Game

1.通过继承

这是一种最传统的方式了,之前我一直使用这种方式。基本上是提供一个基类,基类封装并决定了整个程序控制流,同时基于该控制流,基类提供了一系列的接口(在C++里是虚函数),以供继承类override,并实现定制化的行为。就像下面的这个Game类,run函数决定了整个程序的执行逻辑,同时initialize,update,render等非纯虚函数则提供了接口以供用户定制并实现具体Game想要的行为。

// 通过继承来实现的framework
class Game
{
public:
	void run()
	{
		m_isQuit = false;
		initialize();
		while ( !m_isQuit ) 
		{
			handleInput();
			update();
			render();
		}
		destroy();
	}
	
protected:
	virtual void initialize() {}
	virtual void update() {}
	virtual void render() {}
	virtual void destroy() {}
	virtual void onMouse( Mouse mouse ) {}
	virtual void onKeyboard( Keyboard keyboard ) {}
	
private:
	void handleInput()
	{
		Event e;
		while ( popEvent( &e )  )
		{
			switch ( e.type ) 
			{
			case EVENT_QUIT:
				m_isQuit = true;
				break;
			case EVENT_MOUSE;
				onMouse( e.mouse );
				break;
			case EVENT_KEYBOARD:
				onKeyboard( e.keyboard );
				break;
			default:
				break;
			}
		}
	}
	
private:
	bool m_isQuit;
};

在上面的代码中,我把实现全部写在了类的定义头文件中,在这里只是为了省事,在现实中你最好还是分开在.h和.cpp文件中。而且在这里,Game类还可以做的更多,我这里只是为了说明实现方式,所以依照前面的流程图而尽量让它简单。另外,不要纠结这段代码中的Event,Mouse,Keyboard等几个类和popEvent方法,它们只是我为了将故事说得更圆满一点而假象出来的几个类,我想你应该能猜到它们是用来干嘛的。

基于此framework,一个具体的游戏只需要重写这些虚函数就可以了,像下面的这些代码。

class ConcreteGame : public Game
{
private:
	void initialize()
	{
		// do some real initialization
	}
	
	void update()
	{
		// do some real update
	}
	
	void render()
	{
		// do some real rendering
	}

	void destroy()
	{
		// do some real destroy
	}
	
	void onMouse( Mouse mouse )
	{
		// handle mouse event
	}
	
	void onKeyboard( Keyboard keyboard )
	{
		// handle keyboard event
	}
};

int main()
{
	ConcreteGame mygame;
	mygame.run();
	return 0;
}

2.通过Delegation模式

前一种方法有一个缺点,就是将程序的控制流和具体行为紧耦合在了一起,而且还必须使用继承,不易于扩展。现代软件设计的一些方法告诉我们,要尽量使用接口,且尽量使用组合而非继承。Delegation模式就可以帮我们达到这一目的。

何为Delegation模式,wiki上的解释一语中的:

Delegation is the simple yet powerful concept of handing a task over to another part of the program.

Delegation将一些task委托给程序的另外一部分来处理,以达到了行为使用者和具体行为的松耦合。

以下是通过Delegation模式重新实现的framework。

// 通过Delegation模式来实现的framework
class GameDelegation
{
public:
	virtual void initialize() {}
	virtual void update() {}
	virtual void render() {}
	virtual void destroy() {}
	virtual void onMouse( Mouse mouse ) {}
	virtual void onKeyboard( Keyboard keyboard ) {}
};

class Game
{
public:
	Game( GameDelegation *gameDelegation )
	{
		m_gameDelegation = gameDelegation;
	}
	
	void run()
	{
		m_isQuit = false;
		if ( m_gameDelegation == NULL )
		{
			return;
		}
		
		m_gameDelegation->initialize();
		while ( !m_isQuit ) 
		{
			handleInput();
			m_gameDelegation->update();
			m_gameDelegation->render();
		}
	}
	
private:
	void handleInput()
	{
		Event e;
		while ( popEvent( &e ) )
		{
			switch ( e.type ) 
			{
			case EVENT_QUIT:
				m_isQuit = true;
				break;
			case EVENT_MOUSE;
				m_gameDelegation->onMouse( e.mouse );
				break;
			case EVENT_KEYBOARD:
				m_gameDelegation->onKeyboard( e.keyboard );
				break;
			default:
				break;
			}
		}
	}
	
private:
	bool m_isQuit;
	GameDelegation *m_gameDelegation;
};

基于此framework,当需要具体实现一个游戏的时候,只需要实现GameDelegation接口即可,然后将Game类的GameDelegation设置为你所实现的具体的ConcreteGameDelegation类,代码如下。

class ConcreteGameDelegation : public GameDelegation
{
public:
	void initialize()
	{
		// do some real initialization
	}
	
	void update()
	{
		// do some real update
	}
	
	void render()
	{
		// do some real rendering
	}

	void destroy()
	{
		// do some real destroy
	}
	
	void onMouse( Mouse mouse )
	{
		// handle mouse event
	}
	
	void onKeyboard( Keyboard keyboard )
	{
		// handle keyboard event
	}
};

int main()
{
	ConcreteGameDelegation myGameDelegation;
	Game mygame( &myGameDelegation );
	mygame.run();
	return 0;
}

最近我正好做了一些iOS上开发的研究,发现Delegation在iOS框架中被普遍使用。比如,iOS中的每个应用程序对应的是一个UIApplication类,为每一个UIApplication,开发人员必须要实现一个特定的UIApplicationDelegate,并将它指定给当前的应用程序(在main函数中通过UIApplicationMain函数指定,或者是在nib文件中绑定)。在这个UIApplicationDelegate类中,开发人员就需要重写诸如didFinishLaunchingWithOptions,applicationWillTerminate这样的方法,就类似与上面game framework中的initialize,destroy等方法。当然iOS框架要复杂很多,它还用到其它一系列的设计模式,有空研究些这样设计是非常有趣的。

图片来自于这篇苹果官方关于iOS中delegation的介绍:http://developer.apple.com/library/ios/#documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html

Posted in: C++, Game Programming, iOS / Tagged: C++, delegation, framework, game, 实现, 继承

Game Engine Framework

February 4, 2010 1:44 pm / 2 Comments / Benny Chen
FoC of Game

在这次找工作的过程中,有一道笔试题让我印象深刻,题目只有简单的一句话:please use pseudo code to write a game engine framework(请用伪代码写出一个游戏引擎的框架)

当时看到这道题,完全是一种头皮发麻的感觉,虽然我对游戏引擎还算比较熟悉,但它可是个“巨象”般的庞大结构,要在短短的90分钟的笔试时间内把它“摸”完(而且90分钟也不只这一道题),那可真是天方夜谭。所以我当时在试卷上留下的结果就是,草草的画了几个模块图了事。

之后我才意识到,我根本就完全没有理解这道题,或者说,是完全没有理解一个词的意义——framework。受游戏引擎庞大印象的牵连,我把framework想得太大了。

Framework对于IT人士来说貌似是个挺时髦的词,这个词也经常被我们挂在嘴边,我也如此。但问题是,我几乎从来没有去好好的留心过或者深究过,到底什么才是framework,什么样一个东西才能被称为framework,它的准确定义又是什么呢。

看一般英汉字典里对于framework的解释:

structure giving shape and support  框架; 结构

这只是给了我们framework的中文翻译而已,几乎还是没有给我们什么有用的信息。

记住一句话:有困难,找Wiki。当我看到Wiki上对software framework精确的定义时,突然间,一切都明白了。

原文URL:http://en.wikipedia.org/wiki/Software_framework

A software framework, in computer programming, is an abstraction in which common code providing generic functionality can be selectively overridden or specialized by user code providing specific functionality. Frameworks are a special case of software libraries in that they are reusable abstractions of code wrapped in a well-defined API, yet they contain some key distinguishing features that separate them from normal libraries.

Software frameworks have these distinguishing features that separate them from libraries or normal user applications:

1. inversion of control – In a framework, unlike in libraries or normal user applications, the overall program’s flow of control is not dictated by the caller, but by the framework.
2. default behavior – A framework has a default behavior. This default behavior must actually be some useful behavior and not a series of no-ops.
3. extensibility – A framework can be extended by the user usually by selective overriding or specialized by user code providing specific functionality
4. non-modifiable framework code – The framework code, in general, is not allowed to be modified. Users can extend the framework, but not modify its code.

这段话的大概意思是这样,首先表明了software framework是一种抽象体,这个抽象体通过一些公共代码提供了通用的系统功能,使用framework的用户可以在此基础上进行编码,以覆盖或者特化该系统中的相关功能。接着,这段话还说明framework也是一种库,但跟传统的软件库又不同。framework的特点被总结为以下4点:

  1. framework完全决定了程序的控制流,该控制流绝对不会被调用framework的用户(callee)改变,这就是framework跟传统的软件库不同的地方;
  2. framework提供默认行为,且这些默认行为绝对不是无意义的行为;
  3. 用户可以扩展framework的行为;
  4. framework本身的代码不允许被用户改变。

看到这里,我几乎是只有抱头痛哭的份了。因为,从开始学最基础的DirectX技术起,那每一个Demo中,不管多小的Demo,几乎就包含了这样的一种框架,抑或是说,一种游戏引擎框架。只要理解了framework的意思,这道题就根本不是什么问题。我是完全被“游戏引擎”这4个字吓住了,这道题的目的根本不是要你真正的写一个正规的游戏引擎(那是扯蛋),只要弄出一个基本架子即可,达到“麻雀虽小五脏俱全”的效果。

几乎所有的游戏或者说所有的图形渲染的程序,都是遵循下面这样一个过程,一个再熟悉不过的控制流。

FoC of Game

游戏的整个控制流就可以到这么简单,除了图上所描述的东西之外,再加上一系列的消息处理,就可以组成一个基本的游戏框架了。按照wiki上所描述的基本软件framework的4大特点,再来看看游戏引擎framework是如何体现的。

  1. 很显然,游戏的控制流如上图所示,使用framework的用户无法更改;
  2. 游戏引擎framework当然提供默认的行为,比如Initialize部分封装默认的窗口初始化和一系列的设备初始化等过程;
  3. Update和Render,是framework使用者真正进行艺术创造的地方,是游戏开发者的画板。
  4. 游戏引擎framework的代码同样不允许用户修改。

用代码来表现framework是很简单的,在面向对象的语言中一般用抽象类,既提供一些默认的实现,又提供抽象接口供用户扩展。而用户要使用这个framework,只需自定义一个类继承该抽象类,并提供各个抽象方法的实现。用户所需做的只是做一系列的填空题,当然填的如何精彩这就完全取决于用户了。

写这篇文章的真正目的不是为了说明一个游戏引擎的framework是怎么样的,只是借此来强化framework的概念,这样当我们下次再说出这个词的时候,能够知其所以然,而不是自欺欺人。

如果对游戏引擎framework感兴趣,这里有一个简单的游戏引擎framework的代码可供参考: http://gpwiki.org/index.php/SDL:Tutorials:Simple_Engine_Framework

Posted in: Game Programming, Some Experiences / Tagged: framework, game engine, 框架, 游戏引擎

LinkedIn

Milan Petrovic

Categories

  • In My Life (25)
    • A Day in the Life (8)
    • English Learning (2)
    • Learn a Word (7)
    • Something In The Way (8)
  • Music Heaven (8)
    • Guitar (1)
    • In Concert (1)
    • Lyrics (3)
  • OK Computer (54)
    • 3D (3)
    • C++ (10)
    • Computer Graphics (15)
    • Game Programming (23)
    • iOS (6)
    • Linux (1)
    • Lua (9)
    • My Projects (3)
    • Some Experiences (9)
    • Talking in Code (2)
    • Unity (2)
  • Quotations (2)
  • Uncategorized (1)
  • Visca Barça (24)
    • FCB BJ (5)

Recent Posts

  • [译]优化你的手机游戏(没有延迟的,才是健康的)- 一篇给游戏美术设计师读的文章
  • 新浪微博API for MOAI
  • 稍后继续
  • Unity Developer ++
  • Another Thread @ Moai Forum
  • 1st Day of Golden Week
  • 为SyntaxHighlighter添加新语言
  • 基于Lua的State Pattern
  • Class Diagram of Pacman
  • 基于Moai的Pacman

Recent Comments

  • 约修亚_RK on 为SyntaxHighlighter添加新语言
  • 爱装的小男孩 on 小心DLL链接静态库时的内存错误
  • happyfire on Game Loop的几种实现方式
  • William on 新浪微博API for MOAI
  • Benny Chen on 新浪微博API for MOAI
  • your man on 新浪微博API for MOAI
  • 你家男人 on 稍后继续
  • 逍遥 on 关于对std::vector的遍历
  • papa on Unity Developer ++
  • T客网 ︱ Techpot » Blog Archive » iOS开发与OpenGL ES相关问题整理(1) on iOS开发与OpenGL ES相关问题整理(1)

Tags

2d 3D 3dsmax 3ds max air Apply architecture Asia tour barca Beijing bilbao binary search blocked bob boost bruce springsteen C++ capo CGContextDrawImage Champions League Change DLL DX10 eval exporter flash framework frustum culling game game engine iniesta ios linux lua Moai opengles pacman plug-in plugin 北京 导出插件 崩溃 巴萨 游戏引擎 踢球
© Copyright 2026 - A Game Developer
Infinity Theme by DesignCoral / WordPress