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

📄 battle.cpp

📁 RPG游戏的剧情部分源码。是Visual C++角色扮演游戏程序设计的第七章的源码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
			}
			ASSERT(p != enemy_list.end());
			enemy_list.erase(p);
			if (enemy_list.empty()) {	// 全军覆没
				TRACE("战胜\n");
				BattleEnd(true);
			}
		}
		else {
			list<CCharacter>::iterator p = find(player_list.begin(), player_list.end(), *AttackTo);
			if (&*p != AttackTo) {
				TRACE("error\n");
			}
			ASSERT(p != player_list.end());
			player_list.erase(p);
			if (player_list.empty()) {	// 全军覆没
				TRACE("战败\n");
				BattleEnd(false);
			}
		}
	}
}

// 战斗结束

void CBattleAction::BattleEnd(bool iswin)
{
	// 所有动作都结束
	status = STATUS_BATTLE_END;

	// 把胜负结果存到变量中
	Parent->SetValue("battle", iswin? 1: 0);

 	//为了要移转到事件上,必须将目前所显示的内容储存在“背景”中
	BackLayer->Copy(ViewImage);
	Parent->Invalidate();

	// CBattleAction傪攋婞偡傞
	Parent->ScriptDone();
}

// 魔法

void CBattleAction::Magic(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;
	AttackAnimeState = 0;

	status = STATUS_ANIME;
	Parent->SetTimer(TIMER_MAGIC_ID, TIMER_MAGIC_TIME);
}

// 魔法动作(Heal)

bool CBattleAction::MagicHeal()
{
	switch (AttackAnimeState) {
	  case 0:		// 第1阶段  魔法发动
		if (AttackFrom->MagicAnime(AttackAnimeCount++)) {
			AttackAnimeCount = 0;
			AttackAnimeState++;

			MagicSprite[0].Set(&HealImage, CPoint(0, 0), CPoint(0, 0),
				CSize(HealImage.Width() / 7, HealImage.Height() / 2), 10);	// 前
			MagicSprite[1].Set(&HealImage, CPoint(0, 0), CPoint(0, HealImage.Height() / 2),
				CSize(HealImage.Width() / 7, HealImage.Height() / 2), -10);	// 后傠
			MagicSprite[0].SetMapPoint(AttackTo->GetMapPoint());
			MagicSprite[1].SetMapPoint(AttackTo->GetMapPoint());
			AddSprite(MagicSprite);
			AddSprite(MagicSprite + 1);
		}
		RedrawSprite(AttackFrom);
		break;

	  case 1:		// 第2阶段  效果发挥
		if (AttackAnimeCount < 7) {
			MagicSprite[0].SetSrcPos(
				MagicSprite[0].GetSize().cx * AttackAnimeCount,
				MagicSprite[0].GetSrcPos().y);
			MagicSprite[1].SetSrcPos(
				MagicSprite[1].GetSize().cx * AttackAnimeCount,
				MagicSprite[1].GetSrcPos().y);
			RedrawSprite(MagicSprite);
			RedrawSprite(MagicSprite + 1);
			AttackAnimeCount++;
		}
		else {
			AttackFrom->NormalStatus();
			RedrawSprite(AttackFrom);
			RemoveSprite(MagicSprite);
			RemoveSprite(MagicSprite + 1);
			HealPhase2();
			return true;
		}
	}
	return false;
}

// 第2阶段的魔法恢复/补血

void CBattleAction::HealPhase2()
{
	// 判断魔法
	// 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);

	TRACE("使用魔法 id    : %d\n", magic_param.id);
	TRACE("         type  : %d\n", magic_param.type);
	TRACE("         dist  : %d\n", magic_param.dist);
	TRACE("         power : %d\n", magic_param.power);
	TRACE("         use_mp: %d\n", magic_param.use_mp);

	// MP的消耗
	AttackFrom->status.magic_point -= magic_param.use_mp;

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

	AttackTo->status.hit_point += magic_param.power;
	if (AttackTo->status.hit_point > AttackTo->status.max_hit_point)
		AttackTo->status.hit_point = AttackTo->status.max_hit_point;

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

	// 经验值的计算
	AttackFrom->status.experience += 10;

	// 开始显示恢复量
	AttackAnimeCount = 0;
	status = STATUS_ANIME;
	Parent->SetTimer(TIMER_NUMBER_ID, TIMER_NUMBER_TIME);
}

// 魔法动作(FireBall)

bool CBattleAction::MagicFireBall()
{
	switch (AttackAnimeState) {
	  case 0:		//第1阶段  魔法发动
		if (AttackFrom->MagicAnime(AttackAnimeCount++)) {
			AttackAnimeCount = 0;
			AttackAnimeState++;

			MagicSprite[0].Set(&FireBallImage, AttackFrom->GetCenterPoint(),
				CPoint(0, 0), CSize(FireBallImage.Width(), FireBallImage.Height()), 100);
			MagicSprite[0].SetDrawPos(
				MagicSprite[0].GetDrawPos().x - MagicSprite[0].GetSize().cx / 2,
				MagicSprite[0].GetDrawPos().y - MagicSprite[0].GetSize().cy / 2);
			AddSprite(MagicSprite);
		}
		RedrawSprite(AttackFrom);
		break;

	  case 1:		// 第2阶段  火焰的移动
		{
			CPoint from = AttackFrom->GetCenterPoint();
			CPoint to = AttackTo->GetBottomPoint();
			CSize diff = from - to;
			int n = ((abs(diff.cx) > abs(diff.cy)? abs(diff.cx): abs(diff.cy)) + 31) / 32;
			RemoveSprite(MagicSprite);
			if (AttackAnimeCount <= n) {
				MagicSprite[0].SetDrawPos(
					from.x - diff.cx * AttackAnimeCount / n - MagicSprite[0].GetSize().cx / 2,
					from.y - diff.cy * AttackAnimeCount / n - MagicSprite[0].GetSize().cy / 2);
				AddSprite(MagicSprite);
				AttackAnimeCount++;
			}
			else {
				AttackAnimeCount = 0;
				AttackAnimeState++;
				MagicSprite[0].Set(&Explosion, CPoint(0, 0), CPoint(0, 0),
					CSize(Explosion.Width() / 11, Explosion.Height()), 10);
				MagicSprite[0].SetMapPoint(AttackTo->GetMapPoint());
				AddSprite(MagicSprite);
			}
		}
		break;

	  case 2:		// 第3阶段  爆炸
		if (AttackAnimeCount < 11) {
			MagicSprite[0].SetSrcPos(
				MagicSprite[0].GetSize().cx * AttackAnimeCount,
				MagicSprite[0].GetSrcPos().y);
			RedrawSprite(MagicSprite);
			AttackAnimeCount++;
		}
		else {
			AttackFrom->NormalStatus();
			RemoveSprite(MagicSprite);
			RedrawSprite(AttackFrom);
			FireBallPhase2();
			return true;
		}
	}
	return false;
}

// 第2阶段的攻击魔法

void CBattleAction::FireBallPhase2()
{
	// 判断魔法
	// 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);

	TRACE("使用魔法 id    : %d\n", magic_param.id);
	TRACE("         type  : %d\n", magic_param.type);
	TRACE("         dist  : %d\n", magic_param.dist);
	TRACE("         power : %d\n", magic_param.power);
	TRACE("         use_mp: %d\n", magic_param.use_mp);

	// MP的消耗
	AttackFrom->status.magic_point -= magic_param.use_mp;
	int ap = magic_param.power;
	int dp = AttackTo->status.resistance == 0? 1: AttackTo->status.resistance;
	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);
}

// 搜寻攻击范围(敌方移动使用)

void CBattleAction::FindAttackCalc(int x, int y, int dist)
{
	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))
		FindAttackCalc(x, y - 1, dist - 1);
	if (y < MapRect.bottom - 1 && map_data[y + 1][x].ChkAttack(dist))
		FindAttackCalc(x, y + 1, dist - 1);
	if (x > MapRect.left && map_data[y][x - 1].ChkAttack(dist))
		FindAttackCalc(x - 1, y, dist - 1);
	if (x < MapRect.right - 1 && map_data[y][x + 1].ChkAttack(dist))
		FindAttackCalc(x + 1, y, dist - 1);
}

// 敌军人物的移动

void CBattleAction::MoveEnemy()
{
	TRACE("[%s]的移动\n", enemy_ptr->status.name);
	enemy_ptr->move_done = true;			// 已移动
	attack_target = 0;						// 清除攻击对象

	CPoint mp = enemy_ptr->GetMapPoint();
	FindDist(mp.x, mp.y, enemy_ptr->status.move_dist);
	Parent->UpdateWindow();

	// 为了让后面的处理好做,让目前位置也包含到移动范围之内
	map_data[mp.y][mp.x].type |= MOVEDIST;

	int eval_point = INT_MIN;			// 评分点数
	CPoint move = mp;					// 移动位置

	for (list<CCharacter>::iterator p = player_list.begin(); p != player_list.end(); p++) {
		CPoint pos = p->GetMapPoint();
		FindAttackCalc(pos.x, pos.y, enemy_ptr->status.attack_dist);
		map_data[pos.y][pos.x].type &= ~ATTACKDIST;

		CRect rect(pos.x, pos.y, pos.x + 1, pos.y + 1);
		rect.InflateRect(enemy_ptr->status.attack_dist, enemy_ptr->status.attack_dist);
		rect &= MapRect;

		for (int y=rect.top; y<rect.bottom; y++) {
			for (int x=rect.left; x<rect.right; x++) {
				// 判断是否有可移动、可攻击的位置
				if (map_data[y][x].ChkType(ATTACKDIST | MOVEDIST)) {
					// 评分标准为:
					// 1. 移动距离越少越好
					// 2. 攻击距离越远越好
					// 3. 对方的HP越小越好
					// 4. 对方的攻击力越高越好
					// 依此原则计分
					int point = (enemy_ptr->status.attack_dist - map_data[y][x].attack_dist) * 20
						+ map_data[y][x].move_dist * 50
						- p->status.hit_point * 5
						+ p->status.attack_power;

					// 若得分较高,则更新
					if (eval_point < point) {
						eval_point = point;		// 新的得分
						attack_target = &*p;	// 设定攻击目标
						move.x = x;				// 新的移动位置
						move.y = y;
					}
				}
				// 清除作业区域
				map_data[y][x].attack_dist = 0;
				map_data[y][x].type &= ~ATTACKDIST;
			}
		}
	}

	if (attack_target == 0) {		// 无法移动到可攻击的位置
		CRect rect(mp.x, mp.y, mp.x + 1, mp.y + 1);
		rect.InflateRect(enemy_ptr->status.move_dist, enemy_ptr->status.move_dist);
		rect &= MapRect;

		eval_point = INT_MAX;		// 清除得分

		for (list<CCharacter>::iterator p = player_list.begin(); p != player_list.end(); p++) {
			CPoint pos = p->GetMapPoint();
			for (int y=rect.top; y<rect.bottom; y++) {
				for (int x=rect.left; x<rect.right; x++) {
					if (map_data[y][x].ChkType(MOVEDIST)) {
						int dist = abs(x - pos.x) + abs(y - pos.y);
						if (eval_point > dist) {
							eval_point = dist;
							move.x = x;
							move.y = y;
						}
					}
				}
			}
		}
	}

	// 清除目前位置中的移动范围旗标
	map_data[mp.y][mp.x].type &= ~MOVEDIST;

	::Sleep(70);				// 等待直到出现移动范围的显示

	if (mp == move) {			// 不移动
		ClearDistCursor();
	}
	else {
		MovePlayer(&*enemy_ptr, move);
	}
}

// 敌军人物的攻击

void CBattleAction::AttackEnemy()
{
	TRACE("[%s]的攻击\n", enemy_ptr->status.name);
	enemy_ptr->attack_done = true;	// 已攻击

	if (attack_target) {
		CPoint mp = enemy_ptr->GetMapPoint();
		FindAttack(mp.x, mp.y, enemy_ptr->status.attack_dist);
		Parent->UpdateWindow();
		Sleep(100);
		Attack(&*enemy_ptr, attack_target, false);
	}
}

⌨️ 快捷键说明

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