社区应用 最新帖子 精华区 社区服务 会员列表 统计排行 道具中心
主题 : [第一部分]游戏的简易框架,觉得还是写点砖头,希望有玉来跟哦^^
lw 离线
级别: 分版主
显示用户信息 
0  发表于: 2006-11-03   
来源于 通用编程 分类

[第一部分]游戏的简易框架,觉得还是写点砖头,希望有玉来跟哦^^

(前文,偶妹妹感情问题,偶很难过,然后就特别想写点什么,跑到这里来算是胡乱发表意见好了,权当作发泄……)

写最近自己的一个BALL的开发的构思好了:开发前和朋友好好讨论过游戏的开发,发觉讨论的时候,特别是自己有了一点想法,往往很容易就能够有一个整体策划计划,但是很少,只需要半张纸,也没有你想象的那么多文字,大概还没有从开头写到现在这么多字- -

AC游戏是开源的,偶也很乐意和入门的朋友们分享自己的心得(学网络用语,新手入门,高手免看好了……),这个游戏也觉得比较适合入门观摩(STL部分可能各位会郁闷,因为偶也是刚刚入STL门乱试验的- -)

首先你要有一套引擎(偶只会一点C++,所以其它语言就……不过差不多拉,主要是说说思路),可以是HGE、Y2GE、HMGE、XXGE等等,偶觉得Y2GE很好用,而且是偶的好朋友写得,如果有问题可以直接问作者,方便~,XXGE要到什么够呢?先不要觉得要什么特效都有,只需要能够显示一个PIC就可以了,顶多能够RESIZE或者ROTATE……

于是,你有了:AUDIO SOUND RENDERER ,这些比较适合用一个通用的GAMEEG来静态包装,这样当你使用的时候只需要:
GameEG::Draw( hpic, x, y ) 就这样(参数分别是 图片ID,XY坐标)
GameEG::Play( hmusic ) 播放声音

接下来你知道你要开始做游戏,这会是一个方块(嗯,AC游戏是一个方块游戏)假设你有了图片……嗯……这会很麻烦?联系偶,偶能够做一个比较幼稚等级的方块……

请参考你自己的设计,什么地方会是突破口呢?我做AC游戏的时候是从main这里开始的(请大家不要像我写得这么花哨)
一句话整个游戏……OTZ……
复制代码
  1. auto_ptr<Manager> mgr( new Manager(hInstance) ) ;

大家还是自己编写init + while(loop()) + end比较好……偶纯粹看看STL的autoptr是怎么用的……

那么init loop end应该做什么呢?你会想知道,其实你已经知道了……
你看到了manager,这在AC的计划中是一个游戏的流程管理对象(很深奥吗?说白了,你游戏怎么执行,根据这个对象提供的函数,至于对象有什么作用,简单说,就是你不要把游戏看做一个过程,而是一个游戏对象,对,就是这个AC游戏,它,依次执行了INIT 到 END的过程,好了你觉得还是过程理解好,那就过程好了……)

我知道写太多很多人会不看了……不知道这行大家看到了没^^?

manager下面是player因为考虑到会有两个player玩,所以分了player来表示具体的玩家,你知道AC游戏的player做什么用吗?就是真正和你打交道的那个对象……不懂对象还真的郁闷啊……再多说巴……就是说你在 和 程序交流,通过某个中介,player对象就是这个中介:

你的输入 -- player对象 -- 游戏的流程、游戏的绘制

用代码来说:

manager通过EG获得输入 -- player获得输入 -- 传递给player内部的对象(又是对象啊- -)

player内部的对象就是你要绘制的单位,比如球、人、其它。。。
通用的属性是图片ID、X、Y等,通过这些你直接用EG就可以表现出来了,这个步骤通常就是渲染……


但是这样很乱?是的,你得自己慢慢整理过,偶的AC是MOVE表示一次移动,然后一次渲染,什么FPS,你管它啊……

好了,就啰嗦到这里,并拜谢看到这里的朋友,偶写得是很烂……

pS:顺便再打个广告,偶AC开源,放在GOOGLEPAGE上面,地址在:

http://littlewaterxp.googlepages.com/  

图片常常链接失效就不贴了= =
[ 此贴被lw在2006-11-04 14:32重新编辑 ]
评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
Style-C
shawind 离线
级别: 分版主
显示用户信息 
1  发表于: 2006-11-03   
是这样的吧
main

初始化设备;
游戏循环;
释放设备;
え~え~お!!!
lw 离线
级别: 分版主
显示用户信息 
2  发表于: 2006-11-04   
对的,初始化部分往往是 EG的INIT,RESOURCE的LOAD,一般所有的资源应该被全部加载到内存(除非大型游戏……)
中间部分是逻辑处理为主,偶觉得还是写得太乱了……
RELEASE部分就是指把你的EG的东西卸载掉,别忘了还有资源……不然泄漏了(虽然SYSTEM会负责善后,但是负责的程序员会一点不忘卸载所有的资源……)

另外这篇文章感觉有点虎头蛇尾了……偶有空想想后面部分应该怎么写
Style-C
Yuki 离线
级别: ②入门
显示用户信息 
3  发表于: 2006-11-04   
我也来说一下流程吧.
一般框架型的引擎.会提供一个BaseAppFrameWork 用来封装游戏主体框架.自己写的时候只用继承这个类,并重载所要的函数即可.
不过我这里说的是我的红魔夜的流程.还是用的传统的写法,因为我的Y2GE本身不是一个框架
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
   EnableMemoryLeakCheck();
   Game::InitGame(hInstance);
   Game::RunGame();
   Game::ShutGame();
   return 0;
}
而Game本身是一个static类.就是里面的函数和成员都是static 的.当然这个可以用Singleton来实现.但是我直接写了.
Game里面保存着几个对游戏有整体作用的变量.除了控制游戏主体运行的ObjManager
以外.还有一个非常重要的变量state,作为游戏的主体状态机的状态.
typedef enum
{
   GAME_STATE_INIT,
   GAME_STATE_END,
   GAME_STATE_STARTMENU,
   GAME_STATE_CHOOSEDIFFICULTY,
   GAME_STATE_CHOOSEPLAYER,
   GAME_STATE_STARTLEVEL,
   GAME_STATE_RUN,
   GAME_STATE_PAUSE,
   GAME_STATE_NEWlEVEL,
   GAME_STATE_CONTINUE
}GAME_STATE;
class Game
{
// Interface
public:
   static void InitGame(HINSTANCE hinstance);
   static void RunGame();
   static void ShutGame();
   static bool _func(DWORD a);
   static ObjectMap & GetObjectMap();
protected:
   static int _GameStateInit();
   static int _GameStateEnd();
   static int _GameStatestartMenu();
   static int _GameStateChooseDifficulty();
   static int _GameStateChoosePlayer();
   static int _GameStateStartLevel();
   static int _GameStateRun();
   static int _GameStatePause();
   static int _GameStateNewLevel();
   static int _GameStateContinue();
// Variables
private:    
   static ObjectMap om;
   static HINSTANCE hinstance;
   static int state;
   static int level;
};
Init和Shut 分别负责引擎初始化资源加载 和 资源释放引擎关闭
重点在Run上面.
void Game::RunGame()
{
   engine.Sys_Start(Game::_func,0);
}
这里用我的Y2GE进行游戏循环.
bool Game::_func(DWORD a)
{
   static bool restore = false;

  // game state run
   if (!engine.Video_BeginScene(Color::black()))
   {
       if (restore == false)
       {
           om.ReleaseFont();
           restore = true;
       }
       return true;
   }
   if (restore == true)
   {
       om.RestoreFont();
       restore = false;
   }
   switch (state)
   {
   case GAME_STATE_INIT:
       state = _GameStateInit();
       break;
   case GAME_STATE_END:
       state = _GameStateEnd();
       return false;
       break;
   case GAME_STATE_STARTMENU:
       state = _GameStatestartMenu();
       break;
   case GAME_STATE_CHOOSEDIFFICULTY:
       state = _GameStateChooseDifficulty();
       break;
   case GAME_STATE_CHOOSEPLAYER:
       state = _GameStateChoosePlayer();
       break;
   case GAME_STATE_STARTLEVEL:
       state = _GameStateStartLevel();
       break;
   case GAME_STATE_RUN:
       state = _GameStateRun();
       break;
   case GAME_STATE_PAUSE:
       state = _GameStatePause();
       break;
   case GAME_STATE_NEWlEVEL:
       state = _GameStateNewLevel();
       break;
   case GAME_STATE_CONTINUE:
       state = _GameStateContinue();
       break;
   }
   engine.Video_EndScene();
   
   return true;
}
也就是说每一个状态都有一个对应的函数进行处理.该函数返回下一个应该出现的状态.
然后就可以在主要的state 里面使用ObjManager(就是ObjectMap)来进行游戏主体运行了
int Game::_GameStateRun()
{
   engine.Event_GetKeyboardState();

   if (!Level::ExecuteScript())
       return GAME_STATE_NEWlEVEL;
   om.ProcessInput();
   om.MoveObjects();
   om.ProcessHitEvents();
   if (engine.keyboard.IsKeyDown(DIK_RETURN) || engine.keyboard.IsKeyDown(DIK_ESCAPE))
   {
       Global::PlaySe(SE_CANCEL);
       return GAME_STATE_PAUSE;
   }
   if(!om.IsPlayerAlive())
   {
       return GAME_STATE_CONTINUE;
   }
   om.RenderObjects();
   return GAME_STATE_RUN;
}
简单的游戏框架就是这样了.
代码写的很烂,请大家多包涵..
lw 离线
级别: 分版主
显示用户信息 
4  发表于: 2006-11-04   
看到yuki的这篇,感觉文字少了点,但是很清晰,偶要学学这种 西法 ~

不过这个GAME是一个全static的类……
Style-C
lw 离线
级别: 分版主
显示用户信息 
5  发表于: 2006-11-04   
case GAME_STATE_RUN:
state = _GameStateRun();

这句话恐怕不知道脚本驱动的人会还是云里雾里巴^^
Style-C
Yuki 离线
级别: ②入门
显示用户信息 
6  发表于: 2006-11-04   
引用
引用第4楼lw2006-11-04 14:35发表的:
看到yuki的这篇,感觉文字少了点,但是很清晰,偶要学学这种 西法 ~

不过这个GAME是一个全static的类……

怎么好用就怎么用啊.不过Game类必须要有一个static函数就是_func.Level类也是全static 的.因为要和lua交互.
lw是版主吗.刚看到.
lw 离线
级别: 分版主
显示用户信息 
7  发表于: 2006-11-04   
引用
不过Game类必须要有一个static函数就是_func

因为Y2GE必须调用一个NOMEMEBER FUNCTION哈^^

和LUA交互的时候能不能放到某个level对象中?比如不同的对象 和LUA的不同功能、模块相互交互?当然还会有中间层……
例如:
[LUA_SHOT]   -- lua parser -- shot flowfunc
[LUA_PLAYER] -- lua parser -- player flowfunc
[LUA_ENEMY]   -- lua parser -- enemy flowfunc
等,PS:偶基本不懂lua怎么用的……
Style-C
Yuki 离线
级别: ②入门
显示用户信息 
8  发表于: 2006-11-04   
lua 必须要调用static 的func.把这个func 在lua里面注册了以后.就可以在脚本里面调用.
函数原形必须这样
int _cdecl func (lua_State * ls);
可以从ls里面取得lua传过来的参数.也可以把要返回的值压进去.
lw 离线
级别: 分版主
显示用户信息 
9  发表于: 2006-11-05   
偶大概这样写:
class LUAParser
{
public: static int func(lua_State *ls); ...
};

class LUA_Shoter : public LUAParser
{
public:
  HRESULT do_LUAOnShot() {}
};

class LUA_Enemy : public LUAParser
{
public:
  HRESULT do_LUAOnEnemy() {}
};

... 等等
Style-C
描述
快速回复

认证码:

验证问题:
22-5=?,答案:17 正确答案:17
按"Ctrl+Enter"直接提交