From a9e219ea964177e41abb14b0f861891224f4a049 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 11 May 2025 16:08:55 -0400 Subject: [PATCH] Clicker now moves when you click him. --- demos/clicker_game.cpp | 112 +++++++++++++++++++++++------- include/guecs/sfml/components.hpp | 2 +- src/guecs/sfml/components.cpp | 12 +++- src/guecs/ui.cpp | 1 + 4 files changed, 101 insertions(+), 26 deletions(-) diff --git a/demos/clicker_game.cpp b/demos/clicker_game.cpp index 5464543..05a6906 100644 --- a/demos/clicker_game.cpp +++ b/demos/clicker_game.cpp @@ -3,6 +3,7 @@ #include "guecs/ui.hpp" #include #include +#include constexpr const int WINDOW_WIDTH=1280; constexpr const int WINDOW_HEIGHT=720; @@ -15,9 +16,59 @@ enum class Event { CLICKER, A_BUTTON }; +struct Shake { + float scale_factor = 0.05f; + int frames = 10; + float ease_rate = 0.1f; + bool playing = false; + int current = 0; + float x=0.0; + float y=0.0; + float w=0.0; + float h=0.0; + sf::Vector2f initial_scale; + + float ease() { + float tick = float(frames) / float(current) * ease_rate; + return (std::sin(tick) + 1.0) / 2.0; + } + + void init(lel::Cell& cell) { + x = cell.x; + y = cell.y; + w = cell.w; + h = cell.h; + } + + void play(guecs::Sprite& sprite) { + if(!playing) { + playing = true; + current = 0; + initial_scale = sprite.sprite->getScale(); + } + } + + void render(guecs::Sprite& sprite) { + current++; + + if(playing && current < frames) { + float tick = ease(); + sf::Vector2f scale{ + std::lerp(initial_scale.x, initial_scale.x + scale_factor, tick), + std::lerp(initial_scale.y, initial_scale.y + scale_factor, tick)}; + + sprite.sprite->setScale(scale); + } else { + playing = false; + current = 0; + sprite.sprite->setScale(initial_scale); + } + } +}; struct ClickerUI { guecs::UI $gui; + guecs::Entity $clicker; ClickerUI() { $gui.position(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); @@ -30,33 +81,44 @@ struct ClickerUI { } void init() { - $gui.set($gui.MAIN, {}); - - for(auto& [name, cell] : $gui.cells()) { - auto id = $gui.entity(name); - if(name != "clicker") { - $gui.set(id, {}); - $gui.set(id, {}); - $gui.set(id, { "clicker_treat_bone" }); - fmt::println("button dim: {},{}", cell.w, cell.h); - $gui.set(id, { - [&](auto, auto) { handle_button(Event::A_BUTTON); } - }); - } else { - $gui.set(id, {"clicker_the_dog"}); - $gui.set(id, {"clicker_bark"}); - $gui.set(id, {0.1f, "ui_shader"}); - $gui.set(id, { - [&](auto, auto) { handle_button(Event::CLICKER); } - }); - } - } + $gui.set($gui.MAIN, {$gui.$parser, {0, 0, 0, 255}}); + + for(auto& [name, cell] : $gui.cells()) { + auto id = $gui.entity(name); + if(name != "clicker") { + $gui.set(id, {}); + $gui.set(id, {}); + $gui.set(id, { "clicker_treat_bone" }); + fmt::println("button dim: {},{}", cell.w, cell.h); + $gui.set(id, { + [&](auto, auto) { handle_button(Event::A_BUTTON); } + }); + } + } + + $clicker = $gui.entity("clicker"); + $gui.set($clicker, {"clicker_the_dog"}); + $gui.set($clicker, {"clicker_bark"}); + $gui.set($clicker, { + [&](auto, auto) { handle_button(Event::CLICKER); } + }); + + // custom components need to be initialized manually + $gui.set_init($clicker, {}); $gui.init(); } void render(sf::RenderWindow& window) { + auto& shaker = $gui.get($clicker); + if(shaker.playing) { + auto& sprite = $gui.get($clicker); + shaker.render(sprite); + window.clear(); + } + $gui.render(window); + // $gui.debug_layout(window); } @@ -67,10 +129,12 @@ struct ClickerUI { void handle_button(Event ev) { using enum Event; switch(ev) { - case CLICKER: + case CLICKER: { + auto& shaker = $gui.get($clicker); + auto& sprite = $gui.get($clicker); + shaker.play(sprite); fmt::println("CLICKER LOVES YOU!"); - break; - + } break; case A_BUTTON: fmt::println("a button clicked"); break; diff --git a/include/guecs/sfml/components.hpp b/include/guecs/sfml/components.hpp index 1cf0244..9fdb8b8 100644 --- a/include/guecs/sfml/components.hpp +++ b/include/guecs/sfml/components.hpp @@ -97,7 +97,7 @@ namespace guecs { float y = 0.0f; float w = 0.0f; float h = 0.0f; - sf::Color color = THEME.BG_COLOR; + sf::Color color=THEME.BG_COLOR; shared_ptr shape = nullptr; Background(lel::Parser& parser, sf::Color bg_color=THEME.BG_COLOR) : diff --git a/src/guecs/sfml/components.cpp b/src/guecs/sfml/components.cpp index f41feed..bd1250b 100644 --- a/src/guecs/sfml/components.cpp +++ b/src/guecs/sfml/components.cpp @@ -1,6 +1,7 @@ #include "guecs/ui.hpp" #include "guecs/sfml/backend.hpp" #include +#include namespace guecs { using std::make_shared; @@ -88,10 +89,19 @@ namespace guecs { } void Background::init() { + assert(w > 0.0f && "Background.w must be > 0.0f. Forgot $gui.$parser?"); + assert(h > 0.0f && "Background.h must be > 0.0f. Forgot $gui.$parser?"); + + std::cout << "x=" << x << " y=" << y << " w=" << w << " h=" << h << std::endl; sf::Vector2f size{float(w), float(h)}; - if(shape == nullptr) shape = make_shared(size); + if(shape == nullptr) { + shape = make_shared(size); + } else { + shape->setSize(size); + } shape->setPosition({float(x), float(y)}); shape->setFillColor(color); + assert(shape != nullptr && "failed to make rectangle"); } void Effect::init(lel::Cell &cell) { diff --git a/src/guecs/ui.cpp b/src/guecs/ui.cpp index 50c8b3f..dcb0b69 100644 --- a/src/guecs/ui.cpp +++ b/src/guecs/ui.cpp @@ -2,6 +2,7 @@ #include #include #include +#include namespace guecs { using std::make_shared;