• <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>

            天行健 君子當自強而不息

            游戲腳本的實現(xiàn)(2)

             

            本篇是游戲腳本的實現(xiàn)(1)的續(xù)篇。

             

            腳本條目的創(chuàng)建

            因為ENREY_RULE結(jié)構(gòu)僅包含了行為和條目的規(guī)則,所以需要另外的結(jié)構(gòu)數(shù)組去存儲每個條目的數(shù)據(jù)。這些新的結(jié)構(gòu)包括了在條目中所使用的文本、布爾值、多重選項,我們使用結(jié)構(gòu)體ENTRY來表示。

            //============================================================================
            // structure that store all entries fact information.
            //============================================================================
            typedef struct ENTRY
            {
                
            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;     // BOOL value
                    long    long_value;     // long balue
                    float   float_value;    // float value
                };

                
            char*   text;       // entry text buffer

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

                ~ENTRY()
                {
                    delete[] text;
                }
            } *ENTRY_PTR;

            在處理腳本條目的過程中,當一個腳本出現(xiàn)了許多條目時,最麻煩的問題也就接踵而來。腳本中的每個行為都要求一個相匹配的ENTRY_RULE結(jié)構(gòu),其依次包含了一定數(shù)量的ENTRY結(jié)構(gòu)。為了更好地處理一個腳本的結(jié)構(gòu),還需要其他的結(jié)構(gòu)來記錄屬于腳本行為的每個條目,我們將它命名為SCRPT。

            //============================================================================
            // structure that store all 
            //============================================================================
            typedef struct SCRIPT
            {
                
            long        action_index;   // [0, number of actions - 1]

                
            long        num_entries;    // number of entries in this action
                ENTRY_PTR   entries;        // array of entries

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

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

                ~SCRIPT()
                {
                    delete[] entries;
                    delete next;
                }
            } *SCRIPT_PTR;

            prev和next維護了整個腳本的連接列表,為了構(gòu)造SCRIPT結(jié)構(gòu)的連接列表,從代表腳本的第一個行為的根結(jié)構(gòu)開始,然后使用next和prev將SCRIPT結(jié)構(gòu)連接起來,如下圖所示:

             

            ACTION_TEMPLATE類的整合

            理解了行為模板所使用的結(jié)構(gòu)以及所容納的腳本后,現(xiàn)在開始將它們整合到一起創(chuàng)建一個加載并處理腳本的類。

            //============================================================================
            // This class encapsulate script save and load.
            //============================================================================
            typedef class ACTION_TEMPLATE
            {
            private:
                
            long        m_num_actions;  // number of actions in template
                ACTION_PTR  m_root_action;  // list of template actions  
                
            public:
                ACTION_TEMPLATE();
                ~ACTION_TEMPLATE();

                BOOL load_actions(
            const char* filename);
                
            void free();

                
            long get_num_actions();
                ACTION_PTR get_root_action();
                ACTION_PTR get_action(
            long act_index);

                SCRIPT_PTR create_script(
            long act_index);

                
            long get_num_entries_rule(long act_index);
                ENTRY_RULE_PTR get_entry_rule(
            long act_index, long entry_rule_index);

                
            void expand_default_action_text(char* buffer, ACTION_PTR action);
                BOOL expand_action_text(
            char* buffer, SCRIPT_PTR script);
            } *ACTION_TEMPLATE_PTR;

            實現(xiàn):

            //------------------------------------------------------------------------
            // Get quoted line from file.
            //------------------------------------------------------------------------
            static BOOL _get_quoted_line(FILE* fp, char* data, long max_data_size)
            {
                
            int c;
                
            long pos = 0;

                
            // read until a quote is reached (or EOF)
                while(1)
                {
                    
            if((c = fgetc(fp)) == EOF)
                        
            return FALSE;

                    
            if(c == '"')
                    {
                        
            // read until next quot (or EOF)
                        while(1)
                        {
                            
            if((c = fgetc(fp)) == EOF)
                                
            return FALSE;

                            
            // return text when 2nd quote found
                            if(c == '"')
                            {
                                data[pos] = 0;
                                
            break;
                            }

                            
            // add acceptable text to line
                            if(c != 0x0a && c != 0x0d)  // if character is not linefeed, not carriage.
                            {
                                
            if(pos < max_data_size-1)
                                    data[pos++] = c;
                            }
                        }

                        
            break;
                    }
                }

                
            return TRUE;
            }

            //------------------------------------------------------------------------
            // Get word from file.
            //------------------------------------------------------------------------
            static BOOL _get_word(FILE* fp, char* data, long max_data_size)
            {
                
            int c;
                
            long pos = 0;

                
            // reset word to empty
                data[0] = 0;

                
            // read until an acceptable character found
                while(1)
                {
                    
            if((c = fgetc(fp)) == EOF)
                    {
                        data[0] = 0;
                        
            return FALSE;
                    }

                    
            // check for start of word
                    if(c != 32 && c != 0x0a && c != 0x0d)   // if character is not blank, not linefeed, not carriage.
                    {
                        data[pos++] = c;
                       
                        
            // loop until end of word (or EOF)
                        while((c = fgetc(fp)) != EOF)
                        {
                            
            // break on acceptable word seperators
                            if(c == 32 || c == 0x0a || c == 0x0d)
                                
            break;

                            
            // add if enough room left
                            if(pos < max_data_size-1)
                                data[pos++] = c;
                        }

                        
            // add end of line to text
                        data[pos] = 0;

                        
            break;
                    }
                }

                
            return TRUE;
            }

            //------------------------------------------------------------------------
            // Constructor, zero member data.
            //------------------------------------------------------------------------
            ACTION_TEMPLATE::ACTION_TEMPLATE()
            {
                memset(
            this, 0, sizeof(*this));
            }

            //------------------------------------------------------------------------
            // Destructor, release allocated memory.
            //------------------------------------------------------------------------
            ACTION_TEMPLATE::~ACTION_TEMPLATE()
            {
                free();
            }

            //------------------------------------------------------------------------
            // Release allocated memory.
            //------------------------------------------------------------------------
            void ACTION_TEMPLATE::free()
            {
                delete m_root_action;
                m_num_actions = 0;
            }

            //------------------------------------------------------------------------
            // Load an action template.
            //------------------------------------------------------------------------
            BOOL ACTION_TEMPLATE::load_actions(const char* filename)
            {
                
            const int size = 256;

                
            // free previous action structures
                free();

                FILE* fp;

                
            // open the action file
                if((fp = fopen(filename, "rb")) == NULL)
                    
            return FALSE;

                ACTION_PTR act_ptr = NULL;
                
                
            // keep looping until end of file found
                while(1)
                {
                    
            char text[size];

                    
            // get next quoted action
                    if(! _get_quoted_line(fp, text, size))
                        
            break;

                    
            // quit if no action text
                    if(text[0] == 0)
                        
            break;

                    
            // allocate on action structure and append it to list

                    ACTION_PTR act = 
            new ACTION;
                    act->next = NULL;

                    
            if(act_ptr == NULL)
                        m_root_action = act;
                    
            else
                        act_ptr->next = act;

                    act_ptr = act;

                    
            // copy action text
                    strcpy(act->text, text);

                    
            // store action index
                    act->index = m_num_actions;

                    
            // increase the number of actions loaded
                    m_num_actions++;

                    size_t text_len = strlen(text);

                    
            // count the number of entries in the action
                    for(size_t i = 0; i < text_len; i++)
                    {
                        
            if(text[i] == '~')
                            act->num_entries_rule++;
                    }

                    
            // allocated and read in entries (if any)
                    if(act->num_entries_rule != 0)
                    {
                        act->entries_rule = 
            new ENTRY_RULE[act->num_entries_rule];

                        
            for(short entry_index = 0; entry_index < act->num_entries_rule; entry_index++)
                        {
                            ENTRY_RULE_PTR entry_rule = &act->entries_rule[entry_index];

                            
            // get type of entry
                            _get_word(fp, text, size);
                           
                            
            if(!stricmp(text, "TEXT"))   // TEXT type, nothing data.
                            {
                                entry_rule->type = ENTRY_TEXT;
                            }
                            
            else if(!stricmp(text, "INT"))     // LONG type, get min and max values
                            {
                                entry_rule->type = ENTRY_INT;
                                
                                
            // get min value
                                _get_word(fp, text, size);
                                entry_rule->long_min = atol(text);

                                
            // get max value
                                _get_word(fp, text, size);
                                entry_rule->long_max = atol(text);
                            }
                            
            else if(!stricmp(text, "FLOAT"))    // FLOAT type, get min and max values
                            {
                                entry_rule->type = ENTRY_FLOAT;

                                
            // get min value
                                _get_word(fp, text, size);
                                entry_rule->float_min = (
            float) atof(text);

                                
            // get max value
                                _get_word(fp, text, size);
                                entry_rule->float_max = (
            float) atof(text);
                            }
                            
            else if(!stricmp(text, "BOOL"))     // BOOL type, no options.
                            {
                                entry_rule->type = ENTRY_BOOL;
                            }
                            
            else if(!stricmp(text, "CHOICE"))   // CHOICE type, get number of entries and entry's texts.
                            {
                                entry_rule->type = ENTRY_CHOICE;

                                
            // get the number of choices
                                _get_word(fp, text, size);

                                entry_rule->num_choices = atol(text);
                                entry_rule->choices = 
            new char_ptr[entry_rule->num_choices];

                                
            // get each entry text
                                for(long choice_index = 0; choice_index < entry_rule->num_choices; choice_index++)
                                {
                                    _get_quoted_line(fp, text, size);
                                    entry_rule->choices[choice_index] = strdup(text);
                                }
                            }
                        }
                    }
                }

                fclose(fp);

                
            return TRUE;
            }

            //------------------------------------------------------------------------
            // Return number of actions in template.
            //------------------------------------------------------------------------
            long ACTION_TEMPLATE::get_num_actions()
            {
                
            return m_num_actions;
            }

            //------------------------------------------------------------------------
            // Return root ACTION structure.
            //------------------------------------------------------------------------
            ACTION_PTR ACTION_TEMPLATE::get_root_action()
            {
                
            return m_root_action;
            }

            //------------------------------------------------------------------------
            // Return specified ACTION structure.
            //------------------------------------------------------------------------
            ACTION_PTR ACTION_TEMPLATE::get_action(long act_index)
            {
                
            // return error if higher than number of actions
                if(act_index >= m_num_actions)
                    
            return NULL;

                ACTION_PTR act_ptr = m_root_action;
                
                
            // scan list
                while(act_ptr)
                {
                    
            if(act_ptr->index == act_index)
                        
            return act_ptr;

                    act_ptr = act_ptr->next;
                }

                
            return NULL;
            }

            //------------------------------------------------------------------------
            // Create script from specified action index.
            //------------------------------------------------------------------------
            SCRIPT_PTR ACTION_TEMPLATE::create_script(long act_index)
            {
                
            // make sure it is a valid action
                if(act_index >= m_num_actions)
                    
            return NULL;

                ACTION_PTR act_ptr;

                
            // get pointer to action
                if((act_ptr = get_action(act_index)) == NULL)
                    
            return NULL;

                
            // create new SCRIPT structure
                SCRIPT_PTR script = new SCRIPT;

                script->action_index = act_index;
                script->num_entries  = act_ptr->num_entries_rule;
                script->entries      = 
            new ENTRY[script->num_entries];

                
            // set up each entry
                for(long i = 0; i < script->num_entries; i++)
                {
                    script->entries[i].type = act_ptr->entries_rule[i].type;

                    
            // set up entry data based on type
                    switch(script->entries[i].type)
                    {
                    
            case ENTRY_TEXT:
                        script->entries[i].text = NULL;
                        
            break;

                    
            case ENTRY_INT:
                        script->entries[i].long_value = act_ptr->entries_rule[i].long_min;
                        
            break;

                    
            case ENTRY_FLOAT:
                        script->entries[i].float_value = act_ptr->entries_rule[i].float_min;
                        
            break;    

                    
            case ENTRY_BOOL:
                        script->entries[i].bool_value = TRUE;
                        
            break;  

                    
            case ENTRY_CHOICE:
                        script->entries[i].selection = 0;
                        
            break;
                    }
                }

                
            return script;
            }

            //------------------------------------------------------------------------
            // Return number of entries rule in the specified action.
            //------------------------------------------------------------------------
            long ACTION_TEMPLATE::get_num_entries_rule(long act_index)
            {
                
            // get pointer to specified action
                ACTION_PTR act_ptr = get_action(act_index);

                
            // return 0 if on error
                if(act_ptr == NULL)
                    
            return 0;

                
            return act_ptr->num_entries_rule;
            }

            //------------------------------------------------------------------------
            // Return specified entry rule in specified action.
            //------------------------------------------------------------------------
            ENTRY_RULE_PTR ACTION_TEMPLATE::get_entry_rule(long act_index, long entry_rule_index)
            {
                ACTION_PTR act_ptr = get_action(act_index);

                
            if(act_ptr == NULL || entry_rule_index >= act_ptr->num_entries_rule)
                    
            return NULL;

                
            return &(act_ptr->entries_rule[entry_rule_index]);
            }

            //------------------------------------------------------------------------
            // Expand action text using min/first/TRUE choice values.
            //------------------------------------------------------------------------
            void ACTION_TEMPLATE::expand_default_action_text(char* buffer, ACTION_PTR action)
            {
                
            // copy action text into buffer if no entries rule
                if(action->num_entries_rule == 0)
                {
                    strcpy(buffer, action->text);
                    
            return;
                }

                
            // expand entry types into action text
                size_t buf_pos = 0;
                
            long rule_index = 0;

                size_t text_len = strlen(action->text);
                
            const size_t mem_size = 256;

                
            for(size_t i = 0; i < text_len; i++)
                {
                    
            char memory[mem_size];

                    
            // expand the entry into text based on value, text, etc.
                    if(action->text[i] == '~')
                    {
                        
            if(action->entries_rule[rule_index].type == ENTRY_TEXT)
                        {
                            memcpy(&buffer[buf_pos], "(*TEXT*)", 8);
                            buf_pos += 8;
                        }
                        
            else if(action->entries_rule[rule_index].type == ENTRY_INT)
                        {
                            sprintf(memory, "(*%lu*)", action->entries_rule[rule_index].long_min);
                            memcpy(&buffer[buf_pos], memory, strlen(memory));
                            buf_pos += strlen(memory);
                        }
                        
            else if(action->entries_rule[rule_index].type == ENTRY_FLOAT)
                        {
                            sprintf(memory, "(*%lf*)", action->entries_rule[rule_index].float_min);
                            memcpy(&buffer[buf_pos], memory, strlen(memory));
                            buf_pos += strlen(memory);
                        }
                        
            else if(action->entries_rule[rule_index].type == ENTRY_BOOL)
                        {
                            memcpy(&buffer[buf_pos], "(*TRUE*)", 8);
                            buf_pos += 8;
                        }
                        
            else if(action->entries_rule[rule_index].type == ENTRY_CHOICE)
                        {
                            memcpy(&buffer[buf_pos], "(*", 2);
                            buf_pos += 2;

                            
            char* choice = action->entries_rule[rule_index].choices[0];
                            size_t choice_len = strlen(choice);

                            memcpy(&buffer[buf_pos], choice, choice_len);
                            buf_pos += choice_len;

                            memcpy(&buffer[buf_pos], "*)", 2);
                            buf_pos += 2;
                        }

                        rule_index++;
                    }
                    
            else
                        buffer[buf_pos++] = action->text[i];
                }


                buffer[buf_pos] = 0;
            }

            //------------------------------------------------------------------------
            // Expand action text using selections.
            //------------------------------------------------------------------------
            BOOL ACTION_TEMPLATE::expand_action_text(char* buffer, SCRIPT_PTR script)
            {
                
            // get a pointer to the specified action
                ACTION_PTR act_ptr = get_action(script->action_index);

                
            if(act_ptr == NULL)
                    
            return FALSE;

                
            // copy action text into buffer if no entries
                if(act_ptr->num_entries_rule == 0)
                {
                    strcpy(buffer, act_ptr->text);
                    
            return TRUE;
                }

                
            // expand entry types into action text

                size_t buf_pos = 0;
                size_t entry_index = 0;
                
                
            char memory[256];
                size_t memory_length;    

                size_t act_text_length = strlen(act_ptr->text);

                
            for(size_t i = 0; i < act_text_length; i++)
                {
                    
            // expand the entry into text based on values, text, etc.
                    if(act_ptr->text[i] == '~')
                    {
                        
            if(act_ptr->entries_rule[entry_index].type == ENTRY_TEXT && 
                           script->entries[entry_index].type == ENTRY_TEXT)
                        {                
                            memcpy(&buffer[buf_pos], "(*", 2);
                            buf_pos += 2;

                            
            if(script->entries[entry_index].text)
                            {
                                
            for(long j = 0; j < 32; j++)    // copy at most 32 charaters
                                {
                                    
            if(script->entries[entry_index].text[j] == 0)
                                        
            break;

                                    buffer[buf_pos++] = script->entries[entry_index].text[j];
                                }
                            }

                            memcpy(&buffer[buf_pos], "*)", 2);
                            buf_pos += 2;                
                        }
                        
            else if(act_ptr->entries_rule[entry_index].type == ENTRY_INT)
                        {
                            sprintf(memory, "(*%lu*)", script->entries[entry_index].long_value);
                            
                            memory_length = strlen(memory);

                            memcpy(&buffer[buf_pos], memory, memory_length);
                            buf_pos += memory_length;
                        }
                        
            else if(act_ptr->entries_rule[entry_index].type == ENTRY_FLOAT)
                        {
                            sprintf(memory, "(*%lf*)", script->entries[entry_index].float_value);
                            
                            memory_length = strlen(memory);

                            memcpy(&buffer[buf_pos], memory, memory_length);
                            buf_pos += memory_length;
                        }
                        
            else if(act_ptr->entries_rule[entry_index].type == ENTRY_BOOL)
                        {
                            
            if(script->entries[entry_index].bool_value)
                                memcpy(&buffer[buf_pos], "(*TRUE *)", 9);
                            
            else
                                memcpy(&buffer[buf_pos], "(*FALSE*)", 9);

                            buf_pos += 9;
                        }
                        
            else if(act_ptr->entries_rule[entry_index].type == ENTRY_CHOICE)
                        {
                            memcpy(&buffer[buf_pos], "(*", 2);
                            buf_pos += 2;

                            
            long sel = script->entries[entry_index].selection;
                            
            char* choice = act_ptr->entries_rule[entry_index].choices[sel];
                            size_t choice_len = strlen(choice);

                            memcpy(&buffer[buf_pos], choice, choice_len);
                            buf_pos += choice_len;

                            memcpy(&buffer[buf_pos], "*)", 2);
                            buf_pos += 2;
                        }

                        entry_index++;
                    }
                    
            else
                        buffer[buf_pos++] = act_ptr->text[i];
                }

                buffer[buf_pos] = 0;

                
            return TRUE;
            }

            posted on 2007-11-03 17:05 lovedday 閱讀(554) 評論(0)  編輯 收藏 引用

            公告

            導航

            統(tǒng)計

            常用鏈接

            隨筆分類(178)

            3D游戲編程相關(guān)鏈接

            搜索

            最新評論

            青春久久| 国产精品欧美久久久天天影视| 热re99久久精品国99热| 久久久久综合国产欧美一区二区| 国产成人久久精品激情| 人妻精品久久久久中文字幕69 | 99久久99这里只有免费费精品| 久久久久久久91精品免费观看| 久久亚洲电影| 久久人人爽人人爽人人片AV高清| 麻豆av久久av盛宴av| 国产成人久久精品一区二区三区| 久久精品成人欧美大片| 久久精品蜜芽亚洲国产AV| 久久久久久久99精品免费观看| 国产精品成人精品久久久| 久久国产视频99电影| 少妇无套内谢久久久久| 久久久精品2019免费观看| 91久久九九无码成人网站| 亚洲国产成人久久笫一页| 久久精品99久久香蕉国产色戒 | 精品多毛少妇人妻AV免费久久| 国产精品99久久久久久宅男| 亚洲国产成人精品91久久久| 亚洲国产精品无码久久一线| 久久久久一区二区三区| 久久伊人五月天论坛| 狠狠色婷婷久久一区二区三区| 国内精品久久久久影院网站| 久久无码国产专区精品| 国产精品一久久香蕉国产线看| 久久人人爽人人爽人人片AV东京热| 久久精品久久久久观看99水蜜桃| 久久精品中文騷妇女内射| 久久久久亚洲精品中文字幕| 国产99久久精品一区二区| 久久久久亚洲AV片无码下载蜜桃| 国产精品免费久久久久电影网| 国内精品综合久久久40p| 久久强奷乱码老熟女网站|