From bd899ad6ab502c07a10db76e1365b9940f198fee Mon Sep 17 00:00:00 2001 From: lisyarus Date: Mon, 19 Aug 2024 17:17:45 +0300 Subject: [PATCH] Add tutorial text --- source/application.cpp | 193 +++++++++++++++++++++++++++++++---------- 1 file changed, 146 insertions(+), 47 deletions(-) diff --git a/source/application.cpp b/source/application.cpp index d53f15a..c311f30 100644 --- a/source/application.cpp +++ b/source/application.cpp @@ -98,6 +98,31 @@ namespace gmtk return color_of(r.color); } + card_type transformer_to_card(transformer_type type) + { + switch (type) + { + case transformer_type::mixer: return card_type::mixer; + case transformer_type::square_maker: return card_type::square_maker; + case transformer_type::hue_shifter: return card_type::hue_shifter; + } + + throw util::unknown_enum_value_exception{type}; + } + + std::optional card_to_transformer(card_type type) + { + switch (type) + { + case card_type::mixer: return transformer_type::mixer; + case card_type::square_maker: return transformer_type::square_maker; + case card_type::hue_shifter: return transformer_type::hue_shifter; + default: return std::nullopt; + } + + return std::nullopt; + } + struct recipe { boost::container::flat_set inputs; @@ -258,10 +283,12 @@ namespace gmtk world.get(to).get().belts_from.insert(from); } - void remove_belt(ecs::container & world, ecs::handle from, ecs::handle to) + bool remove_belt(ecs::container & world, ecs::handle from, ecs::handle to) { + bool removed = world.get(from).get().belts_to.contains(to); world.get(from).get().belts_to.erase(to); world.get(to).get().belts_from.erase(from); + return removed; } struct occupied @@ -555,18 +582,7 @@ namespace gmtk } else if (auto t = acc.get_if()) { - switch (t->type) - { - case transformer_type::mixer: - map.put_card(card_type::mixer); - break; - case transformer_type::square_maker: - map.put_card(card_type::square_maker); - break; - case transformer_type::hue_shifter: - map.put_card(card_type::hue_shifter); - break; - } + map.put_card(transformer_to_card(t->type)); } map.world.destroy(*entity); @@ -695,13 +711,9 @@ namespace gmtk draw_structure(bbox, crossing{}, painter); break; case card_type::mixer: - draw_structure(bbox, transformer{transformer_type::mixer}, painter); - break; case card_type::square_maker: - draw_structure(bbox, transformer{transformer_type::square_maker}, painter); - break; case card_type::hue_shifter: - draw_structure(bbox, transformer{transformer_type::hue_shifter}, painter); + draw_structure(bbox, transformer{card_to_transformer(type).value()}, painter); break; case card_type::zoomer: draw_grid(bbox, -1.f, painter, true); @@ -844,6 +856,27 @@ namespace gmtk } } + std::vector card_description(card_type type) + { + switch (type) + { + case card_type::mixer: + return {"Mixer", "Mixes input colors"}; + case card_type::hue_shifter: + return {"Hue shifter", "Shifts the hue of", " input colors"}; + case card_type::square_maker: + return {"Squarer", "Turns circles into squares"}; + case card_type::crossing: + return {"Bridge", "Allows belts to cross", " without merging"}; + case card_type::zoomer: + return {"Grid", "Creates an embedded 3x3 grid", "Zoom using mouse wheel"}; + case card_type::eraser: + return {"Eraser", "Erases placed structures"}; + } + + throw util::unknown_enum_value_exception{type}; + } + std::uint64_t make_seed() { random::device d; @@ -928,31 +961,24 @@ namespace gmtk { if (map_.take_card(*active_card_)) { + bool built = false; switch (*active_card_) { case card_type::mixer: - map_.world.create( - vertex{*selected_}, - transformer{transformer_type::mixer} - ); - break; case card_type::hue_shifter: - map_.world.create( - vertex{*selected_}, - transformer{transformer_type::hue_shifter} - ); - break; case card_type::square_maker: map_.world.create( vertex{*selected_}, - transformer{transformer_type::square_maker} + transformer{card_to_transformer(*active_card_).value()} ); + built = true; break; case card_type::crossing: map_.world.create( vertex{*selected_}, crossing{} ); + built = true; break; case card_type::zoomer: { @@ -967,18 +993,26 @@ namespace gmtk sink_belt(map_.world, c.right()); sink_belt(map_.world, c.bottom()); sink_belt(map_.world, c.top()); + built = true; } break; case card_type::eraser: break; } + + if (built && tutorial_state_ <= 3) + tutorial_state_ = 4; } } } else if (selected_card_) active_card_ = *selected_card_; else if (selected_item_) + { item_killing_spree_ = true; + if (tutorial_state_ <= 4) + tutorial_state_ = 5; + } else if (selected_ && !belt_start_) belt_start_ = *selected_; } @@ -1012,13 +1046,22 @@ namespace gmtk auto & sv = map_.world.get(s).get(); if (sv.belts_to.contains(t)) + { remove_belt(map_.world, s, t); + if (tutorial_state_ <= 1) + tutorial_state_ = 2; + } else { - remove_belt(map_.world, t, s); + if (remove_belt(map_.world, t, s)) + if (tutorial_state_ <= 1) + tutorial_state_ = 2; add_belt(map_.world, s, t); } } + + if (tutorial_state_ <= 0) + tutorial_state_ = 1; } } belt_start_ = std::nullopt; @@ -1108,6 +1151,9 @@ namespace gmtk map_.stage += 1; map_.resource_count = 0; + + if (map_.stage > 1 && tutorial_state_ <= 2) + tutorial_state_ = 3; } map_.world.apply([&](vertex const & v, transformer const & t) @@ -1386,6 +1432,8 @@ namespace gmtk float view_level = view_stack_.back().level; float pixel_size = view_box_[1].length() / screen_size_[1]; + std::vector helper_text; + if (view_transition_) { float t = geom::smoothstep(view_transition_->timer * 2.f); @@ -1467,22 +1515,8 @@ namespace gmtk if (selected_card_ || active_card_) { - switch (selected_card_.value_or(*active_card_)) - { - case card_type::crossing: - case card_type::zoomer: - case card_type::eraser: - break; - case card_type::mixer: - shown_recipies = transformer_type::mixer; - break; - case card_type::hue_shifter: - shown_recipies = transformer_type::hue_shifter; - break; - case card_type::square_maker: - shown_recipies = transformer_type::square_maker; - break; - } + if (auto type = card_to_transformer(selected_card_.value_or(*active_card_))) + shown_recipies = *type; } else if (selected_) { @@ -1496,7 +1530,7 @@ namespace gmtk float const scale = std::pow(3.f, -1.f - view_level); float const step = 1.5f * scale / 9.f; - geom::point pen = view_box_.corner(0, 1) + geom::vector{1.f, -1.f} * view_box_[1].length() / 10.f; + geom::point pen = view_box_.corner(0, 1) + geom::vector{18.f, -120.f} * pixel_size + geom::vector{step, - 3.f * step} / 2.f; for (auto const & recipe : recipies.at(*shown_recipies)) { int i = 0; @@ -1559,6 +1593,69 @@ namespace gmtk } } + if (selected_card_ || active_card_) + helper_text = card_description(selected_card_.value_or(*active_card_)); + else if (selected_) + if (auto entity = map_.world.index().find(*selected_)) + { + auto acc = map_.world.get(*entity); + if (auto t = acc.get_if()) + helper_text = card_description(transformer_to_card(t->type)); + else if (acc.contains()) + helper_text = card_description(card_type::crossing); + else if (acc.contains()) + helper_text = card_description(card_type::zoomer); + else if (acc.contains()) + helper_text = {"Source", "Generates circles"}; + else if (acc.contains()) + helper_text = {"Consumer", "Consumes produced items"}; + } + + if (helper_text.empty()) + { + if (tutorial_state_ == 0) + { + helper_text.push_back("Click and drag to add"); + helper_text.push_back(" conveyor belts"); + } + else if (tutorial_state_ == 1) + { + helper_text.push_back("Drag again to remove belts"); + helper_text.push_back(" or switch direction"); + } + else if (tutorial_state_ == 2) + { + helper_text.push_back("Deliver items from"); + helper_text.push_back("source to consumer"); + } + else if (tutorial_state_ == 3) + { + helper_text.push_back("Place a mixer to"); + helper_text.push_back(" combine items"); + } + else if (tutorial_state_ == 4) + { + helper_text.push_back("Click on items to"); + helper_text.push_back(" remove clogging"); + } + else if (tutorial_state_ == 5) + { + helper_text.push_back("Let's see how far you can get."); + helper_text.push_back(" Good luck!"); + } + } + + { + geom::point pen = view_box_.corner(0, 1) + geom::vector{18.f, -24.f} * pixel_size; + float s = 2.f * pixel_size; + + for (int i = 0; i < helper_text.size(); ++i) + { + painter_.text(pen, helper_text[i], {.scale = {s, -s}, .x = gfx::painter::x_align::left, .y = gfx::painter::y_align::top, .c = gfx::black}); + pen[1] -= 32.f * pixel_size; + } + } + painter_.render(geom::orthographic_camera{view_box_}.transform()); } @@ -1598,6 +1695,8 @@ namespace gmtk std::optional active_card_; util::hash_map card_animation_; + + int tutorial_state_ = 0; }; }