X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fcreature%2Fcreature.cpp;h=ff3a81c06c050b3a8013f5ddc6d44e06ef63696a;hb=refs%2Fheads%2Fmaster;hp=0a8b460c09e8b568af1e138ae7ae962386fc98ca;hpb=ae4f59520574caf5054d4a19cd76fa86c4a97264;p=blobs.git diff --git a/src/creature/creature.cpp b/src/creature/creature.cpp index 0a8b460..ff3a81c 100644 --- a/src/creature/creature.cpp +++ b/src/creature/creature.cpp @@ -11,6 +11,7 @@ #include "Goal.hpp" #include "IdleGoal.hpp" #include "../app/Assets.hpp" +#include "../graphics/color.hpp" #include "../math/const.hpp" #include "../ui/string.hpp" #include "../world/Body.hpp" @@ -20,12 +21,16 @@ #include #include +#include #include #include #include #include +using blobs::graphics::hsl2rgb; +using blobs::graphics::rgb2hsl; + namespace blobs { namespace creature { @@ -182,17 +187,17 @@ void Creature::Ingest(int res, double amount) noexcept { // 30% of solids stays in body AddMass(res, amount * 0.3 * composition.Compatibility(res)); } else { - // 5% of fluids stays in body - AddMass(res, amount * 0.05 * composition.Compatibility(res)); + // 10% of fluids stays in body + AddMass(res, amount * 0.1 * composition.Compatibility(res)); } math::GaloisLFSR &random = sim.Assets().random; if (random.UNorm() < AdaptChance()) { // change color to be slightly more like resource glm::dvec3 color(rgb2hsl(sim.Resources()[res].base_color)); // solids affect base color, others highlight - double p = sim.Resources()[res].state == world::Resource::SOLID ? 0 : 1; - double q = random.UInt(3); // hue, sat, or val - double r = random.UInt(2); // mean or deviation + int p = sim.Resources()[res].state == world::Resource::SOLID ? 0 : 1; + int q = random.UInt(3); // hue, sat, or val + int r = random.UInt(2); // mean or deviation math::Distribution *d = nullptr; double ref = 0.0; if (p == 0) { @@ -236,6 +241,20 @@ void Creature::Ingest(int res, double amount) noexcept { d->StandardDeviation(glm::clamp(d->StandardDeviation() * (1.0 + random.SNorm() * 0.15), 0.0001, 0.5)); } } + if (sim.Resources()[res].state == world::Resource::LIQUID && random.UNorm() < AdaptChance()) { + // change texture randomly + // TODO: make change depending on surroundings and/or resource + int p = random.UInt(2); // back or side + int q = random.UInt(2); // mean or deviation + math::Distribution &d = p ? genome.skin_side : genome.skin_back; + if (q == 0) { + // move ± one standard deviation + d.Mean(d.Mean() + (random.SNorm() * d.StandardDeviation())); + } else { + // scale by ±10%, enforce bounds + d.StandardDeviation(glm::clamp(d.StandardDeviation() * (1.0 + random.SNorm() * 0.1), 0.0001, 0.5)); + } + } } void Creature::DoWork(double amount) noexcept { @@ -631,7 +650,16 @@ void Creature::BuildVAO() { vao->ReserveAttributes(6 * 4, GL_STATIC_DRAW); { auto attrib = vao->MapAttributes(GL_WRITE_ONLY); - const float offset = 1.0f; + constexpr float offset = 1.0f; + constexpr float max_tex = 5.999f; + const float tex[6] = { + 0.0f, // face + float(std::floor(skin_side * max_tex)), // left + float(std::floor(skin_back * max_tex)), // top + float(std::floor(skin_back * max_tex)), // back + float(std::floor(skin_side * max_tex)), // right + 0.0f, // bottom + }; for (int surface = 0; surface < 6; ++surface) { const float tex_u_begin = surface < 3 ? 1.0f : 0.0f; const float tex_u_end = surface < 3 ? 0.0f : 1.0f; @@ -644,7 +672,7 @@ void Creature::BuildVAO() { attrib[4 * surface + 0].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; attrib[4 * surface + 0].texture.x = tex_u_begin; attrib[4 * surface + 0].texture.y = 1.0f; - attrib[4 * surface + 0].texture.z = surface; + attrib[4 * surface + 0].texture.z = tex[surface]; attrib[4 * surface + 1].position[(surface + 0) % 3] = -offset; attrib[4 * surface + 1].position[(surface + 1) % 3] = offset; @@ -654,7 +682,7 @@ void Creature::BuildVAO() { attrib[4 * surface + 1].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; attrib[4 * surface + 1].texture.x = tex_u_end; attrib[4 * surface + 1].texture.y = 1.0f; - attrib[4 * surface + 1].texture.z = surface; + attrib[4 * surface + 1].texture.z = tex[surface]; attrib[4 * surface + 2].position[(surface + 0) % 3] = offset; attrib[4 * surface + 2].position[(surface + 1) % 3] = -offset; @@ -664,7 +692,7 @@ void Creature::BuildVAO() { attrib[4 * surface + 2].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; attrib[4 * surface + 2].texture.x = tex_u_begin; attrib[4 * surface + 2].texture.y = 0.0f; - attrib[4 * surface + 2].texture.z = surface; + attrib[4 * surface + 2].texture.z = tex[surface]; attrib[4 * surface + 3].position[(surface + 0) % 3] = offset; attrib[4 * surface + 3].position[(surface + 1) % 3] = offset; @@ -674,7 +702,7 @@ void Creature::BuildVAO() { attrib[4 * surface + 3].normal[(surface + 2) % 3] = surface < 3 ? 1.0f : -1.0f; attrib[4 * surface + 3].texture.x = tex_u_end; attrib[4 * surface + 3].texture.y = 0.0f; - attrib[4 * surface + 3].texture.z = surface; + attrib[4 * surface + 3].texture.z = tex[surface]; } } vao->BindElements(); @@ -759,7 +787,7 @@ void Spawn(Creature &c, world::Planet &p) { double color_divisor = 0.0; if (p.HasAtmosphere()) { - c.AddMass(p.Atmosphere(), 0.01); + c.AddMass(p.Atmosphere(), 0.005); color_avg += c.GetSimulation().Resources()[p.Atmosphere()].base_color * 0.1; color_divisor += 0.1; } @@ -786,6 +814,9 @@ void Spawn(Creature &c, world::Planet &p) { genome.highlight_saturation = { 1.0 - hsl.y, 0.01 }; genome.highlight_lightness = { 1.0 - hsl.z, 0.01 }; + genome.skin_side = { 0.5, 0.01 }; + genome.skin_back = { 0.5, 0.01 }; + genome.Configure(c); } @@ -817,6 +848,8 @@ void Genome::Configure(Creature &c) const { ); c.BaseColor(hsl2rgb(base_color)); c.HighlightColor(hsl2rgb(highlight_color)); + c.BackSkin(glm::clamp(skin_back.FakeNormal(random.SNorm()), 0.0, 1.0)); + c.SideSkin(glm::clamp(skin_side.FakeNormal(random.SNorm()), 0.0, 1.0)); c.SetBackgroundTask(std::unique_ptr(new BlobBackgroundTask(c))); c.AddGoal(std::unique_ptr(new IdleGoal(c))); } @@ -829,7 +862,10 @@ void Split(Creature &c) { a->Name(c.GetSimulation().Assets().name.Sequential()); c.GetGenome().Configure(*a); for (const auto &cmp : c.GetComposition()) { - a->AddMass(cmp.resource, cmp.value * 0.5); + // require at least 0.1% + if (cmp.value > 0.002) { + a->AddMass(cmp.resource, cmp.value * 0.5); + } } s.GetPlanet().AddCreature(a); // TODO: duplicate situation somehow @@ -844,7 +880,10 @@ void Split(Creature &c) { b->Name(c.GetSimulation().Assets().name.Sequential()); c.GetGenome().Configure(*b); for (const auto &cmp : c.GetComposition()) { - b->AddMass(cmp.resource, cmp.value * 0.5); + // require at least 0.1% + if (cmp.value > 0.002) { + b->AddMass(cmp.resource, cmp.value * 0.5); + } } s.GetPlanet().AddCreature(b); b->GetSituation().SetPlanetSurface(