Added very basic AI that moves and attacks.

This commit is contained in:
Felix Ableitner 2013-04-05 16:54:51 +02:00
parent 5f7c2a8ee4
commit d98609063e
9 changed files with 94 additions and 23 deletions

View file

@ -51,10 +51,10 @@ Game::generate() {
mTileManager.insertTile(TileManager::TilePosition(x, 4), TileManager::Type::WALL);
}
mWorld.insertCharacter(std::shared_ptr<Character>(new Enemy(mWorld,
sf::Vector2f(400.0f, 200.0f), Yaml("enemy.yaml"))));
mWorld.insertCharacter(std::shared_ptr<Character>(new Enemy(mWorld, mTileManager,
sf::Vector2f(200.0f, 600.0f), Yaml("enemy.yaml"))));
mPlayer = std::shared_ptr<Player>(new Player(mWorld,
mPlayer = std::shared_ptr<Player>(new Player(mWorld, mTileManager,
sf::Vector2f(200.0f, 100.0f), Yaml("player.yaml")));
mWorld.insertCharacter(mPlayer);

View file

@ -35,8 +35,10 @@ void
World::remove(std::shared_ptr<Sprite> 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++;
}
}
}

View file

@ -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<std::shared_ptr<Character> >
Character::getCharacters(float maxDistance) const {
return mWorld.getCharacters(getPosition(), maxDistance);
Character::getCharacters() const {
return mWorld.getCharacters(getPosition(), VISION_DISTANCE);
}

View file

@ -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<std::shared_ptr<Character> > getCharacters(float maxDistance) const;
bool isMoving() const;
bool isVisible(const sf::Vector2f& target) const;
std::vector<std::shared_ptr<Character> > 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.

View file

@ -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 <Thor/Vectors.hpp>
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<Character> target;
float distanceSquared = std::numeric_limits<float>::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();
}

View file

@ -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_ */

View file

@ -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) {
}

View file

@ -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();

View file

@ -8,6 +8,8 @@
#ifndef DG_LOG_H_
#define DG_LOG_H_
#include <iostream>
/**
* Logging functions for different levels.
*