From 9bf6926dc3835135f90d97ffea07d49defd28504 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 3 Aug 2025 23:58:59 -0400 Subject: [PATCH] A bit of optimization to keep from generating the sorted sprite list over and over. Also tried to solve the problem of tombstone covering everything but no luck. --- constants.hpp | 1 + gui/fsm.cpp | 2 +- gui/main_ui.cpp | 40 ++++++++++++++++++++-------------------- gui/main_ui.hpp | 2 +- raycaster.cpp | 6 +++--- raycaster.hpp | 1 + spatialmap.cpp | 11 ++++++----- spatialmap.hpp | 2 +- tests/spatialmap.cpp | 3 ++- 9 files changed, 36 insertions(+), 32 deletions(-) diff --git a/constants.hpp b/constants.hpp index 474c198..e975ad2 100644 --- a/constants.hpp +++ b/constants.hpp @@ -18,6 +18,7 @@ constexpr const float AIMED_AT_BRIGHTNESS=0.2f; constexpr const int MAP_TILE_DIM=64; constexpr const int ICONGEN_MAP_TILE_DIM=64; constexpr const int PLAYER_SPRITE_DIR_CORRECTION=270; +constexpr const int RENDER_DISTANCE=500; constexpr const int BOSS_VIEW_WIDTH=1080; constexpr const int BOSS_VIEW_HEIGHT=SCREEN_HEIGHT; diff --git a/gui/fsm.cpp b/gui/fsm.cpp index 3eb06cd..cecf4f9 100644 --- a/gui/fsm.cpp +++ b/gui/fsm.cpp @@ -458,7 +458,7 @@ namespace gui { break; case eGUI::ENTITY_SPAWN: { auto& sprite = world.get(entity); - $main_ui.$rayview.update_sprite(entity, sprite); + $main_ui.$rayview->update_sprite(entity, sprite); $main_ui.dirty(); run_systems(); } break; diff --git a/gui/main_ui.cpp b/gui/main_ui.cpp index 676ed17..8facfe1 100644 --- a/gui/main_ui.cpp +++ b/gui/main_ui.cpp @@ -9,7 +9,7 @@ namespace gui { MainUI::MainUI(sf::RenderWindow& window) : $window(window), - $rayview(RAY_VIEW_WIDTH, RAY_VIEW_HEIGHT) + $rayview(std::make_shared(RAY_VIEW_WIDTH, RAY_VIEW_HEIGHT)) { $window.setVerticalSyncEnabled(VSYNC); $window.setFramerateLimit(FRAME_LIMIT); @@ -23,25 +23,25 @@ namespace gui { auto& player_position = $level.world->get($level.player); auto player = player_position.location; - $rayview.init_shaders(); - $rayview.set_position(RAY_VIEW_X, RAY_VIEW_Y); - $rayview.position_camera(player.x + 0.5, player.y + 0.5); + $rayview->init_shaders(); + $rayview->set_position(RAY_VIEW_X, RAY_VIEW_Y); + $rayview->position_camera(player.x + 0.5, player.y + 0.5); $overlay_ui.init(); } DinkyECS::Entity MainUI::camera_aim() { // what happens if there's two things at that spot - if($level.collision->something_there($rayview.aiming_at)) { - return $level.collision->get($rayview.aiming_at); + if($level.collision->something_there($rayview->aiming_at)) { + return $level.collision->get($rayview->aiming_at); } else { return 0; } } void MainUI::render() { - if($needs_render) $rayview.render(); - $rayview.draw($window); + if($needs_render) $rayview->render(); + $rayview->draw($window); $overlay_ui.render($window); } @@ -51,9 +51,9 @@ namespace gui { } std::optional MainUI::play_rotate() { - if($rayview.play_rotate()) { + if($rayview->play_rotate()) { $needs_render = false; - return std::make_optional($rayview.aiming_at); + return std::make_optional($rayview->aiming_at); } else { $needs_render = true; return std::nullopt; @@ -61,11 +61,11 @@ namespace gui { } std::optional MainUI::play_move() { - if($rayview.play_move()) { + if($rayview->play_move()) { $needs_render = false; return std::make_optional( - $rayview.camera_target(), - $rayview.aiming_at); + $rayview->camera_target(), + $rayview->aiming_at); } else { $needs_render = true; return std::nullopt; @@ -76,15 +76,15 @@ namespace gui { // -1 is left, 1 is right int extra = (amount == 0.5) * dir; $compass_dir = ($compass_dir + dir + extra) % COMPASS.size(); - $rayview.plan_rotate(dir, amount); + $rayview->plan_rotate(dir, amount); } Point MainUI::plan_move(int dir, bool strafe) { - return $rayview.plan_move(dir, strafe); + return $rayview->plan_move(dir, strafe); } void MainUI::abort_plan() { - $rayview.abort_plan(); + $rayview->abort_plan(); } void MainUI::dead_entity(DinkyECS::Entity entity) { @@ -92,7 +92,7 @@ namespace gui { // (see System::distribute_loot) then this can be fixed or improved if($level.world->has(entity)) { auto &sprite = $level.world->get(entity); - $rayview.update_sprite(entity, sprite); + $rayview->update_sprite(entity, sprite); } } @@ -101,10 +101,10 @@ namespace gui { auto& player_position = $level.world->get($level.player); auto player = player_position.location; - $rayview.update_level($level); - $rayview.position_camera(player.x + 0.5, player.y + 0.5); + $rayview->update_level($level); + $rayview->position_camera(player.x + 0.5, player.y + 0.5); - player_position.aiming_at = $rayview.aiming_at; + player_position.aiming_at = $rayview->aiming_at; $compass_dir = 0; diff --git a/gui/main_ui.hpp b/gui/main_ui.hpp index 35982ec..9e89c87 100644 --- a/gui/main_ui.hpp +++ b/gui/main_ui.hpp @@ -19,7 +19,7 @@ namespace gui { sf::RenderWindow& $window; GameLevel $level; OverlayUI $overlay_ui; - Raycaster $rayview; + std::shared_ptr $rayview; MainUI(sf::RenderWindow& window); diff --git a/raycaster.cpp b/raycaster.cpp index 5bf6e71..af220ea 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -101,12 +101,11 @@ void Raycaster::apply_sprite_effect(shared_ptr effect, float width, void Raycaster::sprite_casting(sf::RenderTarget &target) { auto& lights = $level.lights->lighting(); + $level.collision->distance_sorted($sprite_order, {(size_t)$pos_x, (size_t)$pos_y}, RENDER_DISTANCE); - // sort sprites from far to close - auto sprite_order = $level.collision->distance_sorted({(size_t)$pos_x, (size_t)$pos_y}, 500); // after sorting the sprites, do the projection - for(auto& rec : sprite_order) { + for(auto& rec : $sprite_order) { if(!$sprites.contains(rec.entity)) continue; auto& sprite_texture = $sprites.at(rec.entity); @@ -425,6 +424,7 @@ void Raycaster::update_sprite(DinkyECS::Entity ent, components::Sprite& sprite) void Raycaster::update_level(GameLevel level) { $sprites.clear(); + $sprite_order.clear(); $level = level; diff --git a/raycaster.hpp b/raycaster.hpp index 9c82023..4ec2d1e 100644 --- a/raycaster.hpp +++ b/raycaster.hpp @@ -36,6 +36,7 @@ struct Raycaster { int $screen_pos_x = RAY_VIEW_X; int $screen_pos_y = RAY_VIEW_Y; std::unordered_map $sprites; + SortedEntities $sprite_order; GameLevel $level; Matrix $tiles; diff --git a/spatialmap.cpp b/spatialmap.cpp index e437cc2..4fe143f 100644 --- a/spatialmap.cpp +++ b/spatialmap.cpp @@ -98,10 +98,13 @@ inline void update_sorted(SortedEntities& sprite_distance, PointEntityMap& table for(const auto &rec : table) { Point sprite = rec.first; + int inside = (from.x - sprite.x) * (from.x - sprite.x) + (from.y - sprite.y) * (from.y - sprite.y); - if(sprite == seen && from != sprite) { + if(from == sprite || rec.second.collision) { + wiggle = 0.0f; + } else if(sprite == seen) { wiggle += 0.02f; } else { wiggle = 0.0f; @@ -114,14 +117,12 @@ inline void update_sorted(SortedEntities& sprite_distance, PointEntityMap& table } } -SortedEntities SpatialMap::distance_sorted(Point from, int max_dist) { - SortedEntities sprite_distance; +void SpatialMap::distance_sorted(SortedEntities& sprite_distance, Point from, int max_dist) { + sprite_distance.clear(); update_sorted(sprite_distance, $collision, from, max_dist); std::sort(sprite_distance.begin(), sprite_distance.end(), [](auto &a, auto &b) { return a.dist_square > b.dist_square; }); - - return sprite_distance; } diff --git a/spatialmap.hpp b/spatialmap.hpp index d610ed9..d7aa218 100644 --- a/spatialmap.hpp +++ b/spatialmap.hpp @@ -40,6 +40,6 @@ class SpatialMap { DinkyECS::Entity get(Point at) const; FoundEntities neighbors(Point position, bool diag=false) const; - SortedEntities distance_sorted(Point from, int max_distance); + void distance_sorted(SortedEntities& sorted_sprites, Point from, int max_distance); size_t size() { return $collision.size(); } }; diff --git a/tests/spatialmap.cpp b/tests/spatialmap.cpp index 4d77f15..2633ce0 100644 --- a/tests/spatialmap.cpp +++ b/tests/spatialmap.cpp @@ -201,7 +201,8 @@ TEST_CASE("SpatialMap::distance_sorted", "[spatialmap]") { map.insert({4,4}, enemy1, true); map.insert({3, 3}, item, false); - auto result = map.distance_sorted({1, 1}, 100); + SortedEntities result; + map.distance_sorted(result, {1, 1}, 100); REQUIRE(result.size() == 3); REQUIRE(result[0].entity == enemy1); REQUIRE(result[1].entity == item);