Major speed up in rendering by only doing it when we move, but drawing the rendered 3d view texture constantly.

master
Zed A. Shaw 10 months ago
parent 0260e3d345
commit b43553a563
  1. 1
      assets/enemies.json
  2. 5
      gui_fsm.cpp
  3. 10
      main_ui.cpp
  4. 3
      main_ui.hpp
  5. 32
      raycaster.cpp
  6. 2
      raycaster.hpp
  7. 3
      status_ui.cpp

@ -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"}
]

@ -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() {

@ -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<double>(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<Point> MainUI::play_move() {
if($camera.play_move($rayview)) {
$needs_render = false;
return std::make_optional<Point>({
size_t($camera.target_x),
size_t($camera.target_y)});
} else {
$needs_render = true;
return std::nullopt;
}
}

@ -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<Point> play_move();
void plan_rotate(int dir);
bool play_rotate();
std::optional<Point> play_move();
Point plan_move(int dir, bool strafe);
void abort_plan();

@ -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<RGBA[]>($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);
}

@ -39,7 +39,6 @@ struct Raycaster {
Matrix $map;
std::unordered_map<DinkyECS::Entity, textures::SpriteTexture> $sprites;
std::vector<double> $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<int>& order, std::vector<double>& dist, int amount);

@ -17,8 +17,7 @@ namespace gui {
"[button7 | button8 | button9]"
"[*%(100,300)log_view]"
"[_]"
"[_]"
);
"[_]");
}
void StatusUI::render() {