#include #include "Ai.h" #include "Actor.h" #include "Engine.h" #include "Map.h" #include "Destructible.h" #include "Attacker.h" #include "Gui.h" void PlayerAi::update(Actor* owner) { SDL_Event event; int dx = 0, dy = 0; if (owner->destructible && owner->destructible->isDead()) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_EVENT_QUIT: engine->gameStatus = Engine::QUIT; break; default: break; } } return; } while (SDL_PollEvent(&event)) { engine->context->convert_event_coordinates(event); switch (event.type) { case SDL_EVENT_MOUSE_MOTION: engine->mouse.cx = event.motion.x; engine->mouse.cy = event.motion.y; break; case SDL_EVENT_KEY_DOWN: switch (event.key.key) { case SDLK_UP: dy = -1; break; case SDLK_DOWN: dy = 1; break; case SDLK_LEFT: dx = -1; break; case SDLK_RIGHT: dx = 1; break; default: break; } break; case SDL_EVENT_QUIT: engine->gameStatus = Engine::QUIT; break; default: break; } if (dx != 0 || dy != 0) { engine->gameStatus = Engine::NEW_TURN; if (moveOrAttack(owner, owner->x + dx, owner->y + dy)) { engine->map->computeFov(); } } } } bool PlayerAi::moveOrAttack(Actor* owner, int targetx, int targety) { if (engine->map->isWall(targetx, targety)) return false; // look for living actors to attack for (Actor** iterator = engine->actors.begin(); iterator != engine->actors.end(); iterator++) { Actor* actor = *iterator; if (actor->destructible && !actor->destructible->isDead() && actor->x == targetx && actor->y == targety) { owner->attacker->attack(owner, actor); return false; } } for (Actor** iterator = engine->actors.begin(); iterator != engine->actors.end(); iterator++) { Actor* actor = *iterator; if (actor->destructible && actor->destructible->isDead() && actor->x == targetx && actor->y == targety) { engine->gui->message(TCOD_ColorRGB(150,150,150), "There's a %s here\n", actor->name.c_str()); } } owner->x = targetx; owner->y = targety; return true; } static const int TRACKING_TURNS = 3; void MonsterAi::update(Actor* owner) { if (owner->destructible && owner->destructible->isDead()) { return; } if (engine->map->isInFov(owner->x, owner->y)) { // we can see the player. move towards him moveCount = TRACKING_TURNS; } else { moveCount--; } if (moveCount > 0) { // we can see the player. move towards him moveOrAttack(owner, engine->player->x, engine->player->y); } } void MonsterAi::moveOrAttack(Actor* owner, int targetx, int targety) { int dx = targetx - owner->x; int dy = targety - owner->y; int stepdx = (dx > 0 ? 1 : -1); int stepdy = (dy > 0 ? 1 : -1); float distance = sqrtf((float)dx * (float)dx + (float)dy * (float)dy); if (distance >= 2) { dx = (int)(round(dx / distance)); dy = (int)(round(dy / distance)); if (engine->map->canWalk(owner->x + dx, owner->y + dy)) { owner->x += dx; owner->y += dy; } else if (engine->map->canWalk(owner->x + stepdx, owner->y)) { owner->x += stepdx; } else if (engine->map->canWalk(owner->x, owner->y + stepdy)) { owner->y += stepdy; } } else if (owner->attacker) { owner->attacker->attack(owner, engine->player); } }