天行健 君子当自强而不息

游戏脚本的实现(5)

 

本篇是游戏脚本的实现(4)的续篇。

 

add_script将行为列表框中选中的行为添加到脚本列表框中:

//-----------------------------------------------------------------------------------
// Add script.
//-----------------------------------------------------------------------------------
void add_script()
{
    
long sel;

    
// make sure an action is selected
    if((sel = (long)get_listbox_selected(g_action_wnd)) == LB_ERR)
        
return;

    
// create a new script and add it
    
    SCRIPT_PTR script = g_action_template.create_script(sel);

    g_modify_script = script;

    
// call the modify script dialog

    g_show_cancel = TRUE;

    
if(DialogBox(NULL, MAKEINTRESOURCE(IDD_MODIFY), g_hwnd, modify_dialog_proc))
    {
        
// add script to link list

        script->next = g_root_script;

        
if(g_root_script != NULL)
            g_root_script->prev = script;
        
        g_root_script = script;

        
// display script text

        
char text[2048];

        ACTION_PTR act_ptr = g_action_template.get_action(sel);
        g_action_template.expand_action_text(text, script);

        add_string_to_listbox(g_script_wnd, text);

        
// add pointer to script address listbox
        sprintf(text, "%lu", script);
        add_string_to_listbox(g_script_addr_wnd, text);

        
// increase count
        g_num_script++;
    }
    
else
        delete script;
}
 

insert_script将行为列表框中选中的行为脚本添加到脚本列表框中选中脚本的上方:

//-----------------------------------------------------------------------------------
// Insert script.
//-----------------------------------------------------------------------------------
void insert_script()
{
    
int act_index, script_index;

    
// get location to insert action
    if((script_index = (int)get_listbox_selected(g_script_wnd)) == LB_ERR)
        
return;

    
// make sure an action is selected
    if((act_index = (int)get_listbox_selected(g_action_wnd)) == LB_ERR)
        
return;

    
// create a new script
    SCRIPT_PTR script = g_action_template.create_script(act_index);
    g_modify_script = script;

    
// call the modify script dialog
    g_show_cancel = TRUE;

    
if(DialogBox(NULL, MAKEINTRESOURCE(IDD_MODIFY), g_hwnd, modify_dialog_proc))
    {
        
// add the script to link list
        script->prev = NULL;
        script->next = g_root_script;
        g_root_script->prev = script;

        g_root_script = script;

        
char text[2048];

        
// display script action text
        ACTION_PTR act_ptr = g_action_template.get_action(act_index);
        g_action_template.expand_action_text(text, script);
        insert_string_to_listbox(g_script_wnd, script_index, text);

        
// add pointer to script address listbox
        sprintf(text, "%lu", script);
        insert_string_to_listbox(g_script_addr_wnd, script_index, text);

        g_num_script++;
    }
    
else
        delete script;
}

delete_script用于删除脚本列表框中的一条脚本:

 
//-----------------------------------------------------------------------------------
// Delete script.
//-----------------------------------------------------------------------------------
void delete_script()
{
    
int sel;

    
// make sure there is a selection
    if((sel = (int)get_listbox_selected(g_script_wnd)) == LB_ERR)
        
return;

    
char text[2048];

    
// get pointer to script entry
    get_listbox_text(g_script_addr_wnd, sel, text);
    SCRIPT_PTR script = (SCRIPT_PTR) atol(text);

    
// remove script from linked list
    if(script->prev)
        script->prev->next = script->next;
    
else
        g_root_script = script->next;

    
if(script->next)
        script->next->prev = script->prev;

    script->next = NULL;    
// so whole list is not deleted
    delete script;

    
// clear from script and script list
    delete_listbox_string(g_script_wnd, sel);
    delete_listbox_string(g_script_addr_wnd, sel);

    g_num_script--;
}
 

move_up_script和move_down_script分别将脚本上移和下移一行:

//-----------------------------------------------------------------------------------
// Move up script.
//-----------------------------------------------------------------------------------
void move_up_script()
{
    
int sel;

    
// make sure there is a selection
    if((sel = (int)get_listbox_selected(g_script_wnd)) == LB_ERR)
        
return;

    
// make sure it is not topmost selection
    if(sel == 0)
        
return;

    
char text[2048];

    get_listbox_text(g_script_wnd, sel, text);
    delete_listbox_string(g_script_wnd, sel);
    insert_string_to_listbox(g_script_wnd, sel-1, text);

    get_listbox_text(g_script_addr_wnd, sel, text);
    delete_listbox_string(g_script_addr_wnd, sel);
    insert_string_to_listbox(g_script_addr_wnd, sel-1, text);

    set_listbox_selected(g_script_wnd, sel-1);
}

//-----------------------------------------------------------------------------------
// Move down script.
//-----------------------------------------------------------------------------------
void move_down_script()
{
    
int sel;

    
// make sure there is a selection
    if((sel = (int)get_listbox_selected(g_script_wnd)) == LB_ERR)
        
return;

    
// make sure it is not bottommost selection
    if(sel >= count_listbox(g_script_wnd)-1)
        
return;

    
char text[2048];

    get_listbox_text(g_script_wnd, sel, text);
    delete_listbox_string(g_script_wnd, sel);
    insert_string_to_listbox(g_script_wnd, sel+1, text);

    get_listbox_text(g_script_addr_wnd, sel, text);
    delete_listbox_string(g_script_addr_wnd, sel);
    insert_string_to_listbox(g_script_addr_wnd, sel+1, text);

    set_listbox_selected(g_script_wnd, sel+1);
}

修改脚本对话框的窗口处理过程通过modify_dialog_proc来实现:

 
//-----------------------------------------------------------------------------------
// The DialogProc function is an application-defined callback function used with the CreateDialog 
// and DialogBox families of functions. It processes messages sent to a modal or modeless dialog box. 
// The DLGPROC type defines a pointer to this callback function. DialogProc is a placeholder for 
// the application-defined function name. 
//
// INT_PTR CALLBACK DialogProc(HWND hwndDlg,
//    UINT uMsg,
//    WPARAM wParam,
//    LPARAM lParam
// );
//
// hwndDlg:
//      [in] Handle to the dialog box. 
// uMsg:
//      [in] Specifies the message. 
// wParam:
//      [in] Specifies additional message-specific information. 
// lParam:
//      [in] Specifies additional message-specific information. 
//
// Return Value:
//      Typically, the dialog box procedure should return TRUE if it processed the message, 
//      and FALSE if it did not. If the dialog box procedure returns FALSE, the dialog manager performs 
//      the default dialog operation in response to the message.
//
//      If the dialog box procedure processes a message that requires a specific return value, 
//      the dialog box procedure should set the desired return value by calling 
//      SetWindowLong(hwndDlg, DWL_MSGRESULT, lResult) immediately before returning TRUE. 
//      Note that you must call SetWindowLong immediately before returning TRUE; doing so earlier may 
//      result in the DWL_MSGRESULT value being overwritten by a nested dialog box message.
//
//      The following messages are exceptions to the general rules stated above. Consult the documentation 
//      for the specific message for details on the semantics of the return value.
//
//      WM_CHARTOITEM
//      WM_COMPAREITEM
//      WM_CTLCOLORBTN
//      WM_CTLCOLORDLG
//      WM_CTLCOLOREDIT
//      WM_CTLCOLORLISTBOX
//      WM_CTLCOLORSCROLLBAR
//      WM_CTLCOLORSTATIC
//      WM_INITDIALOG
//      WM_QUERYDRAGICON
//      WM_VKEYTOITEM
//
// Remarks:
//      You should use the dialog box procedure only if you use the dialog box class for the dialog box. 
//      This is the default class and is used when no explicit class is specified in the dialog box template.
//      Although the dialog box procedure is similar to a window procedure, it must not call the DefWindowProc 
//      function to process unwanted messages. Unwanted messages are processed internally by the dialog box 
//      window procedure. 
//-----------------------------------------------------------------------------------
BOOL CALLBACK modify_dialog_proc(HWND dlg, UINT msg_id, WPARAM word_param, LPARAM long_param)
{
    
static long entry_index = 0;

    
switch(msg_id)
    {
    
case WM_INITDIALOG:
        
if(g_modify_script == NULL) // return an error if there is no script to modify
        {
            
// The EndDialog function destroys a modal dialog box, causing the system to end any processing 
            // for the dialog box. 
            //        
            // BOOL EndDialog(HWND hDlg,
            //    INT_PTR nResult
            // );
            //
            // hDlg:
            //      [in] Handle to the dialog box to be destroyed. 
            //
            // nResult:
            //      [in] Specifies the value to be returned to the application from the function that created 
            //      the dialog box. 
            //
            // Return Value:
            //      If the function succeeds, the return value is nonzero.
            //
            //      If the function fails, the return value is zero. To get extended error information, 
            //      call GetLastError.
            EndDialog(dlg, FALSE);

            
return FALSE;
        }

        
// edit first entry
        entry_index = 0;

        
// display entry text
        set_modify_dialog(dlg, g_modify_script, entry_index);

        
// show or hide cancel button
        ShowWindow(GetDlgItem(dlg, IDC_CANCEL), g_show_cancel);

        
if(g_show_cancel == FALSE)
        {
            ShowWindow(GetDlgItem(dlg, IDC_OK),  
false);
            ShowWindow(GetDlgItem(dlg, IDC_OK2), 
true);
        }
        
else
            ShowWindow(GetDlgItem(dlg, IDC_OK2), 
false);

        
return TRUE;

    
case WM_COMMAND:
        
switch(LOWORD(word_param))
        {
        
case IDC_OK:
        
case IDC_OK2:
            update_entry(dlg, g_modify_script, entry_index);
            EndDialog(dlg, TRUE);
            
return TRUE;

        
case IDC_CANCEL:
            EndDialog(dlg, FALSE);
            
return TRUE;

        
case IDC_PREV:
            
// only bother if not first entry
            if(entry_index > 0)
            {
                
// apply changes

                // go to previous entry
                update_entry(dlg, g_modify_script, entry_index);
                entry_index--;
                set_modify_dialog(dlg, g_modify_script, entry_index);
            }

            
break;

        
case IDC_NEXT:
            
// only bother if not last entry
            if(entry_index < g_modify_script->num_entries-1)
            {
                
// apply changes

                // go to next entry
                update_entry(dlg, g_modify_script, entry_index);
                entry_index++;
                set_modify_dialog(dlg, g_modify_script, entry_index);
            }

            
break;
        }
    }

    
return FALSE;
}

不同的条目类型修改脚本的对话框外观也不相同,这是通过set_modify_dialog函数来实现:

 
//-----------------------------------------------------------------------------------
// Set information for dialog to be modified.
//-----------------------------------------------------------------------------------
void set_modify_dialog(HWND dlg, SCRIPT_PTR script, long entry_index)
{
    
char text[2048];

    
// display full action text
    g_action_template.expand_action_text(text, script);
    SetWindowText(GetDlgItem(dlg, IDC_ACTIONTEXT), text);

    
// get control handle
    HWND pre_wnd          = GetDlgItem(dlg, IDC_PREV);
    HWND next_wnd         = GetDlgItem(dlg, IDC_NEXT);
    HWND text_wnd         = GetDlgItem(dlg, IDC_TEXT);
    HWND choice_wnd       = GetDlgItem(dlg, IDC_CHOICE);
    HWND true_wnd         = GetDlgItem(dlg, IDC_TRUE);
    HWND false_wnd        = GetDlgItem(dlg, IDC_FALSE);
    HWND min_wnd          = GetDlgItem(dlg, IDC_MIN);
    HWND max_wnd          = GetDlgItem(dlg, IDC_MAX);
    HWND value_wnd        = GetDlgItem(dlg, IDC_VALUE);
    HWND static_min_wnd   = GetDlgItem(dlg, IDC_STATIC_MIN);
    HWND static_max_wnd   = GetDlgItem(dlg, IDC_STATIC_MAX);
    HWND static_value_wnd = GetDlgItem(dlg, IDC_STATIC_VALUE);
    HWND num_wnd          = GetDlgItem(dlg, IDC_NUM);
    HWND frame_wnd        = GetDlgItem(dlg, IDC_FRAME);

    
// hide all controls
    ShowWindow(pre_wnd,           FALSE);
    ShowWindow(next_wnd,          FALSE);
    ShowWindow(text_wnd,          FALSE);
    ShowWindow(choice_wnd,        FALSE);
    ShowWindow(true_wnd,          FALSE);
    ShowWindow(false_wnd,         FALSE);
    ShowWindow(min_wnd,           FALSE);
    ShowWindow(max_wnd,           FALSE);
    ShowWindow(value_wnd,         FALSE);
    ShowWindow(static_min_wnd,    FALSE);
    ShowWindow(static_max_wnd,    FALSE);
    ShowWindow(static_value_wnd,  FALSE);

    
// clear information
    SetWindowText(num_wnd, "");
    SetWindowText(frame_wnd, " No Entries ");

    
// get pointer to action
    ACTION_PTR act_ptr = g_action_template.get_action(script->action_index);
    
    
// return if no entries to edit
    if(act_ptr->num_entries_rule == 0)
        
return;
    
    
if(act_ptr->num_entries_rule > 1)
    {
        ShowWindow(pre_wnd, TRUE);
        ShowWindow(next_wnd, TRUE);
    }

    sprintf(text, "%lu of %lu", entry_index+1, act_ptr->num_entries_rule);
    SetWindowText(num_wnd, text);
    EnableWindow(num_wnd, TRUE);

    
// enable and set specific fields based on entry type
    switch(script->entries[entry_index].type)
    {
    
case ENTRY_TEXT:
        SetWindowText(frame_wnd, " Text entry ");

        
if(script->entries[entry_index].text)
            SetWindowText(text_wnd, script->entries[entry_index].text);

        ShowWindow(text_wnd, TRUE);
        EnableWindow(text_wnd, TRUE);
        
break;

    
case ENTRY_BOOL:
        SetWindowText(frame_wnd, " Boolean entry ");

        
if(script->entries[entry_index].bool_value)
        {
            set_button_state(true_wnd,  BST_CHECKED);
            set_button_state(false_wnd, BST_UNCHECKED);
        }
        
else
        {
            set_button_state(true_wnd,  BST_UNCHECKED);
            set_button_state(false_wnd, BST_CHECKED);
        }

        ShowWindow(true_wnd,  TRUE);
        ShowWindow(false_wnd, TRUE);
        
break;

    
case ENTRY_INT:
        SetWindowText(frame_wnd, " Integer entry ");

        sprintf(text, "%lu", act_ptr->entries_rule[entry_index].long_min);
        SetWindowText(min_wnd, text);

        sprintf(text, "%lu", act_ptr->entries_rule[entry_index].long_max);
        SetWindowText(max_wnd, text);

        sprintf(text, "%lu", script->entries[entry_index].long_value);
        SetWindowText(value_wnd, text);

        ShowWindow(min_wnd,          TRUE);
        ShowWindow(max_wnd,          TRUE);
        ShowWindow(value_wnd,        TRUE);
        ShowWindow(static_min_wnd,   TRUE);
        ShowWindow(static_max_wnd,   TRUE);
        ShowWindow(static_value_wnd, TRUE);

        
break;
    
    
case ENTRY_FLOAT:
        SetWindowText(frame_wnd, " Float entry ");

        sprintf(text, "%lu", act_ptr->entries_rule[entry_index].float_min);
        SetWindowText(min_wnd, text);

        sprintf(text, "%lu", act_ptr->entries_rule[entry_index].float_max);
        SetWindowText(max_wnd, text);

        sprintf(text, "%lu", script->entries[entry_index].float_value);
        SetWindowText(value_wnd, text);

        ShowWindow(min_wnd,          TRUE);
        ShowWindow(max_wnd,          TRUE);
        ShowWindow(value_wnd,        TRUE);
        ShowWindow(static_min_wnd,   TRUE);
        ShowWindow(static_max_wnd,   TRUE);
        ShowWindow(static_value_wnd, TRUE);

        
break;
    
    
case ENTRY_CHOICE:
        SetWindowText(frame_wnd, " Choice entry ");
        reset_combo_content(choice_wnd);

        
if(act_ptr->entries_rule[entry_index].num_choices)
        {
            
for(long i = 0; i < act_ptr->entries_rule[entry_index].num_choices; i++)
                add_string_to_combo(choice_wnd, act_ptr->entries_rule[entry_index].choices[i]);

            set_combo_cur_sel(choice_wnd, script->entries[entry_index].selection);
            ShowWindow(choice_wnd, TRUE);
        }

        
break;
    }
}

布尔型:

整型或浮点型:

多重选项型:

文本型:

 

脚本信息的更新通过update_entry来实现:

//-----------------------------------------------------------------------------------
// Update script entries.
//-----------------------------------------------------------------------------------
void update_entry(HWND dlg, SCRIPT_PTR script, long entry_index)
{
    
// get pointer to action
    ACTION_PTR act_ptr = g_action_template.get_action(script->action_index);

    
// return if no entries to update or incorrect entry index
    if(act_ptr->num_entries_rule == 0 || entry_index >= script->num_entries)
        
return;

    
const int size = 2048;
    
char text[size];

    ENTRY& r_entry = script->entries[entry_index];
    ENTRY_RULE& r_entry_rule = act_ptr->entries_rule[entry_index];

    
// update fields based on type
    switch(r_entry_rule.type)
    {
    
case ENTRY_TEXT:
        
// delete old text
        delete[] r_entry.text;
        r_entry.text = NULL;
        r_entry.length = 0;

        GetWindowText(GetDlgItem(dlg, IDC_TEXT), text, size);

        
if(text)
        {
            r_entry.length = (
long)strlen(text) + 1;
            r_entry.text   = 
new char[r_entry.length];

            strcpy(r_entry.text, text);
        }

        
break;

    
case ENTRY_BOOL:
        
// choose TRUE or FALSE from radio button
        if(get_button_state(GetDlgItem(dlg, IDC_TRUE)) == BST_CHECKED)
            r_entry.bool_value = TRUE;
        
else
            r_entry.bool_value = FALSE;

        
break;

    
case ENTRY_INT:
        
// get int value and bounds check with min/max
        GetWindowText(GetDlgItem(dlg, IDC_VALUE), text, size);

        r_entry.long_value = atol(text);

        
if(r_entry.long_value < r_entry_rule.long_min)
            r_entry.long_value = r_entry_rule.long_min;

        
if(r_entry.long_value > r_entry_rule.long_max)
            r_entry.long_value = r_entry_rule.long_max;

        
break;

    
case ENTRY_FLOAT:
        
// get int value and bounds check with min/max
        GetWindowText(GetDlgItem(dlg, IDC_VALUE), text, size);

        r_entry.float_value = (
float)atof(text);

        
if(r_entry.float_value < r_entry_rule.float_min)
            r_entry.float_value = r_entry_rule.float_min;

        
if(r_entry.float_value > r_entry_rule.float_max)
            r_entry.float_value = r_entry_rule.float_max;

        
break;

    
case ENTRY_CHOICE:
        
// store choice selection
        r_entry.selection = (long)get_combo_cur_sel(GetDlgItem(dlg, IDC_CHOICE));
        
break;
    }
}

截图:

 

下载源码与工程


 

posted on 2007-11-03 18:48 lovedday 阅读(472) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论