明论  

接下来我们进入教程的主菜,进入游戏。

 再此之前,我先给出游戏系统的架构图:

有点复杂,不要紧,让我一点一点的为你分析

 

 

 

先从我们之前看到过的PreGame着手,这里再一次贴出PreGame的定义

class CPreGame : public CGameController
{
public:
    enum State {
        UNKNOWN,
        WAIT_ON_ADDRESS,
        WAIT_ON_SCRIPT,
        WAIT_ON_MAP,
        WAIT_ON_MOD,
        ALL_READY,
    };
    CPreGame(bool server, const std::string& demo, const std::string& save);
    virtual ~CPreGame();

    CglList* showList;

    bool Draw();
    int KeyPressed(unsigned short k,bool isRepeat);
    bool Update();

    bool server;
    State state;
    bool saveAddress;

    bool hasDemo,hasSave;

    static std::string mapName;
    static std::string modName;
    static std::string modArchive;
    static std::string scriptName;
    std::string demoFile;

    void UpdateClientNet();
    unsigned char inbuf[16000];    //buffer space for incomming data
    int inbufpos;                                //where in the input buffer we are
    int inbuflength;                        //last byte in input buffer

    CLoadSaveHandler *savefile;
private:
    CInfoConsole* infoConsole;

    void ShowScriptList();
    void ShowMapList();
    void ShowModList();
    static void SelectScript(std::string s);
    static void SelectMap(std::string s);
    static void SelectMod(std::string s);

};

可以看到 CPreGame我们前面所用于控制函数生成的类,是继承于一个非常重要的类CGameController,上面的 Update();Draw();等控制游戏重要的方法都是CGameController上虚函数的override.

以下是CPreGame的一个方法Update,我们从中可以看到,在获得状态ALL_READY之后,CPreGame将执行开始游戏的一系列操作,包括实例化一个游戏中最重要的类Update(),Cgame.

case ALL_READY: {
            ENTER_MIXED;

            // Map all required archives depending on selected mod(s)
            vector<string> ars = archiveScanner->GetArchives(pregame->modArchive);
            if (ars.empty())
                logOutput.Print("Warning: mod archive ""%s"" is missing?"n", pregame->modArchive.c_str());
            for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i)
                if (!hpiHandler->AddArchive(*i, false))
                    logOutput.Print("Warning: Couldn't load archive '%s'.", i->c_str());

            // Determine if the map is inside an archive, and possibly map needed archives
            CFileHandler* f = SAFE_NEW CFileHandler("maps/" + pregame->mapName);
            if (!f->FileExists()) {
                vector<string> ars = archiveScanner->GetArchivesForMap(pregame->mapName);
                if (ars.empty())
                    logOutput.Print("Warning: map archive ""%s"" is missing?"n", pregame->mapName.c_str());
                for (vector<string>::iterator i = ars.begin(); i != ars.end(); ++i) {
                    if (!hpiHandler->AddArchive(*i, false))
                        logOutput.Print("Warning: Couldn't load archive '%s'.", i->c_str());
                }
            }
            delete f;

            // always load springcontent.sdz
            hpiHandler->AddArchive("base/springcontent.sdz", false);

            const int teamID = gs->players[gu->myPlayerNum]->team;
            const CTeam* team = gs->Team(teamID);
            LoadStartPicture(team->side);

            // create GameServer here where we can ensure to know which map and mod we are using
            if (server) {
                good_fpu_control_registers("before CGameServer creation");
                gameServer = SAFE_NEW CGameServer(gameSetup? gameSetup->hostport : 8452, pregame->mapName, pregame->modArchive, pregame->scriptName, demoFile);
                good_fpu_control_registers("after CGameServer creation");
            }

            game = SAFE_NEW CGame(server, pregame->mapName, pregame->modArchive, infoConsole);

            if (savefile) {
                savefile->LoadGame();
            }

            infoConsole = 0;

            ENTER_UNSYNCED;
            pregame=0;
            delete this;
            return true;

        }

当然在开始之前,该系统有读取文件等异步IO操作的文件系统,我们留到以后再讲,我们先将系统的基本架构理顺。

Cgame与我们前面说过的Pregame都是继承于类 CGameController。这可以说是游戏中最重要的类,所以这个类的构造函数可以说是最重要的构造函数。他几乎启动了系统的所有模块的所有功能。。。。所以各位如果像我刚开始时闷头看我们就看不出什么所以然了。那我们先选择各个击破,大家请看上面的主系统架构图,进入CGame这个重要的模块,我们需要调用到以下的重要子模块或者跟确切的说是方面:

给大家看看他头文件的定义:

class CGame : public CGameController
{
public:
    CR_DECLARE(CGame);            //Don't use CGame pointer in CR_MEMBER()!!!
    void UpdateUI();
    bool ClientReadNet();
    void PostLoad();

    void SimFrame();
    void StartPlaying();
    bool DrawWorld();
    bool Draw();
    bool Update();
    int KeyReleased(unsigned short k);
    int KeyPressed(unsigned short k,bool isRepeat);
    CGame(bool server, std::string mapname, std::string modName, CInfoConsole *infoConsole);
    void ResizeEvent();
    virtual ~CGame();

    bool ActionPressed(const CKeyBindings::Action&, const CKeySet& ks, bool isRepeat);
    bool ActionReleased(const CKeyBindings::Action&);

    int que;
    unsigned int oldframenum;
    unsigned int fps;
    unsigned int thisFps;

    time_t fpstimer, starttime;
    Uint64 lastUpdate;
    Uint64 lastMoveUpdate;
    Uint64 lastModGameTimeMeasure;

    Uint64 lastUpdateRaw;
    float updateDeltaSeconds;

    unsigned int lastframe;
    float totalGameTime;            //time in seconds, stops at game end

    unsigned char inbuf[40000*2];    //buffer space for incomming data    //should be NETWORK_BUFFER_SIZE*2
    int inbufpos;                                //where in the input buffer we are
    int inbuflength;                        //last byte in input buffer

    bool bOneStep;                        //do a single step while game is paused

    int leastQue;

    std::string userInputPrefix;

    int lastTick;
    float timeLeft;
    float consumeSpeed;
    int chatSound;

    int skipping;
    bool playing;
    bool allReady;
    bool chatting;
    bool camMove[8];
    bool camRot[4];
    bool hideInterface;
    bool gameOver;
    bool windowedEdgeMove;
    bool showFPS;
    bool showClock;
    bool noSpectatorChat;            //prevents spectator msgs from being seen by players
    bool drawFpsHUD;

    float maxUserSpeed;
    float minUserSpeed;
    bool gamePausable;

    bool soundEnabled;
    float gameSoundVolume;

    CScript* script;

    CInfoConsole *infoConsole;

    void MakeMemDump(void);

    CConsoleHistory* consoleHistory;
    CWordCompletion* wordCompletion;

    bool creatingVideo;
    CAVIGenerator* aviGenerator;

    void DrawDirectControlHud(void);
#ifdef DIRECT_CONTROL_ALLOWED
    short oldHeading,oldPitch;
    unsigned char oldStatus;
#endif

    void HandleChatMsg(std::string msg, int player, bool demoPlayer);

    void SetHotBinding(const std::string& action) { hotBinding = action; }

protected:
    void SendNetChat(const string& message);

    void DrawInputText();
    void ParseInputTextGeometry(const string& geo);

    void SelectUnits(const string& line);
    void SelectCycle(const string& command);

    void LogNetMsg(const string& msg, int player);
    void ReloadCOB(const string& msg, int player);
    void Skip(const string& msg, bool demoPlayer);

protected:
    std::string hotBinding;
    float inputTextPosX;
    float inputTextPosY;
    float inputTextSizeX;
    float inputTextSizeY;
    float lastCpuUsageTime;

};

 

无论从头文件还是从架构图都可以看到,Cgame所启动的内容首先包括以下几个大方面:

1, UI生成。            ----生成操作界面

2, 图像生成。         ----生成游戏图形

3, 用户操作。         ----响应用户的鼠标或键盘的操作

4, 远程网络通讯。    ----与其他玩家同步游戏信息

5,AI系统                ----当地图中有电脑玩家的时候,与人对战的AI ,也包括单位的基本AI如寻道,等等

 

接下来分大几章为大家介绍这个大游戏是怎么一句一句写出来。




 

 

 

posted on 2008-08-05 15:02  konyel  阅读(570)  评论(0)    收藏  举报