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

📄 gscene_script.cpp

📁 RPG游戏源代码,里面有RPG游戏的制作流程,供大家学习如何制作RPG游戏
💻 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 + -