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.

This commit is contained in:
Zed A. Shaw 2025-08-03 23:58:59 -04:00
parent 077f0e84ea
commit 9bf6926dc3
9 changed files with 36 additions and 32 deletions

View file

@ -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;

View file

@ -458,7 +458,7 @@ namespace gui {
break;
case eGUI::ENTITY_SPAWN: {
auto& sprite = world.get<components::Sprite>(entity);
$main_ui.$rayview.update_sprite(entity, sprite);
$main_ui.$rayview->update_sprite(entity, sprite);
$main_ui.dirty();
run_systems();
} break;

View file

@ -9,7 +9,7 @@ namespace gui {
MainUI::MainUI(sf::RenderWindow& window) :
$window(window),
$rayview(RAY_VIEW_WIDTH, RAY_VIEW_HEIGHT)
$rayview(std::make_shared<Raycaster>(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<Position>($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<Point> MainUI::play_rotate() {
if($rayview.play_rotate()) {
if($rayview->play_rotate()) {
$needs_render = false;
return std::make_optional<Point>($rayview.aiming_at);
return std::make_optional<Point>($rayview->aiming_at);
} else {
$needs_render = true;
return std::nullopt;
@ -61,11 +61,11 @@ namespace gui {
}
std::optional<components::Position> MainUI::play_move() {
if($rayview.play_move()) {
if($rayview->play_move()) {
$needs_render = false;
return std::make_optional<Position>(
$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<components::Sprite>(entity)) {
auto &sprite = $level.world->get<components::Sprite>(entity);
$rayview.update_sprite(entity, sprite);
$rayview->update_sprite(entity, sprite);
}
}
@ -101,10 +101,10 @@ namespace gui {
auto& player_position = $level.world->get<Position>($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;

View file

@ -19,7 +19,7 @@ namespace gui {
sf::RenderWindow& $window;
GameLevel $level;
OverlayUI $overlay_ui;
Raycaster $rayview;
std::shared_ptr<Raycaster> $rayview;
MainUI(sf::RenderWindow& window);

View file

@ -101,12 +101,11 @@ void Raycaster::apply_sprite_effect(shared_ptr<sf::Shader> 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;

View file

@ -36,6 +36,7 @@ struct Raycaster {
int $screen_pos_x = RAY_VIEW_X;
int $screen_pos_y = RAY_VIEW_Y;
std::unordered_map<DinkyECS::Entity, textures::SpriteTexture> $sprites;
SortedEntities $sprite_order;
GameLevel $level;
Matrix $tiles;

View file

@ -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;
}

View file

@ -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(); }
};

View file

@ -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);