1 #include "Creature.hpp"
2 #include "Situation.hpp"
4 #include "InhaleNeed.hpp"
5 #include "IngestNeed.hpp"
7 #include "../app/Assets.hpp"
8 #include "../world/Body.hpp"
9 #include "../world/Planet.hpp"
10 #include "../world/Simulation.hpp"
11 #include "../world/TileType.hpp"
13 #include <glm/gtx/transform.hpp>
29 Creature::~Creature() {
32 void Creature::Hurt(double dt) noexcept {
33 health = std::max(0.0, health - dt);
36 void Creature::Tick(double dt) {
38 for (auto &need : needs) {
41 // do background stuff
42 for (auto &need : needs) {
43 need->ApplyEffect(*this, dt);
47 glm::dmat4 Creature::LocalTransform() noexcept {
48 // TODO: surface transform
49 constexpr double half_height = 0.25;
50 const glm::dvec3 &pos = situation.Position();
51 return glm::translate(glm::dvec3(pos.x, pos.y, pos.z + situation.GetPlanet().Radius() + half_height))
52 * glm::scale(glm::dvec3(half_height, half_height, half_height));
55 void Creature::BuildVAO() {
58 vao.EnableAttribute(0);
59 vao.EnableAttribute(1);
60 vao.EnableAttribute(2);
61 vao.AttributePointer<glm::vec3>(0, false, offsetof(Attributes, position));
62 vao.AttributePointer<glm::vec3>(1, false, offsetof(Attributes, normal));
63 vao.AttributePointer<glm::vec3>(2, false, offsetof(Attributes, texture));
64 vao.ReserveAttributes(6 * 4, GL_STATIC_DRAW);
66 auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
67 const float offset = 1.0f;
68 for (int surface = 0; surface < 6; ++surface) {
69 const float tex_u_begin = surface < 3 ? 1.0f : 0.0f;
70 const float tex_u_end = surface < 3 ? 0.0f : 1.0f;
72 attrib[4 * surface + 0].position[(surface + 0) % 3] = -offset;
73 attrib[4 * surface + 0].position[(surface + 1) % 3] = -offset;
74 attrib[4 * surface + 0].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
75 attrib[4 * surface + 0].normal[(surface + 0) % 3] = 0.0f;
76 attrib[4 * surface + 0].normal[(surface + 1) % 3] = 0.0f;
77 attrib[4 * surface + 0].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f;
78 attrib[4 * surface + 0].texture.x = tex_u_begin;
79 attrib[4 * surface + 0].texture.y = 1.0f;
80 attrib[4 * surface + 0].texture.z = surface;
82 attrib[4 * surface + 1].position[(surface + 0) % 3] = -offset;
83 attrib[4 * surface + 1].position[(surface + 1) % 3] = offset;
84 attrib[4 * surface + 1].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
85 attrib[4 * surface + 1].normal[(surface + 0) % 3] = 0.0f;
86 attrib[4 * surface + 1].normal[(surface + 1) % 3] = 0.0f;
87 attrib[4 * surface + 1].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f;
88 attrib[4 * surface + 1].texture.x = tex_u_end;
89 attrib[4 * surface + 1].texture.y = 1.0f;
90 attrib[4 * surface + 1].texture.z = surface;
92 attrib[4 * surface + 2].position[(surface + 0) % 3] = offset;
93 attrib[4 * surface + 2].position[(surface + 1) % 3] = -offset;
94 attrib[4 * surface + 2].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
95 attrib[4 * surface + 2].normal[(surface + 0) % 3] = 0.0f;
96 attrib[4 * surface + 2].normal[(surface + 1) % 3] = 0.0f;
97 attrib[4 * surface + 2].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f;
98 attrib[4 * surface + 2].texture.x = tex_u_begin;
99 attrib[4 * surface + 2].texture.y = 0.0f;
100 attrib[4 * surface + 2].texture.z = surface;
102 attrib[4 * surface + 3].position[(surface + 0) % 3] = offset;
103 attrib[4 * surface + 3].position[(surface + 1) % 3] = offset;
104 attrib[4 * surface + 3].position[(surface + 2) % 3] = surface < 3 ? offset : -offset;
105 attrib[4 * surface + 3].normal[(surface + 0) % 3] = 0.0f;
106 attrib[4 * surface + 3].normal[(surface + 1) % 3] = 0.0f;
107 attrib[4 * surface + 3].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f;
108 attrib[4 * surface + 3].texture.x = tex_u_end;
109 attrib[4 * surface + 3].texture.y = 0.0f;
110 attrib[4 * surface + 3].texture.z = surface;
114 vao.ReserveElements(6 * 6, GL_STATIC_DRAW);
116 auto element = vao.MapElements(GL_WRITE_ONLY);
117 for (int surface = 0; surface < 3; ++surface) {
118 element[6 * surface + 0] = 4 * surface + 0;
119 element[6 * surface + 1] = 4 * surface + 2;
120 element[6 * surface + 2] = 4 * surface + 1;
121 element[6 * surface + 3] = 4 * surface + 1;
122 element[6 * surface + 4] = 4 * surface + 2;
123 element[6 * surface + 5] = 4 * surface + 3;
125 for (int surface = 3; surface < 6; ++surface) {
126 element[6 * surface + 0] = 4 * surface + 0;
127 element[6 * surface + 1] = 4 * surface + 1;
128 element[6 * surface + 2] = 4 * surface + 2;
129 element[6 * surface + 3] = 4 * surface + 2;
130 element[6 * surface + 4] = 4 * surface + 1;
131 element[6 * surface + 5] = 4 * surface + 3;
137 void Creature::Draw(app::Assets &assets, graphics::Viewport &viewport) {
139 vao.DrawTriangles(6 * 6);
143 void Spawn(Creature &c, world::Planet &p, app::Assets &assets) {
145 c.GetSituation().SetPlanetSurface(p, 0, glm::dvec3(0.0, 0.0, 0.0));
147 // probe surrounding area for common resources
148 int start = p.SideLength() / 2 - 2;
150 std::map<int, double> yields;
151 for (int y = start; y < end; ++y) {
152 for (int x = start; x < end; ++x) {
153 const world::TileType &t = assets.data.tile_types[p.TileAt(0, x, y).type];
154 for (auto yield : t.resources) {
155 yields[yield.resource] += yield.ubiquity;
161 for (auto e : yields) {
162 if (assets.data.resources[e.first].state == world::Resource::LIQUID) {
163 if (liquid < 0 || e.second > yields[liquid]) {
166 } else if (assets.data.resources[e.first].state == world::Resource::SOLID) {
167 if (solid < 0 || e.second > yields[solid]) {
173 if (p.HasAtmosphere()) {
174 std::cout << "require breathing " << assets.data.resources[p.Atmosphere()].label << std::endl;
175 std::unique_ptr<Need> need(new InhaleNeed(p.Atmosphere(), 0.5, 0.1));
176 need->name = assets.data.resources[p.Atmosphere()].label;
178 need->inconvenient = 0.4;
179 need->critical = 0.95;
180 c.AddNeed(std::move(need));
183 std::cout << "require drinking " << assets.data.resources[liquid].label << std::endl;
184 std::unique_ptr<Need> need(new IngestNeed(liquid, 0.2, 0.01));
185 need->name = assets.data.resources[liquid].label;
187 need->inconvenient = 0.6;
188 need->critical = 0.95;
189 c.AddNeed(std::move(need));
192 std::cout << "require eating " << assets.data.resources[solid].label << std::endl;
193 std::unique_ptr<Need> need(new IngestNeed(solid, 0.1, 0.001));
194 need->name = assets.data.resources[solid].label;
196 need->inconvenient = 0.6;
197 need->critical = 0.95;
198 c.AddNeed(std::move(need));
202 Situation::Situation()
209 Situation::~Situation() {
212 bool Situation::OnPlanet() const noexcept {
213 return type == PLANET_SURFACE;
216 bool Situation::OnSurface() const noexcept {
217 return type == PLANET_SURFACE;
220 world::Tile &Situation::GetTile() const noexcept {
221 double side_length = planet->SideLength();
222 double offset = side_length * 0.5;
223 double x = std::max(0.0, std::min(side_length, position.x + offset));
224 double y = std::max(0.0, std::min(side_length, position.y + offset));
225 return planet->TileAt(surface, int(x), int(y));
228 const world::TileType &Situation::GetTileType() const noexcept {
229 return planet->GetSimulation().TileTypes()[GetTile().type];
232 void Situation::SetPlanetSurface(world::Planet &p, int srf, const glm::dvec3 &pos) noexcept {
233 type = PLANET_SURFACE;