游戏开发论坛

 找回密码
 立即注册
搜索
楼主: tarkey

游戏结构。。

[复制链接]

0

主题

32

帖子

32

积分

注册会员

Rank: 2

积分
32
发表于 2004-6-12 13:04:00 | 显示全部楼层

Re:游戏结构。。

楼主能否给出模块的接口,即上面的类CModuleBase的定义。

还有就是我以为内存的管理应该模块级的而非游戏级的。楼主上面将内存池提到和引擎一个级别,那这个内存池势必需要因为各种可能模块的需要而编写地非常灵活,但灵活的代价就是效率的低下(运行效率),当然不一定总是这样。如果由个模块私自管理内存那应该能更有些效率。
当然,按照楼主的说法,这些模块也可以从这个全局的内存池分配到内存后再自行管理,但效果等同于做操作系统的工作。

最后是楼主是按功能进行模块划分的,我想请问是否一个大游戏中的两个小游戏(如RPG中的赌博之类),一个是射击类一个是桌面类,那么这里总共的三个游戏是否应该分属于不同的模块?它们都只使用2D引擎,那么游戏本身是否就是数据,而引擎就变成了一种机器,不同的数据留过引擎就能产生不同的游戏?那么这个数据的结构又应该是怎样的?即一个struct或class的定义。

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
 楼主| 发表于 2004-6-12 17:47:00 | 显示全部楼层

Re:游戏结构。。

回楼上的:

内存的分配的话,那个内存池模版主要是为引擎的内存需要而设计的,具体的模块内部的话,可以自己分配和释放内存,当然,也可以include那个内存模版来用。

如果一个大游戏中的两个小游戏,如果是两个小游戏在一起玩的话,你是需要他们同样的帧数吗?或者是什么的?不太明白你所说的。数据的话,都放在无限状态机里面。

0

主题

32

帖子

32

积分

注册会员

Rank: 2

积分
32
发表于 2004-6-12 22:50:00 | 显示全部楼层

Re:游戏结构。。

我的意思是那两个小游戏及主游戏都会使用2D引擎,同样的也都会使用输入引擎、声音引擎等。其实我这里的意思就是想知道楼主如何设计那个模块的接口?

如果模块是功能模块,不是游戏模块,则是否是应该为第一个小游戏专门编写一个函数(或者是游戏循环),其中调用上面的各个引擎?而另一个小游戏则又编写一函数或循环,并从中调用各个引擎?那么模块到底有什么意义?其不是和一般的SDK没有任何区别了吗?

又或者模块设计的很厉害,其定义了一种数据结构,这个结构能指明如何操作这个模块所对应的引擎。因此是很希望楼主能给出一下模块接口的定义的,即CModuleBase的定义。

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
 楼主| 发表于 2004-6-12 23:37:00 | 显示全部楼层

Re:游戏结构。。

。。。。模块的接口,我是这样定义的:
#ifndef __MODULE_BASE_H__
#define __MODULE_BASE_H__

class CModuleBase
{
    friend class CEngine;

public:
    CModuleBase()
    {
    }

    CModuleBase(int mID)
    {
        m_ID = mID;
    }
       
    virtual int ProcessModule() = 0;

    int GetID()
    {
        return m_ID;
    }

protected:

    int SetID(int mID)
    {
        return m_ID = mID;
    }

    int m_updateFrequency;
    int m_updateTicker;

private:
    int m_ID;
};

#endif
就这么简单,CEngine类呼叫的时候,就只呼叫ProcessModule。
具体这个东西干了什么,CModuleBase的派生类自己去实现。
图形的话,可以在ProcessModule()里面render等等之类的。
声音就在里面播放声音之类的。

一个CEngine一个游戏循环,你也可以弄两个CEngine。

实际上的流程是这样的,CEngine的主循环,检查到哪个模块该更新了。
就呼叫这个模块的ProcessModule,然后具体的这个ProcessModule里面干什么
都好,处理NPC AI啊,渲染啊,播放音乐啊,都不管。这就是CEngine做的事。

0

主题

32

帖子

32

积分

注册会员

Rank: 2

积分
32
发表于 2004-6-13 18:01:00 | 显示全部楼层

Re:游戏结构。。

恕我冒昧

楼主的意思是说一个CEngine的实例是一个游戏,因此我前面说的一个大游戏下的两个小游戏就应该有三个CEngine的实例,而且还不能只是简单的生成CEngine的三个实例就完了,还需要为每个CEngine的实例相应的添加一系列的CModuleBase派生类的实例,并且每个CModuleBase派生类的实例都还不能使用同一个派生类,而必须重新派生另一个新的派生类,因为那三个游戏的输入操作不同、显示不同、声音播放不同,而照楼主说的结果就必须从CModuleBase派生出9个类(假设三个游戏都只使用输入、显示和声音),而每个游戏特有的显示方式、或是特有的键盘输入处理方式或特有的声音播放方式就是通过CModuleBase:rocessModule来实现的。

我想问的问题就是CModuleBase从头至尾根本没有成为类的必要性,上面只需通过在CEngine中纪录模块的函数指针即可了,完全没有成为类的意义。不过这不重要,关键就是上面声音模块和输入模块以及显示模块之间的区别根本就没有表现出来,即按楼主所说,反正所有的render或是play等都是在ProcessModule中由程序员现行编写,那么编写ProcessModule的那个程序员出于什么原因就只在CMusicModule::ProcessModule中编写播放音乐的代码?他也可以编写进行render的代码啊。(并且上面如果两个游戏并行运行,如主程序是网络程序,其一直运行,而玩家在赌博小游戏中休闲,那么按照CEngine的循环就无效了,除非把每个CEngine的实例作成一个线程或是添加其他的紧耦合,但程序架构就变糟了)

我的意思也就是说上面的CModuleBase中的那几个成员变量有什么意义?标识出模块和指定模块的计时器间隔?这不是完全看不出显示模块和音乐模块之间的区别吗?仅仅计时器的间隔不同?那为什么要不同?怎能体现出显示模块和音乐模块的差别?通过对ProcessModule的执行效果的不同来体现?那又何必非得分成多个模块?反正在一个模块的ProcessModule中可以搞定全部。

上面的问题其实属于设计问题,不过我并不是故意来刁难楼主的,只是希望知道楼主原想的游戏具体运作的所有详细过程,就好像上面楼主说的
“检查到哪个模块该更新了。就呼叫这个模块的ProcessModule,然后具体的这个ProcessModule里面干什么都好”
能否说一下CEngine如何知道哪个模块该更新了,比如是检查模块所属的m_updateFrequency或其他什么的,但为什么要这么做。还有多个模块间是如何协调的?比如AI检测到了要“走动”了,然后显示就将相应的画面画在屏幕上,那么显示模块是如何知道要“走动”了?通过全局变量或是内存池之类?那么是否对效率有影响?等等

201

主题

1437

帖子

1963

积分

金牌会员

Rank: 6Rank: 6

积分
1963
QQ
发表于 2004-6-13 19:44:00 | 显示全部楼层

Re:游戏结构。。

实际上就是更新或状态函数的调用和管理问题,对吗?可以这样:将CEngine做成CModule的子类,在CModule加上virtual void Process()=0,并在CEngine里将其实现为对CModule的管理,比如调用它的Process(),这样CEngine也能当成CModule。像楼上那种情况,让控制台CEngine调入子游戏的CEngine就好了,主游戏的CEngine被控制台CEngine暂时挂起。我目前想搞的一个游戏引擎(如果算是的话)就基于此思想,不过叫CBaseWork和CBaseWorker和Do()=0。这可是我脑子想烂了才想出来的方法。

201

主题

1437

帖子

1963

积分

金牌会员

Rank: 6Rank: 6

积分
1963
QQ
发表于 2004-6-13 19:46:00 | 显示全部楼层

Re:游戏结构。。

那内存池是什么东西?管理内存不是系统的事吗?我是初学者,不懂的。

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
 楼主| 发表于 2004-6-13 21:21:00 | 显示全部楼层

Re:游戏结构。。

。。。。看来楼上的还没弄明白我的意思。
CEngine检查m_updateFrequency,每个周期就让模块刷新一次。
比如网络模块,用AddModule方法加入的时候,就可以指定刷新时间,比如说30豪秒之类的,当然有些模块根本不需要刷新,那么加入的时候,就不需要指定m_updateFrequency这个参数。

还有,我只所以实现FSM,就是为了解决你的那个问题,比如说你刷新NPC的时候,发现某个NPC要走了。然后在FSM里面设置一个参数叫FSM_D->Set("npc_move", &pos);然后在渲染的时候,就去FSM_D->Get("npc_move");如果这个是空的话,就什么都不做,如果有东西的话,就取出来渲染。

也就是说,任何模块都只需要把临时状态往FSM里面丢,然后从FSM里面取,不需要知道这个状态是谁发起的,也不需要知道这个状态谁会接收。这样的好处就是,你写模块代码的时候,不需要去询问其他模块的一些情况,直接的在FSM里面设置状态就好了。

0

主题

35

帖子

35

积分

注册会员

Rank: 2

积分
35
发表于 2004-6-14 04:27:00 | 显示全部楼层

Re:游戏结构。。

我是新人。我只想问问这个东西是怎么生成的
static int T[] =
{
    1, 87, 49, 12, 176, 178, 102, 166, 121, 193, 6, 84, 249, 230, 44, 163,
    14, 197, 213, 181, 161, 85, 218, 80, 64, 239, 24, 226, 236, 142, 38, 200,
    110, 177, 104, 103, 141, 253, 255, 50, 77, 101, 81, 18, 45, 96, 31, 222,
    25, 107, 190, 70, 86, 237, 240, 34, 72, 242, 20, 214, 244, 227, 149, 235,
    97, 234, 57, 22, 60, 250, 82, 175, 208, 5, 127, 199, 111, 62, 135, 248,
  174, 169, 211, 58, 66, 154, 106, 195, 245, 171, 17, 187, 182, 179, 0, 243,
132, 56, 148, 75, 128, 133, 158, 100, 130, 126, 91, 13, 153, 246, 216, 219,
    119, 68, 223, 78, 83, 88, 201, 99, 122, 11, 92, 32, 136, 114, 52, 10,
    138, 30, 48, 183, 156, 35, 61, 26, 143, 74, 251, 94, 129, 162, 63, 152,
    170, 7, 115, 167, 241, 206, 3, 150, 55, 59, 151, 220, 90, 53, 23, 131,
    125, 173, 15, 238, 79, 95, 89, 16, 105, 137, 225, 224, 217, 160, 37, 123,
    118, 73, 2, 157, 46, 116, 9, 145, 134, 228, 207, 212, 202, 215, 69, 229,
    27, 188, 67, 124, 168, 252, 42, 4, 29, 108, 21, 247, 19, 205, 39, 203,
233, 40, 186, 147, 198, 192, 155, 33, 164, 191, 98, 204, 165, 180, 117, 76,
    140, 36, 210, 172, 41, 54, 159, 8, 185, 232, 113, 196, 231, 47, 146, 120,
    51, 65, 28, 144, 254, 221, 93, 189, 194, 139, 112, 43, 71, 109, 184, 209,
};

59

主题

1104

帖子

1199

积分

金牌会员

Rank: 6Rank: 6

积分
1199
 楼主| 发表于 2004-6-14 12:40:00 | 显示全部楼层

Re:游戏结构。。

不是生成的,是Peter K. Pearson在CACM 33-6, 发表的一篇关于专门针对字符串的HASH表算法。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-20 07:51

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表