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

            搜索

            最新評論

            亚洲精品国产综合久久一线| 久久国产精品一区| 中文无码久久精品| 99久久99久久精品国产片果冻 | 无码国内精品久久人妻蜜桃| 久久久久亚洲av成人网人人软件 | 国产一区二区精品久久| 伊人丁香狠狠色综合久久| 精品久久综合1区2区3区激情 | 久久国产影院| 久久精品国产亚洲av日韩| 亚洲午夜精品久久久久久人妖| 亚洲另类欧美综合久久图片区| 久久久久亚洲精品天堂| 久久人人超碰精品CAOPOREN| 精品久久人妻av中文字幕| 青青草原1769久久免费播放 | 色综合久久精品中文字幕首页| 亚洲国产精品无码久久久久久曰| 91精品国产综合久久久久久| 久久精品国产99久久久古代 | 久久久国产精华液| 久久精品中文字幕第23页| 九九精品99久久久香蕉| 少妇人妻综合久久中文字幕| 国产精品成人99久久久久 | 伊人久久综合精品无码AV专区 | 精品久久久久久无码不卡| 国产99久久久久久免费看| 97久久久精品综合88久久| 亚洲精品无码久久久影院相关影片| 狠狠精品久久久无码中文字幕| 久久精品成人免费网站| 久久99国产精品久久99| 国产精品久久久久影院嫩草 | 欧美黑人又粗又大久久久| 国产精品久久久久蜜芽| 尹人香蕉久久99天天拍| 国产一区二区久久久| 国产偷久久久精品专区| 亚洲国产精品无码成人片久久|