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

📄 script.cpp

📁 源代码演示了在Windows下角色扮演游戏的制作过程
💻 CPP
字号:
//
// 执行Script
//
//		Copyright (c) 2000-2002 Chihiro.SAKAMOTO (HyperWorks)
//
#include "stdafx.h"
#include <stdlib.h>
#include "MainWin.h"
#include "File.h"
#include "Misc.h"
#include "Script.h"

//
// 错误消息的格式
//
char *__cdecl CScriptAction::Format(const char *fmt, ...)
{
	static	char	tmp[256];

	va_list	args;
	va_start(args, fmt);
	vsprintf(tmp, fmt, args);
	va_end(args);

	return tmp;
}

//
// 初始化
//
void CScriptAction::Initialize(CMainWin *parent, unsigned param1, unsigned param2)
{
	CAction::Initialize(parent, param1, param2);

	status = Continue;
	Pressed = FALSE;
	MenuSelect = -1;
	PlayMode = param1;

	memset(value_tab, 0, sizeof(value_tab));

	delete[] script_buffer;
	script_buffer = 0;
}

//
// 按下鼠标左键的处理
//
void CScriptAction::LButtonDown(UINT modKeys, CPoint point)
{
	switch (status) {
	  case WaitMenuDone:	// 等待菜单
		Pressed = TRUE;
		break;
	}
}

//
// 放开左键的处理
//
void CScriptAction::LButtonUp(UINT modKeys, CPoint point)
{
	switch (status) {
	  case WaitKeyPressed:	// 等待按键
		Parent->HideWaitMark();
		status = Continue;
		break;

	  case WaitMenuDone:	// 等待菜单
		if (Pressed) {
			Pressed = FALSE;
			MouseMove(modKeys, point);

			if (MenuSelect >= 0) {
				SetValue(MenuAnserAddr, Parent->GetMenuAnser(MenuSelect));
				Parent->HideMenuWindow();
				status = Continue;
			}
			MenuSelect = -1;
		}
		break;
	}
}

//
// 按下鼠标右键时的处理
//
void CScriptAction::RButtonDown(UINT modKeys, CPoint point)
{
	switch (status) {
	  case WaitKeyPressed:	// 等待按键
		Parent->FlipMessageWindow();
		break;
	}
}

//
// 移动右键时的处理
//
void CScriptAction::MouseMove(UINT modKeys, CPoint point)
{
	switch (status) {
	  case WaitMenuDone:	// 等待菜单
		{
			int sel = Parent->GetMenuSelect(point);
			if (sel != MenuSelect) {
				Parent->SelectMenu(MenuSelect, false);
				MenuSelect = sel;
				Parent->SelectMenu(MenuSelect, true);
			}
		}
		break;
	}
}

//
// 键盘按键按下时的处理
//
void CScriptAction::KeyDown(UINT key)
{
	switch (key) {
	  case VK_RETURN:
	  case VK_SPACE:
		switch (status) {
		  case WaitKeyPressed:	// 等待按键
			Parent->HideWaitMark();
			status = Continue;
			break;

		  case WaitMenuDone:	// 等待菜单
			if (MenuSelect >= 0) {
				SetValue(MenuAnserAddr, Parent->GetMenuAnser(MenuSelect));
				Parent->HideMenuWindow();
				status = Continue;
				MenuSelect = -1;
			}
			break;
		}
		break;

	  case VK_ESCAPE:
		switch (status) {
		  case WaitKeyPressed:	// 等待按键
			Parent->FlipMessageWindow();
			break;
		}
		break;

	  case VK_UP:
		if (status == WaitMenuDone) {	// 等待菜单
			Parent->SelectMenu(MenuSelect, false);
			MenuSelect--;
			if (MenuSelect < 0)
				MenuSelect = Parent->GetMenuItemCount() - 1;
			Parent->SelectMenu(MenuSelect, true);
		}
		break;

	  case VK_DOWN:
		if (status == WaitMenuDone) {	// 等待菜单
			Parent->SelectMenu(MenuSelect, false);
			MenuSelect++;
			if (MenuSelect >= Parent->GetMenuItemCount())
				MenuSelect = 0;
			Parent->SelectMenu(MenuSelect, true);
		}
		break;
	}
}

//
// IDLE处理
//
BOOL CScriptAction::IdleAction()
{
	if (status == Continue) {				// “继续”执行
		do {
			status = Step();				// 执行1步
		} while (status == Continue) ;		// 继续?

		if (status == BreakGame) {			// 结束
			Abort();
		}
		else if (status == WaitNextIdle) {	// 等到下一次IDLE再进来
			status = Continue;				// 改为继续
			return TRUE;
		}
	}
	return FALSE;
}

//
// 结束
//
void CScriptAction::Abort()
{
	if (status == WaitMenuDone)				// 如果是等待菜单状态
		Parent->HideMenuWindow();			// 关闭菜单
	Parent->HideMessageWindow();			// 关闭文字框

	status = BreakGame;
	delete[] script_buffer;					// 释放脚本
	script_buffer = 0;

	Parent->SetAction(CMainWin::ActionScriptDone);
}

//
// 读取脚本档
//
int CScriptAction::LoadFile(const char *name)
{
	char	path[_MAX_PATH];
	sprintf(path, SCRIPTPATH "%s.scr", name);

	delete[] script_buffer;
	script_buffer = 0;

	CFile	file(path);

	if (!file)
		return FileCannotOpen;

	int		length = file.GetFileSize();

	if ((script_buffer = new char [length]) == 0)
		return NotEnoughMemory;

	if (file.Read(script_buffer, length) != length)
		return FileCannotRead;

	return FileNoError;
}

//
// 从文件读取脚本,存储脚本的空间也是在这里配置
//
BOOL CScriptAction::Load(const char *name)
{
	switch (LoadFile(name)) {
	  case FileCannotOpen:
		Parent->MessageBox(Format("脚本 [%s] 无法开启。", name));
		return FALSE;

	  case NotEnoughMemory:
		Parent->MessageBox(Format("内存不足, 无法读取脚本[%s]。", name));
		return FALSE;

	  case FileCannotRead:
		Parent->MessageBox(Format("无法读取脚本。[%s]", name));
		return FALSE;
	}

	script_t *header = (script_t *)script_buffer;

	if (memcmp(header->magic, SCRIPT_MAGIC, 8) != 0) {
		Parent->MessageBox(Format("没有脚本数据。[%s]", name));
		return FALSE;
	}

	current.ncommand = header->ncommand;
	current.commands = (byte_t *)(header + 1);

	position = 0;

	return TRUE;
}

//
// 执行脚本的1步
//
int CScriptAction::Step()
{
	ASSERT(script_buffer);

	command_t *cmd = GetCommand();

	switch (cmd->common.type) {
	  case SET_VALUE_CMD:
		SetValue(cmd->set.value_addr, cmd->set.set_value);
		break;

	  case CALC_VALUE_CMD:
		CalcValue(cmd->calc.value_addr, cmd->calc.add_value);
		break;

	  case TEXT_CMD:
		Parent->WriteMessage(GetString(cmd->text.msg_len));
		return WaitKeyPressed;

	  case CLEAR_TEXT_CMD:
		Parent->ClearMessage();
		return WaitNextIdle;

	  case GOTO_CMD:
		GotoCommand(cmd->goto_cmd.goto_label);
		break;

	  case IF_TRUE_CMD:
		if (GetValue(cmd->if_cmd.value1, cmd->if_cmd.flag & 1) == GetValue(cmd->if_cmd.value2, cmd->if_cmd.flag & 2))
			GotoCommand(cmd->if_cmd.goto_label);
		break;

	  case IF_FALSE_CMD:
		if (GetValue(cmd->if_cmd.value1, cmd->if_cmd.flag & 1) != GetValue(cmd->if_cmd.value2, cmd->if_cmd.flag & 2))
			GotoCommand(cmd->if_cmd.goto_label);
		break;

	  case IF_BIGGER_CMD:
		if (GetValue(cmd->if_cmd.value1, cmd->if_cmd.flag & 1) > GetValue(cmd->if_cmd.value2, cmd->if_cmd.flag & 2))
			GotoCommand(cmd->if_cmd.goto_label);
		break;

	  case IF_SMALLER_CMD:
		if (GetValue(cmd->if_cmd.value1, cmd->if_cmd.flag & 1) < GetValue(cmd->if_cmd.value2, cmd->if_cmd.flag & 2))
			GotoCommand(cmd->if_cmd.goto_label);
		break;

	  case IF_BIGGER_EQU_CMD:
		if (GetValue(cmd->if_cmd.value1, cmd->if_cmd.flag & 1) >= GetValue(cmd->if_cmd.value2, cmd->if_cmd.flag & 2))
			GotoCommand(cmd->if_cmd.goto_label);
		break;

	  case IF_SMALLER_EQU_CMD:
		if (GetValue(cmd->if_cmd.value1, cmd->if_cmd.flag & 1) <= GetValue(cmd->if_cmd.value2, cmd->if_cmd.flag & 2))
			GotoCommand(cmd->if_cmd.goto_label);
		break;

	  case MENU_INIT_CMD:
		Parent->ClearMenuItemCount();
		break;

	  case MENU_ITEM_CMD:
		Parent->SetMenuItem(GetString(cmd->menu_item.label_len), cmd->menu_item.number);
		break;

	  case MENU_CMD:
		MenuSelect = -1;
		MenuAnserAddr = cmd->menu.value_addr;
		Parent->OpenMenu();
		return WaitMenuDone;

	  case EXEC_CMD:
		if (!Load(GetString(cmd->exec_cmd.path_len)))
			return BreakGame;
		PlayMode = MODE_SCENARIO;
		break;

	  case LOAD_CMD:
		return LoadGraphic(GetString(cmd->load.path_len), cmd->load.flag);

	  case UPDATE_CMD:
		return UpdateImage();

	  case CLEAR_CMD:
		return Clear(cmd->clear.pos);

	  case MODE_CMD:
		PlayMode = cmd->mode.mode;
		break;

	  case SYS_EXIT_CMD:
		Parent->SendMessage(WM_CLOSE);
		return WaitNextIdle;

	  case SYS_CLEAR_CMD:
		ClearAllValues();
		break;

	  case END_CMD:
		return BreakGame;

	  default:
		ASSERT(false);
		break;
	}
	return Continue;
}

//
// 读取图片档CG
//
int CScriptAction::LoadGraphic(const char *file, int pos)
{
	BOOL	result = FALSE;
	switch (pos) {
	  case POSITION_BACK:			// 背景
		Parent->ClearOverlap();
		// no break

	  case POSITION_BACKONLY:		// 只有背景
		result = Parent->LoadImageBack(file);
		break;

	  case POSITION_CENTER:			// 中间
		result = Parent->LoadImageCenter(file);
		break;

	  case POSITION_LEFT:			// 左
		result = Parent->LoadImageLeft(file);
		break;

	  case POSITION_RIGHT:			// 右
		result = Parent->LoadImageRight(file);
		break;

	  case POSITION_OVERLAP:		// 重叠
		result = Parent->LoadImageOverlap(file);
		break;
	}

	if (!result) {
		Parent->MessageBox(Format("文件无法读取。[%s]", file));
		if (PlayMode == MODE_SYSTEM)
			Parent->SendMessage(WM_CLOSE);
		return BreakGame;
	}
	return Continue;
}

//
// 清除图片CG
//
int CScriptAction::Clear(int pos)
{
	switch (pos) {
	  case POSITION_BACK:			// 背景
		Parent->ClearOverlap();
		// no break

	  case POSITION_BACKONLY:		// 只有背景
		Parent->ClearBack();
		break;

	  case POSITION_CENTER:			// 中间
		Parent->ClearCenter();
		break;

	  case POSITION_LEFT:			// 左
		Parent->ClearLeft();
		break;

	  case POSITION_RIGHT:			// 右
		Parent->ClearRight();
		break;

	  case POSITION_OVERLAP:		// 重叠
		Parent->ClearOverlap();
		break;
	}
	return Continue;
}

//
// 更新显示
//
int CScriptAction::UpdateImage()
{
	CRect	rect = Parent->GetInvalidRect();
	Parent->UpdateImage(rect);
	return WaitNextIdle;
}

⌨️ 快捷键说明

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