• <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 閱讀(144) 評論(0)  編輯 收藏 引用

            公告

            導航

            統計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關鏈接

            搜索

            最新評論

            免费精品久久久久久中文字幕| 人妻无码精品久久亚瑟影视| 狠狠色丁香婷婷久久综合不卡| 久久综合久久久| 青青久久精品国产免费看| 思思久久精品在热线热| 97热久久免费频精品99| 日韩欧美亚洲综合久久影院Ds| 久久婷婷色综合一区二区| 亚洲国产天堂久久综合网站| 2019久久久高清456| 久久久精品一区二区三区| 久久天天躁狠狠躁夜夜不卡| 久久99热这里只有精品国产| 亚洲精品乱码久久久久久久久久久久| 色综合久久中文色婷婷| 国产成人精品综合久久久| 999久久久免费国产精品播放| 久久久久亚洲AV无码专区首JN| 久久99精品国产一区二区三区| 77777亚洲午夜久久多喷| 久久久精品人妻无码专区不卡| 伊人久久综在合线亚洲2019| 漂亮人妻被黑人久久精品| 久久久久久久女国产乱让韩| 亚洲日本va午夜中文字幕久久| 色综合久久久久网| 2021国产成人精品久久| 天天爽天天爽天天片a久久网| 国产婷婷成人久久Av免费高清| 一本色道久久88精品综合| 久久精品国产2020| 亚洲综合伊人久久综合| 人妻无码αv中文字幕久久| 国产免费久久精品99re丫y| 久久国产亚洲精品| 久久精品国产欧美日韩99热| 四虎国产精品成人免费久久| 国产成人无码精品久久久性色| 国内精品伊人久久久久777| 亚洲精品乱码久久久久久|