diff --git a/Makefile b/Makefile index ece7c1d..ef52c74 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ tracy_build: meson compile -j 10 -C builddir test: - ./builddir/runtests -d yes + ./builddir/runtests -d yes "[coro]" run: build test ifeq '$(OS)' 'Windows_NT' @@ -60,7 +60,7 @@ clean: meson compile --clean -C builddir debug_test: build - gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests -e + gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests -e "[coro]" win_installer: powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp' @@ -70,3 +70,6 @@ coverage_report: money: scc --exclude-dir subprojects + +arena: + ./builddir/arena diff --git a/animation.cpp b/animation.cpp index ea077fe..3ea924b 100644 --- a/animation.cpp +++ b/animation.cpp @@ -36,11 +36,14 @@ namespace components { if(playing && current < frames) { float tick = twitching(); - scale_out.x = std::lerp(scale_out.x, scale_out.x + scale, tick); - scale_out.y = std::lerp(scale_out.y, scale_out.y + scale, tick); if(stationary) { + scale_out.x = std::lerp(scale, max_scale, tick); + scale_out.y = std::lerp(scale, max_scale, tick); pos_out.y = pos_out.y - (pos_out.y * scale_out.y - pos_out.y); + } else { + scale_out.x = std::lerp(scale_out.x * scale, scale_out.x * max_scale, tick); + scale_out.y = std::lerp(scale_out.y * scale, scale_out.y * max_scale, tick); } if(!simple) { @@ -58,6 +61,8 @@ namespace components { rect_out.position.x += current * frame_width; } } else { + scale_out.x = scale; + scale_out.y = scale; playing = false; current = 0; subframe = 0.0f; diff --git a/assets/animations.json b/assets/animations.json index 97d922b..1cf57af 100644 --- a/assets/animations.json +++ b/assets/animations.json @@ -4,6 +4,7 @@ "easing": 0, "ease_rate": 0.5, "scale": 1.0, + "max_scale": 1.0, "simple": false, "frames": 5, "speed": 0.1, @@ -14,6 +15,7 @@ "easing": 0, "ease_rate": 0.5, "scale": 1.0, + "max_scale": 1.0, "simple": false, "frames": 3, "speed": 0.08, @@ -24,6 +26,7 @@ "easing": 0, "ease_rate": 0.5, "scale": 1.0, + "max_scale": 1.0, "simple": false, "frames": 3, "speed": 0.08, @@ -34,6 +37,7 @@ "easing": 0, "ease_rate": 0.5, "scale": 1.0, + "max_scale": 1.0, "simple": false, "frames": 5, "speed": 0.5, @@ -44,6 +48,7 @@ "easing": 0, "ease_rate": 0.5, "scale": 1.0, + "max_scale": 1.0, "simple": false, "frames": 3, "speed": 0.2, @@ -54,6 +59,7 @@ "easing": 3, "ease_rate": 0.2, "scale": 0.5, + "max_scale": 0.5, "simple": true, "frames": 1, "speed": 0.03, @@ -63,7 +69,8 @@ "_type": "Animation", "easing": 1, "ease_rate": 0.2, - "scale": 0.1, + "scale": 1.1, + "max_scale": 1.2, "simple": true, "frames": 10, "speed": 0.3, @@ -73,7 +80,8 @@ "_type": "Animation", "easing": 1, "ease_rate": 0.2, - "scale": 0.1, + "scale": 1.1, + "max_scale": 1.2, "simple": true, "frames": 10, "speed": 0.3, @@ -83,7 +91,8 @@ "_type": "Animation", "easing": 3, "ease_rate": 0.5, - "scale": 0.1, + "scale": 1.1, + "max_scale": 1.2, "simple": true, "frames": 1, "speed": 0.6, @@ -93,7 +102,8 @@ "_type": "Animation", "easing": 3, "ease_rate": 0.5, - "scale": 0.1, + "scale": 1.0, + "max_scale": 0.9, "simple": true, "frames": 1, "speed": 1.0, @@ -103,7 +113,8 @@ "_type": "Animation", "easing": 2, "ease_rate": 0.5, - "scale": 0.1, + "scale": 0.9, + "max_scale": 1.1, "simple": true, "frames": 10, "speed": 1.0, @@ -114,6 +125,7 @@ "easing": 1, "ease_rate": 0.5, "scale": 0.4, + "max_scale": 0.4, "simple": true, "frames": 1, "speed": 0.02, @@ -123,7 +135,8 @@ "_type": "Animation", "easing": 4, "ease_rate": 0.9, - "scale": 0.8, + "scale": 0.6, + "max_scale": 0.7, "simple": false, "frames": 2, "speed": 0.02, diff --git a/boss/ui.cpp b/boss/ui.cpp index 31567bb..36cc22d 100644 --- a/boss/ui.cpp +++ b/boss/ui.cpp @@ -82,7 +82,6 @@ namespace boss { } void UI::render(sf::RenderWindow& window) { - $actions.render(window); $combat_ui.render(window); @@ -139,6 +138,8 @@ namespace boss { // deltaTime = end - start // lerp(a, b, 1 - f ^ deltaTime) // std::this_thread::sleep_for(16ms); + } else { + animation::apply($boss_anim, *$boss_sprite.sprite, $boss_pos); } } } diff --git a/components.hpp b/components.hpp index 3d4eba2..1ee3351 100644 --- a/components.hpp +++ b/components.hpp @@ -109,7 +109,6 @@ namespace components { string name; int width; int height; - float scale; }; struct Sound { @@ -118,7 +117,8 @@ namespace components { }; struct Animation { - float scale = 0.0f; + float scale = 1.0f; + float max_scale = 1.0f; bool simple = true; int frames = 10; float speed = 0.3f; @@ -150,7 +150,7 @@ namespace components { ENROLL_COMPONENT(Tile, display, foreground, background); ENROLL_COMPONENT(BossFight, background, floor, floor_pos, player, boss); - ENROLL_COMPONENT(Sprite, name, width, height, scale); + ENROLL_COMPONENT(Sprite, name, width, height); ENROLL_COMPONENT(Curative, hp); ENROLL_COMPONENT(LightSource, strength, radius); ENROLL_COMPONENT(Position, location.x, location.y); @@ -159,7 +159,7 @@ namespace components { ENROLL_COMPONENT(Motion, dx, dy, random); ENROLL_COMPONENT(Combat, hp, max_hp, damage, dead); ENROLL_COMPONENT(Device, config, events); - ENROLL_COMPONENT(Animation, scale, simple, frames, + ENROLL_COMPONENT(Animation, scale, max_scale, simple, frames, speed, easing, ease_rate, stationary); ENROLL_COMPONENT(Sound, attack, death); ENROLL_COMPONENT(Collision, has); diff --git a/meson.build b/meson.build index 0c3b3e5..c2c5d37 100644 --- a/meson.build +++ b/meson.build @@ -131,6 +131,7 @@ sources = [ executable('runtests', sources + [ 'tests/ai.cpp', 'tests/animation.cpp', + 'tests/animation2.cpp', 'tests/base.cpp', 'tests/battle.cpp', 'tests/components.cpp', @@ -168,6 +169,13 @@ executable('zedcaster', override_options: exe_defaults, dependencies: dependencies) +executable('arena', + sources + [ 'tools/arena.cpp' ], + cpp_args: cpp_args, + link_args: link_args, + override_options: exe_defaults, + dependencies: dependencies) + executable('icongen', [ 'palette.cpp', 'textures.cpp', 'config.cpp', 'dbc.cpp', 'tools/icongen.cpp' ], cpp_args: cpp_args, diff --git a/stats.hpp b/stats.hpp index f7d3759..8c8749e 100644 --- a/stats.hpp +++ b/stats.hpp @@ -49,7 +49,10 @@ struct Stats { inline void sample_time(TimeBullshit start) { auto end = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration(end - start); - sample(1/elapsed.count()); + + if(elapsed.count() > 0.0) { + sample(1.0/elapsed.count()); + } } void dump(std::string msg=""); diff --git a/systems.cpp b/systems.cpp index d8295fa..bb3631d 100644 --- a/systems.cpp +++ b/systems.cpp @@ -53,7 +53,6 @@ void System::lighting() { light.update_fow(position.location, lightsource); } }); - } void System::generate_paths() { @@ -231,7 +230,6 @@ void System::death() { } } - void System::combat(int attack_id) { auto& level = GameDB::current_level(); auto& collider = *level.collision; @@ -671,7 +669,7 @@ void System::spawn_attack(World& world, int attack_id, DinkyECS::Entity enemy) { auto effect = ritual.element == FIRE ? "burning_animation" : "lightning_animation"; auto effect_id = world.entity(); - world.set(effect_id, {effect, 256, 256, 1.0}); + world.set(effect_id, {effect, 256, 256}); world.set(effect_id, {true}); auto shader = shaders::get(ritual.element == FIRE ? "flame" : "lightning"); diff --git a/tools/arena.cpp b/tools/arena.cpp index c2adf3e..4d876b9 100644 --- a/tools/arena.cpp +++ b/tools/arena.cpp @@ -1,45 +1,77 @@ -#include "arena_fsm.hpp" +#include "gui/fsm.hpp" #include "textures.hpp" #include "sound.hpp" +#include "autowalker.hpp" #include "ai.hpp" #include "animation.hpp" #include +#include "shaders.hpp" +#include "backend.hpp" +#include "game_level.hpp" +#include "boss/system.hpp" +#include "gui/fsm_events.hpp" +#include "events.hpp" +#include "constants.hpp" +#include "gui/event_router.hpp" -int main(int argc, char* argv[]) { - try { - dbc::check(argc == 2, "USAGE: arena enemy_name"); - std::string enemy_name{argv[1]}; +void craft_weapon() { + auto world = GameDB::current_world(); + auto& the_belt = world->get_the(); + ritual::Action action{1.0, 20, ritual::Kind::MAGICK, ritual::Element::FIRE, {"fake"}}; + the_belt.equip(the_belt.next(), action); +} - textures::init(); - sound::init(); - ai::init("ai"); - animation::init(); +int main(int, char*[]) { + components::init(); + sfml::Backend backend; + guecs::init(&backend); + ai::init("ai"); + animation::init(); + GameDB::init(); - sound::mute(false); - sound::play("ambient_1", true); + sf::RenderWindow window(sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Bossfight Testing Arena"); + gui::routing::Router router; - arena::FSM main(enemy_name); + sound::mute(true); + sound::play("ambient_1", true); - main.event(arena::Event::STARTED); + GameDB::create_level(); + craft_weapon(); - while(main.active()) { - main.render(); + auto main = boss::System::create_bossfight(); + auto world = GameDB::current_world(); - // ZED: need to sort out how to deal with this in the FSM - if(main.in_state(arena::State::IDLE)) { - main.event(arena::Event::TICK); + + while(!main->in_state(boss::State::END)) { + main->mouse_pos = window.mapPixelToCoords(router.position); + + while(const auto ev = window.pollEvent()) { + auto gui_ev = router.process_event(ev); + + if(gui_ev == gui::Event::QUIT || main->event(gui_ev, {})) { + return 0; + } else { + main->event(gui::Event::TICK, {}); } - - main.keyboard_mouse(); - - main.handle_world_events(); } - return 0; - } catch(const std::system_error& e) { - std::cout << "WARNING: On OSX you'll get this error on shutdown.\n"; - std::cout << "Caught system_error with code " - "[" << e.code() << "] meaning " - "[" << e.what() << "]\n"; + while(world->has_event()) { + auto [evt, entity, data] = world->recv(); + + // FIX YOUR DAMN EVENTS + switch(evt) { + case Events::GUI::ATTACK: + main->event(gui::Event::ATTACK, data); + break; + default: + fmt::println("GUI EVENT: {} entity={}", int(evt), entity); + } + } + + window.clear(); + main->render(window); + window.display(); } + + return 0; } diff --git a/tools/arena_fsm.cpp b/tools/arena_fsm.cpp deleted file mode 100644 index 6219070..0000000 --- a/tools/arena_fsm.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "gui_fsm.hpp" -#include -#include -#include -#include -#include "components.hpp" -#include -#include "systems.hpp" -#include "events.hpp" -#include "sound.hpp" -#include -#include "arena_fsm.hpp" - -namespace arena { - using namespace components; - - FSM::FSM(std::string enemy_name) : - $enemy_name(enemy_name), - $window(sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Arena Battle Tester"), - $font{FONT_FILE_NAME} - { - } - - void FSM::event(Event ev) { - switch($state) { - FSM_STATE(State, START, ev); - FSM_STATE(State, IDLE, ev); - FSM_STATE(State, END, ev); - } - } - - void FSM::START(Event ) { - run_systems(); - dbc::sentinel("THIS IS FUCKED"); - $level = $level_mgr.current(); - - auto entity_id = $level_mgr.spawn_enemy($enemy_name); - - $arena_ui = make_shared($level.world, entity_id); - $arena_ui->init(); - state(State::IDLE); - } - - void FSM::END(Event ev) { - dbc::log(fmt::format("END: received event after done: {}", int(ev))); - } - - void FSM::IDLE(Event ev) { - using enum Event; - - switch(ev) { - case QUIT: - $window.close(); - state(State::END); - return; // done - case CLOSE: - dbc::log("Nothing to close."); - break; - case TICK: - // do nothing - break; - case ATTACK: - dbc::log("ATTACK!"); - break; - default: - dbc::sentinel("unhandled event in IDLE"); - } - } - - void FSM::keyboard_mouse() { - while(const auto ev = $window.pollEvent()) { - if(ev->is()) { - event(Event::QUIT); - } - - if(const auto* mouse = ev->getIf()) { - if(mouse->button == sf::Mouse::Button::Left) { - sf::Vector2f pos = $window.mapPixelToCoords(mouse->position); - (void)pos; - } - } - - if(const auto* key = ev->getIf()) { - using KEY = sf::Keyboard::Scan; - - switch(key->scancode) { - case KEY::Escape: - event(Event::CLOSE); - break; - case KEY::Space: - event(Event::ATTACK); - break; - default: - break; // ignored - } - } - } - } - - void FSM::draw_gui() { - if($arena_ui != nullptr) { - $arena_ui->render($window); - } - } - - void FSM::render() { - $window.clear(); - draw_gui(); - $window.display(); - } - - void FSM::run_systems() { - } - - bool FSM::active() { - return !in_state(State::END); - } - - void FSM::handle_world_events() { - } -} diff --git a/tools/arena_fsm.hpp b/tools/arena_fsm.hpp deleted file mode 100644 index 40d4afd..0000000 --- a/tools/arena_fsm.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#include "constants.hpp" -#include "stats.hpp" -#include "fsm.hpp" -#include "main_ui.hpp" -#include "combat_ui.hpp" -#include "status_ui.hpp" -#include "arena_ui.hpp" -#include "map_view.hpp" -#include "mini_map.hpp" - -namespace arena { - enum class State { - START, - IDLE, - END - }; - - enum class Event { - STARTED=0, - TICK=1, - CLOSE = 7, - ATTACK = 10, - QUIT = 14 - }; - - class FSM : public DeadSimpleFSM { - public: - std::string $enemy_name; - sf::RenderWindow $window; - sf::Font $font; - shared_ptr $arena_ui = nullptr; - - FSM(std::string enemy_name); - - void event(Event ev); - void START(Event ); - void IDLE(Event ev); - void END(Event ev); - - void try_move(int dir, bool strafe); - void keyboard_mouse(); - void draw_gui(); - void render(); - bool active(); - void run_systems(); - void handle_world_events(); - }; -}