diff --git a/raycaster.cpp b/raycaster.cpp index ffa093b..5bf6e71 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -107,19 +107,19 @@ void Raycaster::sprite_casting(sf::RenderTarget &target) { // after sorting the sprites, do the projection for(auto& rec : sprite_order) { - if(!$sprites.contains(rec.second)) continue; + if(!$sprites.contains(rec.entity)) continue; - auto& sprite_texture = $sprites.at(rec.second); + auto& sprite_texture = $sprites.at(rec.entity); int texture_width = (float)sprite_texture.frame_size.x; int texture_height =(float)sprite_texture.frame_size.y; int half_height = texture_height / 2; auto& sf_sprite = sprite_texture.sprite; - auto sprite_pos = $level.world->get(rec.second); + auto sprite_pos = $level.world->get(rec.entity); - double sprite_x = double(sprite_pos.location.x) - $pos_x + 0.5; - double sprite_y = double(sprite_pos.location.y) - $pos_y + 0.5; + double sprite_x = double(sprite_pos.location.x) - rec.wiggle - $pos_x + 0.5; + double sprite_y = double(sprite_pos.location.y) - rec.wiggle - $pos_y + 0.5; double inv_det = 1.0 / ($plane_x * $dir_y - $dir_x * $plane_y); // required for correct matrix multiplication @@ -185,8 +185,8 @@ void Raycaster::sprite_casting(sf::RenderTarget &target) { sf::Vector2f position{x + origin.x * scale.x, y + origin.y * scale.y}; sf::IntRect in_texture{ {tex_x, tex_y}, {tex_render_width, texture_height}}; - if($level.world->has(rec.second)) { - auto& animation = $level.world->get(rec.second); + if($level.world->has(rec.entity)) { + auto& animation = $level.world->get(rec.entity); if(animation.playing) animation.step(scale, position, in_texture); } @@ -195,13 +195,9 @@ void Raycaster::sprite_casting(sf::RenderTarget &target) { sf_sprite->setTextureRect(in_texture); sf_sprite->setPosition(position); - // the SpatialMap.distance_sorted only calculates the - // (x1-x2)^2 + (y1-y2)^2 portion of distance, so to get - // the actual distance we need to sqrt that. - // float level = sqrt(rec.first); float level = lights[sprite_pos.location.y][sprite_pos.location.x] * PERCENT; - shared_ptr effect = System::sprite_effect($level, rec.second); + shared_ptr effect = System::sprite_effect($level, rec.entity); if(effect) { apply_sprite_effect(effect, sprite_width, sprite_height); diff --git a/spatialmap.cpp b/spatialmap.cpp index 2d2c877..4263926 100644 --- a/spatialmap.cpp +++ b/spatialmap.cpp @@ -93,13 +93,23 @@ FoundEntities SpatialMap::neighbors(Point cell, bool diag) const { } inline void update_sorted(SortedEntities& sprite_distance, PointEntityMap& table, Point from, int max_dist) { + Point seen{0,0}; + float wiggle = 0.0f; + 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) { + wiggle += 0.02f; + } else { + wiggle = 0.0f; + seen = sprite; + } + if(inside < max_dist) { - sprite_distance.push_back({inside, rec.second.entity}); + sprite_distance.push_back({inside, rec.second.entity, wiggle}); } } } @@ -109,7 +119,9 @@ SortedEntities SpatialMap::distance_sorted(Point from, int max_dist) { update_sorted(sprite_distance, $collision, from, max_dist); - std::sort(sprite_distance.begin(), sprite_distance.end(), std::greater<>()); + 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 9805ba8..d610ed9 100644 --- a/spatialmap.hpp +++ b/spatialmap.hpp @@ -10,10 +10,16 @@ struct CollisionData { bool collision = false; }; +struct EntityDistance { + int dist_square=0; + DinkyECS::Entity entity=DinkyECS::NONE; + float wiggle=0.0f; +}; + // Point's has is in point.hpp using EntityList = std::vector; using PointEntityMap = std::unordered_multimap; -using SortedEntities = std::vector>; +using SortedEntities = std::vector; struct FoundEntities { bool found; diff --git a/tests/spatialmap.cpp b/tests/spatialmap.cpp index 4fc4bd0..4d77f15 100644 --- a/tests/spatialmap.cpp +++ b/tests/spatialmap.cpp @@ -203,13 +203,13 @@ TEST_CASE("SpatialMap::distance_sorted", "[spatialmap]") { auto result = map.distance_sorted({1, 1}, 100); REQUIRE(result.size() == 3); - REQUIRE(result[0].second == enemy1); - REQUIRE(result[1].second == item); - REQUIRE(result[2].second == player); + REQUIRE(result[0].entity == enemy1); + REQUIRE(result[1].entity == item); + REQUIRE(result[2].entity == player); int prev_dist = std::numeric_limits::max(); - for(auto [dist, entity] : result) { - REQUIRE(dist < prev_dist); - prev_dist = dist; + for(auto rec : result) { + REQUIRE(rec.dist_square < prev_dist); + prev_dist = rec.dist_square; } }