diff --git a/Makefile b/Makefile index f202640..562ac6d 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ reset: %.cpp : %.rl ragel -o $@ $< -build: ansi_parser.cpp lel_parser.cpp +build: lel_parser.cpp meson compile -j 10 -C builddir release_build: diff --git a/ansi_parser.cpp b/ansi_parser.cpp deleted file mode 100644 index 19f4d7c..0000000 --- a/ansi_parser.cpp +++ /dev/null @@ -1,376 +0,0 @@ - -#line 1 "ansi_parser.rl" -#include -#include -#include "dbc.hpp" -#include -#include "ansi_parser.hpp" -#include - -using namespace fmt; - - -#line 122 "ansi_parser.rl" - - - -#line 13 "ansi_parser.cpp" -static const char _ansi_parser_actions[] = { - 0, 1, 0, 1, 3, 1, 4, 1, - 5, 1, 6, 1, 7, 1, 8, 1, - 9, 1, 10, 1, 11, 1, 15, 1, - 16, 2, 1, 12, 2, 1, 13, 2, - 6, 7, 2, 16, 5, 3, 1, 14, - 2 -}; - -static const char _ansi_parser_key_offsets[] = { - 0, 0, 1, 2, 11, 12, 14, 17, - 18, 22, 23, 27, 28, 29, 30, 31, - 33, 36, 38, 41, 43, 46, 47, 50, - 51, 52, 53, 54, 55 -}; - -static const int _ansi_parser_trans_keys[] = { - 27, 91, 48, 49, 50, 51, 52, 55, - 57, 53, 54, 109, 48, 109, 34, 48, - 55, 109, 50, 52, 55, 109, 109, 49, - 56, 57, 109, 109, 59, 50, 59, 48, - 57, 59, 48, 57, 48, 57, 59, 48, - 57, 48, 57, 109, 48, 57, 109, 56, - 57, 109, 59, 50, 109, 109, 27, 27, - 0 -}; - -static const char _ansi_parser_single_lengths[] = { - 0, 1, 1, 7, 1, 2, 3, 1, - 4, 1, 4, 1, 1, 1, 1, 0, - 1, 0, 1, 0, 1, 1, 3, 1, - 1, 1, 1, 1, 1 -}; - -static const char _ansi_parser_range_lengths[] = { - 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0 -}; - -static const char _ansi_parser_index_offsets[] = { - 0, 0, 2, 4, 13, 15, 18, 22, - 24, 29, 31, 36, 38, 40, 42, 44, - 46, 49, 51, 54, 56, 59, 61, 65, - 67, 69, 71, 73, 75 -}; - -static const char _ansi_parser_trans_targs[] = { - 2, 1, 3, 0, 4, 5, 8, 10, - 22, 26, 6, 7, 0, 28, 0, 6, - 28, 0, 7, 7, 7, 0, 28, 0, - 7, 7, 9, 28, 0, 28, 0, 11, - 12, 21, 28, 0, 28, 0, 13, 0, - 14, 0, 15, 0, 16, 0, 17, 16, - 0, 18, 0, 19, 18, 0, 20, 0, - 28, 20, 0, 28, 0, 23, 25, 28, - 0, 24, 0, 14, 0, 28, 0, 28, - 0, 2, 1, 2, 1, 0 -}; - -static const char _ansi_parser_trans_actions[] = { - 0, 7, 0, 0, 21, 21, 21, 21, - 21, 21, 21, 21, 0, 31, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 17, 0, 15, 0, 0, - 0, 0, 0, 0, 19, 0, 0, 0, - 3, 0, 0, 0, 1, 0, 25, 0, - 0, 1, 0, 28, 0, 0, 1, 0, - 37, 0, 0, 9, 0, 0, 0, 0, - 0, 0, 0, 5, 0, 11, 0, 13, - 0, 0, 7, 23, 34, 0 -}; - -static const char _ansi_parser_eof_actions[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 23 -}; - -static const int ansi_parser_start = 27; -static const int ansi_parser_first_final = 27; -static const int ansi_parser_error = 0; - -static const int ansi_parser_en_main = 27; - - -#line 125 "ansi_parser.rl" - -#include - -ANSIParser::ANSIParser(sf::Color default_fg, sf::Color default_bg) : - $default_fg(default_fg), - $default_bg(default_bg) -{ -} - -bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb) { - const wchar_t *start = nullptr; - int cs = 0; - unsigned int value = 0; - const wchar_t *p = codes.data(); - const wchar_t *pe = p + codes.size(); - const wchar_t *eof = pe; - sf::Color bgcolor($default_bg); - sf::Color color($default_fg); - sf::Color* target = &color; - - -#line 120 "ansi_parser.cpp" - { - cs = ansi_parser_start; - } - -#line 146 "ansi_parser.rl" - -#line 123 "ansi_parser.cpp" - { - int _klen; - unsigned int _trans; - const char *_acts; - unsigned int _nacts; - const int *_keys; - - if ( p == pe ) - goto _test_eof; - if ( cs == 0 ) - goto _out; -_resume: - _keys = _ansi_parser_trans_keys + _ansi_parser_key_offsets[cs]; - _trans = _ansi_parser_index_offsets[cs]; - - _klen = _ansi_parser_single_lengths[cs]; - if ( _klen > 0 ) { - const int *_lower = _keys; - const int *_mid; - const int *_upper = _keys + _klen - 1; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + ((_upper-_lower) >> 1); - if ( (*p) < *_mid ) - _upper = _mid - 1; - else if ( (*p) > *_mid ) - _lower = _mid + 1; - else { - _trans += (unsigned int)(_mid - _keys); - goto _match; - } - } - _keys += _klen; - _trans += _klen; - } - - _klen = _ansi_parser_range_lengths[cs]; - if ( _klen > 0 ) { - const int *_lower = _keys; - const int *_mid; - const int *_upper = _keys + (_klen<<1) - 2; - while (1) { - if ( _upper < _lower ) - break; - - _mid = _lower + (((_upper-_lower) >> 1) & ~1); - if ( (*p) < _mid[0] ) - _upper = _mid - 2; - else if ( (*p) > _mid[1] ) - _lower = _mid + 2; - else { - _trans += (unsigned int)((_mid - _keys)>>1); - goto _match; - } - } - _trans += _klen; - } - -_match: - cs = _ansi_parser_trans_targs[_trans]; - - if ( _ansi_parser_trans_actions[_trans] == 0 ) - goto _again; - - _acts = _ansi_parser_actions + _ansi_parser_trans_actions[_trans]; - _nacts = (unsigned int) *_acts++; - while ( _nacts-- > 0 ) - { - switch ( *_acts++ ) - { - case 0: -#line 14 "ansi_parser.rl" - { - start = p; - } - break; - case 1: -#line 18 "ansi_parser.rl" - { - value = 0; - size_t len = p - start; - dbc::check(start[0] != '-', "negative numbers not supported"); - - switch(len) { - case 10: value += (start[len-10] - '0') * 1000000000; [[fallthrough]]; - case 9: value += (start[len- 9] - '0') * 100000000; [[fallthrough]]; - case 8: value += (start[len- 8] - '0') * 10000000; [[fallthrough]]; - case 7: value += (start[len- 7] - '0') * 1000000; [[fallthrough]]; - case 6: value += (start[len- 6] - '0') * 100000; [[fallthrough]]; - case 5: value += (start[len- 5] - '0') * 10000; [[fallthrough]]; - case 4: value += (start[len- 4] - '0') * 1000; [[fallthrough]]; - case 3: value += (start[len- 3] - '0') * 100; [[fallthrough]]; - case 2: value += (start[len- 2] - '0') * 10; [[fallthrough]]; - case 1: value += (start[len- 1] - '0'); - break; - default: - dbc::sentinel("can't process > 10 digits"); - } - } - break; - case 2: -#line 40 "ansi_parser.rl" - { - color_cb(color, bgcolor); - } - break; - case 3: -#line 43 "ansi_parser.rl" - { - target = &color; - } - break; - case 4: -#line 46 "ansi_parser.rl" - { - target = &bgcolor; - } - break; - case 5: -#line 50 "ansi_parser.rl" - { - write_cb((*p)); - } - break; - case 6: -#line 54 "ansi_parser.rl" - { - color = $default_fg; - color_cb(color, bgcolor); - } - break; - case 7: -#line 58 "ansi_parser.rl" - { - bgcolor = $default_bg; - color_cb(color, bgcolor); - } - break; - case 8: -#line 62 "ansi_parser.rl" - { - color = $default_bg; - bgcolor = $default_fg; - color_cb(color, bgcolor); - } - break; - case 9: -#line 67 "ansi_parser.rl" - { - color = $default_fg; - bgcolor = $default_bg; - color_cb(color, bgcolor); - } - break; - case 10: -#line 72 "ansi_parser.rl" - { - color = sf::Color(100,100,100); - color_cb(color, bgcolor); - } - break; - case 11: -#line 76 "ansi_parser.rl" - { - color = sf::Color::Red; - color_cb(color, bgcolor); - } - break; - case 12: -#line 81 "ansi_parser.rl" - { target->r = value; } - break; - case 13: -#line 82 "ansi_parser.rl" - { target->g = value; } - break; - case 14: -#line 83 "ansi_parser.rl" - { target->b = value; } - break; - case 15: -#line 84 "ansi_parser.rl" - { value = 0; } - break; - case 16: -#line 85 "ansi_parser.rl" - {} - break; -#line 296 "ansi_parser.cpp" - } - } - -_again: - if ( cs == 0 ) - goto _out; - if ( ++p != pe ) - goto _resume; - _test_eof: {} - if ( p == eof ) - { - const char *__acts = _ansi_parser_actions + _ansi_parser_eof_actions[cs]; - unsigned int __nacts = (unsigned int) *__acts++; - while ( __nacts-- > 0 ) { - switch ( *__acts++ ) { - case 16: -#line 85 "ansi_parser.rl" - {} - break; -#line 314 "ansi_parser.cpp" - } - } - } - - _out: {} - } - -#line 147 "ansi_parser.rl" - - bool good = pe - p == 0; - - if(!good) { - p -= 10; - // dear cthuhlu, save me from the pain that is wstring - for(int i = 0; i < 100; i++) { - try { - print("{}", p[i] == 0x1B ? '^' : char(p[i])); - } catch(...) { - print("?=", int(p[i])); - } - } - } - - (void)ansi_parser_first_final; - (void)ansi_parser_error; - (void)ansi_parser_en_main; - - - return good; -} diff --git a/ansi_parser.hpp b/ansi_parser.hpp deleted file mode 100644 index 9dd054c..0000000 --- a/ansi_parser.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include -#include -#include -#include - -typedef std::function ColorCB; - -typedef std::function WriteCB; - -class ANSIParser { - sf::Color $default_fg; - sf::Color $default_bg; - std::wstring_convert> $converter; - -public: - ANSIParser(sf::Color default_fg, sf::Color default_bg); - - // disable copying - ANSIParser(ANSIParser& ap) = delete; - - bool parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb); -}; diff --git a/ansi_parser.rl b/ansi_parser.rl deleted file mode 100644 index cc2219e..0000000 --- a/ansi_parser.rl +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include "dbc.hpp" -#include -#include "ansi_parser.hpp" -#include - -using namespace fmt; - -%%{ - machine ansi_parser; - alphtype int; - - action tstart { - start = fpc; - } - - action number { - value = 0; - size_t len = fpc - start; - dbc::check(start[0] != '-', "negative numbers not supported"); - - switch(len) { - case 10: value += (start[len-10] - '0') * 1000000000; [[fallthrough]]; - case 9: value += (start[len- 9] - '0') * 100000000; [[fallthrough]]; - case 8: value += (start[len- 8] - '0') * 10000000; [[fallthrough]]; - case 7: value += (start[len- 7] - '0') * 1000000; [[fallthrough]]; - case 6: value += (start[len- 6] - '0') * 100000; [[fallthrough]]; - case 5: value += (start[len- 5] - '0') * 10000; [[fallthrough]]; - case 4: value += (start[len- 4] - '0') * 1000; [[fallthrough]]; - case 3: value += (start[len- 3] - '0') * 100; [[fallthrough]]; - case 2: value += (start[len- 2] - '0') * 10; [[fallthrough]]; - case 1: value += (start[len- 1] - '0'); - break; - default: - dbc::sentinel("can't process > 10 digits"); - } - } - - action color_out { - color_cb(color, bgcolor); - } - action is_fg { - target = &color; - } - action is_bg { - target = &bgcolor; - } - - action out { - write_cb(fc); - } - - action reset_fg { - color = $default_fg; - color_cb(color, bgcolor); - } - action reset_bg { - bgcolor = $default_bg; - color_cb(color, bgcolor); - } - action invert { - color = $default_bg; - bgcolor = $default_fg; - color_cb(color, bgcolor); - } - action reset_invert { - color = $default_fg; - bgcolor = $default_bg; - color_cb(color, bgcolor); - } - action half_bright { - color = sf::Color(100,100,100); - color_cb(color, bgcolor); - } - action red_text { - color = sf::Color::Red; - color_cb(color, bgcolor); - } - - action red { target->r = value; } - action blue { target->g = value; } - action green { target->b = value; } - action start { value = 0; } - action end {} - action log { println("command {}", (char)fc); } - - ESC = 0x1B; - start = ESC "["; - fg = "38;" %is_fg; - bg = "48;" %is_bg; - reset = ("39" %reset_fg | "49" %reset_bg); - num = digit+ >tstart %number; - color256 = "5;"; - color24b = "2;"; - - ansi = ( - start %start - ( - reset | - "0" %reset_fg %reset_bg | - "1" | - "2" %half_bright | - "3" | - "4" | - "5" | - "6" | - "7" %invert | - "31" %red_text | - "22" | - "24" | - "27" %reset_invert | - "9" ["0"-"7"] | - "10" ["0"-"7"] | - (fg|bg) (color24b num %red ";" num %blue ";" num %green ) %color_out - ) "m" %end - ); - - other = (any+ @out -- ESC)*; - - main := (other :> ansi)**; -}%% - -%% write data; - -#include - -ANSIParser::ANSIParser(sf::Color default_fg, sf::Color default_bg) : - $default_fg(default_fg), - $default_bg(default_bg) -{ -} - -bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_cb) { - const wchar_t *start = nullptr; - int cs = 0; - unsigned int value = 0; - const wchar_t *p = codes.data(); - const wchar_t *pe = p + codes.size(); - const wchar_t *eof = pe; - sf::Color bgcolor($default_bg); - sf::Color color($default_fg); - sf::Color* target = &color; - - %% write init; - %% write exec; - - bool good = pe - p == 0; - - if(!good) { - p -= 10; - // dear cthuhlu, save me from the pain that is wstring - for(int i = 0; i < 100; i++) { - try { - print("{}", p[i] == 0x1B ? '^' : char(p[i])); - } catch(...) { - print("?=", int(p[i])); - } - } - } - - (void)ansi_parser_first_final; - (void)ansi_parser_error; - (void)ansi_parser_en_main; - - return good; -} diff --git a/assets/bosses.json b/assets/bosses.json index 9e1bfa8..2d18cdb 100644 --- a/assets/bosses.json +++ b/assets/bosses.json @@ -3,7 +3,7 @@ "components": [ {"_type": "BossFight", "background": "boss_fight_background", - "stage": false, + "stage": null, "weapon_sound": "Sword_Hit_2" }, {"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false}, @@ -24,7 +24,7 @@ "components": [ {"_type": "BossFight", "background": "devils_fingers_background", - "stage": false, + "stage": "devils_fingers_stage", "weapon_sound": "Sword_Hit_2" }, {"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 20, "dead": false}, diff --git a/autowalker.cpp b/autowalker.cpp index f4279c9..8ce8c66 100644 --- a/autowalker.cpp +++ b/autowalker.cpp @@ -178,6 +178,8 @@ void Autowalker::rotate_player(Point current, Point target) { facing = fsm.$main_ui.$compass_dir; } + while(fsm.in_state(gui::State::ROTATING)) send_event(gui::Event::TICK); + dbc::check(fsm.$main_ui.$compass_dir == target_facing, "player isn't facing the correct direction"); } @@ -229,6 +231,14 @@ void Autowalker::handle_player_walk(ai::State& start, ai::State& goal) { send_event(gui::Event::ATTACK); } else if(action.name == "kill_enemy") { status("KILLING ENEMY"); + + // TODO: find the enemy and then rotate toward them + Point current = get_current_position(); + if(fsm.in_state(gui::State::IN_COMBAT)) { + rotate_player(current, {current.x - 1, current.y - 1}); + dbc::log("TODO: you should find the enemy and face them instead of THIS GARBAGE!"); + } + process_combat(); } else if(action.name == "use_healing") { status("USING HEALING"); @@ -283,7 +293,6 @@ void Autowalker::process_move(Pathing& paths) { } rotate_player(current, target); - while(fsm.in_state(gui::State::ROTATING)) send_event(gui::Event::TICK); send_event(gui::Event::MOVE_FORWARD); while(fsm.in_state(gui::State::MOVING)) send_event(gui::Event::TICK); diff --git a/components.cpp b/components.cpp index 146bac8..7e10528 100644 --- a/components.cpp +++ b/components.cpp @@ -43,11 +43,11 @@ namespace components { case ease::SINE: return ease::sine(float(frames) / subframe * ease_rate); case ease::OUT_CIRC: - return ease::sine(ease::out_circ(float(frames) / subframe * ease_rate)); + return ease::out_circ(ease::sine(float(frames) / subframe * ease_rate)); case ease::OUT_BOUNCE: - return ease::sine(ease::out_bounce(float(frames) / subframe * ease_rate)); + return ease::out_bounce(ease::sine(float(frames) / subframe * ease_rate)); case ease::IN_OUT_BACK: - return ease::sine(ease::in_out_back(float(frames) / subframe * ease_rate)); + return ease::in_out_back(ease::sine(float(frames) / subframe * ease_rate)); default: dbc::sentinel( fmt::format("Invalid easing {} given to animation", diff --git a/components.hpp b/components.hpp index 0feac2d..b9e8f92 100644 --- a/components.hpp +++ b/components.hpp @@ -120,7 +120,7 @@ namespace components { bool stationary = false; int current = 0; bool playing = false; - float subframe = 0; + float subframe = 1.0f; int texture_width = TEXTURE_WIDTH; void play(); diff --git a/config.cpp b/config.cpp index 755abb7..ea3ef62 100644 --- a/config.cpp +++ b/config.cpp @@ -15,13 +15,6 @@ json &Config::operator[](const std::string &key) { return $config[key]; } -std::wstring Config::wstring(const std::string key) { - dbc::check($config.contains(key), fmt::format("ERROR wstring in config, key {} doesn't exist.", key)); - std::wstring_convert> $converter; - const std::string& str_val = $config[key]; - return $converter.from_bytes(str_val); -} - std::wstring Config::wstring(const std::string main_key, const std::string sub_key) { dbc::check($config.contains(main_key), fmt::format("ERROR wstring main/key in config, main_key {} doesn't exist.", main_key)); dbc::check($config[main_key].contains(sub_key), fmt::format("ERROR wstring in config, main_key/key {}/{} doesn't exist.", main_key, sub_key)); diff --git a/config.hpp b/config.hpp index 39dd917..52bf664 100644 --- a/config.hpp +++ b/config.hpp @@ -14,7 +14,6 @@ struct Config { nlohmann::json &operator[](const std::string &key); nlohmann::json &json() { return $config; }; - std::wstring wstring(const std::string main_key); std::wstring wstring(const std::string main_key, const std::string sub_key); std::vector keys(); }; diff --git a/easings.hpp b/easings.hpp index 5c6aa26..9a05a33 100644 --- a/easings.hpp +++ b/easings.hpp @@ -4,7 +4,7 @@ namespace ease { enum Style { - NONE, SINE, OUT_CIRC, OUT_BOUNCE, IN_OUT_BACK + NONE, SINE, OUT_CIRC, OUT_BOUNCE, IN_OUT_BACK, FUCKFACE }; inline double sine(double x) { @@ -12,7 +12,7 @@ namespace ease { } inline double out_circ(double x) { - return std::sqrt(1.0f - std::pow(x - 1.0f, 2.0f)); + return std::sqrt(1.0f - ((x - 1.0f) * (x - 1.0f))); } inline double out_bounce(double x) { diff --git a/gui_fsm.cpp b/gui_fsm.cpp index 98e6efe..7ccba73 100644 --- a/gui_fsm.cpp +++ b/gui_fsm.cpp @@ -15,7 +15,6 @@ namespace gui { FSM::FSM() : $window(sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Zed's Raycaster Thing"), $main_ui($window), - $renderer($window), $level($levels.current()), $map_ui($level), $combat_ui($level), @@ -53,11 +52,6 @@ namespace gui { $boss_fight_ui = $levels.create_bossfight($level.world); $boss_fight_ui->init(); - $renderer.init_terminal(); - $map_ui.create_render(); - $map_ui.resize_canvas(); - $renderer.resize_grid(BASE_MAP_FONT_SIZE, $map_ui); - run_systems(); state(State::IDLE); } @@ -106,6 +100,7 @@ namespace gui { break; default: dbc::log(fmt::format("In ATTACKING state, unhandled event {}", (int)ev)); + state(State::IDLE); } } @@ -152,8 +147,6 @@ namespace gui { state(State::ROTATING); break; case MAP_OPEN: - $renderer.resize_grid(BASE_MAP_FONT_SIZE, $map_ui); - $map_ui.resize_canvas(); state(State::MAPPING); break; case ATTACK: @@ -327,8 +320,6 @@ namespace gui { void FSM::render() { if(in_state(State::MAPPING)) { $window.clear(); - $map_ui.render(); - $renderer.draw($map_ui); } else if(in_state(State::NEXT_LEVEL)) { $window.clear(); $boss_fight_ui->render($window); diff --git a/gui_fsm.hpp b/gui_fsm.hpp index 387a968..acff410 100644 --- a/gui_fsm.hpp +++ b/gui_fsm.hpp @@ -3,7 +3,6 @@ #include "stats.hpp" #include "levelmanager.hpp" #include "fsm.hpp" -#include "render.hpp" #include "map_view.hpp" #include "main_ui.hpp" #include "combat_ui.hpp" @@ -49,7 +48,6 @@ namespace gui { bool autowalking = false; LevelManager $levels; MainUI $main_ui; - SFMLRender $renderer; GameLevel $level; shared_ptr $boss_fight_ui = nullptr; MapViewUI $map_ui; diff --git a/map_view.cpp b/map_view.cpp index fbd1bec..befb89b 100644 --- a/map_view.cpp +++ b/map_view.cpp @@ -1,14 +1,11 @@ #include "map_view.hpp" #include #include -#include "systems.hpp" namespace gui { using namespace components; - using ftxui::Color; MapViewUI::MapViewUI(GameLevel &level) : - Panel(0, 0, 0, 0, true), $level(level) { } @@ -18,54 +15,6 @@ namespace gui { } void MapViewUI::draw_map() { - const auto& debug = $level.world->get_the(); - const auto& player = $level.world->get_the(); - const auto& player_position = $level.world->get(player.entity); - Point start = $level.map->center_camera(player_position.location, width, height); - auto &tiles = $level.map->tiles(); - auto &paths = $level.map->paths(); - auto &lighting = $level.lights->lighting(); - // WARN: this is exploiting that -1 in size_t becomes largest - size_t end_x = std::min(size_t(width), $level.map->width() - start.x); - size_t end_y = std::min(size_t(height), $level.map->height() - start.y); - - for(size_t y = 0; y < end_y; ++y) { - for(size_t x = 0; x < end_x; ++x) - { - const Tile& tile = tiles.at(start.x+x, start.y+y); - // light value is an integer that's a percent - float light_value = debug.LIGHT ? 80 * PERCENT : lighting[start.y+y][start.x+x] * PERCENT; - int dnum = debug.PATHS ? paths[start.y+y][start.x+x] : WALL_PATH_LIMIT; - - if(debug.PATHS && dnum != WALL_PATH_LIMIT) { - string num = dnum > 15 ? "*" : fmt::format("{:x}", dnum); - - $canvas.DrawText(x * 2, y * 4, num, [dnum, tile](auto &pixel) { - pixel.foreground_color = Color::HSV(dnum * 20, 150, 200); - pixel.background_color = Color::HSV(30, 20, tile.foreground[2] * 50 * PERCENT); - }); - } else { - $canvas.DrawText(x * 2, y * 4, tile.display, [tile, light_value](auto &pixel) { - pixel.foreground_color = Color::HSV(tile.foreground[0], tile.foreground[1], tile.foreground[2] * light_value); - pixel.background_color = Color::HSV(tile.background[0], tile.background[1], tile.background[2] * light_value); - }); - } - } - } - - System::draw_entities(*$level.world, *$level.map, lighting, $canvas, start, width, height); - } - - void MapViewUI::create_render() { - set_renderer(Renderer([&] { - draw_map(); - return canvas($canvas); - })); - } - - void MapViewUI::resize_canvas() { - // set canvas to best size - $canvas = Canvas(width * 2, height * 4); } } diff --git a/map_view.hpp b/map_view.hpp index d144784..959e39c 100644 --- a/map_view.hpp +++ b/map_view.hpp @@ -1,19 +1,12 @@ #pragma once -#include "panel.hpp" -#include #include "levelmanager.hpp" -using ftxui::Canvas; - namespace gui { - class MapViewUI : public Panel { + class MapViewUI { public: - Canvas $canvas; GameLevel $level; MapViewUI(GameLevel &level); - void create_render(); - void resize_canvas(); void draw_map(); void update_level(GameLevel &level); }; diff --git a/meson.build b/meson.build index 39814da..fefe1ca 100644 --- a/meson.build +++ b/meson.build @@ -68,22 +68,17 @@ sfml_system = dependency('sfml_system') sfml_window = dependency('sfml_window', default_options: ['default_library=shared']) -ftxui_screen = dependency('ftxui-screen') -ftxui_dom = dependency('ftxui-dom') -ftxui_component = dependency('ftxui-component') - dependencies += [ fmt, json, freetype2, flac, ogg, vorbis, vorbisfile, vorbisenc, sfml_audio, sfml_graphics, sfml_network, sfml_system, - sfml_window, ftxui_screen, ftxui_dom, ftxui_component + sfml_window ] sources = [ 'ai.cpp', 'ai_debug.cpp', - 'ansi_parser.cpp', 'autowalker.cpp', 'boss_fight_ui.cpp', 'camera.cpp', @@ -106,11 +101,9 @@ sources = [ 'matrix.cpp', 'matrix.cpp', 'overlay_ui.cpp', - 'panel.cpp', 'pathing.cpp', 'rand.cpp', 'raycaster.cpp', - 'render.cpp', 'rituals.cpp', 'save.cpp', 'shiterator.hpp', @@ -125,15 +118,14 @@ sources = [ ] executable('runtests', sources + [ - 'tests/ansi_parser.cpp', + 'tests/ai.cpp', 'tests/base.cpp', - 'tests/rituals.cpp', 'tests/components.cpp', 'tests/config.cpp', 'tests/dbc.cpp', 'tests/dinkyecs.cpp', + 'tests/easings.cpp', 'tests/fsm.cpp', - 'tests/ai.cpp', 'tests/guecs.cpp', 'tests/inventory.cpp', 'tests/lel.cpp', @@ -142,6 +134,7 @@ executable('runtests', sources + [ 'tests/map.cpp', 'tests/matrix.cpp', 'tests/pathing.cpp', + 'tests/rituals.cpp', 'tests/sound.cpp', 'tests/spatialmap.cpp', 'tests/textures.cpp', diff --git a/panel.cpp b/panel.cpp deleted file mode 100644 index e3a3cbf..0000000 --- a/panel.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "panel.hpp" -#include "dbc.hpp" - -void Panel::resize(int w, int h) { - $dirty = true; - width = w; - height = h; - $screen = Screen(width, height); -} - -void Panel::set_renderer(Component renderer) { - $dirty = true; - $component = renderer; -} - -void Panel::add(Component child) { - dbc::pre("must set_renderer first", $component != nullptr); - $dirty = true; - $component->Add(child); -} - -void Panel::render() { - $dirty = true; - if(must_clear) $screen.Clear(); - Render($screen, $component->Render()); -} - -const std::wstring& Panel::to_string() { - if($dirty) { - std::string as_text = $screen.ToString(); - $screenout = $converter.from_bytes(as_text); - $dirty = false; - } - - return $screenout; -} - -void Panel::mouse_click(ftxui::Mouse::Button btn, Point pos) { - ftxui::Mouse mev{ - .button=btn, - .motion=ftxui::Mouse::Motion::Pressed, - .x=int(pos.x), .y=int(pos.y) - }; - - $component->OnEvent(ftxui::Event::Mouse("", mev)); -} - -void Panel::mouse_release(ftxui::Mouse::Button btn, Point pos) { - ftxui::Mouse mev{ - .button=btn, - .motion=ftxui::Mouse::Motion::Released, - .x=int(pos.x), .y=int(pos.y) - }; - - $component->OnEvent(ftxui::Event::Mouse("", mev)); -} - -const Screen& Panel::screen() { - return $screen; -} - -void Panel::key_press(ftxui::Event event) { - $component->OnEvent(event); -} diff --git a/panel.hpp b/panel.hpp deleted file mode 100644 index e764708..0000000 --- a/panel.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#include // for Render -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "color.hpp" -#include "point.hpp" - -const int UI_PANEL_BORDER_PX=5; - -using ftxui::Renderer, ftxui::Component, ftxui::Element, ftxui::Screen; - -class Panel { -public: - int x; - int y; - int width; - int height; - bool has_border = false; - bool must_clear = true; - bool grid = false; - sf::Color default_bg = ColorValue::BLACK; - sf::Color default_fg = ColorValue::LIGHT_LIGHT; - sf::Color border_color = ColorValue::MID; - int border_px = UI_PANEL_BORDER_PX; - - bool $dirty = true; - Component $component = nullptr; - Screen $screen; - std::wstring_convert> $converter; - std::wstring $screenout; - - Panel(int x, int y, int width, int height, bool is_grid=false) : - x(x), - y(y), - width(width), - height(height), - grid(is_grid), - $screen(Screen(width, height)) - { - must_clear = !is_grid; - }; - - void resize(int width, int height); - void set_renderer(Component renderer); - void add(Component child); - void render(); - void mouse_click(ftxui::Mouse::Button btn, Point pos); - void mouse_release(ftxui::Mouse::Button btn, Point pos); - void key_press(ftxui::Event event); - const std::wstring &to_string(); - const Screen &screen(); -}; diff --git a/render.cpp b/render.cpp deleted file mode 100644 index adf4fd0..0000000 --- a/render.cpp +++ /dev/null @@ -1,275 +0,0 @@ -#include "render.hpp" -#include "ansi_parser.hpp" -#include -#include -#include -#include "map.hpp" -#include -#include "color.hpp" - -#if defined(_WIN64) || defined(_WIN32) - #include - #include - #include -#endif - -using namespace fmt; - -SFMLRender::SFMLRender(sf::RenderWindow &window) : - $window(window), - $map_font_size(0), - $line_spacing(0), - $default_fg(ColorValue::LIGHT_MID), - $default_bg(ColorValue::BLACK), - $bg_sprite($font_texture), - $font(FONT_FILE_NAME), - $ui_text($font), - $ansi($default_fg, $default_bg) -{ - // force true color, but maybe I want to support different color sets - $font.setSmooth(false); - $ui_text.setPosition({0,0}); - $ui_text.setCharacterSize($config.ui_font_size); - $ui_text.setFillColor(ColorValue::LIGHT_MID); - sf::Glyph glyph = $font.getGlyph($config.ui_base_char, $config.ui_font_size, false); - $text_bounds = glyph.bounds; - $cells_w = std::ceil($config.video_x / $text_bounds.size.x); - $cells_h = std::ceil($config.video_y / $text_bounds.size.y); -} - -sf::Sprite &SFMLRender::get_text_sprite(wchar_t tile) { - if(!$sprites.contains(tile)) { - sf::Glyph glyph = $font.getGlyph(tile, $map_font_size, false); - // WARNING! we actually have to do this here because SFML caches - // the glyphs on the font texture, so this gets loaded each time - // we get a new glyph from the font. - $font_texture = $font.getTexture($map_font_size); - $sprites.try_emplace(tile, $font_texture, glyph.textureRect); - } - - return $sprites.at(tile); -} - -void SFMLRender::clear_cache() { - $sprites.clear(); - bool good = $font.openFromFile(FONT_FILE_NAME); - dbc::check(good, "Failed to load the font."); - $font.setSmooth(false); - $ui_text.setFont($font); -} - -void SFMLRender::center_panel(Panel &panel) { - int cell_center_x = ($cells_w - panel.width) / 2; - int cell_center_y = ($cells_h - panel.height) / 2; - - panel.x = cell_center_x * $text_bounds.size.x; - panel.y = cell_center_y * $text_bounds.size.y; -} - -void SFMLRender::resize_grid(int new_size, Panel &panel_out) { - auto glyph = $font.getGlyph($config.bg_tile, new_size, false); - int view_x = std::ceil(($config.video_x - panel_out.x) / glyph.bounds.size.x); - int view_y = std::ceil(($config.video_y - panel_out.y) / glyph.bounds.size.y); - - // looks good, set 'em all - $base_glyph = glyph; - $map_font_size = new_size; - $sprites.clear(); // need to reset the sprites for the new size - $line_spacing = $font.getLineSpacing($map_font_size); - $bg_sprite = get_text_sprite($config.bg_tile); - $grid_bounds = $bg_sprite.getLocalBounds(); - panel_out.resize(view_x, view_y); -} - -inline void configure_tile(const sf::Sprite &sprite, sf::FloatRect &sp_bounds, sf::FloatRect grid_bounds, float &width_delta, float &height_delta) { - // BUG: I think I could create a struct that kept this info for all sprites loaded - // should look into caching all this instead of calcing it each time - sp_bounds = sprite.getLocalBounds(); - - // calculate where to center the sprite, but only if it's smaller - width_delta = grid_bounds.size.x > sp_bounds.size.x ? (grid_bounds.size.x - sp_bounds.size.x) / 2 : 0; - height_delta = grid_bounds.size.y > sp_bounds.size.x ? (grid_bounds.size.y - sp_bounds.size.y) / 2 : 0; -} - -void SFMLRender::render_grid(const std::wstring &text, sf::Color default_fg, sf::Color default_bg, float x, float y) { - wchar_t last_tile = $config.bg_tile; - sf::FloatRect sp_bounds; - float width_delta = 0; - float height_delta = 0; - sf::Sprite &sprite = get_text_sprite(last_tile); - const float start_x = x; - sf::Color cur_fg = default_fg; - sf::Color cur_bg = default_bg; - - $ansi.parse(text, [&](auto fg, auto bg) { - cur_fg = fg; - cur_bg = bg; - }, - - [&](wchar_t tile) { - switch(tile) { - case '\r': break; // ignore it - case '\n': { - // don't bother processing newlines, just skip - y += $line_spacing; - x = start_x; - } - break; - default: { - // only get a new sprite if the tile changed - if(last_tile != tile) { - sprite = get_text_sprite(tile); - configure_tile(sprite, sp_bounds, $grid_bounds, width_delta, height_delta); - last_tile = tile; // update last tile seen - } - - sprite.setPosition({x+width_delta, y+height_delta}); - sprite.setColor(cur_fg); - - // only draw background char if it's different from default - if(cur_bg != default_bg) { - $bg_sprite.setPosition({x, y}); - $bg_sprite.setColor(cur_bg); - $window.draw($bg_sprite); - } - - $window.draw(sprite); - // next cell - x += $base_glyph.advance; - } - } - }); -} - -inline sf::FloatRect draw_chunk(sf::RenderWindow& window, - sf::FloatRect text_bounds, sf::Text& text, sf::Color default_bg, - sf::Color bgcolor, int bg_box_offset, float x, float y, std::wstring &out) -{ - text.setString(out); - text.setPosition({x, y}); - // get a base character for the cell size - sf::FloatRect bounds({x, y}, {text_bounds.size.x * out.size(), text_bounds.size.y}); - - if(default_bg != bgcolor) { - sf::RectangleShape backing(bounds.size); - backing.setFillColor(bgcolor); - backing.setPosition({bounds.position.x, bounds.position.y + bg_box_offset}); - window.draw(backing); - } - - window.draw(text); - out.clear(); - return bounds; -} - -void SFMLRender::render_text(const std::wstring &text, sf::Color default_fg, sf::Color default_bg, float start_x, float start_y) { - std::wstring out; - float x = start_x; - float y = start_y; - sf::Color cur_bg = default_bg; - - // start with the default_fg until it's changed - $ui_text.setFillColor(default_fg); - - $ansi.parse(text, - [&](auto fg, auto bg) { - if(out.size() > 0 ) { - auto bounds = draw_chunk($window, - $text_bounds, $ui_text, - default_bg, cur_bg, $config.bg_box_offset, x, y, out); - x += bounds.size.x; - } - cur_bg = bg; - $ui_text.setFillColor(fg); - }, - [&](wchar_t tile) { - switch(tile) { - case '\r': break; // ignore it - case '\n': { - sf::FloatRect bounds; - - if(out.size() > 0) { - bounds = draw_chunk($window, $text_bounds, - $ui_text, default_bg, cur_bg, $config.bg_box_offset, x, y, out); - } else { - bounds = $ui_text.getLocalBounds(); - } - - y += bounds.size.y; - x = start_x; // reset to the original position - } - break; - default: - out += tile; - break; - } - } - ); - - if(out.size() > 0) { - draw_chunk($window, $text_bounds, $ui_text, default_bg, cur_bg, $config.bg_box_offset, x, y, out); - } -} - -void SFMLRender::draw_sprite(sf::Sprite &sprite, sf::Shader *shader) { - $window.draw(sprite, shader); -} - -/* - * Does not render the panel, you have to do that so you can control - * when things render. - */ -void SFMLRender::draw(Panel &panel, float x_offset, float y_offset) { - const std::wstring &panelout = panel.to_string(); - - auto bounds = panel.grid ? $grid_bounds : $text_bounds; - - sf::RectangleShape backing( - sf::Vector2f(bounds.size.x * panel.width + panel.border_px, - bounds.size.y * panel.height + panel.border_px)); - - backing.setFillColor(panel.default_bg); - - if(panel.has_border) { - backing.setOutlineColor(panel.border_color); - backing.setOutlineThickness(panel.border_px); - } - - backing.setPosition({panel.x + x_offset, panel.y + y_offset}); - $window.draw(backing); - - if(panel.grid) { - render_grid(panelout, panel.default_fg, panel.default_bg, panel.x + x_offset, panel.y + y_offset); - } else { - render_text(panelout, panel.default_fg, panel.default_bg, panel.x + x_offset, panel.y + y_offset); - } -} - -bool SFMLRender::mouse_position(Panel &panel, Point &out) { - // yes, you have to do this in sfml - sf::Vector2f pos = $window.mapPixelToCoords(sf::Mouse::getPosition($window)); - - auto bounds = panel.grid ? $grid_bounds : $text_bounds; - - if(pos.x >= panel.x && pos.y >= panel.y - && pos.x <= (panel.x + panel.width * bounds.size.x) - && pos.y <= (panel.y + panel.height * bounds.size.y)) - { - out = { - size_t((pos.x - panel.x) / bounds.size.x), - size_t((pos.y - panel.y) / bounds.size.y) - }; - - return true; - } - - return false; -} - -void SFMLRender::init_terminal() { -#if defined(_WIN64) || defined(_WIN32) - _setmode(_fileno(stdout), _O_U16TEXT); -#endif - - ftxui::Terminal::SetColorSupport(ftxui::Terminal::Color::TrueColor); -} diff --git a/render.hpp b/render.hpp deleted file mode 100644 index 238b2df..0000000 --- a/render.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include "point.hpp" -#include -#include "ansi_parser.hpp" -#include "panel.hpp" -#include "constants.hpp" -#include - -using ftxui::Canvas, ftxui::Screen; - -/* - * BUG: This could be so much better. - */ -struct RenderConfig { - unsigned int video_x = SCREEN_WIDTH; - unsigned int video_y = SCREEN_HEIGHT; - int ui_font_size=UI_FONT_SIZE; - int base_map_font_size=BASE_MAP_FONT_SIZE; - wchar_t bg_tile = BG_TILE; - wchar_t ui_base_char = UI_BASE_CHAR; - int bg_box_offset=BG_BOX_OFFSET; -}; - -struct SFMLRender { - int $cells_w = 0; - int $cells_h = 0; - RenderConfig $config; - sf::RenderWindow& $window; - int $map_font_size; - float $line_spacing; - sf::Color $default_fg; - sf::Color $default_bg; - sf::Texture $font_texture; - sf::Sprite $bg_sprite; - sf::Font $font; - sf::Text $ui_text; - ANSIParser $ansi; - - std::unordered_map $sprites; - sf::Glyph $base_glyph; - sf::FloatRect $grid_bounds; - std::wstring_convert> $converter; - sf::FloatRect $text_bounds; - - SFMLRender(sf::RenderWindow& window); - - // disable copy - SFMLRender(SFMLRender &other) = delete; - - sf::Sprite &get_text_sprite(wchar_t tile); - void resize_grid(int new_size, Panel &panel_out); - void render_grid(const std::wstring &text, sf::Color default_fg, sf::Color default_bg, float x, float y); - void render_text(const std::wstring &text, sf::Color default_fg, sf::Color default_bg, float x, float y); - - void draw(Panel &panel, float x_offset=0.0f, float y_offset=0.0f); - void draw_sprite(sf::Sprite &sprite, sf::Shader *shader); - void center_panel(Panel &panel); - - std::optional poll_event() { - return $window.pollEvent(); - } - - void close() { return $window.close(); } - - bool is_open() { return $window.isOpen(); } - - int font_size() { return $map_font_size; } - void clear() { $window.clear(); } - void display() { $window.display(); } - bool mouse_position(Panel &panel, Point &out); - void clear_cache(); - static void init_terminal(); -}; diff --git a/save.cpp b/save.cpp index 5489a2e..881f6f7 100644 --- a/save.cpp +++ b/save.cpp @@ -8,27 +8,6 @@ using namespace components; using namespace fmt; -template -inline void extract(DinkyECS::World &world, std::map &into) { - auto from_world = world.entity_map_for(); - for(auto [entity, value] : from_world) { - into[entity] = std::any_cast(value); - } -} - -void save::to_file(fs::path path, DinkyECS::World &world, Map &map) { - (void)path; - (void)world; - (void)map; -} - - -void save::from_file(fs::path path, DinkyECS::World &world_out, Map &map_out) { - (void)path; - (void)world_out; - (void)map_out; -} - void save::load_configs(DinkyECS::World &world) { Config game("./assets/config.json"); Config enemies("./assets/enemies.json"); diff --git a/save.hpp b/save.hpp index a13558d..5e3df38 100644 --- a/save.hpp +++ b/save.hpp @@ -10,29 +10,5 @@ namespace save { namespace fs = std::filesystem; - struct MapData { - size_t width; - size_t height; - std::vector rooms; - Matrix walls; - }; - - struct Facts { - components::Player player; - }; - - struct SaveData { - Facts facts; - MapData map; - - std::map position; - std::map motion; - std::map combat; - std::map tile; - // std::map inventory; - }; - - void to_file(fs::path path, DinkyECS::World &world, Map &map); - void from_file(fs::path path, DinkyECS::World &world_out, Map &map); void load_configs(DinkyECS::World &world); } diff --git a/scripts/coverage_report.ps1 b/scripts/coverage_report.ps1 index 88f62a6..79e38de 100644 --- a/scripts/coverage_report.ps1 +++ b/scripts/coverage_report.ps1 @@ -4,7 +4,10 @@ cp *.cpp,*.hpp,*.rl builddir . .venv/Scripts/activate rm -recurse -force coverage +cp scripts\gcovr_patched_coverage.py .venv\Lib\site-packages\gcovr\coverage.py -gcovr -o coverage/ --html --html-details --gcov-ignore-errors all -e builddir/subprojects -e subprojects . +gcovr -o coverage/ --html --html-details --html-theme github.dark-blue --gcov-ignore-errors all --gcov-ignore-parse-errors negative_hits.warn_once_per_file -e builddir/subprojects -e builddir -e subprojects -j 10 . + +rm *.gcov.json.gz start .\coverage\coverage_details.html diff --git a/systems.cpp b/systems.cpp index c86abf3..c7be574 100644 --- a/systems.cpp +++ b/systems.cpp @@ -16,7 +16,6 @@ using std::string; using namespace fmt; using namespace components; using lighting::LightSource; -using ftxui::Color; void System::lighting(GameLevel &level) { auto &light = *level.lights; @@ -331,11 +330,9 @@ void System::plan_motion(DinkyECS::World& world, Point move_to) { /* * This one is called inside the MapViewUI very often so - * just avoide GameMap unlike the others. - * - * BUG: Just get rid of this and use the new UI to do the map + * just avoid GameMap unlike the others. */ -void System::draw_entities(DinkyECS::World &world, Map &map, const Matrix &lights, ftxui::Canvas &canvas, const Point &cam_orig, size_t view_x, size_t view_y) { +void System::draw_entities(DinkyECS::World &world, Map &map, const Matrix &lights, const Point &cam_orig, size_t view_x, size_t view_y) { auto &tiles = map.tiles(); world.query([&](auto, auto &pos, auto &tile) { @@ -346,11 +343,10 @@ void System::draw_entities(DinkyECS::World &world, Map &map, const Matrix &light float light_value = lights[pos.location.y][pos.location.x] * PERCENT; const Tile& cell = tiles.at(pos.location.x, pos.location.y); - // the 2 and 4 are from ftxui::Canvas since it does a kind of "subpixel" drawing - canvas.DrawText(loc.x*2, loc.y*4, tile.display, [tile, light_value, cell](auto &pixel) { - pixel.foreground_color = Color::HSV(tile.foreground[0], tile.foreground[1], tile.foreground[2] * light_value); - pixel.background_color = Color::HSV(cell.background[0], cell.background[1], cell.background[2] * light_value); - }); + (void)loc; // not used yet, this after ripping out map so needs rewrite + (void)light_value; + (void)cell; + (void)tile; } }); } diff --git a/systems.hpp b/systems.hpp index f4a4653..9e5f1eb 100644 --- a/systems.hpp +++ b/systems.hpp @@ -1,7 +1,6 @@ #pragma once #include "components.hpp" #include "levelmanager.hpp" -#include namespace System { @@ -18,7 +17,7 @@ namespace System { void init_positions(DinkyECS::World &world, SpatialMap &collider); void device(DinkyECS::World &world, DinkyECS::Entity actor, DinkyECS::Entity item); void plan_motion(DinkyECS::World& world, Point move_to); - void draw_entities(DinkyECS::World &world, Map &map, const Matrix &lights, ftxui::Canvas &canvas, const Point &cam_orig, size_t view_x, size_t view_y); + void draw_entities(DinkyECS::World &world, Map &map, const Matrix &lights, const Point &cam_orig, size_t view_x, size_t view_y); void enemy_ai(GameLevel &level); void combat(GameLevel &level); diff --git a/tests/components.cpp b/tests/components.cpp index 386bef8..5f95c23 100644 --- a/tests/components.cpp +++ b/tests/components.cpp @@ -3,6 +3,7 @@ #include "dinkyecs.hpp" #include "config.hpp" #include +#include "easings.hpp" using namespace components; using namespace DinkyECS; @@ -27,3 +28,66 @@ TEST_CASE("confirm component loading works", "[components]") { } } } + +TEST_CASE("make sure json_mods works", "[components]") { + Config config("assets/bosses.json"); + // this confirms that loading something with an optional + // field works with the json conversions in json_mods.hpp + for(auto& comp_data : config["RAT_KING"]["components"]) { + if(comp_data["_type"] == "BossFight") { + auto comp = components::convert(comp_data); + // the boss fight for the rat king doesn't have a stage so false=optional + REQUIRE(comp.stage == std::nullopt); + } + } + + // this then confirms everything else about the json conversion + + ComponentMap comp_map; + components::configure(comp_map); + + DinkyECS::World world; + auto rat_king = world.entity(); + + components::configure_entity(comp_map, world, rat_king, config["RAT_KING"]["components"]); + + auto boss = world.get(rat_king); + REQUIRE(boss.stage == std::nullopt); + + // now load the other one for the other way optional is used + auto devils_fingers = world.entity(); + components::configure_entity(comp_map, world, devils_fingers, config["DEVILS_FINGERS"]["components"]); + auto boss2 = world.get(devils_fingers); + REQUIRE(boss2.stage != std::nullopt); +} + + +TEST_CASE("animation component special cases", "[components]") { + Animation anim; + + anim.easing = ease::NONE; + float res = anim.twitching(); + REQUIRE(res == 0.0); + + anim.easing = ease::SINE; + anim.subframe = 1.0f; + res = anim.twitching(); + REQUIRE(!std::isnan(res)); + + anim.easing = ease::OUT_CIRC; + res = anim.twitching(); + REQUIRE(!std::isnan(res)); + + anim.easing = ease::OUT_BOUNCE; + res = anim.twitching(); + REQUIRE(!std::isnan(res)); + + anim.easing = ease::IN_OUT_BACK; + res = anim.twitching(); + REQUIRE(!std::isnan(res)); + + anim.easing = ease::FUCKFACE; + bool throws = false; + try { anim.twitching(); } catch(...) { throws = true; } + REQUIRE(throws); +} diff --git a/tests/config.cpp b/tests/config.cpp index 96e59cc..f7b41e6 100644 --- a/tests/config.cpp +++ b/tests/config.cpp @@ -5,7 +5,9 @@ TEST_CASE("confirm basic config loader ops", "[config]") { Config config("assets/devices.json"); auto data_list = config.json(); + auto the_keys = config.keys(); + REQUIRE(the_keys.size() > 0); for(auto& [key, data] : data_list.items()) { auto wide1 = config.wstring(key, "name"); diff --git a/tests/easings.cpp b/tests/easings.cpp new file mode 100644 index 0000000..005bb62 --- /dev/null +++ b/tests/easings.cpp @@ -0,0 +1,17 @@ +#include +#include "easings.hpp" +#include + +TEST_CASE("make sure the easing functions at least run", "[easings]") { + double out = ease::sine(1.3); + REQUIRE(out <= 1.0); + + out = ease::out_circ(3.444); + REQUIRE(std::isnan(out)); + + out = ease::out_bounce(1.13); + REQUIRE(out <= 10 ); + + out = ease::in_out_back(3.4); + REQUIRE(out < 250.0); +} diff --git a/wraps/ftxui.wrap b/wraps/ftxui.wrap deleted file mode 100644 index bec78a6..0000000 --- a/wraps/ftxui.wrap +++ /dev/null @@ -1,15 +0,0 @@ -[wrap-file] -directory = FTXUI-5.0.0 -source_url = https://github.com/ArthurSonzogni/FTXUI/archive/refs/tags/v5.0.0.tar.gz -source_filename = FTXUI-5.0.0.tar.gz -source_hash = a2991cb222c944aee14397965d9f6b050245da849d8c5da7c72d112de2786b5b -patch_filename = ftxui_5.0.0-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/ftxui_5.0.0-1/get_patch -patch_hash = 21c654e82739b90b95bd98c1d321264608d37c50d29fbcc3487f790fd5412909 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/ftxui_5.0.0-1/FTXUI-5.0.0.tar.gz -wrapdb_version = 5.0.0-1 - -[provide] -ftxui-screen = screen_dep -ftxui-dom = dom_dep -ftxui-component = component_dep