]> git.localhorst.tv Git - blank.git/blob - src/ai/ai.cpp
use "forces" for entity control and RK4 integrator
[blank.git] / src / ai / ai.cpp
1 #include "Chaser.hpp"
2 #include "Controller.hpp"
3 #include "RandomWalk.hpp"
4
5 #include "../model/geometry.hpp"
6 #include "../world/Entity.hpp"
7 #include "../world/World.hpp"
8 #include "../world/WorldCollision.hpp"
9
10 #include <glm/glm.hpp>
11
12
13 namespace blank {
14
15 Chaser::Chaser(World &world, Entity &ctrl, Entity &tgt) noexcept
16 : Controller(ctrl)
17 , world(world)
18 , tgt(tgt)
19 , chase_speed(0.002f)
20 , flee_speed(-0.005f)
21 , stop_dist(10)
22 , flee_dist(5) {
23         tgt.Ref();
24 }
25
26 Chaser::~Chaser() {
27         tgt.UnRef();
28 }
29
30 void Chaser::Update(int dt) {
31         if (Target().Dead()) {
32                 Controlled().Kill();
33                 return;
34         }
35
36         glm::vec3 diff(Target().AbsoluteDifference(Controlled()));
37         float dist = length(diff);
38         if (dist < std::numeric_limits<float>::epsilon()) {
39                 Controlled().TargetVelocity(glm::vec3(0.0f));
40                 return;
41         }
42         glm::vec3 norm_diff(diff / dist);
43
44         bool line_of_sight = true;
45         Ray aim{Target().Position() - diff, norm_diff};
46         WorldCollision coll;
47         if (world.Intersection(aim, glm::mat4(1.0f), Target().ChunkCoords(), coll)) {
48                 line_of_sight = coll.depth > dist;
49         }
50
51         if (!line_of_sight) {
52                 Controlled().TargetVelocity(glm::vec3(0.0f));
53         } else if (dist > stop_dist) {
54                 Controlled().TargetVelocity(norm_diff * chase_speed);
55         } else if (dist < flee_dist) {
56                 Controlled().TargetVelocity(norm_diff * flee_speed);
57         } else {
58                 Controlled().TargetVelocity(glm::vec3(0.0f));
59         }
60 }
61
62
63 Controller::Controller(Entity &e) noexcept
64 : entity(e) {
65         entity.Ref();
66 }
67
68 Controller::~Controller() {
69         entity.UnRef();
70 }
71
72
73 RandomWalk::RandomWalk(Entity &e, std::uint64_t seed) noexcept
74 : Controller(e)
75 , random(seed)
76 , start_vel(e.Velocity())
77 , target_vel(start_vel)
78 , start_rot(e.AngularVelocity())
79 , target_rot(start_rot)
80 , switch_time(0)
81 , lerp_max(1.0f)
82 , lerp_time(0.0f) {
83
84 }
85
86 RandomWalk::~RandomWalk() {
87
88 }
89
90 void RandomWalk::Update(int dt) {
91         switch_time -= dt;
92         lerp_time -= dt;
93         if (switch_time < 0) {
94                 switch_time += 2500 + (random.Next<unsigned short>() % 5000);
95                 lerp_max = 1500 + (random.Next<unsigned short>() % 1000);
96                 lerp_time = lerp_max;
97                 Change();
98         } else if (lerp_time > 0) {
99                 float a = std::min(lerp_time / lerp_max, 1.0f);
100                 Controlled().TargetVelocity(mix(target_vel, start_vel, a));
101                 Controlled().AngularVelocity(mix(target_rot, start_rot, a));
102         } else {
103                 Controlled().TargetVelocity(target_vel);
104                 Controlled().AngularVelocity(target_rot);
105         }
106 }
107
108 void RandomWalk::Change() noexcept {
109         start_vel = target_vel;
110         start_rot = target_rot;
111
112         constexpr float base = 0.000001f;
113
114         target_vel.x = base * (random.Next<short>() % 1024);
115         target_vel.y = base * (random.Next<short>() % 1024);
116         target_vel.z = base * (random.Next<short>() % 1024);
117
118         target_rot.x = base * (random.Next<short>() % 1024);
119         target_rot.y = base * (random.Next<short>() % 1024);
120         target_rot.z = base * (random.Next<short>() % 1024);
121 }
122
123 }