📄 battle.cpp
字号:
}
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 + -