Added very basic AI that moves and attacks.
This commit is contained in:
parent
5f7c2a8ee4
commit
d98609063e
9 changed files with 94 additions and 23 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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) {
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#ifndef DG_LOG_H_
|
||||
#define DG_LOG_H_
|
||||
|
||||
#include <iostream>
|
||||
|
||||
/**
|
||||
* Logging functions for different levels.
|
||||
*
|
||||
|
|
Reference in a new issue