📄 battle.cpp
字号:
}
// 寻找移动范围
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 + -