Improved start screen and made the animation optional in scenes since they aren't needed always.

This commit is contained in:
Zed A. Shaw 2026-04-02 12:15:51 -04:00
parent 903fad871f
commit 532366091b
13 changed files with 114 additions and 27 deletions

View file

@ -196,11 +196,8 @@ void WorldBuilder::place_stairs(DinkyECS::World& world, GameConfig& config) {
auto& device_config = config.devices.json();
auto entity_data = device_config["STAIRS_DOWN"];
// auto at_end = $map.$dead_ends.back();
configure_entity_in_map(world, entity_data, {
player_pos.location.x+1,
player_pos.location.y
});
auto at_end = $map.$dead_ends.back();
configure_entity_in_map(world, entity_data, at_end);
}
void WorldBuilder::configure_starting_items(DinkyECS::World &world) {

View file

@ -249,13 +249,12 @@ namespace animation {
sequence.INVARIANT();
}
Animation load(const std::string &file, const std::string &anim_name) {
std::optional<Animation> maybe_load(const std::string &file, const std::string &anim_name) {
using nlohmann::json;
std::ifstream infile(file);
auto data = json::parse(infile);
dbc::check(data.contains(anim_name),
$F("{} animation config does not have animation {}", file, anim_name));
if(!data.contains(anim_name)) return std::nullopt;
Animation anim;
animation::from_json(data[anim_name], anim);
@ -269,6 +268,15 @@ namespace animation {
return anim;
}
Animation load(const std::string &file, const std::string &anim_name) {
auto anim = maybe_load(file, anim_name);
dbc::check(anim != std::nullopt,
$F("FAILED to load animation {} from file {}", anim_name, file));
return *anim;
}
void Sequence::INVARIANT(const std::source_location location) {
dbc::check(frames.size() == durations.size(),
$F("frames.size={} doesn't match durations.size={}",
@ -297,8 +305,12 @@ namespace animation {
void configure(DinkyECS::World& world, DinkyECS::Entity entity) {
auto sprite = world.get_if<components::Sprite>(entity);
if(sprite != nullptr && has(sprite->name)) {
world.set<Animation>(entity, animation::load("assets/animation.json", sprite->name));
// sprite doesn't exist, abort
if(sprite == nullptr) return;
// lazy load any animations
if(auto anim = animation::maybe_load("assets/animation.json", sprite->name)) {
world.set<Animation>(entity, *anim);
}
}

View file

@ -134,6 +134,7 @@ namespace animation {
};
Animation load(const std::string &file, const std::string &anim_name);
std::optional<Animation> maybe_load(const std::string &file, const std::string &anim_name);
// BUG: brought over from animation to finish the refactor, but these may not be needed or maybe they go in system.cpp?
bool has(const std::string& name);

View file

@ -18,10 +18,13 @@ namespace scene {
bool flipped = config["flipped"];
// BUG: put the .json file to load as a default/optional arg
auto anim = animation::load("./assets/animation.json", sprite_name);
anim.play();
auto anim = animation::maybe_load("./assets/animation.json", sprite_name);
anim.transform.flipped = flipped;
if(anim) {
// only start it if there's an animation set
anim->play();
anim->transform.flipped = flipped;
}
std::string cell = config["cell"];
std::string name = config["name"];
@ -103,7 +106,7 @@ namespace scene {
for(auto& actor : $actors) {
view.draw(*actor.st.sprite, actor.effect.get());
if(actor.anim.playing) view.draw(actor.text);
if(actor.anim && actor.anim->playing) view.draw(actor.text);
}
$camera.render(view);
@ -126,20 +129,25 @@ namespace scene {
void Engine::animate_actor(const std::string& actor, const std::string& form) {
auto& config = actor_config(actor);
config.anim.set_form(form);
if(!config.anim.playing) {
config.anim.play();
// no animation set, abort
if(!config.anim) return;
config.anim->set_form(form);
if(!config.anim->playing) {
config.anim->play();
}
}
inline void this_is_stupid_refactor(std::vector<Element>& elements) {
for(auto& element : elements) {
if(element.anim.playing) {
element.anim.update();
element.anim.motion(*element.st.sprite, element.pos, element.scale);
element.anim.apply(*element.st.sprite);
if(element.effect != nullptr) element.anim.apply_effect(element.effect);
// skip any without animation
if(element.anim && element.anim->playing) {
element.anim->update();
element.anim->motion(*element.st.sprite, element.pos, element.scale);
element.anim->apply(*element.st.sprite);
if(element.effect != nullptr) element.anim->apply_effect(element.effect);
}
}
}
@ -178,8 +186,12 @@ namespace scene {
}
void Engine::set_end_cb(std::function<void()> cb) {
for(auto& actor : $actors) {
actor.anim.onLoop = [&,cb](auto& seq, auto& tr) -> bool {
// no animation set so no point doing a end cb
if(!actor.anim) continue;
actor.anim->onLoop = [&,cb](auto& seq, auto& tr) -> bool {
seq.current = tr.toggled ? seq.frame_count - 1 : 0;
cb();
actor.effect = nullptr;

View file

@ -17,7 +17,7 @@ namespace scene {
struct Element {
std::string name;
textures::SpriteTexture st;
animation::Animation anim;
std::optional<animation::Animation> anim;
std::string cell;
sf::Vector2f scale{1.0f, 1.0f};
sf::Vector2f pos{0.0f, 0.0f};