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

            搜索

            最新評論

            精品久久久久久无码专区| 精品久久久无码中文字幕天天| 亚洲精品NV久久久久久久久久| 人妻丰满?V无码久久不卡| 亚洲人成网亚洲欧洲无码久久 | 久久免费高清视频| 久久国产成人精品国产成人亚洲| 一级A毛片免费观看久久精品| 久久夜色精品国产欧美乱| 精品国产热久久久福利| 国产亚洲精品久久久久秋霞| 亚洲国产精品久久| 国产精品亚洲综合久久| 成人久久精品一区二区三区| 婷婷国产天堂久久综合五月| 久久精品国产影库免费看| 亚洲国产精品无码久久久不卡| 久久人人爽人人爽AV片| 久久免费小视频| 久久Av无码精品人妻系列| 人妻无码久久精品| 国产免费福利体检区久久| 久久亚洲精品国产精品| 久久久久久久久波多野高潮| 久久国产精品免费| 精品国产一区二区三区久久蜜臀| 九九99精品久久久久久| 久久精品aⅴ无码中文字字幕重口| 97视频久久久| 久久免费视频1| 久久精品国产久精国产一老狼| 一级A毛片免费观看久久精品| 亚洲国产成人精品91久久久| 欧美久久综合性欧美| 四虎国产精品免费久久久| 狠狠色婷婷综合天天久久丁香| 精品久久久久久成人AV| 久久久av波多野一区二区| 国产精品免费福利久久| 精品一区二区久久久久久久网站| 久久99国产精品久久99|