#define FSM_DEBUG 1 #include "sound.hpp" #include "ai.hpp" #include "animation.hpp" #include #include "shaders.hpp" #include "backend.hpp" #include "constants.hpp" #include "animate2.hpp" #include "tools/animator.hpp" using namespace std::chrono_literals; bool YES_SYNC=true; animate2::Sheet sheet{ .width{720*2}, .height{720}, .frame_width{720}, .frame_height{720}, }; animate2::Sequence sequence{ .frames{0,1}, .durations{800ms, 200ms} }; animate2::Transform scale_tr{ .min_x{0.6f}, .min_y{0.6f}, .max_x{0.8f}, .max_y{0.8f}, .simple{false}, .flipped{false}, .ease_rate{4.0f}, .scaled{true}, .toggled{false}, .looped{true}, .easing = ease2::in_out_back, .motion = ease2::move_rush, }; animate2::Transform move_tr{ .min_x{-20.0f}, .min_y{-20.0f}, .max_x{20.0f}, .max_y{20.0f}, .simple{false}, .flipped{false}, .ease_rate{2.5f}, .scaled{true}, .toggled{false}, .looped{true}, .easing = ease2::normal_dist, .motion = ease2::move_shake, }; animate2::Animate2 anim{sheet, sequence, scale_tr}; namespace animator { void FSM::init(const std::string &sprite_name) { $ui.init(sprite_name, *this); if(YES_SYNC) { $window.setVerticalSyncEnabled(VSYNC); if(FRAME_LIMIT) $window.setFramerateLimit(FRAME_LIMIT); } $window.setPosition({0,0}); } void FSM::event(Event ev, std::any data) { switch($state) { FSM_STATE(State, START, ev); FSM_STATE(State, ANIMATE, ev); FSM_STATE(State, END, ev); } } void FSM::START(Event ev) { switch(ev) { case Event::TICK: state(State::ANIMATE); break; default: state(State::START); } } void FSM::ANIMATE(Event ev) { switch(ev) { case Event::TICK: // stuff break; case Event::PLAY: if(!anim.playing) anim.play(); break; case Event::STOP: if(anim.playing) anim.stop(); break; case Event::LOOP: anim.$transform.looped = !anim.$transform.looped; break; case Event::TOGGLE: anim.$transform.toggled = !anim.$transform.toggled; break; default: state(State::START); } } void FSM::END(Event ev) { } void FSM::handle_keyboard_mouse() { while(const auto ev = $window.pollEvent()) { using enum game::Event; auto gui_ev = $router.process_event(ev); auto mouse_pos = $window.mapPixelToCoords($router.position); switch(gui_ev) { case MOUSE_CLICK: $ui.mouse(mouse_pos.x, mouse_pos.y, guecs::NO_MODS); break; case MOUSE_MOVE: $ui.mouse(mouse_pos.x, mouse_pos.y, {1 << guecs::ModBit::hover}); break; case QUIT: state(State::END); default: break; // ignored } } } void FSM::render() { $window.clear(); $ui.render($window); $window.display(); } bool FSM::active() { return !in_state(State::END); } void UI::button(const std::string& name, std::function cb) { auto comp = $ui.entity(name); $ui.set(comp, {}); $ui.set(comp, {guecs::to_wstring(name)}); $ui.set(comp, {}); $ui.set(comp, {cb}); } void UI::init(const std::string& sprite_name, FSM& fsm) { $ui.position(0,0, SCREEN_WIDTH, SCREEN_HEIGHT); $ui.layout( "[play|*%=(300,400)viewer|_|_]" "[stop|_|_|_]" "[loop|_|_|_]" "[toggled|_|_|_]"); auto viewer = $ui.entity("viewer"); $ui.set(viewer, { sprite_name, 0, false}); button("stop", [&](auto){ fsm.event(Event::STOP, {}); }); button("play", [&](auto){ fsm.event(Event::PLAY, {}); }); button("loop", [&](auto){ fsm.event(Event::LOOP, {}); }); button("toggled", [&](auto){ fsm.event(Event::TOGGLE, {}); }); $ui.init(); } void UI::render(sf::RenderWindow& window) { $ui.render(window); } bool UI::mouse(float x, float y, guecs::Modifiers mods) { return $ui.mouse(x, y, mods); } std::shared_ptr UI::get_sprite() { auto viewer = $ui.entity("viewer"); return $ui.get(viewer).sprite; } } int main(int argc, char* argv[]) { shaders::init(); components::init(); sfml::Backend backend; guecs::init(&backend); ai::init("ai"); animation::init(); dbc::check(argc == 2, "USAGE: animator "); std::string sprite_name{argv[1]}; sound::mute(true); sound::play("ambient_1", true); animator::FSM main; main.init(argv[1]); anim.play(); auto sprite = main.$ui.get_sprite(); // need to keep these aroung auto pos = sprite->getPosition(); auto scale = sprite->getScale(); while(main.active()) { auto [ticks, alpha] = anim.commit(); for(int i = 0; i < ticks; i++) { main.event(animator::Event::TICK, {}); if(anim.playing) { anim.update(); anim.apply(*sprite); anim.motion(*sprite, pos, scale); } } main.render(); main.handle_keyboard_mouse(); } return 0; }