From d98609063e24137c4c013492f65ae894700e9306 Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Fri, 5 Apr 2013 16:54:51 +0200 Subject: [PATCH] Added very basic AI that moves and attacks. --- source/Game.cpp | 6 +++--- source/World.cpp | 16 +++++++++------ source/abstract/Character.cpp | 29 +++++++++++++++++++++++---- source/abstract/Character.h | 11 +++++++++-- source/sprites/Enemy.cpp | 37 ++++++++++++++++++++++++++++++++--- source/sprites/Enemy.h | 6 +++++- source/sprites/Player.cpp | 7 ++++--- source/sprites/Player.h | 3 ++- source/util/Log.h | 2 ++ 9 files changed, 94 insertions(+), 23 deletions(-) diff --git a/source/Game.cpp b/source/Game.cpp index a646817..2a29632 100644 --- a/source/Game.cpp +++ b/source/Game.cpp @@ -51,10 +51,10 @@ Game::generate() { mTileManager.insertTile(TileManager::TilePosition(x, 4), TileManager::Type::WALL); } - mWorld.insertCharacter(std::shared_ptr(new Enemy(mWorld, - sf::Vector2f(400.0f, 200.0f), Yaml("enemy.yaml")))); + mWorld.insertCharacter(std::shared_ptr(new Enemy(mWorld, mTileManager, + sf::Vector2f(200.0f, 600.0f), Yaml("enemy.yaml")))); - mPlayer = std::shared_ptr(new Player(mWorld, + mPlayer = std::shared_ptr(new Player(mWorld, mTileManager, sf::Vector2f(200.0f, 100.0f), Yaml("player.yaml"))); mWorld.insertCharacter(mPlayer); diff --git a/source/World.cpp b/source/World.cpp index b85a378..cbd5934 100755 --- a/source/World.cpp +++ b/source/World.cpp @@ -35,8 +35,10 @@ void World::remove(std::shared_ptr drawable) { for (auto v = mDrawables.begin(); v != mDrawables.end(); v++) { auto item = std::find(v->second.begin(), v->second.end(), drawable); - if (item != v->second.end()) + if (item != v->second.end()) { v->second.erase(item); + break; + } } } @@ -297,11 +299,13 @@ World::step(int elapsed) { */ void World::think(int elapsed) { - for (auto it : mCharacters) { - if (it->getDelete()) - removeCharacter(it); - else - it->onThink(elapsed); + for (auto it = mCharacters.begin(); it != mCharacters.end(); ) { + if ((*it)->getDelete()) + removeCharacter(*it); + else { + (*it)->onThink(elapsed); + it++; + } } } diff --git a/source/abstract/Character.cpp b/source/abstract/Character.cpp index 5655583..7fe09bf 100644 --- a/source/abstract/Character.cpp +++ b/source/abstract/Character.cpp @@ -11,6 +11,7 @@ #include "../items/Weapon.h" #include "../sprites/Corpse.h" +#include "../sprites/TileManager.h" #include "../util/Log.h" #include "../util/Yaml.h" #include "../World.h" @@ -22,17 +23,21 @@ const float Character::DEFAULT_SPEED = 100; const float Character::POINT_REACHED_DISTANCE = 1.0f; const std::string Character::KEY_WEAPON = "weapon"; const std::string Character::DEFAULT_WEAPON = "weapon.yaml"; +const float Character::VISION_DISTANCE = 500.0f; /** * Saves pointer to this instance in static var for think(). */ -Character::Character(World& world, const Data& data, const Yaml& config) : +Character::Character(World& world, TileManager& tileManager, const Data& data, + const Yaml& config) : Sprite(data, config), mWorld(world), + mTileManager(tileManager), mMaxHealth(config.get(KEY_HEALTH, DEFAULT_HEALTH)), mCurrentHealth(mMaxHealth), mMovementSpeed(config.get(KEY_SPEED, DEFAULT_SPEED)), - mWeapon(new Weapon(world, *this, Yaml(config.get(KEY_WEAPON, DEFAULT_WEAPON)))) { + mWeapon(new Weapon(world, *this, + Yaml(config.get(KEY_WEAPON, DEFAULT_WEAPON)))) { } Character::~Character() { @@ -130,10 +135,26 @@ Character::move() { } } +/** + * Returns true if the character is currently moving. + */ +bool +Character::isMoving() const { + return !mPath.empty(); +} + +/** + * Tests if a target is visible from the current position. + */ +bool +Character::isVisible(const sf::Vector2f& target) const { + return mTileManager.raycast(getPosition(), target); +} + /** * Calls World::getCharacters with current position. */ std::vector > -Character::getCharacters(float maxDistance) const { - return mWorld.getCharacters(getPosition(), maxDistance); +Character::getCharacters() const { + return mWorld.getCharacters(getPosition(), VISION_DISTANCE); } diff --git a/source/abstract/Character.h b/source/abstract/Character.h index 633cc91..91f14ed 100644 --- a/source/abstract/Character.h +++ b/source/abstract/Character.h @@ -10,6 +10,7 @@ #include "Sprite.h" +class TileManager; class World; class Weapon; class Yaml; @@ -19,7 +20,8 @@ class Yaml; */ class Character : public Sprite { public: - explicit Character(World& world, const Data& data, const Yaml& config); + explicit Character(World& world, TileManager& tileManager, + const Data& data, const Yaml& config); virtual ~Character() = 0; void onDamage(int damage); @@ -32,7 +34,9 @@ protected: void releaseTrigger(); bool setDestination(const sf::Vector2f& destination); void move(); - std::vector > getCharacters(float maxDistance) const; + bool isMoving() const; + bool isVisible(const sf::Vector2f& target) const; + std::vector > getCharacters() const; private: static const std::string KEY_HEALTH; @@ -43,9 +47,12 @@ private: static const std::string DEFAULT_WEAPON; /// The distance to a point where it is considered reached (in pixels). static const float POINT_REACHED_DISTANCE; + /// Maximum distance where an enemy will be detected. + static const float VISION_DISTANCE; friend class World; World& mWorld; + TileManager& mTileManager; const int mMaxHealth; int mCurrentHealth; //< Current health. Between 0 and mMaxHealth. diff --git a/source/sprites/Enemy.cpp b/source/sprites/Enemy.cpp index 9a8b550..4852e16 100644 --- a/source/sprites/Enemy.cpp +++ b/source/sprites/Enemy.cpp @@ -7,7 +7,38 @@ #include "Enemy.h" -Enemy::Enemy(World& world, const sf::Vector2f& position, - const Yaml& config) : - Character(world, Data(position, CATEGORY_ACTOR, MASK_ALL), config) { +#include + +Enemy::Enemy(World& world, TileManager& tileManager, + const sf::Vector2f& position, const Yaml& config) : + Character(world, tileManager, Data(position, CATEGORY_ACTOR, MASK_ALL), + config) { +} + +void +Enemy::onThink(int elapsed) { + Character::onThink(elapsed); + + auto characters = getCharacters(); + std::shared_ptr target; + float distanceSquared = std::numeric_limits::max(); + for (auto it : characters) { + if (distanceSquared > thor::squaredLength(it->getPosition() - getPosition())) { + target = it; + distanceSquared = thor::squaredLength(it->getPosition() - getPosition()); + } + } + if (target) { + if (isVisible(target->getPosition())) { + setDestination(getPosition()); + setDirection(target->getPosition() - getPosition()); + pullTrigger(); + } + else if (isMoving()) + move(); + else + setDestination(target->getPosition()); + } + else + releaseTrigger(); } diff --git a/source/sprites/Enemy.h b/source/sprites/Enemy.h index d61ed3d..a942165 100644 --- a/source/sprites/Enemy.h +++ b/source/sprites/Enemy.h @@ -15,7 +15,11 @@ class Yaml; class Enemy : public Character { public: - explicit Enemy(World& world, const sf::Vector2f& position, const Yaml& config); + explicit Enemy(World& world, TileManager& tileManager, + const sf::Vector2f& position, const Yaml& config); + +protected: + virtual void onThink(int elapsed); }; #endif /* DG_ENEMY_H_ */ diff --git a/source/sprites/Player.cpp b/source/sprites/Player.cpp index cbfcf4a..350eb7d 100644 --- a/source/sprites/Player.cpp +++ b/source/sprites/Player.cpp @@ -12,9 +12,10 @@ /** * Initializes Sprite. */ -Player::Player(World& world, const sf::Vector2f& position, - const Yaml& config) : - Character(world, Data(position, CATEGORY_ACTOR, MASK_ALL), config), +Player::Player(World& world, TileManager& tileManager, + const sf::Vector2f& position, const Yaml& config) : + Character(world, tileManager, Data(position, CATEGORY_ACTOR, MASK_ALL), + config), mDirection(0) { } diff --git a/source/sprites/Player.h b/source/sprites/Player.h index fb5e632..1eea09c 100644 --- a/source/sprites/Player.h +++ b/source/sprites/Player.h @@ -29,7 +29,8 @@ public: }; public: - explicit Player(World& world, const sf::Vector2f& position, const Yaml& config); + explicit Player(World& world, TileManager& tileManager, + const sf::Vector2f& position, const Yaml& config); void setCrosshairPosition(const sf::Vector2f& position); void pullTrigger(); diff --git a/source/util/Log.h b/source/util/Log.h index f4d00bf..f364eea 100644 --- a/source/util/Log.h +++ b/source/util/Log.h @@ -8,6 +8,8 @@ #ifndef DG_LOG_H_ #define DG_LOG_H_ +#include + /** * Logging functions for different levels. *