📄 gscene_script.cpp
字号:
//////////////////////////////////////////////////////////////////////
// GScene_Script.cpp: implementation of the CGScene::RunScript
// RPGDemo框架程序 场景类
// written by Yboy
// Modified by 萧萧落木
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RPGGame.h"
#include "GScene.h"
#include <assert.h>
#include <vector>
#include <string>
#include <fstream>
using namespace std;
typedef vector<string> stringvector;
//////////////////////////////////////////////////////////////////////
// 用于定义脚本命令的宏
// 格式为:DEFINE_COMMAND("脚本命令",对应的处理函数);
//////////////////////////////////////////////////////////////////////
#define DEFINE_COMMAND(command,fuction) if (m_Command==command) return fuction();
//////////////////////////////////////////////////////////////////////
// 脚本引擎类
//////////////////////////////////////////////////////////////////////
class CScript
{
public:
CScript(LPCTSTR szScriptFileName,CGScene* pScene);
~CScript();
HRESULT Run(); //运行该脚本文件
BOOL CompileLine(); //分析一行脚本
BOOL CheckCommand(); //判断并执行脚本命令
BOOL ReportError(const char * Format, ... ); //用统一的格式报告错误
protected:
CGScene* m_pScene; //场景指针
//MODIFIED BY ROCWOOD
CRPGGame* pTheApp;
//MODIFIED BY ROCWOOD
string m_filename; //脚本文件名
int m_linenumber; //当前处理的脚本文件行号
std::fstream m_file; //脚本文件对象
string m_buffer; //行缓冲区
string m_Command; //当前脚本命令
stringvector m_Param; //当前脚本命令的参数
protected:
BOOL FuncTalk(); //Talk命令的处理函数--显示对话
//MODIFIED BY ROCWOOD
BOOL FuncAddEAP();
BOOL FuncAddEDP();
BOOL FuncAddHP();
BOOL FuncAddMP();
BOOL FuncAddItemOnce();
BOOL FuncCombat();
BOOL FuncGameEnd();
//MODIFIED BY ROCWOOD
};
//////////////////////////////////////////////////////////////////////
// 运行脚本文件 ----供CGScene调用
// szScriptFileName 脚本文件名
//////////////////////////////////////////////////////////////////////
HRESULT CGScene::RunScript(LPCTSTR szScriptFileName)
{
CScript ScriptFile(szScriptFileName,this); //构造一个脚本文件对象
return ScriptFile.Run(); //运行这个脚本
}
//////////////////////////////////////////////////////////////////////
// szScriptFileName 脚本文件名
// pScene CGScene场景指针
//////////////////////////////////////////////////////////////////////
CScript::CScript(LPCTSTR szScriptFileName,CGScene* pScene)
{
//MODIFIED BY ROCWOOD
assert(pScene);
m_pScene = pScene; //保存场景指针
assert(szScriptFileName);
m_filename = "SCRIPT\\";
m_filename.append(szScriptFileName); //保存文件名
pTheApp = static_cast<CRPGGame*>(GAFGetApp());
assert(pTheApp);
//MODIFIED BY ROCWOOD
}
CScript::~CScript()
{
}
//////////////////////////////////////////////////////////////////////
// 运行脚本文件 ----内部调用
//////////////////////////////////////////////////////////////////////
HRESULT CScript::Run()
{
//打开脚本文件
m_file.open(m_filename.c_str(),ios::in|ios::nocreate);
if (m_file.is_open()==0)
{
ReportError("找不到脚本文件:%s!",m_filename);
return E_FAIL;
}
//开始分析并执行脚本命令
m_linenumber=0;
while(!m_file.eof() //MODIFIED BY ROCWOOD
&&(pTheApp->GAFGameStatus == GAF_GAMESTATUS_INSCENE))
{
getline(m_file,m_buffer,';'); //读入一行脚本
m_linenumber++;
if (!CompileLine()) return E_FAIL; //分析脚本命令
if (m_Command=="Return") break; //判断是否返回命令
if (!CheckCommand()) return E_FAIL; //执行当前脚本命令
}
//关闭脚本文件
m_file.close();
//返回S_OK表示执行成功
return S_OK;
}
//定义脚本命令
BOOL CScript::CheckCommand()
{
DEFINE_COMMAND("Talk",FuncTalk);
//TODO:加入你自己的脚本命令检测语句
//格式为:DEFINE_COMMAND("脚本命令",对应的处理函数);
//MODIFIED BY ROCWOOD
DEFINE_COMMAND("AddEAP",FuncAddEAP);
DEFINE_COMMAND("AddEDP",FuncAddEDP);
DEFINE_COMMAND("AddHP",FuncAddHP);
DEFINE_COMMAND("AddMP",FuncAddMP);
DEFINE_COMMAND("AddItemOnce",FuncAddItemOnce);
DEFINE_COMMAND("Combat",FuncCombat);
DEFINE_COMMAND("GameEnd",FuncGameEnd);
//MODIFIED BY ROCWOOD
//如果脚本命令错误
return ReportError("未知的脚本命令%s!",m_Command.c_str());
}
BOOL CScript::CompileLine()
{
int pos;
//忽略注释的行
while((pos=m_buffer.find("//"))>=0)
{
m_buffer=m_buffer.substr(m_buffer.find('\n')+1);
}
//删除控制字符
for (string::iterator it=m_buffer.end();it>=m_buffer.begin();it--)
if (((*it<32)&&(*it>=0))||(*it=='\"')) m_buffer.erase(it);
if (m_buffer.empty()) return ReportError("文件末尾没有Return()!");
//检查语法错误
pos=m_buffer.find('(');
if (pos<0) return ReportError("没有左括号!");
m_Command=m_buffer.substr(0,pos);//分离脚本命令
m_buffer=m_buffer.substr(pos+1);
pos=m_buffer.find(')');
if (pos<0) return ReportError("没有右括号!");
m_buffer[pos]=',';
//分离脚本命令参数
m_Param.erase(m_Param.begin(),m_Param.end());
while((pos=m_buffer.find(','))>0)
{
m_Param.push_back(m_buffer.substr(0,pos));
m_buffer=m_buffer.substr(pos+1);
}
return TRUE;
}
//报告错误
BOOL CScript::ReportError(const char * Format, ... )
{
char Message[256];
char Message2[128];
sprintf(Message,"脚本文件%s第%d行:",m_filename.c_str(),m_linenumber);
va_list argList;
va_start(argList, Format);
_vsntprintf(Message2, sizeof(Message2), Format, argList);
va_end(argList);
//MODIFIED BY ROCWOOD
strncat(Message,Message2,255);
GAFMessageBox(Message,"脚本引擎错误",MB_OK|MB_ICONWARNING);
//MODIFIED BY ROCWOOD
return FALSE;
}
#define TALK_DIALOG_WIDTH 500 //显示对话内容的区域高度
#define TALK_DIALOG_HEIGHT 120 //显示对话内容的区域高度
#define TALK_DIALOG_NAMEPOS_X 25 //人名的显示位置
#define TALK_DIALOG_NAMEPOS_Y 5
#define TALK_DIALOG_WORDSPOS_X 25 //对话内容的显示位置
#define TALK_DIALOG_WORDSPOS_Y 30
//显示对话的字体参数
#define TALK_FONT_NAME "楷体_GB2312"
#define TALK_FONT_HEIGHT 18
#define TALK_FONT_WIDTH 18
BOOL CScript::FuncTalk()
{
//MODIFIED BY ROCWOOD
static CGAFDDrawSurface TALKDialog;
if(TALKDialog.GetSurface()==NULL) //还未创建表面
{
if(FAILED(TALKDialog.CreateSurface(&GAFDDraw,TALK_DIALOG_WIDTH,TALK_DIALOG_HEIGHT,GAFMEM_SYSTEMONLY)))
return FALSE;
}
//MODIFIED BY ROCWOOD
//监测命令合法性
if (m_Param.size()!=2) return ReportError("Talk的参数应为两个!");
string name=m_Param[0];
string words=m_Param[1];
//根据分辨率大小计算对话的显示坐标
DWORD ScreenWidth=GAFDDraw.GetBack()->GetWidth();
DWORD ScreenHeight=GAFDDraw.GetBack()->GetHeight();
POINT pos;
//MODIFIED BY ROCWOOD
pos.x=(ScreenWidth-TALK_DIALOG_WIDTH)/2;
//MODIFIED BY ROCWOOD
pos.y=ScreenHeight-150;
//根据分辨率计算每行、每页显示的字数
//DWORD WordsPerLine=/*(ScreenWidth-140)/TALK_FONT_WIDTH*2*/;
//MODIFIED BY ROCWOOD
DWORD WordsPerLine=TALK_DIALOG_WIDTH/TALK_FONT_WIDTH*2;
//MODIFIED BY ROCWOOD
DWORD LinesPerPage=TALK_DIALOG_HEIGHT/TALK_FONT_HEIGHT-2;
DWORD WordsPerPage=WordsPerLine*LinesPerPage;
//下面显示对话
while(TRUE)
{
if(GAFAppProcessMessage()==FALSE) return FALSE;
//处理用户输入
GAFDInput.Update(TRUE,TRUE);
if (GAFDInput.GetMouseKeyState(DIK_MOUSELEFT)==GAFDIKEY_RELEASE)
{
if (words.length()>WordsPerPage) words=words.substr(WordsPerPage);
else break;
}
//渲染场景
m_pScene->RenderScene();
static RECT rt;
SetRect(&rt,pos.x,pos.y,pos.x+TALK_DIALOG_WIDTH,pos.y+TALK_DIALOG_HEIGHT);
GAFDDraw.GetBack()->BltFastTo(&TALKDialog,0,0,FALSE,&rt,TRUE);
GAFDDraw.GetBack()->AlphaConstBlt(&TALKDialog,rt.left,rt.top,192,FALSE,NULL,TRUE);
//选择一个好看的字体
//MODIFIED BY ROCWOOD
//GAFDDraw.GetBack()->SetFont(TALK_FONT_NAME,TALK_FONT_HEIGHT,0,FW_SEMIBOLD);
//MODIFIED BY ROCWOOD
//显示人名
GAFDDraw.GetBack()->TextXY(
pos.x+TALK_DIALOG_NAMEPOS_X,pos.y+TALK_DIALOG_NAMEPOS_Y,
0xFFFFFF,name.c_str());
//显示对话
for (int i=0;i<LinesPerPage;i++)
if ((i*WordsPerLine)<words.length())
GAFDDraw.GetBack()->TextXY(
pos.x+TALK_DIALOG_WORDSPOS_X,
pos.y+TALK_DIALOG_WORDSPOS_Y+i*(TALK_FONT_HEIGHT+2),
RGB(255,255,0),words.substr(i*WordsPerLine,WordsPerLine).c_str());
//MODIFIED BY ROCWOOD
//GAFDDraw.GetBack()->SetFont("System",16);
//MODIFIED BY ROCWOOD
GAFDDraw.Present(FALSE,TRUE); //更新屏幕
}
//MODIFIED BY ROCWOOD
//GAFDDraw.GetBack()->SetFont("System",16);
//MODIFIED BY ROCWOOD
return TRUE;
}
BOOL CScript::FuncAddEAP()
{
//监测命令合法性
if (m_Param.size()!=1) return ReportError("AddEAP的参数应为1个!");
string str=m_Param[0];
LPCGRole pLeader=m_pScene->GetRole(m_pScene->GetLeaderRoleIndex());
if(!pLeader) return FALSE;
LONG x=atoi(str.c_str());
pLeader->AddEAP(x);
return TRUE;
}
BOOL CScript::FuncAddEDP()
{
//监测命令合法性
if (m_Param.size()!=1) return ReportError("AddEDP的参数应为1个!");
string str=m_Param[0];
LPCGRole pLeader=m_pScene->GetRole(m_pScene->GetLeaderRoleIndex());
if(!pLeader) return FALSE;
LONG x=atoi(str.c_str());
pLeader->AddEDP(x);
return TRUE;
}
BOOL CScript::FuncAddHP()
{
//监测命令合法性
if (m_Param.size()!=1) return ReportError("AddHP的参数应为1个!");
string str=m_Param[0];
LPCGRole pLeader=m_pScene->GetRole(m_pScene->GetLeaderRoleIndex());
if(!pLeader) return FALSE;
LONG x=atoi(str.c_str());
pLeader->AddHP(x);
return TRUE;
}
BOOL CScript::FuncAddMP()
{
//监测命令合法性
if (m_Param.size()!=1) return ReportError("AddMP的参数应为1个!");
string str=m_Param[0];
LPCGRole pLeader=m_pScene->GetRole(m_pScene->GetLeaderRoleIndex());
if(!pLeader) return FALSE;
LONG x=atoi(str.c_str());
pLeader->AddMP(x);
return TRUE;
}
BOOL CScript::FuncAddItemOnce()
{
//监测命令合法性
if (m_Param.size()!=1) return ReportError("AddItemOnce的参数应为1个!");
string str=m_Param[0];
HRESULT hr=m_pScene->m_gObjManager.AddItemOnce(str.c_str());
if(FAILED(hr)) return FALSE;
return TRUE;
}
BOOL CScript::FuncGameEnd()
{
//监测命令合法性
if (m_Param.size()!=0) return ReportError("GameEnd应该无参数!");
GAFDDraw.GetBack()->Fill(0);
GAFDDraw.GetBack()->TextXY(160,200,0xFFFFFF,"恭喜这位大侠凭借过人的勇气成功打败大魔王!");
GAFDDraw.Present();
pTheApp->GAFGameStatus = GAF_GAMESTATUS_MAINTITLE;
Sleep(2000);
return TRUE;
}
BOOL CScript::FuncCombat()
{
//监测命令合法性
if (m_Param.size()!=1) return ReportError("Combat的参数应为1个!");
string str=m_Param[0];
HRESULT hr=m_pScene->RunCombat(str.c_str());
if(FAILED(hr)) return FALSE;
if(hr==COMBAT_FAILED)
{
GAFDDraw.GetBack()->Fill(0);
GAFDDraw.GetBack()->TextXY(200,200,0xFFFFFF,"战斗失败,这位大侠重新来过吧!");
GAFDDraw.Present();
pTheApp->GAFGameStatus = GAF_GAMESTATUS_MAINTITLE;
Sleep(2000);
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -