--- /dev/null
+#ifndef BLANK_AI_CHASER_HPP_
+#define BLANK_AI_CHASER_HPP_
+
+#include "Controller.hpp"
+
+
+namespace blank {
+
+class Chaser
+: public Controller {
+
+public:
+ Chaser(Entity &ctrl, Entity &tgt) noexcept;
+ ~Chaser();
+
+ Entity &Target() noexcept { return tgt; }
+ const Entity &Target() const noexcept { return tgt; }
+
+ void Update(int dt) override;
+
+private:
+ Entity &tgt;
+ float speed;
+ float stop_dist;
+ float flee_dist;
+
+};
+
+}
+
+#endif
--- /dev/null
+#ifndef BLANK_AI_CONTROLLER_HPP_
+#define BLANK_AI_CONTROLLER_HPP_
+
+
+namespace blank {
+
+class Entity;
+
+class Controller {
+
+public:
+ explicit Controller(Entity &e) noexcept;
+ virtual ~Controller();
+
+ Entity &Controlled() noexcept { return entity; }
+ const Entity &Controlled() const noexcept { return entity; }
+
+ virtual void Update(int dt) = 0;
+
+private:
+ Entity &entity;
+
+};
+
+}
+
+#endif
+++ /dev/null
-#include "RandomWalk.hpp"
-
-#include "../world/Entity.hpp"
-
-
-namespace blank {
-
-RandomWalk::RandomWalk(Entity &e) noexcept
-: entity(e)
-, time_left(0) {
-
-}
-
-
-void RandomWalk::Update(int dt) noexcept {
- time_left -= dt;
- if (time_left > 0) return;
- time_left += 2500 + (rand() % 5000);
-
- constexpr float move_vel = 0.0005f;
-
- glm::vec3 new_vel = entity.Velocity();
-
- switch (rand() % 9) {
- case 0:
- new_vel.x = -move_vel;
- break;
- case 1:
- new_vel.x = 0.0f;
- break;
- case 2:
- new_vel.x = move_vel;
- break;
- case 3:
- new_vel.y = -move_vel;
- break;
- case 4:
- new_vel.y = 0.0f;
- break;
- case 5:
- new_vel.y = move_vel;
- break;
- case 6:
- new_vel.z = -move_vel;
- break;
- case 7:
- new_vel.z = 0.0f;
- break;
- case 8:
- new_vel.z = move_vel;
- break;
- }
-
- entity.Velocity(new_vel);
-}
-
-}
-#ifndef BLANK_APP_RANDOMWALK_HPP_
-#define BLANK_APP_RANDOMWALK_HPP_
+#ifndef BLANK_AI_RANDOMWALK_HPP_
+#define BLANK_AI_RANDOMWALK_HPP_
-#include <glm/glm.hpp>
+#include "Controller.hpp"
namespace blank {
-class Entity;
-
/// Randomly start or stop moving in axis directions every now and then.
-class RandomWalk {
+class RandomWalk
+: public Controller {
public:
explicit RandomWalk(Entity &) noexcept;
+ ~RandomWalk();
- Entity &Controlled() noexcept { return entity; }
- const Entity &Controlled() const noexcept { return entity; }
-
- void Update(int dt) noexcept;
+ void Update(int dt) override;
private:
- Entity &entity;
-
int time_left;
};
#include "Spawner.hpp"
+#include "Chaser.hpp"
#include "RandomWalk.hpp"
#include "../world/BlockType.hpp"
#include "../world/BlockTypeRegistry.hpp"
}
Spawner::~Spawner() {
-
+ for (auto &ctrl : controllers) {
+ delete ctrl;
+ }
}
TrySpawn();
}
for (auto &ctrl : controllers) {
- ctrl.Update(dt);
+ ctrl->Update(dt);
}
}
void Spawner::CheckDespawn() noexcept {
const Entity &reference = world.Player();
for (auto iter = controllers.begin(), end = controllers.end(); iter != end;) {
- Entity &e = iter->Controlled();
+ Entity &e = (*iter)->Controlled();
glm::vec3 diff(reference.AbsoluteDifference(e));
if (dot(diff, diff) > despawn_range) {
e.Remove();
+ delete *iter;
iter = controllers.erase(iter);
} else {
++iter;
e.WorldCollidable(true);
e.SetShape(world.BlockTypes()[1].shape, color);
e.AngularVelocity(glm::quat(glm::vec3{ 0.00001f, 0.000006f, 0.000013f }));
- controllers.emplace_back(e);
+ Controller *ctrl;
+ if (rand() % 2) {
+ ctrl = new RandomWalk(e);
+ } else {
+ ctrl = new Chaser(e, world.Player());
+ }
+ controllers.emplace_back(ctrl);
}
}
#include "../app/IntervalTimer.hpp"
-#include <list>
+#include <vector>
#include <glm/glm.hpp>
namespace blank {
-class RandomWalk;
+class Controller;
class World;
class Spawner {
private:
World &world;
- std::list<RandomWalk> controllers;
+ std::vector<Controller *> controllers;
IntervalTimer timer;
float despawn_range;
--- /dev/null
+#include "Chaser.hpp"
+#include "Controller.hpp"
+#include "RandomWalk.hpp"
+
+#include "../world/Entity.hpp"
+
+#include <glm/glm.hpp>
+
+
+namespace blank {
+
+Chaser::Chaser(Entity &ctrl, Entity &tgt) noexcept
+: Controller(ctrl)
+, tgt(tgt)
+, speed(0.002f)
+, stop_dist(5 * 5)
+, flee_dist(3 * 3) {
+
+}
+
+Chaser::~Chaser() {
+
+}
+
+void Chaser::Update(int dt) {
+ glm::vec3 diff(Target().AbsoluteDifference(Controlled()));
+ float dist = dot (diff, diff);
+ // TODO: line of sight test
+ if (dist > stop_dist) {
+ Controlled().Velocity(normalize(diff) * speed);
+ } else if (dist < flee_dist) {
+ Controlled().Velocity(normalize(diff) * -speed);
+ } else {
+ Controlled().Velocity(glm::vec3(0.0f));
+ }
+}
+
+
+Controller::Controller(Entity &e) noexcept
+: entity(e) {
+
+}
+
+Controller::~Controller() {
+
+}
+
+
+RandomWalk::RandomWalk(Entity &e) noexcept
+: Controller(e)
+, time_left(0) {
+
+}
+
+RandomWalk::~RandomWalk() {
+
+}
+
+void RandomWalk::Update(int dt) {
+ time_left -= dt;
+ if (time_left > 0) return;
+ time_left += 2500 + (rand() % 5000);
+
+ constexpr float move_vel = 0.0005f;
+
+ glm::vec3 new_vel = Controlled().Velocity();
+
+ switch (rand() % 9) {
+ case 0:
+ new_vel.x = -move_vel;
+ break;
+ case 1:
+ new_vel.x = 0.0f;
+ break;
+ case 2:
+ new_vel.x = move_vel;
+ break;
+ case 3:
+ new_vel.y = -move_vel;
+ break;
+ case 4:
+ new_vel.y = 0.0f;
+ break;
+ case 5:
+ new_vel.y = move_vel;
+ break;
+ case 6:
+ new_vel.z = -move_vel;
+ break;
+ case 7:
+ new_vel.z = 0.0f;
+ break;
+ case 8:
+ new_vel.z = move_vel;
+ break;
+ }
+
+ Controlled().Velocity(new_vel);
+}
+
+}