From d0badedbd9070b4ccff368df8c813bb0dbe5f5b4 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Tue, 4 Feb 2025 22:52:04 -0500 Subject: [PATCH] More cleanup of the raycaster, finally removed the window as a dependency but I went against making it an sf::Drawable since that had a lot of code quality problems. --- gui.cpp | 13 ++--------- raycaster.cpp | 52 ++++++++++++-------------------------------- raycaster.hpp | 28 +++++------------------- spatialmap.cpp | 2 +- tests/spatialmap.cpp | 4 ++-- 5 files changed, 25 insertions(+), 74 deletions(-) diff --git a/gui.cpp b/gui.cpp index 126266e..d61f7ac 100644 --- a/gui.cpp +++ b/gui.cpp @@ -13,7 +13,7 @@ namespace gui { $window(sf::VideoMode({SCREEN_WIDTH, SCREEN_HEIGHT}), "Zed's Raycaster Thing"), $font{"./assets/text.otf"}, $text{$font}, - $rayview($window, $textures, RAY_VIEW_WIDTH, RAY_VIEW_HEIGHT) + $rayview($textures, RAY_VIEW_WIDTH, RAY_VIEW_HEIGHT) { $window.setVerticalSyncEnabled(VSYNC); $window.setFramerateLimit(FRAME_LIMIT); @@ -21,7 +21,6 @@ namespace gui { $text.setPosition({10,10}); $textures.load_tiles(); $textures.load_sprites(); - $rayview.init_shaders(); } void FSM::event(Event ev) { @@ -132,13 +131,6 @@ namespace gui { case KEY::R: $stats.reset(); break; - case KEY::P: - if($rayview.$active_shader == nullptr) { - $rayview.$active_shader = &$rayview.$paused; - } else { - $rayview.$active_shader = nullptr; - } - break; default: break; // ignored } @@ -182,7 +174,7 @@ namespace gui { void FSM::render() { auto start = std::chrono::high_resolution_clock::now(); - $rayview.render(); + $rayview.draw($window); auto end = std::chrono::high_resolution_clock::now(); auto elapsed = std::chrono::duration(end - start); $stats.sample(1/elapsed.count()); @@ -194,7 +186,6 @@ namespace gui { void FSM::mouse() { if(sf::Mouse::isButtonPressed(sf::Mouse::Button::Left)) { - $rayview.$anim.play(false); $rotation = -30.0f; } else { $rotation = -10.0f; diff --git a/raycaster.cpp b/raycaster.cpp index 689fe0f..6a392a7 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -32,12 +32,11 @@ inline uint32_t dumb_lighting(uint32_t pixel, double distance) { return conv.as_int; } -Raycaster::Raycaster(sf::RenderWindow& window, TexturePack &textures, int width, int height) : +Raycaster::Raycaster(TexturePack &textures, int width, int height) : $textures(textures), $view_texture({(unsigned int)width, (unsigned int)height}), $view_sprite($view_texture), $width(width), $height(height), - $window(window), ZBuffer(width), $anim(256, 256, 10, "assets/monster-1.ogg") { @@ -46,13 +45,6 @@ Raycaster::Raycaster(sf::RenderWindow& window, TexturePack &textures, int width, $view_texture.setSmooth(false); } -void Raycaster::init_shaders() { - bool good = $paused.loadFromFile("shaders/modal.frag", sf::Shader::Type::Fragment); - dbc::check(good, "shader could not be loaded"); - $paused.setUniform("offsetFactor", sf::Glsl::Vec2{0.01f, 0.01f}); - $paused.setUniform("darkness", 0.01f); -} - void Raycaster::set_position(int x, int y) { $view_sprite.setPosition({(float)x, (float)y}); } @@ -65,25 +57,19 @@ void Raycaster::position_camera(float player_x, float player_y) { void Raycaster::draw_pixel_buffer() { $view_texture.update((uint8_t *)$pixels.get(), {(unsigned int)$width, (unsigned int)$height}, {0, 0}); - $window.draw($view_sprite, $active_shader); -} - -void Raycaster::clear() { - std::fill_n($pixels.get(), $width * $height, 0); - $window.clear(); } -void Raycaster::sprite_casting() { +void Raycaster::sprite_casting(sf::RenderTarget &target) { const int textureWidth = TEXTURE_WIDTH; const int textureHeight = TEXTURE_HEIGHT; const int halfHeight = TEXTURE_HEIGHT / 2; // sort sprites from far to close - auto sprite_order = $collision.distance_sorted({(size_t)$posX, (size_t)$posY}); + auto sprite_order = $level.collision->distance_sorted({(size_t)$posX, (size_t)$posY}); // after sorting the sprites, do the projection for(auto& rec : sprite_order) { - Sprite& sprite_rec = $sprites[rec.second]; + const Sprite& sprite_rec = $sprites.at(rec.second); // TODO: this must die auto sf_sprite = sprite_rec.sprite.sprite; @@ -148,7 +134,7 @@ void Raycaster::sprite_casting() { $anim.step(*sf_sprite, texX, texY, texX_end - texX, textureHeight); sf_sprite->setPosition({x, y}); - $window.draw(*sf_sprite, $active_shader); + target.draw(*sf_sprite); } } } @@ -333,32 +319,22 @@ void Raycaster::draw_ceiling_floor() { } } -void Raycaster::render() { +void Raycaster::draw(sf::RenderTarget& target) { draw_ceiling_floor(); cast_rays(); draw_pixel_buffer(); - sprite_casting(); -} - -bool Raycaster::empty_space(int new_x, int new_y) { - dbc::check((size_t)new_x < matrix::width($map), - format("x={} too wide={}", new_x, matrix::width($map))); - dbc::check((size_t)new_y < matrix::height($map), - format("y={} too high={}", new_y, matrix::height($map))); - - return $map[new_y][new_x] == 0; -} - -DinkyECS::Entity Raycaster::position_sprite(Point pos, string name) { - auto sprite_txt = $textures.sprite_textures[name]; - $sprites.emplace_back(pos.x + 0.5, pos.y + 0.5, sprite_txt); - DinkyECS::Entity ent = $sprites.size() - 1; - $collision.insert({pos.x, pos.y}, ent); - return ent; + target.draw($view_sprite); + sprite_casting(target); } void Raycaster::set_level(GameLevel level) { $level = level; auto& tiles = $level.map->tiles(); $map = $textures.convert_char_to_texture(tiles.$tile_ids); + + // this will need to go away too but for now everything is evil eye + for(auto &thing : $level.collision->table) { + auto sprite_txt = $textures.sprite_textures.at("evil_eye"); + $sprites.try_emplace(thing.second, thing.first.x + 0.5, thing.first.y + 0.5, sprite_txt); + } } diff --git a/raycaster.hpp b/raycaster.hpp index 88d8829..ef90859 100644 --- a/raycaster.hpp +++ b/raycaster.hpp @@ -32,42 +32,26 @@ struct Raycaster { int $width; int $height; - sf::RenderWindow& $window; GameLevel $level; Matrix $map; - SpatialMap $collision; - std::vector $sprites; + std::unordered_map $sprites; std::vector ZBuffer; // width Animator $anim; - sf::Shader $paused; - sf::Shader* $active_shader = nullptr; - Raycaster(sf::RenderWindow& window, TexturePack &textures, int width, int height); + Raycaster(TexturePack &textures, int width, int height); - void draw_pixel_buffer(); - void clear(); void cast_rays(); void draw_ceiling_floor(); - void sprite_casting(); + void draw_pixel_buffer(); + void sprite_casting(sf::RenderTarget& target); + void draw(sf::RenderTarget& target); + void sort_sprites(std::vector& order, std::vector& dist, int amount); - void render(); - bool empty_space(int new_x, int new_y); void position_camera(float player_x, float player_y); - void set_position(int x, int y); - void init_shaders(); - DinkyECS::Entity position_sprite(Point pos, string name); inline size_t pixcoord(int x, int y) { - if(!(x >=0 && x < $width)) { - dbc::sentinel(fmt::format("pixcoord x={} but $width={}", x, $width)); - } - - if(!(y >= 0 && y < $height)) { - dbc::sentinel(fmt::format("pixcoord y={} but $height={}", y, $height)); - } - return ((y) * $width) + (x); } diff --git a/spatialmap.cpp b/spatialmap.cpp index 90a8b6a..5c96233 100644 --- a/spatialmap.cpp +++ b/spatialmap.cpp @@ -76,7 +76,7 @@ SortedEntities SpatialMap::distance_sorted(Point from) { sprite_distance.push_back({inside, rec.second}); } - std::sort(sprite_distance.begin(), sprite_distance.end()); + std::sort(sprite_distance.begin(), sprite_distance.end(), std::greater<>()); return sprite_distance; } diff --git a/tests/spatialmap.cpp b/tests/spatialmap.cpp index 9a893bd..fc34d28 100644 --- a/tests/spatialmap.cpp +++ b/tests/spatialmap.cpp @@ -154,10 +154,10 @@ TEST_CASE("confirm can iterate through all", "[spatialmap-sort]") { auto sprite_distance = collider.distance_sorted(player); - int prev_dist = 0; + int prev_dist = sprite_distance[0].first; for(auto dist : sprite_distance) { - REQUIRE(prev_dist <= dist.first); + REQUIRE(prev_dist >= dist.first); prev_dist = dist.first; } }