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

📄 battle.cpp

📁 RPG游戏的剧情部分源码。是Visual C++角色扮演游戏程序设计的第七章的源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
}

// 寻找移动范围

void CBattleAction::FindDist(int x, int y, int dist, bool first)
{
	if (!first) {
		AddDistCursor(x, y, dist, 0);
		map_data[y][x].type |= MOVEDIST;
		map_data[y][x].move_dist = dist;
	}
	if (dist == 0)
		return;
	if (y > MapRect.top && map_data[y - 1][x].ChkMove(dist))
		FindDist(x, y - 1, dist - 1, false);
	if (y < MapRect.bottom - 1 && map_data[y + 1][x].ChkMove(dist))
		FindDist(x, y + 1, dist - 1, false);
	if (x > MapRect.left && map_data[y][x - 1].ChkMove(dist))
		FindDist(x - 1, y, dist - 1, false);
	if (x < MapRect.right - 1 && map_data[y][x + 1].ChkMove(dist))
		FindDist(x + 1, y, dist - 1, false);
}

// 搜寻攻击范围

void CBattleAction::FindAttack(int x, int y, int dist, bool first)
{
	if (!first) {
		AddDistCursor(x, y, dist, 1);
		map_data[y][x].type |= ATTACKDIST;
		map_data[y][x].attack_dist = dist;
	}
	if (dist == 0)
		return;
	if (y > MapRect.top && map_data[y - 1][x].ChkAttack(dist))
		FindAttack(x, y - 1, dist - 1, false);
	if (y < MapRect.bottom - 1 && map_data[y + 1][x].ChkAttack(dist))
		FindAttack(x, y + 1, dist - 1, false);
	if (x > MapRect.left && map_data[y][x - 1].ChkAttack(dist))
		FindAttack(x - 1, y, dist - 1, false);
	if (x < MapRect.right - 1 && map_data[y][x + 1].ChkAttack(dist))
		FindAttack(x + 1, y, dist - 1, false);
}

// 显示范围

void CBattleAction::AddDistCursor(int x, int y, int dist, int type)
{
	// 已登录的部分
	if ((map_data[y][x].type & (MOVEDIST | ATTACKDIST)) != 0)
		return;

	cursor_list.push_back(CMapSprite(&Cursor, x, y, CSize(MAPGRID_WIDTH, MAPGRID_HEIGHT), 1));
	CMapSprite &s = cursor_list.back();
	s.SetSrcPos(0, 32 + type * 32);
	AddSprite(&s);
}

// 删除显示范围

void CBattleAction::ClearDistCursor()
{
	while (cursor_list.size()) {
		CMapSprite &cr = cursor_list.front();
		CPoint pos = cr.GetMapPoint();
		RemoveSprite(&cr);
		map_data[pos.y][pos.x].type &= ~(MOVEDIST | ATTACKDIST);
		map_data[pos.y][pos.x].move_dist = 0;
		map_data[pos.y][pos.x].attack_dist = 0;
		cursor_list.pop_front();
	}
}

// 人物移动

void CBattleAction::MovePlayer(CCharacter *character, CPoint point)
{
	CPoint pos = character->GetMapPoint();
	map_data[pos.y][pos.x].move_dist = character->status.move_dist;
	MoveCharacter(point.x, point.y, map_data[point.y][point.x].move_dist, character);

	map_data[pos.y][pos.x].type = NONE;
	map_data[pos.y][pos.x].sprite = 0;
	map_data[pos.y][pos.x].move_dist = 0;

	SetCursor(CPoint(-1, -1));
	ClearDistCursor();
	StartAnime();
}

// 登录人物的移动动画

void CBattleAction::MoveCharacter(int x, int y, int dist, CCharacter *character)
{
	if (map_data[y][x].sprite != character) {
		dist++;
		if (y > MapRect.top && map_data[y - 1][x].move_dist == dist) {
			MoveCharacter(x, y - 1, dist, character);
			anime.push_back(MoveAnime(character, CCharacter::DOWN));
		}
		else if (y < MapRect.bottom - 1 && map_data[y + 1][x].move_dist == dist) {
			MoveCharacter(x, y + 1, dist, character);
			anime.push_back(MoveAnime(character, CCharacter::UP));
		}
		else if (x > MapRect.left && map_data[y][x - 1].move_dist == dist) {
			MoveCharacter(x - 1, y, dist, character);
			anime.push_back(MoveAnime(character, CCharacter::RIGHT));
		}
		else if (x < MapRect.right - 1 && map_data[y][x + 1].move_dist == dist) {
			MoveCharacter(x + 1, y, dist, character);
			anime.push_back(MoveAnime(character, CCharacter::LEFT));
		}
	}
}

// 执行移动动画

void CBattleAction::StartAnime()
{
	if (anime.size()) {
		Parent->SetTimer(TIMER_MOVE_ID, TIMER_MOVE_TIME);
		status = STATUS_ANIME;
	}
	else {
		status = STATUS_NONE;
	}
}

// 变成轮到敌方

void CBattleAction::ChangeTurn(int _turn)
{
	status = STATUS_NONE;
	turn = _turn;
	switch (turn) {
	  case PLAYER_TURN:
		for_each(player_list.begin(), player_list.end(), mem_fun_ref(&CCharacter::ClearStatus));
		break;

	  case ENEMY_TURN:
		for_each(enemy_list.begin(), enemy_list.end(), mem_fun_ref(&CCharacter::ClearStatus));
		enemy_ptr = enemy_list.begin();
		break;
	}
}

// 显示命令菜单

CPoint CBattleAction::CommandIndex(int idx)
{
	// 移动
	switch (idx) {
	  case COMMAND_MOVE:		// 移动
		return CPoint(SelChar->move_done? 140: 0, 0);

	  case COMMAND_ATTACK:		// 直接攻击
		return CPoint(SelChar->attack_done? 140: 0, 22);

	  default:					// 魔法
		idx -= COMMAND_MAGIC_FIRST;
		if (SelChar->IsMagicOk(idx)) {
			return CPoint(SelChar->attack_done? 140: 0,
				SelChar->GetMagicParam(idx).id * 22 + 44);
		}
		return CPoint(-1, -1);
	}
}

void CBattleAction::ShowCommand(CPoint point)
{
	if (point.x > 320)
		point.x -= 70 + 24;
	else
		point.x += 24;

	status = STATUS_COMMAND;
	select = COMMAND_NO_SELECT;

	for (int i=0; i<MAX_COMMAND; i++) {
		CPoint src = CommandIndex(i);
		if (src.x >= 0) {
			CommandSprite[i].SetDrawPos(point.x, point.y);
			CommandSprite[i].SetSrcPos(src.x, src.y);
			CommandSprite[i].Show();
			RedrawSprite(CommandSprite + i);
			point.y += 23;
		}
	}
}

// 选择命令菜单--让它反白

void CBattleAction::HighlightCommand(int newsel, bool selection)
{
	if (newsel != COMMAND_NO_SELECT) {
		CSprite *sp = CommandSprite + newsel;
		sp->SetSrcPos(selection? 70: 0, sp->GetSrcPos().y);
		RedrawSprite(sp);
	}
}

void CBattleAction::HighlightCommand(CPoint point)
{
	int newsel = FindCommand(point);
	if (select != newsel) {
		HighlightCommand(select, false);
		select = newsel;
		HighlightCommand(select, true);
	}
}

// 删除命令菜单

void CBattleAction::HideCommand()
{
	for (int i=0; i<MAX_COMMAND; i++) {
		if (CommandSprite[i].IsShow()) {
			CommandSprite[i].Show(false);
			RedrawSprite(CommandSprite + i);
		}
	}
}

// 选择命令菜单

void CBattleAction::SelectCommand(CPoint point)
{
	int sel = FindCommand(point);
	switch (sel) {
	  case COMMAND_NO_SELECT:
		break;

	  case COMMAND_MOVE:
		HideCommand();
		status = STATUS_MOVE;
		FindDist(SelPos.x, SelPos.y, SelChar->status.move_dist);
		break;

	  case COMMAND_ATTACK:
		HideCommand();
		status = STATUS_ATTACK;
		FindAttack(SelPos.x, SelPos.y, SelChar->status.attack_dist);
		break;

	  default:
		HideCommand();
		magic_param = SelChar->GetMagicParam(sel - COMMAND_MAGIC_FIRST);
		if (magic_param.type == MAGIC_TYPE_SELF) {
			status = STATUS_MAGIC_PLAYER;
			FindAttack(SelPos.x, SelPos.y, magic_param.dist, false);
		}
		else {
			status = STATUS_MAGIC_ENEMY;
			FindAttack(SelPos.x, SelPos.y, magic_param.dist);
		}
		break;
	}
}

// 从命令菜单的位置开始搜寻

int CBattleAction::FindCommand(CPoint point)
{
	if (!SelChar->move_done && CommandSprite[COMMAND_MOVE].PtIn(point))
		return COMMAND_MOVE;

	if (!SelChar->attack_done) {
		for (int i=COMMAND_ATTACK; i<MAX_COMMAND; i++) {
			if (CommandSprite[i].PtIn(point))
				return i;
		}
	}
	return COMMAND_NO_SELECT;
}

// 显示 TURN END 菜单

void CBattleAction::ShowTurnEnd(CPoint point)
{
	if (point.x > 320)
		point.x -= 70 + 24;
	else
		point.x += 24;

	TurnEndSprite.SetDrawPos(point.x, point.y);
	TurnEndSprite.SetSrcPos(0, 0);
	status = STATUS_NEXTTURN;
	sel_turnend = false;
	RedrawSprite(&TurnEndSprite);
}

// 隐藏 TURN END 菜单

void CBattleAction::HideTurnEnd()
{
	RedrawSprite(&TurnEndSprite);
}

// 选取 TURN END 菜单

void CBattleAction::SelectTurnEnd(bool sel)
{
	if (sel_turnend != sel) {
		sel_turnend = sel;
		TurnEndSprite.SetSrcPos(sel? 70: 0, 0);
		RedrawSprite(&TurnEndSprite);
	}
}

// 攻击

void CBattleAction::Attack(CCharacter *from, CCharacter *to, bool player)
{
	// 删除光标
	SetCursor(CPoint(-1, -1));

	// 删除范围显示
	ClearDistCursor();
	CPoint pos = from->GetMapPoint();
	map_data[pos.y][pos.x].type &= ~ATTACKDIST;
	map_data[pos.y][pos.x].attack_dist = 0;

	CSize diff = from->GetMapPoint() - to->GetMapPoint();

	// 调整人物方向
	if (abs(diff.cx) > abs(diff.cy)) {
		if (diff.cx < 0) {
			from->SetDirection(CCharacter::RIGHT);
			to->SetDirection(CCharacter::LEFT);
		}
		else {
			from->SetDirection(CCharacter::LEFT);
			to->SetDirection(CCharacter::RIGHT);
		}
	}
	else {
		if (diff.cy < 0) {
			from->SetDirection(CCharacter::DOWN);
			to->SetDirection(CCharacter::UP);
		}
		else {
			from->SetDirection(CCharacter::UP);
			to->SetDirection(CCharacter::DOWN);
		}
	}
	RedrawSprite(from);
	RedrawSprite(to);

	// 攻击动画开始
	AttackFrom = from;
	AttackTo = to;
	AttackPlayerToEnemy = player;
	AttackAnimeCount = 0;

	status = STATUS_ANIME;
	Parent->SetTimer(TIMER_ATTACK_ID, TIMER_ATTACK_TIME);
}

// 攻击阶段2

void CBattleAction::AttackPhase2()
{
	// 判断攻击
	// debug用,追踪变量
	TRACE("攻方参数:[%s]\n", AttackFrom->status.name);
	TRACE(" 攻击力 : %4d\n", AttackFrom->status.attack_power);
	TRACE(" 防御力 : %4d\n", AttackFrom->status.defence_power);
	TRACE(" 剩余HP : %4d\n", AttackFrom->status.hit_point);
	TRACE("守方参数:[%s]\n", AttackTo->status.name);
	TRACE(" 攻击力 : %4d\n", AttackTo->status.attack_power);
	TRACE(" 防御力 : %4d\n", AttackTo->status.defence_power);
	TRACE(" 剩余HP : %4d\n", AttackTo->status.hit_point);

	// 这个方法只用来计算而已,并没有使用乱数。
	// 破坏力 = 攻方攻击力 * 攻方攻击力 / 守方攻击力
	int ap = AttackFrom->status.attack_power;
	int dp = AttackTo->status.defence_power == 0? 1: AttackTo->status.defence_power;
	int attack = ap * ap / dp;
	if (attack <= 0)	// 最低1点就有破坏力
		attack = 1;

	// 显示破坏力
	char damage[8];
	NumberView = sprintf(damage, "%d", attack);
	CPoint view = AttackTo->GetDrawPos();
	view.x += (AttackTo->GetSize().cx - NumberView * 8) / 2;
	view.y -= 12;
	for (int i=0; i<NumberView; i++) {
		damage[i] -= '0';
		Number[i].Set(&PopupParts, view, CPoint(damage[i] * 8, 0), CSize(8, 10), 0);
		view.x += 8;
		RedrawSprite(Number + i);
	}

	if (attack > AttackTo->status.hit_point)
		attack = AttackTo->status.hit_point;

	TRACE(" 破坏力 : %4d\n", attack);

	AttackTo->status.hit_point -= attack;

	TRACE(" 剩余HP : %4d\n", AttackTo->status.hit_point);

	// 计算经验值
	// 每次攻击就有基本 10 point,若被打败倒地则+20 point
	// 如果有等级差距时
	// 攻方等级 > 守方等级  减低所获得的经验值
	// 攻方等级 < 守方等级  提高所获得的经验值
	int experience = 10;
	if (AttackTo->status.hit_point == 0)
		experience += 20;
	int level_diff = AttackFrom->status.level - AttackTo->status.level;
	if (level_diff > 0) {	// 攻击较弱的对手
		experience >>= level_diff;
	}
	else if (level_diff) {
		experience <<= -level_diff;
	}

	TRACE(" 经验值 = %d + %d = %d\n",
		AttackFrom->status.experience, experience,
		AttackFrom->status.experience + experience);

	AttackFrom->status.experience += experience;

	// 破坏力的显示开始
	AttackAnimeCount = 0;
	status = STATUS_ANIME;
	Parent->SetTimer(TIMER_NUMBER_ID, TIMER_NUMBER_TIME);
}

// 攻击阶段3

void CBattleAction::AttackPhase3()
{
	// 最后处理
	status = STATUS_NONE;

	// 更改游戏者状态的显示
	ChangePlayerStatus(AttackFrom);
	ChangePlayerStatus(AttackTo);

	// 阵亡判断
	if (AttackTo->status.hit_point == 0) {	// 已无HP = 阵亡
		TRACE(" > Killed\n");

		CPoint po = AttackTo->GetMapPoint();
		map_data[po.y][po.x].sprite = 0;
		map_data[po.y][po.x].type &= ~(PLAYER | ENEMY | OBJECT);
		RemoveSprite(AttackTo);		// 从sprite清单中删除

		//
		// 判断战斗结束
		//
		// 这里的结束条件是有一方全军覆没,
		// 因此当有人物阵亡时即须判断。
		//
		if (turn == PLAYER_TURN) {
			list<CCharacter>::iterator p = find(enemy_list.begin(), enemy_list.end(), *AttackTo);
			if (&*p != AttackTo) {
				TRACE("error\n");

⌨️ 快捷键说明

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