• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            天行健 君子當自強而不息

            Controlling Players and Characters(15)

             

            To see more details about game script,see 游戲腳本的實現

             

            Scripting and Characters


            Scripting keeps popping its head up throughout these last few chapters, and true
            to form, scripting plays a major role when dealing with characters. Scripts work
            with conversations, spells, character movement, and much more.


            What you need at this point is a clean-cut method of processing the game scripts.
            The best way to do this is to create a class to entwine into your character and other
            application processing.

             

            The Script Class

            it becomes even easier to execute scripts when you put the whole script processing in a class.

            enum ENTRY_TYPE { ENTRY_NONE = 0, ENTRY_TEXT, ENTRY_BOOL, ENTRY_INT, ENTRY_FLOAT, ENTRY_CHOICE };

            typedef 
            struct sEntry
            {
                
            long    type;               // type of blank entry (ENTRY_TEXT, ENTRY_BOOL, )

                union
                {
                    
            long    io_value;       // used for saving/loading
                    long    length;         // length of text (0 terminator)
                    long    selection;      // selection in choice
                    BOOL    bool_value;     
                    
            long    long_value;     
                    
            float   float_value;    
                };

                
            char*   text;               // entry text buffer

                sEntry()
                {
                    memset(
            this, 0, sizeof(*this));
                }

                ~sEntry()
                {
                    delete[] text;
                }
            } *sEntryPtr;

            ////////////////////////////////////////////////////////////////////////////////////

            typedef 
            struct sScriptInfo
            {
                
            long        action_index;   // [0, number of actions - 1]

                
            long        num_entries;    // number of entries in this action
                sEntry*     entries;        // array of entries

                sScriptInfo*     prev;      
            // previous in linked list
                sScriptInfo*     next;      // next in linked list

                sScriptInfo()
                {
                    memset(
            this, 0, sizeof(*this));
                }

                ~sScriptInfo()
                {
                    delete[] entries;
                    delete next;
                }
            } *sScriptInfoPtr;

            ////////////////////////////////////////////////////////////////////////////////////

            typedef 
            class cScript
            {
            private:
                
            long            m_num_actions;
                sScriptInfo*    m_root_script_info;

            private:
                
            virtual bool prepare() { return true; }
                
            virtual bool release() { return true; }

                
            virtual sScriptInfo* process(sScriptInfo* script_info)
                {
                    
            return script_info->next;
                }

            public:
                cScript()
                {
                    m_num_actions = 0;
                    m_root_script_info = NULL;
                }

                ~cScript()
                {
                    free();
                }

                
            void free()
                {
                    delete m_root_script_info;
                    m_root_script_info = NULL;

                    m_num_actions = 0;
                }

                sScriptInfo* get_root_script_info()
                {
                    
            return m_root_script_info;
                }
                
                
            bool load(const char* filename);
                
            void execute(const char* filename);    
            } *cScriptPtr;

            Although deceptively small, the cScript class packs a punch. Loading a script is
            accomplished via the Load function. Once it’s loaded, you can process the script
            with a call to Execute. If you don’t want to hassle with loading a script
            before processing, a call to the Execute function takes a script file
            to load and execute in the same function call (plus it frees the script when execution is complete).


            bool cScript::load(const char* filename)
            {
                free();

                FILE* fp;

                
            if((fp = fopen(filename, "rb")) == NULL)
                    
            return false;

                fread(&m_num_actions, 1, 
            sizeof(m_num_actions), fp);

                sScriptInfo* head = NULL;
                sScriptInfo* ptr = NULL;

                
            // loop through each script action
                for(long i = 0; i < m_num_actions; i++)
                {
                    
            // allocate a script structure and link in

                    sScriptInfo* info = 
            new sScriptInfo;
                    info->next = NULL;

                    
            if(ptr == NULL)
                        head = info;
                    
            else
                        ptr->next = info;

                    ptr = info;

                    fread(&info->action_index, 1, 
            sizeof(info->action_index), fp);
                    fread(&info->num_entries, 1, 
            sizeof(info->num_entries), fp);

                    
            // get entry data (if any)
                    if(info->num_entries)
                    {
                        info->entries = 
            new sEntry[info->num_entries];

                        
            // load in each entry
                        for(long j = 0; j < info->num_entries; j++)
                        {
                            fread(&info->entries[j].type, 1, 
            sizeof(info->entries[j].type), fp);
                            fread(&info->entries[j].io_value, 1, 
            sizeof(info->entries[j].io_value), fp);

                            
            // get text (if any)
                            if(info->entries[j].type == ENTRY_TEXT && info->entries[j].length)
                            {
                                info->entries[j].text = 
            new char[info->entries[j].length];
                                fread(info->entries[j].text, 1, info->entries[j].length, fp);
                            }
                        }
                    }
                }

                fclose(fp);

                m_root_script_info = head;

                
            return true;
            }

            void cScript::execute(const char* filename)
            {
                
            // load script if none already
                if(filename)
                    load(filename);

                
            // prepare script data for execution
                if(! prepare())
                    
            return;

                
            // start at beginning of script
                sScriptInfo* ptr = m_root_script_info;
                
            if(ptr == NULL)
                    
            return;
                
                
            // loop until no more script actions
                while(ptr)
                {
                    
            // Call script function and break on NULL return value.
                    // Any other return type is the pointer to the next function, which is typically ptr->next.
                    ptr = process(ptr);
                }

                release();

                
            // release script if execute loaded it
                if(filename)
                    free();
            }

            TIP
            Using the Load function to load a script is useful if the script is processed many times
            because you don’t have to free it between uses. Loading a script within the Execute
            function forces the script to be loaded and freed every time, wasting precious time.

            The way the cScript class processes scripts is ingenious. You actually have to derive the cScript class to
            parse each script action as it is processed. That’s the purpose of the Process function.
            Once a script is loaded, the Process function is called for every script action to process.

            Each script pointer is queried for the script action number, and you must decide
            what to do with the action. Then you need to update the script pointers by returning
            the pointer to the next script action in the linked list.


            posted on 2007-11-14 19:45 lovedday 閱讀(143) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            久久精品国产一区二区| 久久久久女人精品毛片| 午夜不卡888久久| 色欲综合久久躁天天躁| 久久久SS麻豆欧美国产日韩| 久久99久久99精品免视看动漫| 久久综合九色综合欧美狠狠| 亚洲七七久久精品中文国产| 亚洲中文精品久久久久久不卡| 日韩亚洲欧美久久久www综合网 | 亚洲国产精品狼友中文久久久| 久久毛片一区二区| 777久久精品一区二区三区无码 | 中文精品久久久久国产网址| 国产欧美久久久精品影院| 精品免费tv久久久久久久| 久久天天躁夜夜躁狠狠| 久久久中文字幕日本| 久久国产精品久久| 久久婷婷国产剧情内射白浆| 久久精品成人欧美大片| 久久久久亚洲AV无码专区体验| 久久久精品波多野结衣| 国产精品久久久久久福利漫画| 久久中文字幕人妻熟av女| 久久精品国产精品亚洲人人| 欧美亚洲另类久久综合| 69久久精品无码一区二区| 无码人妻久久一区二区三区免费 | 久久99久国产麻精品66 | 99国产精品久久| 久久精品国产色蜜蜜麻豆| 久久亚洲精品无码aⅴ大香| 久久中文字幕无码专区| 四虎国产精品免费久久| 欧美色综合久久久久久 | 久久精品国产亚洲AV无码偷窥| 亚洲精品美女久久777777| 欧美日韩精品久久久免费观看| 亚洲性久久久影院| 精品人妻伦九区久久AAA片69|