现在的位置: 首页 > 综合 > 正文

36. 命令脚本系统

2012年10月20日 ⁄ 综合 ⁄ 共 11080字 ⁄ 字号 评论关闭

命令脚本是一种在文件中包含许多命令的脚本。命令脚本和属性脚本非常相似,除了每一行第一个单词所代表的意思不同之外。在基于命令的脚本中,通常要有一个文件,并且会解释该文件,直到文件执行到结束或是出现错误为止。

伪代码:

Open the script file and get the line count.

Create an array of strings for each line.

In the application loop through each line.

Get the command and check if it is invalid or a comment.

if valid, get any additional pieces of info from the script

and process it based on what the command is.

Once complete we are done with the script.

命令脚本需要随着进度解释信息。在发现错误时就会在屏幕上显示错误信息。也可以预处理这些脚本从而确保在执行脚本之前它们是有效的。

CommondScript.h

#ifndef _UGP_CCOMMAND_SCRIPT_H_
#define _UGP_CCOMMAND_SCRIPT_H_

#define MAX_COMMAND_SIZE 32
#define MAX_LINE_SIZE 3072
#define MAX_PARAM_SIZE 2048


struct stVector
{
stVector() : x(
0), y(0), z(0) {}
float x, y, z;
};


class CCommandScript
{
public:
CCommandScript();
~CCommandScript();

bool LoadScriptFile(char *filename);

// 该函数用于获取某一行中的某个属性,保存在参数destCommand中
// 从脚本文件提取命令。它只包括一个参数,该参数在函数完成工作时保存命令。
void ParseCommand(char *destCommand);

// 该函数获取文件中的下一组文本,直到遇到分隔符为止。
void ParseStringParam(char *destString);

bool ParseBoolParam();

int ParseIntParam();

float ParseFloatParam();

void Shutdown();

void MoveToStart();
void MoveToNextLine();
int GetCurrentLineNum();
int GetTotalLines();
bool IsLineComment();

private:
int totalScriptLines; // 总行数
int currentLine; // 当前行
int currentLineChar; // 所处当前行中的当前字符
char** m_script; // 保存整个文件
};

#endif

  

CommondScript.cpp

#include"CommandScript.h"
#include
<fstream>

using namespace std;


CCommandScript::CCommandScript() : totalScriptLines(
0), currentLine(0),
currentLineChar(
0), m_script(0)
{
}


CCommandScript::
~CCommandScript()
{
Shutdown();
}


bool CCommandScript::LoadScriptFile(char *filename)
{
ifstream input, input2;
char tempLine[MAX_LINE_SIZE];

input.open(filename);
if(!input.is_open())
return false;

Shutdown();

// Open and get number of lines.
while(!input.eof())
{
input.getline(tempLine, MAX_LINE_SIZE,
'\n');
totalScriptLines
++;
}

input.close();

input2.open(filename);
if(!input2.is_open())
return false;

// Load in every line of text.
m_script = new char*[totalScriptLines];

for(int i = 0; i < totalScriptLines; i++)
{
m_script[i]
= new char[MAX_LINE_SIZE + 1];
input2.getline(m_script[i], MAX_LINE_SIZE,
'\n');
}

input2.close();
return true;
}


void CCommandScript::ParseCommand(char *destCommand)
{
// This function will take the first word of the current
// line and save it in destCommand.

int commandSize = 0;

// If destcommand is NULL, or if we run out of lines, or at the end
// of the current line then we return.
if(!destCommand) return;
if(currentLine >= totalScriptLines) return;
if(currentLineChar >= (int)strlen(m_script[currentLine])) return;

// Init string.
destCommand[0] = '\0';

// Since commands start each line we can say that if there is
// a # at the start of the line, then this is a comment.
if(IsLineComment())
{
destCommand[
0] = '#';
destCommand[
1] = '\0';
return;
}

// Loop through every character until you find a space or newline.
// That means we are at the end of a command.
while(currentLineChar < (int)strlen(m_script[currentLine]))
{
if(m_script[currentLine][currentLineChar] == ' ' ||
m_script[currentLine][currentLineChar]
== '\n')
break;

// Save the text in the array.
destCommand[commandSize] = m_script[currentLine][currentLineChar];
commandSize
++;
currentLineChar
++;
}

// Skip next space or newline.
currentLineChar++;
destCommand[commandSize]
= '\0';
}


void CCommandScript::ParseStringParam(char *destString)
{
// This function will take a text inside " and " and save
// it to destString.

int paramSize = 0;
bool endQuoteFound = false;

// If destcommand is NULL, or if we run out of lines, or at the end
// of the current line then we return.
if(!destString) return;
if(currentLine >= totalScriptLines) return;
if(currentLineChar >= (int)strlen(m_script[currentLine])) return;

// Initialize string.
destString[0] = '\0';

// Skip beginning quote.
currentLineChar++;

// Loop through every character until you find a end quote or newline.
// That means we are at the end of a string.
while(currentLineChar < (int)strlen(m_script[currentLine]))
{
if(m_script[currentLine][currentLineChar] == '"')
{
endQuoteFound
= true;
break;
}

if(m_script[currentLine][currentLineChar] == '\n')
break;

// Save the text in the array.
destString[paramSize] = m_script[currentLine][currentLineChar];
paramSize
++;
currentLineChar
++;
}

// Skip end quotes and next space or newline. In this system we don't
// allow strings to take up multiple lines. You can simple have
// multiple print string commands instead.
if(endQuoteFound)
currentLineChar
+= 2;
else
currentLineChar
++;

destString[paramSize]
= '\0';
}


bool CCommandScript::ParseBoolParam()
{
// This function will get the next text and will return
// true if this text is "true" or false if it is "false".

char string[MAX_PARAM_SIZE];
int paramSize = 0;

// If we run out of lines, or at the end
// of the current line then we return.
if(currentLine >= totalScriptLines) return 0;
if(currentLineChar >= (int)strlen(m_script[currentLine])) return 0;

// Loop through every character until you find a space or newline.
// That means we are at the end of a variable.
while(currentLineChar < (int)strlen(m_script[currentLine]))
{
if(m_script[currentLine][currentLineChar] == ' ' ||
m_script[currentLine][currentLineChar]
== '\n')
break;

// Save the text in the array.
string[paramSize] = m_script[currentLine][currentLineChar];
paramSize
++;
currentLineChar
++;
}

// Skip next space or newline.
currentLineChar++;
string[paramSize] = '\0';

if(stricmp(string, "true") == 0)
return true;
return false;
}


int CCommandScript::ParseIntParam()
{
// This funciton will take the next text and convert
// it to a int that is returned.

char string[MAX_PARAM_SIZE];
int paramSize = 0;

// If we run out of lines, or at the end
// of the current line then we return.
if(currentLine >= totalScriptLines) return 0;
if(currentLineChar >= (int)strlen(m_script[currentLine])) return 0;

// Loop through every character until you find a space or newline.
// That means we are at the end of a variable.
while(currentLineChar < (int)strlen(m_script[currentLine]))
{
if(m_script[currentLine][currentLineChar] == ' ' ||
m_script[currentLine][currentLineChar]
== '\n')
break;

// Save the text in the array.
string[paramSize] = m_script[currentLine][currentLineChar];
paramSize
++;
currentLineChar
++;
}

// Skip next space or newline.
currentLineChar++;
string[paramSize] = '\0';
return atoi(string);
}


float CCommandScript::ParseFloatParam()
{
// This funciton will take the next text and convert
// it to a float that is returned.

char string[MAX_PARAM_SIZE];
int paramSize = 0;

// If we run out of lines, or at the end
// of the current line then we return.
if(currentLine >= totalScriptLines) return 0;
if(currentLineChar >= (int)strlen(m_script[currentLine])) return 0;

// Loop through every character until you find a space or newline.
// That means we are at the end of a variable.
while(currentLineChar < (int)strlen(m_script[currentLine]))
{
if(m_script[currentLine][currentLineChar] == ' ' ||
m_script[currentLine][currentLineChar]
== '\n')
break;

// Save the text in the array.
string[paramSize] = m_script[currentLine][currentLineChar];
paramSize
++;
currentLineChar
++;
}

// Skip next space or newline.
currentLineChar++;
string[paramSize] = '\0';
return (float)atof(string);
}


void CCommandScript::MoveToStart()
{
currentLine
= 0;
currentLineChar
= 0;
}


void CCommandScript::MoveToNextLine()
{
currentLine
++;
currentLineChar
= 0;
}


int CCommandScript::GetCurrentLineNum()
{
return currentLine;
}


int CCommandScript::GetTotalLines()
{
return totalScriptLines;
}


bool CCommandScript::IsLineComment()
{
// If the first character of a line a # then
// the line must be commented out.
if(m_script[currentLine][0] == '#') return true;
return false;
}


void CCommandScript::Shutdown()
{
if(m_script)
{
// Delete every line in the script file.
for(int i = 0; i < totalScriptLines; i++)
{
if(m_script[i])
{
delete[] m_script[i];
m_script[i]
= 0;
}
}

delete m_script;
m_script
= 0;
}

// Reset variables.
totalScriptLines = 0;
currentLineChar
= 0;
currentLine
= 0;
}

  

main.cpp

#include<d3d9.h>
#include
<d3dx9.h>
#include
<stdio.h>
#include
"CommandScript.h"

#define WINDOW_CLASS "UGPDX"
#define WINDOW_NAME "Command Scripting"
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

// Function Prototypes...
bool InitializeD3D(HWND hWnd, bool fullscreen);
bool InitializeObjects();
void RenderScene();
void Shutdown();

// Direct3D object and device.
LPDIRECT3D9 g_D3D = NULL;
LPDIRECT3DDEVICE9 g_D3DDevice
= NULL;

// Matrices.
D3DXMATRIX g_projection;
D3DXMATRIX g_ViewMatrix;
D3DXMATRIX g_WorldMatrix;

// Mesh objects
LPD3DXMESH g_teapot = NULL;
D3DMATERIAL9 g_material;
// 材质

// Scene light source.
D3DLIGHT9 g_light; // 灯光

// Application specific language definitions.
// 用于定义基于命令的语言
#define SET_POSITION "SetPosition"
#define SET_COLOR "SetColor"
#define COMMENT "#"

LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
switch(msg)
{
case WM_DESTROY:
PostQuitMessage(
0);
return 0;
break;

case WM_KEYUP:
if(wp == VK_ESCAPE) PostQuitMessage(0);
break;
}

return DefWindowProc(hWnd, msg, wp, lp);
}

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE ph, LPSTR cmd, int s)
{
// Register the window class
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
WINDOW_CLASS, NULL };
RegisterClassEx(
&wc);

// Create the application's window
HWND hWnd = CreateWindow(WINDOW_CLASS, WINDOW_NAME,
WS_OVERLAPPEDWINDOW,
100, 100, WINDOW_WIDTH, WINDOW_HEIGHT,
GetDesktopWindow(), NULL, wc.hInstance, NULL);

// Initialize Direct3D
if(InitializeD3D(hWnd, false))
{
// Show the window
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);

// Enter the message loop
MSG msg;
ZeroMemory(
&msg, sizeof(msg));

while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(
&msg);
DispatchMessage(
&msg);
}
else
RenderScene();
}
}

// Release any and all resources.
Shutdown();

// Unregister our window.
UnregisterClass(WINDOW_CLASS, wc.hInstance);
return 0;
}

bool InitializeD3D(HWND hWnd, bool fullscreen)
{
D3DDISPLAYMODE displayMode;

// Create the D3D object.
g_D3D = Direct3DCreate9(D3D_SDK_VERSION);
if(g_D3D == NULL) return false;

// Get the desktop display mode.
if(FAILED(g_D3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT,
&displayMode))) return false;

// Set up the structure used to create the D3DDevice
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(
&d3dpp, sizeof(d3dpp));

if(fullscreen)
{
d3dpp.Windowed
= FALSE;
d3dpp.BackBufferWidth
= WINDOW_WIDTH;
d3dpp.BackBufferHeight
= WINDOW_HEIGHT;
}
else
d3dpp.Windowed
= TRUE;
d3dpp.SwapEffect
= D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat
= displayMode.Format;

// Create the D3DDevice
if(FAILED(g_D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&g_D3DDevice))) return false;

// Set the projection matrix.
D3DXMatrixPerspectiveFovLH(&g_projection, 45.0f,
WINDOW_WIDTH
/WINDOW_HEIGHT, 0.1f, 1000.0f);
g_D3DDevice
->SetTransform(D3DTS_PROJECTION, &g_projection);

// Initialize any objects we will be displaying.
if(!InitializeObjects()) return false;

return true;
}

bool InitializeObjects()
{
// Command scripting system.
CCommandScript commandScript;
stVector teapotCol, camPos;

// Load the script.
if(!commandScript.LoadScriptFile("script.spt"))
return false;

char command[MAX_COMMAND_SIZE];

// Loop through and execute each command that is given.
for(int i = 0; i < commandScript.GetTotalLines(); i++)
{
commandScript.ParseCommand(command);

// Depending on the command will depend on what we do.
if(stricmp(command, SET_POSITION) == 0)
{
camPos.x
= commandScript.ParseFloatParam();
camPos.y
= commandScript.ParseFloatParam();
camPos.z
= commandScript.ParseFloatParam();
}
else if(stricmp(command, SET_COLOR) == 0)
{
teapotCol.x
= commandScript.ParseFloatParam();
teapotCol.y
= commandScript.ParseFloatParam();
teapotCol.z
= commandScript.ParseFloatParam();
}
else if(stricmp(command, COMMENT) == 0)
{
// Do nothing is we see a comment.
}
else
{
// Here you can handle invalid commands (syntax errors).
char err[64];

sprintf(err, "Error in script on line %d.",
commandScript.GetCurrentLineNum()
+ 1);
MessageBox(NULL, err,
"Error", MB_OK);

commandScript.Shutdown();
return false;
}

// Go to the next line of the script.
commandScript.MoveToNextLine();
}

// Release all resources. This script was designed
// to only run during the initialization.
commandScript.Shutdown();

// Set default rendering states.
g_D3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
g_D3DDevice
->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_COLORVALUE(0.3f, 0.3f,

抱歉!评论已关闭.