This commit is contained in:
Nikita Lisitsa 2024-08-18 23:38:44 +03:00
parent 52091cc52e
commit de3aefac44

View file

@ -10,6 +10,7 @@
#include <psemek/util/clock.hpp>
#include <psemek/geom/box.hpp>
#include <psemek/geom/camera.hpp>
#include <psemek/geom/contains.hpp>
#include <psemek/ecs/container.hpp>
#include <psemek/ecs/declare_uuid.hpp>
@ -74,28 +75,6 @@ namespace gmtk
resource_type output;
};
static util::hash_map<transformer_type, util::hash_map<resource_type, int>> const construction_recipe
{
{
transformer_type::furnace,
{
{resource_type::stone, 30},
},
},
{
transformer_type::factory,
{
{resource_type::stone_brick, 30},
},
},
};
static util::hash_map<resource_type, int> const zoomer_construction_recipe
{
{resource_type::iron_plate, 30},
{resource_type::copper_plate, 30},
};
static util::hash_map<transformer_type, std::vector<recipe>> const recipies
{
{
@ -205,14 +184,6 @@ namespace gmtk
resource_type type;
};
struct build_site
{
psemek_ecs_declare_uuid("build_site")
std::optional<transformer_type> type; // null means zoomer
util::hash_map<resource_type, int> resources = {};
};
struct transformer
{
psemek_ecs_declare_uuid("transformer")
@ -287,13 +258,11 @@ namespace gmtk
friend auto operator <=> (timestamp const & x, timestamp const & y) = default;
};
struct task
struct lab
{
psemek_ecs_declare_uuid("task")
psemek_ecs_declare_uuid("lab")
resource_type type;
int count = 0;
util::hash_map<resource_type, int> count = {};
};
struct map
@ -421,47 +390,6 @@ namespace gmtk
sink(world, c, m);
}
void generate_next_task(random::generator & rng, map & map)
{
resource_type type;
util::hash_set<resource_type> existing_tasks;
int task_count = 0;
map.world.apply<task const>([&](task const & task)
{
existing_tasks.insert(task.type);
task_count += 1;
});
while (true)
{
type = random::uniform_from(rng, resource_type_values());
if (task_count >= 3)
break;
if (!existing_tasks.contains(type))
break;
}
while (true)
{
int x = random::uniform(rng, 0, 2);
int y = random::uniform<bool>(rng) ? -1 : 3;
if (random::uniform<bool>(rng))
std::swap(x, y);
if (map.world.index<index>().find({0, {x, y}}))
continue;
map.world.create(
vertex{{0, {x, y}}},
task{type}
);
break;
}
}
map starting_map(random::generator & rng)
{
map result;
@ -475,7 +403,7 @@ namespace gmtk
);
result.world.create(
vertex{{0, {0, 3}}},
vertex{{0, {-1, 2}}},
source{resource_type::iron_ore}
);
@ -485,13 +413,13 @@ namespace gmtk
);
result.world.create(
vertex{{0, {2, 3}}},
vertex{{0, {3, 2}}},
source{resource_type::copper_ore}
);
result.world.create(
vertex{{0, {1, -1}}},
task{resource_type::red_science_pack}
lab{}
);
(void)rng;
@ -592,40 +520,27 @@ namespace gmtk
painter.triangle(p0, p2, p3, color);
};
map.world.apply<vertex const, build_site const>([&](vertex const & v, build_site const & t)
{
if (t.type)
draw_transformer(v.location, *t.type, true);
else
draw_grid(v.location, view_level, painter, true);
float vs = std::pow(3.f, - v.location.level) * 0.01f;
auto text_bbox = v.location.bbox(-0.4f);
auto pen = text_bbox.corner(0.5f, 1.f);
auto & recipe = t.type ? construction_recipe.at(*t.type) : zoomer_construction_recipe;
for (auto const & p : recipe)
{
int have = t.resources.contains(p.first) ? t.resources.at(p.first) : 0;
int need = p.second;
painter.text(pen, std::format("{}/{}", have, need), {.scale = {vs, -vs}, .c = color_of(p.first)});
pen[1] -= 12.f * vs;
}
});
map.world.apply<vertex const, transformer const>([&](vertex const & v, transformer const & t)
{
draw_transformer(v.location, t.type, false);
});
map.world.apply<vertex const, task const>([&](vertex const & v, task const & t)
map.world.apply<vertex const, lab const>([&](vertex const & v, lab const & l)
{
painter.rect(v.location.bbox(-0.2f), {128, 192, 255, 255});
auto pen = v.location.bbox(-0.4f).corner(0.5f, 1.f);
float vs = std::pow(3.f, - v.location.level) * 0.01f;
painter.rect(v.location.bbox(-0.2f), color_of(t.type));
painter.text(v.location.center(), std::format("{}", t.count), {.scale = {vs, -vs}, .c = {0, 0, 0, 255}});
for (auto type : {resource_type::red_science_pack, resource_type::green_science_pack})
{
if (l.count.contains(type))
{
painter.text(pen, std::to_string(l.count.at(type)), {.scale = {vs, -vs}, .c = color_of(type)});
pen[1] -= 12.f * vs;
}
}
});
map.world.apply<item const>([&](item const & i)
@ -729,13 +644,26 @@ namespace gmtk
if (event.down && event.button == app::mouse_button::left)
{
if (selected_ && !view_transition_)
{
bool transitioned = false;
if (auto entity = map_.world.index<index>().find(*selected_))
if (map_.world.get(*entity).contains<zoomer>())
{
view_transition_ = {view_stack_.back()};
view_stack_.push_back(*selected_);
selected_ = std::nullopt;
transitioned = true;
}
if (!transitioned && selected_->level == view_stack_.back().level + 1 && selected_->up() != view_stack_.back())
{
view_transition_ = {view_stack_.back()};
view_stack_.back() = selected_->up();
selected_ = std::nullopt;
transitioned = true;
}
}
}
if (event.down && event.button == app::mouse_button::right)
@ -794,8 +722,8 @@ namespace gmtk
}
}
}
belt_start_ = std::nullopt;
}
belt_start_ = std::nullopt;
}
if (event.down && event.key == app::keycode::F)
@ -804,7 +732,7 @@ namespace gmtk
{
map_.world.create(
vertex{*selected_},
build_site{transformer_type::furnace}
transformer{transformer_type::furnace}
);
}
}
@ -815,7 +743,7 @@ namespace gmtk
{
map_.world.create(
vertex{*selected_},
build_site{transformer_type::factory}
transformer{transformer_type::factory}
);
}
}
@ -826,8 +754,15 @@ namespace gmtk
{
map_.world.create(
vertex{*selected_},
build_site{std::nullopt}
zoomer{}
);
auto c = selected_->down();
sink_belt(map_.world, c.left());
sink_belt(map_.world, c.right());
sink_belt(map_.world, c.bottom());
sink_belt(map_.world, c.top());
}
}
@ -838,16 +773,11 @@ namespace gmtk
if (auto entity = map_.world.index<index>().find(*selected_))
{
auto acc = map_.world.get(*entity);
if (!acc.contains<source>() && !acc.contains<task>() && !acc.contains<zoomer>())
if (!acc.contains<source>() && !acc.contains<lab>() && !acc.contains<zoomer>())
map_.world.destroy(*entity);
}
}
}
if (event.down && event.key == app::keycode::SPACE)
{
generate_next_task(rng_, map_);
}
}
bool running() const override
@ -890,48 +820,6 @@ namespace gmtk
);
}
map_.world.apply<vertex const, build_site>([&](ecs::handle entity, vertex const & v, build_site & b)
{
bool built = true;
auto & recipe = b.type ? construction_recipe.at(*b.type) : zoomer_construction_recipe;
for (auto const & p : recipe)
{
if (!b.resources.contains(p.first))
{
built = false;
break;
}
if (b.resources.at(p.first) < p.second)
{
built = false;
break;
}
}
if (built)
{
auto type = b.type;
auto l = v.location;
map_.world.detach<build_site>(entity);
if (type)
{
map_.world.attach(entity, transformer{*type});
}
else
{
map_.world.attach(entity, zoomer{});
auto c = l.down();
sink_belt(map_.world, c.left());
sink_belt(map_.world, c.right());
sink_belt(map_.world, c.bottom());
sink_belt(map_.world, c.top());
}
}
});
map_.world.apply<vertex const, transformer const>([&](vertex const & v, transformer const & t)
{
boost::container::flat_map<resource_type, location> has_inputs;
@ -1038,17 +926,9 @@ namespace gmtk
if (auto cell = map_.world.index<index>().find(i.start.up()))
{
if (auto t = map_.world.get(*cell).get_if<build_site>())
if (auto l = map_.world.get(*cell).get_if<lab>())
{
t->resources[i.type] += 1;
map_.world.destroy(entity);
return;
}
if (auto t = map_.world.get(*cell).get_if<task>())
{
if (t->type == i.type)
t->count += 1;
l->count[i.type] += 1;
map_.world.destroy(entity);
return;
}
@ -1124,10 +1004,32 @@ namespace gmtk
location p{1 + l.level, {std::floor(m[0]), std::floor(m[1])}};
if (p.coords[0] >= 3 * l.coords[0] && p.coords[0] < 3 * l.coords[0] + 3 && p.coords[1] >= 3 * l.coords[1] && p.coords[1] < 3 * l.coords[1] + 3)
geom::interval xrange{3 * l.coords[0], 3 * l.coords[0] + 2};
geom::interval yrange{3 * l.coords[1], 3 * l.coords[1] + 2};
auto xwrange = geom::expand(xrange, 1);
auto ywrange = geom::expand(yrange, 1);
if (geom::contains(xrange, p.coords[0]) && geom::contains(yrange, p.coords[1]))
selected_ = p;
else if (auto entity = map_.world.index<index>().find(p))
else if (view_stack_.size() > 1 && within_grid(p) && ((geom::contains(xwrange, p.coords[0]) && geom::contains(yrange, p.coords[1])) || (geom::contains(xrange, p.coords[0]) && geom::contains(ywrange, p.coords[1]))))
{
selected_ = p;
while (selected_->level > 0)
{
if (auto entity = map_.world.index<index>().find(p.up()))
if (map_.world.get(*entity).contains<zoomer>())
break;
selected_ = std::nullopt;
break;
// TODO:
selected_ = selected_->up();
}
}
else if (!within_grid(p))
if (auto entity = map_.world.index<index>().find(p))
selected_ = p;
}
}