From b43553a563842d5bccffe9ea0833e91f002c679b Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Fri, 21 Feb 2025 11:34:46 -0500 Subject: [PATCH] Major speed up in rendering by only doing it when we move, but drawing the rendered 3d view texture constantly. --- assets/enemies.json | 1 - gui_fsm.cpp | 5 ++++- main_ui.cpp | 10 ++++++++-- main_ui.hpp | 3 ++- raycaster.cpp | 32 +++++++++++++++++++++++--------- raycaster.hpp | 2 +- status_ui.cpp | 3 +-- 7 files changed, 39 insertions(+), 17 deletions(-) diff --git a/assets/enemies.json b/assets/enemies.json index a20d8f0..8011e27 100644 --- a/assets/enemies.json +++ b/assets/enemies.json @@ -21,7 +21,6 @@ }, {"_type": "Combat", "hp": 20, "max_hp": 20, "damage": 1, "dead": false}, {"_type": "Motion", "dx": 0, "dy": 0, "random": false}, - {"_type": "LightSource", "strength": 40, "radius": 1.2}, {"_type": "EnemyConfig", "hearing_distance": 5}, {"_type": "Sprite", "name": "armored_knight"} ] diff --git a/gui_fsm.cpp b/gui_fsm.cpp index d85d9bb..aa59245 100644 --- a/gui_fsm.cpp +++ b/gui_fsm.cpp @@ -248,6 +248,9 @@ namespace gui { case KEY::Escape: event(Event::CLOSE); break; + case KEY::Space: + event(Event::ATTACK); + break; case KEY::P: $main_ui.debug(); break; @@ -259,9 +262,9 @@ namespace gui { } void FSM::draw_gui() { + $main_ui.draw(); $status_ui.draw($window); $combat_ui.draw($window); - $main_ui.draw(); } void FSM::render() { diff --git a/main_ui.cpp b/main_ui.cpp index 612a551..6644c89 100644 --- a/main_ui.cpp +++ b/main_ui.cpp @@ -65,13 +65,15 @@ namespace gui { $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.render(); } void MainUI::draw() { auto start = std::chrono::high_resolution_clock::now(); + + if($needs_render) $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()); @@ -85,16 +87,20 @@ namespace gui { } bool MainUI::play_rotate() { - return $camera.play_rotate($rayview); + bool done = $camera.play_rotate($rayview); + $needs_render = !done; + return done; } // this could be an optional that returs a Point std::optional MainUI::play_move() { if($camera.play_move($rayview)) { + $needs_render = false; return std::make_optional({ size_t($camera.target_x), size_t($camera.target_y)}); } else { + $needs_render = true; return std::nullopt; } } diff --git a/main_ui.hpp b/main_ui.hpp index a571dc1..8e7b5d3 100644 --- a/main_ui.hpp +++ b/main_ui.hpp @@ -11,6 +11,7 @@ namespace gui { class MainUI { public: + bool $needs_render = true; Point $player{0,0}; Stats $stats; sf::RenderWindow& $window; @@ -26,9 +27,9 @@ namespace gui { void draw_stats(); void draw_blood(); - std::optional play_move(); void plan_rotate(int dir); bool play_rotate(); + std::optional play_move(); Point plan_move(int dir, bool strafe); void abort_plan(); diff --git a/raycaster.cpp b/raycaster.cpp index 7a953ce..09ffaaa 100644 --- a/raycaster.cpp +++ b/raycaster.cpp @@ -23,6 +23,11 @@ union ColorConv { uint32_t as_int; }; +/* It's hard to believe, but this is faster than any bitfiddling + * I could devise. Just use a union with a struct, do the math + * and I guess the compiler can handle it better than shifting + * bits around. + */ inline uint32_t new_lighting(uint32_t pixel, int level) { float factor = level * PERCENT; @@ -38,8 +43,7 @@ Raycaster::Raycaster(int width, int height) : $view_texture(sf::Vector2u{(unsigned int)width, (unsigned int)height}), $view_sprite($view_texture), $width(width), $height(height), - $zbuffer(width), - $anim(256, 256, 10, "assets/monster-1.ogg") + $zbuffer(width) { $view_sprite.setPosition({0, 0}); $pixels = make_unique($width * $height); @@ -99,6 +103,7 @@ void Raycaster::sprite_casting(sf::RenderTarget &target) { // calculate width the the sprite // same as height of sprite, given that it's square int sprite_width = abs(int($height / transform_y)); + // CUT int draw_start_x = -sprite_width / 2 + sprite_screen_x; if(draw_start_x < 0) draw_start_x = 0; @@ -119,8 +124,6 @@ void Raycaster::sprite_casting(sf::RenderTarget &target) { //calculate lowest and highest pixel to fill in current stripe int draw_start_y = -sprite_height / 2 + $height / 2; if(draw_start_y < 0) draw_start_y = 0; - int draw_end_y = sprite_height / 2 + $height / 2; - if(draw_end_y >= $height) draw_end_y = $height - 1; int tex_x = int(texture_width * (draw_start_x - (-sprite_width / 2 + sprite_screen_x)) * texture_width / sprite_width) / texture_width; int tex_render_width = tex_x_end - tex_x; @@ -130,14 +133,22 @@ void Raycaster::sprite_casting(sf::RenderTarget &target) { float x = float(draw_start_x + $screen_pos_x); float y = float(draw_start_y + $screen_pos_y); - float sprite_w = float(sprite_width) / float(texture_width); - float sprite_h = float(sprite_height) / float(texture_height); + + if(x < $screen_pos_x) fmt::println("X < rayview left bounds"); + if(y < $screen_pos_y) fmt::println("Y < rayview top bounds"); + if(x >= SCREEN_WIDTH) fmt::println("OUT OF BOUNDS X"); + if(y >= $height) fmt::println("OUT OF BOUNDS Y"); + + float sprite_scale_w = float(sprite_width) / float(texture_width); + float sprite_scale_h = float(sprite_height) / float(texture_height); int d = y * texture_height - $height * half_height + sprite_height * half_height; int tex_y = ((d * texture_height) / sprite_height) / texture_height; - sf_sprite->setScale({sprite_w, sprite_h}); - $anim.step(*sf_sprite, tex_x, tex_y, tex_render_width, texture_height); + sf_sprite->setScale({sprite_scale_w, sprite_scale_h}); + sf_sprite->setTextureRect(sf::IntRect({ + {tex_x, tex_y}, + {tex_render_width, texture_height}})); sf_sprite->setPosition({x, y}); $brightness.setUniform("offsetFactor", sf::Glsl::Vec2{0.0f, 0.0f}); @@ -333,10 +344,13 @@ void Raycaster::draw_ceiling_floor() { } } -void Raycaster::draw(sf::RenderTarget& target) { +void Raycaster::render() { draw_ceiling_floor(); cast_rays(); draw_pixel_buffer(); +} + +void Raycaster::draw(sf::RenderTarget& target) { target.draw($view_sprite); sprite_casting(target); } diff --git a/raycaster.hpp b/raycaster.hpp index 0f114db..b10c9fd 100644 --- a/raycaster.hpp +++ b/raycaster.hpp @@ -39,7 +39,6 @@ struct Raycaster { Matrix $map; std::unordered_map $sprites; std::vector $zbuffer; // width - Animator $anim; Raycaster(int width, int height); @@ -47,6 +46,7 @@ struct Raycaster { void draw_ceiling_floor(); void draw_pixel_buffer(); void sprite_casting(sf::RenderTarget& target); + void render(); void draw(sf::RenderTarget& target); void sort_sprites(std::vector& order, std::vector& dist, int amount); diff --git a/status_ui.cpp b/status_ui.cpp index fb56153..a7784fd 100644 --- a/status_ui.cpp +++ b/status_ui.cpp @@ -17,8 +17,7 @@ namespace gui { "[button7 | button8 | button9]" "[*%(100,300)log_view]" "[_]" - "[_]" - ); + "[_]"); } void StatusUI::render() {