⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winmain.cpp

📁 [游戏开发参考书-用DirectX编写RPG游戏]这是一个系列的丛书如果你都看并且懂的话你就可以你工作啦!
💻 CPP
字号:
/**************************************************
WinMain.cpp
Chapter 14 Mad Lib Script Demo

Programming Role-Playing Games with DirectX
by Jim Adams (01 Jan 2002)
**************************************************/

#include <windows.h>
#include <stdio.h>
#include "resource.h"

// Script structures ////////////////////////////////////////////
enum Types { _NONE = 0, _TEXT, _BOOL, _INT, _FLOAT, _CHOICE };

typedef struct sScriptEntry
{
  long   Type;         // Type of entry

  union {
    long   IOValue;    // Used for saving/loading
    long   Length;     // Length of text (w/0 terminator)
    long   Selection;  // Selection in choice
    BOOL   bValue;     // BOOL value
    long   lValue;     // long value
    float  fValue;     // float value
  };
  char    *Text;       // Text buffer

  sScriptEntry()
  {
    Type = _NONE;
    IOValue = 0;
    Text = NULL;
  }

  ~sScriptEntry()
  {
    delete [] Text;
  }
} sScriptEntry;

typedef struct sScript
{
  long          Type;        // 0-(#actions)-1
  long          NumEntries;  // # entries
  sScriptEntry *Entries;     // Array of entries

  sScript      *Prev;        // Prev in list
  sScript      *Next;        // Next in a list

  sScript()
  { 
    Type = 0;
    NumEntries = 0;
    Entries = NULL;
    Prev = Next = NULL;
  }

  ~sScript()
  {
    delete [] Entries;
    delete Next;
  }
} sScript;

// Application variables ////////////////////////////////////////////
HWND g_hWnd;                   // Window handle
char g_szClass[] = "MLSDEMO";  // Class name

long     g_NumScriptActions = 0; // # script actions
sScript *g_ScriptParent = NULL;  // Script data
BOOL     g_Flags[256];           // script flags

OPENFILENAME g_ofn;                   // Open dialog data
char         g_ScriptFile[MAX_PATH];  // Filename for script files

// The script function prototypes
sScript *Script_IfFlagThen(sScript*);
sScript *Script_Else(sScript*);
sScript *Script_EndIf(sScript*);
sScript *Script_SetFlag(sScript*);
sScript *Script_Print(sScript*);
sScript *Script_Move(sScript*);
sScript *Script_GainLoss(sScript*);
sScript *Script_Battle(sScript*);
sScript *Script_End(sScript*);

// The script action execution structure
typedef struct sScriptProcesses {
  sScript *(*Func)(sScript *ScriptPtr);
} sScriptProcesses;

// The list of script action structure functions
sScriptProcesses ScriptProcesses[] = {
  { Script_IfFlagThen },
  { Script_Else       },
  { Script_EndIf      },
  { Script_SetFlag    },
  { Script_Print      }, 
  { Script_Move       },
  { Script_GainLoss   },
  { Script_Battle     },
  { Script_End        } 
};
  
// Application prototypes ///////////////////////////////////////////
int  PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow);
long FAR PASCAL WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

sScript *LoadScript(char *Filename, long *NumActions = NULL);
BOOL     RunScript();

// Application //////////////////////////////////////////////////////
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
{
  WNDCLASS wc;
  MSG      Msg;

  // Register window class
  wc.style         = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc   = WindowProc;
  wc.cbClsExtra    = 0;
  wc.cbWndExtra    = DLGWINDOWEXTRA;
  wc.hInstance     = hInst;
  wc.hIcon         = LoadIcon(hInst, IDI_APPLICATION);
  wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
  wc.lpszMenuName  = NULL;
  wc.lpszClassName = g_szClass;
  RegisterClass(&wc);

  // Create the dialog box window and show it
  g_hWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_DEMO), 0, NULL);
  UpdateWindow(g_hWnd);
  ShowWindow(g_hWnd, nCmdShow);

  // Message loop
  while(GetMessage(&Msg, NULL, 0, 0)) {
    TranslateMessage(&Msg);
    DispatchMessage(&Msg);
  }

  // Free script actions
  delete g_ScriptParent;

  // Clean up
  UnregisterClass(g_szClass, hInst);

  return 0;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch(uMsg) {
    case WM_COMMAND:
      switch(LOWORD(wParam)) {

        // Load a script file
        case IDC_LOAD: 
          // Ask for filename
          if(!GetOpenFileName(&g_ofn))
            break;

          // Delete the current script
          delete g_ScriptParent;
          if((g_ScriptParent = LoadScript(g_ScriptFile, &g_NumScriptActions)) == NULL)
            MessageBox(hWnd, g_ScriptFile, "Unable to open file.", MB_OK);

          // Display script file name
          SetWindowText(GetDlgItem(g_hWnd, IDC_TITLE), g_ScriptFile);
 
          break;

        // Run a script file
        case IDC_EXECUTE: 
          RunScript();
          break;
      }
      break;

    case WM_CREATE:
      // Initialize the save/load dialog box info
      ZeroMemory(&g_ofn, sizeof(OPENFILENAME));
      g_ofn.lStructSize = sizeof(OPENFILENAME);
      g_ofn.nMaxFile    = MAX_PATH;
      g_ofn.Flags       = OFN_HIDEREADONLY | OFN_CREATEPROMPT;
      g_ofn.hwndOwner   = g_hWnd;
      g_ofn.lpstrFile   = g_ScriptFile;
      g_ofn.lpstrTitle  = "Load Script File";
      g_ofn.lpstrFilter = "MLS Script Files (*.mls)\0*.mls\0All Files (*.*)\0*.*\0\0";
      g_ofn.lpstrDefExt = "mls";
      g_ofn.nMaxFileTitle = MAX_PATH;

      // Clear script filename
      strcpy(g_ScriptFile, "..\\data\\test.mls");

      // Clear script output box
      SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_RESETCONTENT, 0, 0);

      break;


    case WM_DESTROY:
      PostQuitMessage(0);
      break;

    default: return DefWindowProc(hWnd, uMsg, wParam, lParam);
  }

  return 0;
}

sScript *LoadScript(char *Filename, long *NumActions)
{
  FILE *fp;
  long i, j, Num;
  sScript *ScriptHead = NULL, *Script, *ScriptPtr = NULL;

  // Open the file for input
  if((fp=fopen(Filename, "rb"))==NULL)
    return NULL;

  // Get # of script actions and store them
  fread(&Num, 1, sizeof(long), fp);
  if(NumActions != NULL)
    *NumActions = NULL;

  // Loop through each script action
  for(i=0;i<Num;i++) {
    // Allocate a script structure and link in
    Script = new sScript();
    Script->Next = NULL;
    if(ScriptPtr == NULL)
      ScriptHead = Script;
    else
      ScriptPtr->Next = Script;
    ScriptPtr = Script;

    // Get type of action and # of entries
    fread(&Script->Type, 1, sizeof(long), fp);
    fread(&Script->NumEntries, 1, sizeof(long), fp);

    // Get entry data (if any)
    if(Script->NumEntries) {

      // Allocate entry array
      Script->Entries = new sScriptEntry[Script->NumEntries]();

      // Load in each entry
      for(j=0;j<Script->NumEntries;j++) {
        // Get entry type and data
        fread(&Script->Entries[j].Type, 1, sizeof(long), fp);
        fread(&Script->Entries[j].IOValue, 1, sizeof(long), fp);

        // Get text (if any)
        if(Script->Entries[j].Type == _TEXT && Script->Entries[j].Length) {
          Script->Entries[j].Text = new char[Script->Entries[j].Length];
          fread(Script->Entries[j].Text, 1, Script->Entries[j].Length, fp);
        }
      }
    }
  }

  fclose(fp);

  return ScriptHead;
}

BOOL RunScript()
{
  sScript *ScriptPtr;

  // Clear flags 
  for(short i=0;i<256;i++)
    g_Flags[i] = FALSE;

  // Start at beginning of script
  if((ScriptPtr = g_ScriptParent) == NULL)
    return FALSE;

  // Clear the script output box
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_RESETCONTENT, 0, 0);

  // Loop until no more script actions
  while(ScriptPtr != NULL) {
    // Call script function and break on NULL return value.
    // Any other return type is the pointer to the next function,
    // which is typically ScriptPtr->Next.
    ScriptPtr = ScriptProcesses[ScriptPtr->Type].Func(ScriptPtr);
  }

  return TRUE;
}

sScript *Script_IfFlagThen(sScript *ScriptPtr)
{
  BOOL Skipping;

  // See if a flag matches second entry
  if(g_Flags[ScriptPtr->Entries[0].lValue % 256] == ScriptPtr->Entries[1].bValue)
    Skipping = FALSE;
  else 
    Skipping = TRUE;

  // At this point, Skipping states if the script actions
  // need to be skipped due to a conditional if..then statement.
  // Actions are further processed if skipped = FALSE, looking
  // for an else to flip the skip mode, or an endif to end
  // the conditional block.

  // Go to next action to process
  ScriptPtr = ScriptPtr->Next;

  while(ScriptPtr != NULL) {
    // if else, flip skip mode
    if(ScriptPtr->Type == 1)
      Skipping = (Skipping == TRUE) ? FALSE : TRUE;

    // break on end if
    if(ScriptPtr->Type == 2)
      return ScriptPtr->Next;

    // Process script function in conditional block
    // making sure to skip actions when condition not met.
    if(Skipping == TRUE)
      ScriptPtr = ScriptPtr->Next;
    else {
      if((ScriptPtr = ScriptProcesses[ScriptPtr->Type].Func(ScriptPtr)) == NULL)
        return NULL;
    }
  }
  return NULL; // end of script reached
}

sScript *Script_Else(sScript *ScriptPtr)
{
  return ScriptPtr->Next;
}

sScript *Script_EndIf(sScript *ScriptPtr)
{
  return ScriptPtr->Next;
}

sScript *Script_SetFlag(sScript *ScriptPtr)
{
  // Set boolean value
  g_Flags[ScriptPtr->Entries[0].lValue % 256] = ScriptPtr->Entries[1].bValue;
  return ScriptPtr->Next;
}

sScript *Script_Print(sScript *ScriptPtr)
{
  // Display text
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)"Print string:");
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)ScriptPtr->Entries[0].Text);
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)"");

  return ScriptPtr->Next;
}

sScript *Script_Move(sScript *ScriptPtr)
{
  char Text[256];

  // Construct a string containing move coordinates
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)"Moving character to:");
  sprintf(Text, "%lf, %lf, %lf", 
                  ScriptPtr->Entries[0].fValue,
                  ScriptPtr->Entries[1].fValue,
                  ScriptPtr->Entries[2].fValue);
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)Text);
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)"");

  return ScriptPtr->Next;
}

sScript *Script_GainLoss(sScript *ScriptPtr)
{
  char Options[7][64] = {
    { "Main character" }, 
    { "Caster"         },
    { "Target"         },
    { "Gains"          },
    { "Looses"         },
    { "Hit"            },
    { "Magic"          }
  };
  char Text[1024];

  // Construct a string containing choices and display
  sprintf(Text, "%s %s %lu %s points", 
               Options[ScriptPtr->Entries[0].Selection],
               Options[ScriptPtr->Entries[1].Selection+3],
               ScriptPtr->Entries[2].lValue,
               Options[ScriptPtr->Entries[3].Selection+5]);
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)Text);
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)"");

  return ScriptPtr->Next;
}

sScript *Script_Battle(sScript *ScriptPtr)
{
  char Text[256];

  // Show battle sequence #
  sprintf(Text, "Engaging in battle #%lu", ScriptPtr->Entries[0].lValue);
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)Text);
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)"");

  return ScriptPtr->Next;
}

sScript *Script_End(sScript *ScriptPtr)
{
  // Display an end of script dialog
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)"End of Script");
  SendMessage(GetDlgItem(g_hWnd, IDC_SCRIPT), LB_ADDSTRING, 0, (LPARAM)"");

  return NULL;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -