|
本人水平有限,只能写些初学者的探讨话题。希望大家给与支持,谢谢。
本文讨论程序的框架写法,很多方面可能不仅仅是游戏相关。
言归正传。
写这个的用意是我对自己的程序很不满意。因为我的程序太乱,里面充斥着 extern XXXX之类的东西,这样的程序如果只是一味的往上添加东西也还好,一旦要修改一个变量属性,或者增加一个状态值,立刻蜘蛛网结界的威力便显示出来。。。即使是创造者本人也很为难啊。
程序开发的方法大概两种,一种是基于传统的类似c的方法,一种是面向对象。
传统的c式的开发方式是大家都熟悉的方法:全局变量,外部声明,一组组的函数。开发过程中不断的引用不知是那里定义的变量,数组,状态值。然后结果就是蜘蛛网。。
这种开发方式的优点在于开发出的程序“高效“,确实高效,直接引用能不高效么。而且,老少都能立刻动手开始写,不用多想。当然这是优点还是缺点却也一下说不清。
面向对象就蛮不是这么回事。要消灭extern 就至少要对模式有些认识,然后利用一些精巧的设计处理所有对象间的关系。这,就有些不妙了。更不妙的是在蜘蛛网式开发中可以直接命中的对象变量在这里却要通过杂耍般的过程后才能得到。 效率啊。。。我相信关注效率的人一定气死了。
请醒一醒,虽然我对这个问题也无能为力,但是,随着cpu和gpu的分离,看起来影响刷新率更主要的因素在gpu上,也许,虚函数不再是什么问题,至少在未来前景还是光明的啊。
或者,我们需要铭记于心的就只是面向对象设计中最主要的准则:
开放封闭法则。
这个法则说我们的对象要尽可能的满足未来的需求。而不必再修改代码。面向需求的开放和面向修改的封闭。
换句话说,这就是代码复用的最高境界。这就是面向对象技术的精髓。
我对我程序的框架的改写是从CRender类开始的。在这之前,我已经尝试将d3d简单封装成一个动态链界库。这个库最大的作用就是返回一个d3ddevice的对象。有了这个就可以渲染了,不是么。
在那之前我的render只是个函数(这个大家都见惯了吧)。里面正如常见那样
switch()
{
case gamestart:
GameBeginRender(); //开始画面渲染。。 。
break;
。。。。
}
现在把它变成了一个类,问题在于如果修改,比方说加入一个结束时的渲染,
那么需要添加
case end:
gameEndRender();
break;
那么我们怎么做才能避免日后的手动修改这个类呢?
我们可以用到函数的指针数组来解决
calss Render{
int mGameStateSumNumber; //程序中总的状态
void setGameStateSumNumber(int number)
{mGameStateSumNumber = number; }
//每次程序初始时候放入
typedef void (*FUNCTION)(void); //定义指向函数的指针类型
FUNCTION * function;
initFunction() //初始化每个状态下的渲染函数数组
{
function = new FUNCTION[mGameStateSumNumber] ;
ZeroMemory(...)
}
然后是在适当的时候放入某状态下的渲染函数
SetFuction(FUNCTION func,int state) //状态值用0,1,2。。。
{
function[state] = func;
}
};
然后渲染的时候就查询一下现在系统的状态,
调用 function[state]();就行了。
这样,基本避免的以后修改这个类。
接下来就是处理winmain的窗口框架。。
下次再说吧。
不过在书店看那个新出的小日本(版本千寻,真是好名字)的 冒险游戏设计 里对这个框架做了打包成一个lib,使用只需重载几个函数。我觉得和我的想法是类似的,大家不妨也去书店一观。
|
|