• <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游戲編程相關鏈接

            搜索

            最新評論

            麻豆精品久久精品色综合| 久久精品国产亚洲AV香蕉| 久久久精品2019免费观看| 久久久精品人妻一区二区三区蜜桃| 久久久久久曰本AV免费免费| 久久国产精品一国产精品金尊| 精品综合久久久久久97超人| 久久国产香蕉一区精品| 久久中文字幕精品| 国产精品福利一区二区久久| 精品综合久久久久久88小说| 7777久久久国产精品消防器材| 夜夜亚洲天天久久| 狠狠综合久久综合88亚洲| 久久青草国产精品一区| 久久亚洲AV无码精品色午夜| 国产精品99久久久久久宅男| 亚洲熟妇无码另类久久久| 国产精品美女久久久久AV福利 | 亚洲精品乱码久久久久久按摩| 精品久久久久久国产| 久久久国产精华液| 久久婷婷五月综合色99啪ak| 人妻无码αv中文字幕久久| 久久久精品国产Sm最大网站| 久久夜色精品国产噜噜麻豆 | 久久夜色精品国产网站| 伊人久久精品影院| 久久亚洲天堂| 久久久久亚洲精品无码网址| 久久精品国产精品青草app| 久久99精品国产麻豆宅宅| 亚州日韩精品专区久久久| 精品久久久无码中文字幕| 久久国产免费观看精品| 99久久中文字幕| 久久99精品国产自在现线小黄鸭| 亚洲国产精品无码久久| 一本一道久久综合狠狠老| 伊人久久综合精品无码AV专区| 亚洲人成无码网站久久99热国产|