diff --git a/assets/config.json b/assets/config.json index 94338f0..8ae40f8 100644 --- a/assets/config.json +++ b/assets/config.json @@ -51,7 +51,8 @@ "devils_fingers_sprite": "assets/devils_fingers_sprite.png", "devils_fingers_stage": "assets/devils_fingers_stage.png", "tunnel_with_rocks": "assets/tunnel_with_rocks.png", - "tunnel_with_rocks_stage": "assets/tunnel_with_rocks_stage.png" + "tunnel_with_rocks_stage": "assets/tunnel_with_rocks_stage.png", + "ritual_crafting_area": "assets/ritual_crafting_area.png" }, "worldgen": { "enemy_probability": 50, diff --git a/assets/ritual_crafting_area.png b/assets/ritual_crafting_area.png new file mode 100644 index 0000000..ac8db7d Binary files /dev/null and b/assets/ritual_crafting_area.png differ diff --git a/components.cpp b/components.cpp index 7e10528..8898df0 100644 --- a/components.cpp +++ b/components.cpp @@ -32,6 +32,7 @@ namespace components { void Animation::play() { if(!playing) { current = 0; + subframe = 0.0f; playing = true; } } @@ -71,6 +72,14 @@ namespace components { subframe += speed; current = int(subframe); + } else if(!looped) { + playing = false; + current = frames - 1; + subframe = float(frames - 1); + + if(!simple) { + rect_out.position.x += current * texture_width; + } } else { playing = false; current = 0; diff --git a/components.hpp b/components.hpp index b9e8f92..e68b3d5 100644 --- a/components.hpp +++ b/components.hpp @@ -120,7 +120,9 @@ namespace components { bool stationary = false; int current = 0; bool playing = false; - float subframe = 1.0f; + float subframe = 0.0f; + bool looped = false; + // BUG: this is weirdly not used in most animations but also named wrong should be frame_width int texture_width = TEXTURE_WIDTH; void play(); diff --git a/status_ui.cpp b/status_ui.cpp index 99c44a6..e385079 100644 --- a/status_ui.cpp +++ b/status_ui.cpp @@ -14,9 +14,9 @@ namespace gui { { $gui.position(STATUS_UI_X, STATUS_UI_Y, STATUS_UI_WIDTH, STATUS_UI_HEIGHT); $gui.layout( + "[ ritual_ui ]" "[inv_slot1 | inv_slot2 | inv_slot3]" "[inv_slot4 | inv_slot5 | inv_slot6]" - "[inv_slot7 | inv_slot8 | inv_slot9]" "[*%(100,300)log_view]" "[_]" "[_]"); @@ -42,15 +42,54 @@ namespace gui { $gui.set(button, {}); $gui.set(button, {""}); $gui.set(button, {make_any(name)}); - $gui.set(button, { - [this](auto ent, auto data){ select_slot(ent, data); } - }); + + if(name == "ritual_ui") { + $gui.set(button, { + [this](auto, auto){ select_ritual(); } + }); + } else { + $gui.set(button, { + [this](auto ent, auto data){ select_slot(ent, data); } + }); + } } } + $ritual_ui = textures::get("ritual_crafting_area"); + $ritual_ui.sprite->setPosition({0,0}); + $ritual_ui.sprite->setTextureRect($ritual_closed_rect); + $ritual_state = RitualUIState::CLOSED; + $ritual_anim.simple = false; + $ritual_anim.looped = false; + $ritual_anim.easing = ease::NONE; + $ritual_anim.stationary = true; + $ritual_anim.texture_width = 380; + $ritual_anim.frames = 3; + $ritual_anim.speed = 0.2f; + $gui.init(); } + void StatusUI::select_ritual() { + using enum RitualUIState; + + switch($ritual_state) { + case OPEN: + $ritual_state = CLOSING; + break; + case CLOSED: + $ritual_state = OPENING; + $ritual_anim.play(); + break; + case OPENING: // ignored + break; + case CLOSING: // ignored + break; + default: + dbc::sentinel("INVALID RitualUIState"); + } + } + void StatusUI::select_slot(DinkyECS::Entity ent, any slot_name) { dbc::check(slot_name.has_value(), "passed select_slot an any without a value"); @@ -113,7 +152,45 @@ namespace gui { } void StatusUI::render(sf::RenderWindow &window) { - $gui.render(window); + sf::IntRect rect; + sf::Vector2f scale{1.0, 1.0}; + sf::Vector2f pos{0, 0}; + + using enum RitualUIState; + switch($ritual_state) { + case OPEN: { + rect = $ritual_open_rect; + } break; + case CLOSED: { + $gui.render(window); + rect = $ritual_closed_rect; + } + break; + case OPENING: { + $gui.render(window); + if($ritual_anim.playing) { + rect = $ritual_closed_rect; + $ritual_anim.step(scale, pos, rect); + } else { + $ritual_state = OPEN; + rect = $ritual_open_rect; + } + } + break; + case CLOSING: { + $gui.render(window); + rect = $ritual_closed_rect; + $ritual_state = CLOSED; + } break; + default: + dbc::sentinel("INVALID RitualUIState"); + } + + $ritual_ui.sprite->setTextureRect(rect); + $ritual_ui.sprite->setPosition(pos); + $ritual_ui.sprite->setScale(scale); + + window.draw(*$ritual_ui.sprite); } void StatusUI::log(string msg) { diff --git a/status_ui.hpp b/status_ui.hpp index 73be66f..ba243e3 100644 --- a/status_ui.hpp +++ b/status_ui.hpp @@ -6,8 +6,20 @@ #include "guecs.hpp" namespace gui { + enum class RitualUIState { + OPEN=0, + CLOSED=1, + OPENING=2, + CLOSING=3 + }; + class StatusUI { public: + sf::IntRect $ritual_closed_rect{{0,0},{380,720}}; + sf::IntRect $ritual_open_rect{{380 * 2,0},{380,720}}; + RitualUIState $ritual_state = RitualUIState::CLOSED; + textures::SpriteTexture $ritual_ui; + components::Animation $ritual_anim; guecs::UI $gui; DinkyECS::Entity $log_to; std::map $slots; @@ -16,6 +28,7 @@ namespace gui { StatusUI(GameLevel level); void select_slot(DinkyECS::Entity ent, std::any data); + void select_ritual(); void update_level(GameLevel &level); void log(std::string msg); void init();