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

📄 battle.cpp

📁 RPG游戏的剧情部分源码。是Visual C++角色扮演游戏程序设计的第七章的源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		Error(reader, "无法读取CG资料");
		return false;
	}
	return true;
}

//
// 把map上的文字改成状态
//
int CBattleAction::FindMapStatus(const char *find)
{
	struct {
		char str[4];
		unsigned type;
	} table[] = {
		{ "□", NONE },
		{ "■", RESTRICTED_AREA },
		{ "一", PLAYER | (0 << 8) },
		{ "二", PLAYER | (1 << 8) },
		{ "三", PLAYER | (2 << 8) },
		{ "四", PLAYER | (3 << 8) },
		{ "五", PLAYER | (4 << 8) },
		{ "六", PLAYER | (5 << 8) },
		{ "七", PLAYER | (6 << 8) },
		{ "八", PLAYER | (7 << 8) },
		{ "九", PLAYER | (8 << 8) },
		{ "1", ENEMY | (0 << 8) },
		{ "2", ENEMY | (1 << 8) },
		{ "3", ENEMY | (2 << 8) },
		{ "4", ENEMY | (3 << 8) },
		{ "5", ENEMY | (4 << 8) },
		{ "6", ENEMY | (5 << 8) },
		{ "7", ENEMY | (6 << 8) },
		{ "8", ENEMY | (7 << 8) },
		{ "9", ENEMY | (8 << 8) },
		{ "Ⅰ", OBJECT | (0 << 8) },
		{ "Ⅱ", OBJECT | (1 << 8) },
		{ "Ⅲ", OBJECT | (2 << 8) },
		{ "Ⅳ", OBJECT | (3 << 8) },
		{ "Ⅴ", OBJECT | (4 << 8) },
		{ "Ⅵ", OBJECT | (5 << 8) },
		{ "Ⅶ", OBJECT | (6 << 8) },
		{ "Ⅷ", OBJECT | (7 << 8) },
		{ "Ⅸ", OBJECT | (8 << 8) },
	} ;
	for (int i=0; i<(sizeof(table) / sizeof(table[0])); i++) {
		if (strcmp(find, table[i].str) == 0)
			return table[i].type;
	}
	return -1;
}

// map
bool CBattleAction::MapCmd(TextReader &reader, Lexer &lexer)
{
	if (map_data == 0) {	// 此时,已经要决定地图的大小
		Error(reader, "请先设定mapsize");
		return false;
	}

	for (int y=0; y<MapSize.cy; y++) {
		const char *str = reader.GetString();
		if (str == 0) {
			Error(reader, "文法错误");
			return false;
		}
		for (int x=0; x<MapSize.cx; x++) {
			char chip[3];
			chip[0] = str[x * 2 + 0];
			chip[1] = str[x * 2 + 1];
			chip[2] = 0;

			int idx = FindMapStatus(chip);
			if (idx < 0) {
				Error(reader, "文法错误");
				return false;
			}
			map_data[y][x].type = (unsigned char)idx;
			if (idx != RESTRICTED_AREA && idx != NONE) {
				map<int, CChip>::iterator p = chip_list.find(idx);
				if (p == chip_list.end()) {		// 尚未登录
					Error(reader, "人物角色尚未登录");
					return false;
				}
				else {
					TRACE("[%s] = %d, %d\n", p->second.name.c_str(), x, y);
					if ((idx & PLAYER) != 0) {
						player_list.push_back(CCharacter(p->second.image, x, y, CCharacter::DEPTH_CHAR));
						CCharacter &s = player_list.back();

						// 根据人物姓名读入状态
						CStatus *status = Parent->GetParam().GetStatus(p->second.name.c_str());
						if (status == 0) {	// 无的状态
							Error(reader, "找不到人物%s的状态信息");
							return false;
						}
						s.status = *status;

						sprite.insert(&s);
						s.SetDirection(CCharacter::RIGHT);
						map_data[y][x].sprite = &s;

						StatusCharacter[idx >> 8] = &s;	// 显示用人物相关信息
					}
					else if ((idx & ENEMY) != 0) {
						enemy_list.push_back(CCharacter(p->second.image, x, y, CCharacter::DEPTH_CHAR));
						CCharacter &s = enemy_list.back();

						// 根据人物姓名读入状态
						CStatus *status = Parent->GetParam().GetStatus(p->second.name.c_str());
						if (status == 0) {	// 无的状态
							Error(reader, "找不到人物%s的状态信息");
							return false;
						}
						s.status = *status;

						sprite.insert(&s);
						s.SetDirection(CCharacter::LEFT);
						map_data[y][x].sprite = &s;
					}
					else if ((idx & OBJECT) != 0) {
						object_list.push_back(CMapSprite(p->second.image, x, y, CMapSprite::DEPTH_OBJECT));
						CMapSprite &s = object_list.back();
						sprite.insert(&s);
						map_data[y][x].sprite = &s;
					}
				}
			}
		}
	}
	return true;
}

//
// 读入地图定义档
//
bool CBattleAction::LoadMap(const char *name)
{
	typedef bool (CBattleAction::*cmd_t)(TextReader &, Lexer &);
	typedef pair<const char *, cmd_t>	CmdTab;
	typedef map<const char *, cmd_t, ic_less>	cmdmap;
	cmdmap	cmd_table;

	cmd_table.insert(CmdTab("player",	&CBattleAction::PlayerCmd));
	cmd_table.insert(CmdTab("enemy",	&CBattleAction::EnemyCmd));
	cmd_table.insert(CmdTab("object",	&CBattleAction::ObjectCmd));
	cmd_table.insert(CmdTab("mapsize",	&CBattleAction::MapSizeCmd));
	cmd_table.insert(CmdTab("mapimage",	&CBattleAction::MapImageCmd));
	cmd_table.insert(CmdTab("map",		&CBattleAction::MapCmd));

	char	path[_MAX_PATH];
	sprintf(path, MAPPATH "%s.txt", name);

	TextReader	reader(path);
	if (!reader) {
		Parent->MessageBox("无法读取地图档案。");
		return false;
	}

	const char *str;
	while ((str = reader.GetString()) != 0) {
		Lexer	lexer(str);

		if (lexer.NumToken()) {
			const char *cmd = lexer.GetString(0);
			if (stricmp(cmd, "end") == 0)	// 结束
				break;

			cmdmap::iterator p = cmd_table.find(cmd);
			if (p != cmd_table.end()) {
				if (!(this->*p->second)(reader, lexer))
					return false;
			}
			else {
				Error(reader, "文法错误");
				return false;
			}
		}
	}
	return true;
}

//
// 读入战斗地图的资料
//
bool CBattleAction::Load(const char *name)
{
	// 若仍残留之前的状态,则为error
	// 应该不会有这个状态,故设为ASSERT
	ASSERT(map_data == 0);
	ASSERT(_map_data == 0);

	// 读入地图资料
	if (!LoadMap(name))
		return false;

	// 读入CG资料
	if (!Cursor.LoadImage("cursor")
	 || !Command.LoadImage("command")
	 || !TurnEnd.LoadImage("turnend")
	 || !StatusBase.LoadImage("status")
	 || !PopupImageBase.LoadImage("popup")
	 || !PopupParts.LoadImage("popup_parts")
	 || !FireBallImage.LoadImage("fireball")
	 || !HealImage.LoadImage("heal")
	 || !Explosion.LoadImage("explosion"))
		return false;
	// 产生图像
	CClientDC	dc(Parent);
	if (!PopupImage.Create(dc, PopupImageBase.Width(), PopupImageBase.Height()))
		return false;

	// 设定sprite
	CursorSprite.Set(&Cursor, CPoint(0, 0), CSize(MAPGRID_WIDTH, MAPGRID_HEIGHT), CMapSprite::DEPTH_CURSOR);

	{
		for (int i=0; i<MAX_COMMAND; i++) {
			CommandSprite[i].Set(&Command, CPoint(0, 0), CPoint(0, i * 22), CSize(70, 22), 0);
			CommandSprite[i].Show(false);
		}
	}
	TurnEndSprite.Set(&TurnEnd, CPoint(0, 0), CPoint(0, 0), CSize(70, 22), 0);
	PopupSprite.Set(&PopupImage, CPoint(0, 0), CPoint(0, 0), PopupImage.Size(), 0);

	// 人物的状态
	int total_width = StatusBase.Width() * MAX_CHARACTER + 3 * (MAX_CHARACTER - 1);
	int x = (WindowWidth - total_width) / 2;
	int y = WindowHeight - StatusBase.Height() - 10;
	{
		for (int i=0; i<MAX_CHARACTER; i++) {
			if (!Status[i].Create(dc, StatusBase.Width(), StatusBase.Height()))
				return false;
			StatusSprite[i].Set(Status + i, CPoint(x, y), CPoint(0, 0), StatusBase.Size(), 0);
			x += StatusBase.Width() + 3;
			SetPlayerStatus(i);
		}
	}

	CursorPos.x = -1;
	CursorPos.y = -1;
	SelPos.x = -1;
	SelPos.y = -1;
	SelChar = 0;
	status = STATUS_WAIT_START;
	turn = PLAYER_TURN;
	NumberView = 0;

	StatusChar = 0;

	DrawMap(MixedImage);

	Parent->WipeIn();

	return true;
}

//
// 产生地图画面
//
void CBattleAction::DrawMap(CImage *image, const CRect &rect)
{
	// 若地图有背景,则显示之
	if (MapImage.IsOK()) {
		image->Copy(&MapImage, rect);
	}
	// 显示sprite
	for (mapset::iterator p = sprite.begin(); p != sprite.end(); p++) {
		(*p)->Draw(image, rect);
	}
	// 显示角色的状态
	for (int i=0; i<MAX_CHARACTER; i++) {
		StatusSprite[i].Draw(image, rect);
	}
	// 显示光标位置的状态
	if (StatusChar != 0) {
		PopupSprite.Draw(image, rect);
	}
	// 照编号显示贴图零件(sprite)
	for (int j=0; j<NumberView; j++)
		Number[j].Draw(image, rect);

	// 显示菜单
	switch (status) {
	  case STATUS_COMMAND:
		{
			for (int i=0; i<MAX_COMMAND; i++) {
				if (CommandSprite[i].IsShow())
					CommandSprite[i].Draw(image, rect);
			}
		}
		break;

	  case STATUS_NEXTTURN:
		TurnEndSprite.Draw(image, rect);
		break;
	}
}

//
// 显示地图(整个地图)
//
void CBattleAction::DrawMap(CImage *image)
{
	DrawMap(image, CRect(0, 0, WindowWidth, WindowHeight));
}

//
// 建立人物状态的图像
//
void CBattleAction::SetPlayerStatus(int player)
{
	Status[player].Copy(&StatusBase);
	if (StatusCharacter[player] != 0) {
		CStatus &status = StatusCharacter[player]->status;
		CImageDC dc(Status + player);
		HFONT	oldFont = dc.SelectObject(hFont);
		dc.SetTextColor(WhitePixel);
		dc.SetBkMode(TRANSPARENT);

		char str[256];
		dc.ExtTextOut(10, 4, 0, 0, status.name, strlen(status.name), NULL);
		dc.ExtTextOut(10, 22, 0, 0, str, sprintf(str, "等级   %7d", status.level), NULL);
		dc.ExtTextOut(10, 40, 0, 0, str, sprintf(str, "经验值  %7d", status.experience), NULL);
		dc.ExtTextOut(10, 58, 0, 0, str, sprintf(str, "HP值  %3d/%3d", status.hit_point, status.max_hit_point), NULL);
		dc.ExtTextOut(10, 76, 0, 0, str, sprintf(str, "MP值  %3d/%3d", status.magic_point, status.max_magic_point), NULL);
		dc.SelectObject(oldFont);
	}
}

//
// 显示角色的状态
//
void CBattleAction::ChangePlayerStatus(CCharacter *ch)
{
	for (int i=0; i<MAX_CHARACTER; i++) {
		if (StatusCharacter[i] == ch) {
			SetPlayerStatus(i);
			RedrawSprite(StatusSprite + i);
		}
	}
}

//
// 显示突现式状态说明
//
void CBattleAction::ChangeStatus(CPoint point)
{
	if (MapRect.PtInRect(point) && map_data[point.y][point.x].type & (PLAYER | ENEMY)) {
		if (StatusChar != (CCharacter *)map_data[point.y][point.x].sprite) {
			StatusChar = 0;

			RedrawSprite(&PopupSprite);		// 删除之前的显示
			StatusChar = (CCharacter *)map_data[point.y][point.x].sprite;
			CStatus &status = StatusChar->status;

			// 组合状态显示的零件
			PopupImage.Copy(&PopupImageBase);	// 复制原始图像
			PopupImage.DrawText(hFont, 1, 1, status.name, RGB(0, 0, 0));
			PopupImage.DrawText(hFont, 0, 0, status.name);

			int hp_len = status.hit_point * 76 / status.max_hit_point;
			int mp_len = status.magic_point * 76 / status.max_magic_point;
			PopupImage.Copy(&PopupParts, CRect(21, 17, 21 + hp_len, 20), CPoint(0, 20));
			PopupImage.Copy(&PopupParts, CRect(21, 32, 21 + mp_len, 35), CPoint(0, 23));

			char hp_str[4], mp_str[4], mhp_str[4], mmp_str[4];
			sprintf(hp_str, "%03d", status.hit_point);
			sprintf(mp_str, "%03d", status.magic_point);
			sprintf(mhp_str, "%03d", status.max_hit_point);
			sprintf(mmp_str, "%03d", status.max_magic_point);

			for (int i=0; i<3; i++) {
				PopupImage.Copy(&PopupParts, CRect(42 + i * 8, 21, 50 + i * 8, 31), CPoint((hp_str[i] - '0') * 8, 0));
				PopupImage.Copy(&PopupParts, CRect(74 + i * 8, 21, 82 + i * 8, 31), CPoint((mhp_str[i] - '0') * 8, 0));
				PopupImage.Copy(&PopupParts, CRect(42 + i * 8, 36, 50 + i * 8, 46), CPoint((mp_str[i] - '0') * 8, 10));
				PopupImage.Copy(&PopupParts, CRect(74 + i * 8, 36, 82 + i * 8, 46), CPoint((mmp_str[i] - '0') * 8, 10));
			}
			point = IndexToPoint(point);
			point.x += (MAPGRID_WIDTH - PopupImage.Width()) / 2;
			point.y -= 64;

			// 若不在范围内,则放在窗口内
			if (point.x < 0) {
				point.x = 0;
			}
			else if (point.x >= WindowWidth - PopupImage.Width()) {
				point.x = WindowWidth - PopupImage.Width();
			}
			if (point.y < 0) {
				point.y = 0;
			}

			PopupSprite.SetDrawPos(point);
			RedrawSprite(&PopupSprite);		// 显示
		}
	}
	else if (StatusChar != 0) {				// 有显示状态,但不在人物上
		StatusChar = 0;
		RedrawSprite(&PopupSprite);			// 删除之前的显示
	}
}

//
// 移动地图光标
//
void CBattleAction::SetCursor(CPoint point)
{
	if (CursorPos != point) {		// 若地图位置有更改
		ClearCursor();				// 则删除目前显示的光标
		CursorPos = point;			// 重新设定新的位置
		DrawCursor();				// 显示新的光标
		ChangeStatus(point);		// 变更角色的状态
	}
}

//
// 删除地图光标
//
void CBattleAction::ClearCursor()
{
	if (MapRect.PtInRect(CursorPos)) {
		RemoveSprite(&CursorSprite);
	}
	CursorPos.x = CursorPos.y = -1;
}

//
// 显示地图光标
//
void CBattleAction::DrawCursor()
{
	if (MapRect.PtInRect(CursorPos)) {
		CursorSprite.SetMapPoint(CursorPos);
		AddSprite(&CursorSprite);
	}
}

// 重新绘制sprite

void CBattleAction::RedrawSprite(CSprite *s)
{
	CRect	rect;
	s->GetRect(&rect);
	UpdateRect(rect);
}

// 新增sprite

void CBattleAction::AddSprite(CSprite *s)
{
	sprite.insert(s);
	RedrawSprite(s);
}

// 删除sprite

void CBattleAction::RemoveSprite(CSprite *s)
{
	if (sprite.erase(s)) {
		RedrawSprite(s);
	}

⌨️ 快捷键说明

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