From c486db5a5792eb5abe34ae8eb261f5e448a4e25a Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 12 Nov 2025 11:42:22 -0500 Subject: [PATCH] Can now export the time code/actions from Reaper as json data and the storyboard will play them. --- assets/config.json | 1 + components.cpp | 1 + components.hpp | 9 +++++++++ game_level.cpp | 3 ++- storyboard/ui.cpp | 47 +++++++++++++++++++++++++++++++++------------- storyboard/ui.hpp | 6 ++++-- 6 files changed, 51 insertions(+), 16 deletions(-) diff --git a/assets/config.json b/assets/config.json index 4d0d149..ad49a19 100644 --- a/assets/config.json +++ b/assets/config.json @@ -1,5 +1,6 @@ { "sounds": { + "epic_theme": "assets/sounds/epic_theme.mp3", "Sword_Hit_1": "assets/sounds/Creature_Sounds-Sword_Hit_1.ogg", "Evil_Eye_Sound_1": "assets/sounds/Creature_Sounds-Evil_Eye_Sound_1.ogg", "Evil_Eye_Sound_2": "assets/sounds/Creature_Sounds-Evil_Eye_Sound_2.ogg", diff --git a/components.cpp b/components.cpp index 8ff6b8b..a185324 100644 --- a/components.cpp +++ b/components.cpp @@ -18,6 +18,7 @@ namespace components { void init() { if(!MAP_configured) { components::enroll(MAP); + components::enroll(MAP); components::enroll(MAP); components::enroll(MAP); components::enroll(MAP); diff --git a/components.hpp b/components.hpp index 32a5085..3a2c0f9 100644 --- a/components.hpp +++ b/components.hpp @@ -61,6 +61,7 @@ namespace components { settings::Config devices; settings::Config bosses; settings::Config rituals; + settings::Config stories; }; struct Personality { @@ -90,6 +91,13 @@ namespace components { json fixtures; }; + struct Storyboard { + std::string image; + std::string audio; + std::vector layout; + json beats; + }; + struct Combat { int hp; int max_hp; @@ -170,6 +178,7 @@ namespace components { ENROLL_COMPONENT(Motion, dx, dy, random); ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead); ENROLL_COMPONENT(Device, config, events); + ENROLL_COMPONENT(Storyboard, image, audio, layout, beats); ENROLL_COMPONENT(Animation, min_x, min_y, max_x, max_y, simple, frames, speed, easing, motion, ease_rate, diff --git a/game_level.cpp b/game_level.cpp index 1157660..05a81b6 100644 --- a/game_level.cpp +++ b/game_level.cpp @@ -123,7 +123,8 @@ namespace GameDB { settings::get("tiles"), settings::get("devices"), settings::get("bosses"), - settings::get("rituals") + settings::get("rituals"), + settings::get("stories") }); } } diff --git a/storyboard/ui.cpp b/storyboard/ui.cpp index a6183cb..f5545fb 100644 --- a/storyboard/ui.cpp +++ b/storyboard/ui.cpp @@ -2,6 +2,11 @@ #include "components.hpp" #include "animation.hpp" #include "sound.hpp" +#include "config.hpp" +#include +#include +#include +#include namespace storyboard { UI::UI() : @@ -11,25 +16,26 @@ namespace storyboard { { $view_sprite.setPosition({0, 0}); $camera.style("pan"); - sound::play("ambient_1", true); } void UI::init() { + auto config = settings::get("stories"); + $story = components::convert(config["rat_king"]); + $ui.position(0,0, SCREEN_WIDTH, SCREEN_HEIGHT); $ui.set($ui.MAIN, {$ui.$parser, guecs::THEME.TRANSPARENT}); auto& background = $ui.get($ui.MAIN); - background.set_sprite("test_story", true); + background.set_sprite($story.image, true); - $ui.layout( - "[a|b|c]" - "[*%(200,100)d|_|f]" - "[g|h|i]"); - - for(auto& [key, value] : $ui.$parser.cells) { - $cell_names.push_back(key); + for(auto& line : $story.layout) { + $layout.append(line); } + + $ui.layout($layout); + + sound::play($story.audio, true); } void UI::render(sf::RenderWindow &window) { @@ -44,10 +50,23 @@ namespace storyboard { window.draw($view_sprite); } - void UI::track_audio() { - int track_head = int($audio->getPlayingOffset().asSeconds()); + sf::Time parse_time_code(const std::string& time) { + std::chrono::seconds out{}; - if(track_head % 3 == 0) { + std::istringstream is{time}; + is >> std::chrono::parse("%M:%S", out); + dbc::check(!is.fail(), fmt::format("Time parse failed: {}", time)); + + return sf::Time(out); + } + + void UI::track_audio() { + auto& beat = $story.beats[cur_beat % $story.beats.size()]; + + auto track_head = $audio->getPlayingOffset(); + auto next_beat = parse_time_code(beat[0]); + + if(track_head >= next_beat) { if($moving) return; $moving = true; // prevent motion until next tick @@ -55,10 +74,12 @@ namespace storyboard { auto& cell = $ui.cell_for($zoom_target); $camera.position(cell.mid_x, cell.mid_y); + $zoom_target = beat[1]; + $camera.style(beat[2]); // get the new target from the cell names - $zoom_target = $cell_names.at(track_head % $cell_names.size()); zoom($zoom_target); $camera.play(); + cur_beat++; } else { $moving = false; } diff --git a/storyboard/ui.hpp b/storyboard/ui.hpp index a0e4875..4278158 100644 --- a/storyboard/ui.hpp +++ b/storyboard/ui.hpp @@ -13,8 +13,10 @@ namespace storyboard { cinematic::Camera $camera; std::shared_ptr $audio; std::string $zoom_target = "a"; - int $moving = false; - std::vector $cell_names; + bool $moving = false; + int cur_beat = 0; + components::Storyboard $story; + std::string $layout; UI();