Merge pull request 'Switches to a rendering pipeline with separated out steps, closes #8' (#9) from feature/rla-8_RenderingPipeline into master

Reviewed-on: #9
This commit was merged in pull request #9.
This commit is contained in:
2023-07-18 22:38:12 +00:00
10 changed files with 117 additions and 23 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
/cmake-build-debug/ /cmake-build-debug/
.name

View File

@@ -7,7 +7,7 @@ project(rla_iipp) # Defines the project name.
conan_basic_setup() # Prepares the CMakeList.txt for Conan.]] conan_basic_setup() # Prepares the CMakeList.txt for Conan.]]
# $source_files is a space-delimited list of filenames. # $source_files is a space-delimited list of filenames.
add_executable(rla_iipp src/main.cpp src/engine/engine.hpp src/engine/game/game.hpp src/engine/rendering/renderer.hpp src/game/visualizer.hpp src/game/visualizer.cpp src/engine/rendering/sdl/sdlrenderer.cpp src/engine/rendering/sdl/sdlrenderer.hpp src/engine/rendering/sdl/sdlrenderer.cpp src/engine/rendering/sdl/sdlrenderer.hpp src/engine/engine.cpp src/engine/engine.hpp src/engine/rendering/sdl/sdltexturemanager.cpp src/engine/rendering/sdl/sdltexturemanager.hpp src/engine/resources/resourcemanager.hpp src/engine/rendering/sdl/sdlfontmanager.cpp src/engine/rendering/sdl/sdlfontmanager.hpp src/engine/input/inputprocessor.hpp src/engine/input/sdlinputprocessor.cpp src/engine/input/sdlinputprocessor.hpp src/engine/utility/camera.cpp src/engine/utility/camera.hpp src/engine/utility/point.hpp src/engine/utility/rectangle.hpp src/engine/utility/grid2d.hpp src/engine/scripting/luacontextmanager.cpp src/engine/scripting/luacontextmanager.hpp src/game/algorithmmanager.cpp src/game/algorithmmanager.hpp src/game/tilemap.cpp src/game/tilemap.hpp src/engine/rlengineexception.hpp) # Specifies the executable to build. add_executable(rla_iipp src/main.cpp src/engine/engine.hpp src/engine/game/game.hpp src/engine/rendering/renderer.hpp src/game/visualizer.hpp src/game/visualizer.cpp src/engine/rendering/sdl/sdlrenderer.cpp src/engine/rendering/sdl/sdlrenderer.hpp src/engine/rendering/sdl/sdlrenderer.cpp src/engine/rendering/sdl/sdlrenderer.hpp src/engine/engine.cpp src/engine/engine.hpp src/engine/rendering/sdl/sdltexturemanager.cpp src/engine/rendering/sdl/sdltexturemanager.hpp src/engine/resources/resourcemanager.hpp src/engine/rendering/sdl/sdlfontmanager.cpp src/engine/rendering/sdl/sdlfontmanager.hpp src/engine/input/inputprocessor.hpp src/engine/input/sdlinputprocessor.cpp src/engine/input/sdlinputprocessor.hpp src/engine/utility/camera.cpp src/engine/utility/camera.hpp src/engine/utility/point.hpp src/engine/utility/rectangle.hpp src/engine/utility/grid2d.hpp src/engine/scripting/luacontextmanager.cpp src/engine/scripting/luacontextmanager.hpp src/game/algorithmmanager.cpp src/game/algorithmmanager.hpp src/game/tilemap.cpp src/game/tilemap.hpp src/engine/rlengineexception.hpp src/engine/rendering/renderingpipelinestep.hpp src/engine/rendering/pipeline_steps/gamerenderingstep.cpp src/engine/rendering/pipeline_steps/gamerenderingstep.hpp src/engine/rendering/pipeline_steps/fpscounterrenderingstep.cpp src/engine/rendering/pipeline_steps/fpscounterrenderingstep.hpp) # Specifies the executable to build.
# vcpkg packages # vcpkg packages
find_package(SDL2 CONFIG REQUIRED) find_package(SDL2 CONFIG REQUIRED)

View File

@@ -5,6 +5,8 @@
#include "engine.hpp" #include "engine.hpp"
#include "rendering/sdl/sdlrenderer.hpp" #include "rendering/sdl/sdlrenderer.hpp"
#include "rlengineexception.hpp" #include "rlengineexception.hpp"
#include "rendering/pipeline_steps/gamerenderingstep.hpp"
#include "rendering/pipeline_steps/fpscounterrenderingstep.hpp"
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <exception> #include <exception>
@@ -21,21 +23,27 @@ void Engine::start_loop() {
renderer->flush(); renderer->flush();
auto game_params = GameInitArgs{this->config.target_fps, this->config.window_width, this->config.window_height}; auto game_params = GameInitArgs{this->config.target_fps, this->config.window_width, this->config.window_height};
game->initialize(game_params); game->initialize(game_params);
std::vector<std::unique_ptr<RenderingPipelineStep>> rendering_steps = build_render_pipline();
auto duration_per_frame = one_second_milli / this->config.target_fps; auto duration_per_frame = one_second_milli / this->config.target_fps;
auto last_frame = std::chrono::high_resolution_clock::now();
while(true) { while(true) {
auto starttime = std::chrono::high_resolution_clock::now(); auto starttime = std::chrono::high_resolution_clock::now();
// Input and update
auto input = this->input_processor->process_input(); auto input = this->input_processor->process_input();
bool end = game->update(input); bool end = game->update(input);
if(end) { if(end) {
break; break;
} }
game->render(renderer.get());
// Rendering
std::for_each(rendering_steps.begin(), rendering_steps.end(), [this](std::unique_ptr<RenderingPipelineStep>& step) {
step->render_step(this->renderer.get());
});
renderer->flush();
// timing and sleep
auto endtime = std::chrono::high_resolution_clock::now(); auto endtime = std::chrono::high_resolution_clock::now();
auto update_duration = std::chrono::duration_cast<std::chrono::milliseconds>(endtime - starttime); auto update_duration = std::chrono::duration_cast<std::chrono::milliseconds>(endtime - starttime);
last_frame = render_fps(endtime, last_frame);
renderer->flush(); // not technically correct to do this here, but is done so we can put the fps over the display
std::this_thread::sleep_for(duration_per_frame - update_duration); std::this_thread::sleep_for(duration_per_frame - update_duration);
} }
} }
@@ -48,18 +56,6 @@ Engine::Engine(std::unique_ptr<Game> game,
this->setup_renderer(this->config.selected_renderer); this->setup_renderer(this->config.selected_renderer);
} }
std::chrono::time_point<std::chrono::system_clock>
Engine::render_fps(std::chrono::time_point<std::chrono::system_clock> end,
std::chrono::time_point<std::chrono::system_clock> lastframe) {
double frames = 1;
std::chrono::duration<double> dur = end - lastframe;
if(this->config.show_fps) {
//printf("fps: %f\n", frames/dur.count());
this->renderer->draw_text(std::nullopt, fmt::format("{:.2f}", frames/dur.count()), 0, 0);
}
return end;
}
void Engine::load_config(const std::string &path, const std::function<void (toml::table)>& f) { void Engine::load_config(const std::string &path, const std::function<void (toml::table)>& f) {
std::string full_path = fmt::format("{}/{}", CONFIG_DIR, path); std::string full_path = fmt::format("{}/{}", CONFIG_DIR, path);
auto table = toml::parse_file(full_path); auto table = toml::parse_file(full_path);
@@ -92,6 +88,15 @@ void Engine::setup_renderer(RendererTypes rendering_engine) {
this->renderer = std::move(rendering_engine_ptr); this->renderer = std::move(rendering_engine_ptr);
} }
std::vector<std::unique_ptr<RenderingPipelineStep>> Engine::build_render_pipline() {
std::vector<std::unique_ptr<RenderingPipelineStep>> result = std::vector<std::unique_ptr<RenderingPipelineStep>>();
result.push_back(std::make_unique<GameRenderingStep>(this->game.get()));
if(this->config.show_fps) {
result.push_back(std::make_unique<FpsCounterRenderingStep>());
}
return result;
}
Engine::~Engine() = default; Engine::~Engine() = default;

View File

@@ -13,6 +13,8 @@
#include <functional> #include <functional>
#include "rendering/renderer.hpp" #include "rendering/renderer.hpp"
#include "input/inputprocessor.hpp" #include "input/inputprocessor.hpp"
#include "rendering/renderingpipelinestep.hpp"
#define MISSING_GAME_ERROR "Game pointer is null" #define MISSING_GAME_ERROR "Game pointer is null"
#define MISSING_RENDERER_ERROR "Renderer pointer is null" #define MISSING_RENDERER_ERROR "Renderer pointer is null"
#define RESOURCE_DIR "assets" #define RESOURCE_DIR "assets"
@@ -54,9 +56,9 @@ private:
std::unique_ptr<Game> game = nullptr; std::unique_ptr<Game> game = nullptr;
std::unique_ptr<Renderer> renderer = nullptr; std::unique_ptr<Renderer> renderer = nullptr;
std::unique_ptr<InputProcessor> input_processor = nullptr; std::unique_ptr<InputProcessor> input_processor = nullptr;
std::chrono::time_point<std::chrono::system_clock> render_fps(std::chrono::time_point<std::chrono::system_clock> end, std::chrono::time_point<std::chrono::system_clock> lastframe);
void parse_config(const std::string& config_file_path); void parse_config(const std::string& config_file_path);
void setup_renderer(RendererTypes rendering_engine); void setup_renderer(RendererTypes rendering_engine);
std::vector<std::unique_ptr<RenderingPipelineStep>> build_render_pipline();
}; };
class MissingGameException : public std::exception { class MissingGameException : public std::exception {

View File

@@ -0,0 +1,18 @@
//
// Created by m on 7/18/23.
//
#include <fmt/format.h>
#include "fpscounterrenderingstep.hpp"
void FpsCounterRenderingStep::render_step(Renderer *renderer) {
double frames = 1;
std::chrono::time_point<std::chrono::system_clock> end = std::chrono::system_clock::now();
std::chrono::duration<double> dur = end - this->lastFrame;
renderer->draw_text(std::nullopt, fmt::format("{:.2f}", frames/dur.count()), 0, 0);
this->lastFrame = end;
}
FpsCounterRenderingStep::FpsCounterRenderingStep() {
this->lastFrame = std::chrono::high_resolution_clock::now();
}

View File

@@ -0,0 +1,22 @@
//
// Created by m on 7/18/23.
//
#ifndef RLA_IIPP_FPSCOUNTERRENDERINGSTEP_HPP
#define RLA_IIPP_FPSCOUNTERRENDERINGSTEP_HPP
#include <chrono>
#include "../renderingpipelinestep.hpp"
class FpsCounterRenderingStep : public RenderingPipelineStep {
void render_step(Renderer *renderer) override;
public:
FpsCounterRenderingStep();
private:
std::chrono::time_point<std::chrono::system_clock> lastFrame;
};
#endif //RLA_IIPP_FPSCOUNTERRENDERINGSTEP_HPP

View File

@@ -0,0 +1,11 @@
//
// Created by m on 7/18/23.
//
#include "gamerenderingstep.hpp"
void GameRenderingStep::render_step(Renderer *renderer) {
game->render(renderer);
}
GameRenderingStep::GameRenderingStep(Game *game) : game(game) {}

View File

@@ -0,0 +1,22 @@
//
// Created by m on 7/18/23.
//
#ifndef RLA_IIPP_GAMERENDERINGSTEP_HPP
#define RLA_IIPP_GAMERENDERINGSTEP_HPP
#include "../renderingpipelinestep.hpp"
#include "../../game/game.hpp"
class GameRenderingStep : public RenderingPipelineStep {
void render_step(Renderer *renderer) override;
private:
Game* game;
public:
explicit GameRenderingStep(Game *game);
};
#endif //RLA_IIPP_GAMERENDERINGSTEP_HPP

View File

@@ -0,0 +1,17 @@
//
// Created by m on 7/18/23.
//
#ifndef RLA_IIPP_RENDERINGPIPELINESTEP_HPP
#define RLA_IIPP_RENDERINGPIPELINESTEP_HPP
#include "renderer.hpp"
class RenderingPipelineStep {
public:
virtual ~RenderingPipelineStep() = default;
virtual void render_step(Renderer* renderer) = 0;
};
#endif //RLA_IIPP_RENDERINGPIPELINESTEP_HPP

View File

@@ -31,7 +31,6 @@ void Visualizer::render(Renderer *renderer) {
auto grass = Sprite{&tiles, 0}; auto grass = Sprite{&tiles, 0};
auto wall = Sprite{&tiles, 497}; auto wall = Sprite{&tiles, 497};
auto character = Sprite{&characters, this->sprite_index}; auto character = Sprite{&characters, this->sprite_index};
auto bounds = this->camera.get_bounds();
for(Point p : camera.get_range()) { for(Point p : camera.get_range()) {
auto wp = camera.camera_coords_to_screen_coords(p); auto wp = camera.camera_coords_to_screen_coords(p);
int wx = wp.x, wy = wp.y; int wx = wp.x, wy = wp.y;
@@ -64,9 +63,6 @@ void Visualizer::initialize(GameInitArgs args) {
this->camera = Camera(Point{x,y}, tilesx, tilesy, tile_map.get_width(), tile_map.get_height()); this->camera = Camera(Point{x,y}, tilesx, tilesy, tile_map.get_width(), tile_map.get_height());
this->algorithm_manager = AlgorithmManager(args.target_fps); this->algorithm_manager = AlgorithmManager(args.target_fps);
this->initialize_context(); this->initialize_context();
} }
void Visualizer::initialize_map(int width, int height) { void Visualizer::initialize_map(int width, int height) {