Implement scene system; move render loop from Game to Engine
This commit is contained in:
parent
b4635cdb99
commit
48b70b0bc8
6 changed files with 196 additions and 89 deletions
|
|
@ -47,12 +47,10 @@ export namespace rutile
|
|||
return sdl::AppResult::Continue;
|
||||
}
|
||||
|
||||
sdl::AppResult handle_event(const sdl::Event& event)
|
||||
sdl::AppResult handle_event(const sdl::Event& event) const
|
||||
{
|
||||
try {
|
||||
if (!engine_->handle_event(event)) {
|
||||
game_->handle_event(event);
|
||||
}
|
||||
engine_->handle_event(event);
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
std::cerr << "Unhandled exception during event handling: " << e.what() << '\n';
|
||||
|
|
@ -62,12 +60,11 @@ export namespace rutile
|
|||
return engine_->keep_running() ? sdl::AppResult::Continue : sdl::AppResult::Success;
|
||||
}
|
||||
|
||||
sdl::AppResult iterate()
|
||||
sdl::AppResult iterate() const
|
||||
{
|
||||
try {
|
||||
engine_->update();
|
||||
game_->update();
|
||||
game_->render();
|
||||
engine_->render();
|
||||
}
|
||||
catch (const std::runtime_error& e) {
|
||||
std::cerr << "Unhandled exception during updating: " << e.what() << '\n';
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import std;
|
|||
import rutile.config;
|
||||
import rutile.core.render_server;
|
||||
import rutile.core.resource_server;
|
||||
import rutile.core.scenes.scene_manager;
|
||||
import rutile.core.ui.ui_server;
|
||||
import wrappers.sdl;
|
||||
|
||||
|
|
@ -16,7 +17,7 @@ export namespace rutile
|
|||
class Engine
|
||||
{
|
||||
// Whether this class is currently instantiated (to prevent multiple instances)
|
||||
static bool instantiated_;
|
||||
static Engine* instance_;
|
||||
|
||||
// If this is set to false, the application will exit
|
||||
bool keep_running_ = true;
|
||||
|
|
@ -24,6 +25,7 @@ export namespace rutile
|
|||
sdl::Window window_;
|
||||
RenderServer render_server_;
|
||||
ResourceServer resource_server_;
|
||||
SceneManager scene_manager_;
|
||||
UIServer ui_server_;
|
||||
|
||||
// Private constructor
|
||||
|
|
@ -33,7 +35,7 @@ export namespace rutile
|
|||
resource_server_{render_server_.get_renderer()},
|
||||
ui_server_{render_server_.get_renderer(), window_}
|
||||
{
|
||||
instantiated_ = true;
|
||||
instance_ = this;
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -47,13 +49,13 @@ export namespace rutile
|
|||
|
||||
~Engine()
|
||||
{
|
||||
instantiated_ = false;
|
||||
instance_ = nullptr;
|
||||
}
|
||||
|
||||
static std::unique_ptr<Engine> create()
|
||||
{
|
||||
// Prevent the class from being instantiated multiple times
|
||||
assert(!instantiated_);
|
||||
assert(!instance_);
|
||||
|
||||
auto [sdl_window, sdl_renderer] = sdl::create_window_and_renderer(
|
||||
config::get_window_title(),
|
||||
|
|
@ -72,6 +74,13 @@ export namespace rutile
|
|||
// NOLINTEND
|
||||
}
|
||||
|
||||
// Get singleton instance of engine
|
||||
static Engine& get()
|
||||
{
|
||||
assert(instance_);
|
||||
return *instance_;
|
||||
}
|
||||
|
||||
bool keep_running() const
|
||||
{
|
||||
return keep_running_;
|
||||
|
|
@ -92,6 +101,11 @@ export namespace rutile
|
|||
return resource_server_;
|
||||
}
|
||||
|
||||
SceneManager& get_scene_manager()
|
||||
{
|
||||
return scene_manager_;
|
||||
}
|
||||
|
||||
UIServer& get_ui_server()
|
||||
{
|
||||
return ui_server_;
|
||||
|
|
@ -110,11 +124,38 @@ export namespace rutile
|
|||
return true;
|
||||
}
|
||||
|
||||
const auto scene = scene_manager_.get_current_scene();
|
||||
if (scene && scene->handle_event(event)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void update()
|
||||
void update() const
|
||||
{
|
||||
// Update current scene
|
||||
if (const auto scene = scene_manager_.get_current_scene()) {
|
||||
scene->update();
|
||||
}
|
||||
|
||||
// Update UI
|
||||
ui_server_.update();
|
||||
}
|
||||
|
||||
void render() const
|
||||
{
|
||||
render_server_.start_frame();
|
||||
|
||||
// Render current scene
|
||||
if (const auto scene = scene_manager_.get_current_scene()) {
|
||||
scene->render(render_server_);
|
||||
}
|
||||
|
||||
// Render UI
|
||||
ui_server_.render();
|
||||
|
||||
render_server_.finish_frame();
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
|
|
@ -122,5 +163,5 @@ export namespace rutile
|
|||
}
|
||||
};
|
||||
|
||||
bool Engine::instantiated_ = false;
|
||||
Engine* Engine::instance_ = nullptr;
|
||||
}
|
||||
|
|
|
|||
27
src/rutile/core/scenes/base_scene.cppm
Normal file
27
src/rutile/core/scenes/base_scene.cppm
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
module;
|
||||
|
||||
export module rutile.core.scenes.base_scene;
|
||||
|
||||
import std;
|
||||
import rutile.core.render_server;
|
||||
import rutile.core.resource_server;
|
||||
import wrappers.sdl;
|
||||
|
||||
export namespace rutile
|
||||
{
|
||||
class BaseScene
|
||||
{
|
||||
public:
|
||||
// Always define virtual destructor in abstract classes
|
||||
virtual ~BaseScene() = default;
|
||||
|
||||
// Handle an SDL event. Return true if the event has been handled.
|
||||
virtual bool handle_event(const sdl::Event& event) = 0;
|
||||
|
||||
// Update the scene
|
||||
virtual void update() = 0;
|
||||
|
||||
// Render the scene
|
||||
virtual void render(const RenderServer& render_server) = 0;
|
||||
};
|
||||
}
|
||||
26
src/rutile/core/scenes/scene_manager.cppm
Normal file
26
src/rutile/core/scenes/scene_manager.cppm
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
module;
|
||||
|
||||
export module rutile.core.scenes.scene_manager;
|
||||
|
||||
import rutile.core.scenes.base_scene;
|
||||
|
||||
export namespace rutile
|
||||
{
|
||||
class SceneManager
|
||||
{
|
||||
// Pointer to current scene
|
||||
// TODO: Ownership? Should this be a regular pointer or maybe a shared_ptr shared with Game?
|
||||
BaseScene* current_scene_ = nullptr;
|
||||
|
||||
public:
|
||||
BaseScene* get_current_scene() const
|
||||
{
|
||||
return current_scene_;
|
||||
}
|
||||
|
||||
void set_current_scene(BaseScene& scene)
|
||||
{
|
||||
current_scene_ = &scene;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -5,13 +5,12 @@ module;
|
|||
export module rutile.game.game;
|
||||
|
||||
import std;
|
||||
import rutile.core.drawing.sprite;
|
||||
import rutile.core.drawing.tile_map;
|
||||
import rutile.core.engine;
|
||||
import rutile.core.render_server;
|
||||
import rutile.core.scenes.base_scene;
|
||||
import rutile.game.scenes.game_scene;
|
||||
import wrappers.rmlui.core;
|
||||
import wrappers.sdl;
|
||||
import wrappers.sdl_image;
|
||||
|
||||
export namespace rutile
|
||||
{
|
||||
|
|
@ -23,26 +22,12 @@ export namespace rutile
|
|||
// Reference to the engine
|
||||
Engine& engine_;
|
||||
|
||||
// Sprites and stuff for testing
|
||||
Sprite player_sprite_;
|
||||
std::vector<Sprite> sprites_;
|
||||
TileMap tile_map_;
|
||||
// Main game scene
|
||||
GameScene game_scene_;
|
||||
|
||||
// Private constructor
|
||||
explicit Game(Engine& engine)
|
||||
: engine_(engine),
|
||||
player_sprite_{
|
||||
Sprite::create_from_texture(
|
||||
engine_.get_resource_server().load_texture("assets/sprites/neocat_64.png"),
|
||||
std::nullopt,
|
||||
sdl::FPoint{0, 0},
|
||||
sdl::FPoint{-32, -32}
|
||||
)
|
||||
},
|
||||
tile_map_{
|
||||
engine_.get_resource_server().load_tile_set("assets/tilesets/terrain.json"),
|
||||
32, 16, 12, {50, 50}
|
||||
}
|
||||
: engine_{engine}
|
||||
{
|
||||
// Initialize UI
|
||||
const auto& ui_server = engine_.get_ui_server();
|
||||
|
|
@ -50,13 +35,8 @@ export namespace rutile
|
|||
Rml::ElementDocument* document = ui_server.load_document("assets/ui/main_ui.rml");
|
||||
document->Show();
|
||||
|
||||
// Initialize tile map with example data
|
||||
for (auto x = 0; x < 10; x++) {
|
||||
for (auto y = 0; y < 10; y++) {
|
||||
const auto tile_index = 2 + (x + y) % 2;
|
||||
tile_map_.set_tile(x, y, tile_index);
|
||||
}
|
||||
}
|
||||
// Set current scene
|
||||
engine_.get_scene_manager().set_current_scene(game_scene_);
|
||||
|
||||
instantiated_ = true;
|
||||
}
|
||||
|
|
@ -84,55 +64,6 @@ export namespace rutile
|
|||
};
|
||||
}
|
||||
|
||||
// Handles an SDL event. Returns true if the event has been handled.
|
||||
bool handle_event(const sdl::Event& event)
|
||||
{
|
||||
if (event.type == sdl::EventTypes::MouseMotion) {
|
||||
player_sprite_.set_position({event.motion.x, event.motion.y});
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.type == sdl::EventTypes::MouseButtonUp) {
|
||||
sprites_.push_back(
|
||||
Sprite::create_from_texture(
|
||||
engine_.get_resource_server().load_texture("assets/sprites/neofox_64.png"),
|
||||
std::nullopt,
|
||||
sdl::FPoint{event.motion.x, event.motion.y},
|
||||
sdl::FPoint{-32, -32}
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
// TODO: Move this to Engine
|
||||
engine_.get_ui_server().update();
|
||||
}
|
||||
|
||||
void render() const
|
||||
{
|
||||
const auto& render_server = engine_.get_render_server();
|
||||
render_server.start_frame();
|
||||
|
||||
// Render tilemap
|
||||
tile_map_.draw(render_server);
|
||||
|
||||
// Render sprites
|
||||
for (const Sprite& sprite : sprites_) {
|
||||
sprite.draw(render_server);
|
||||
}
|
||||
player_sprite_.draw(render_server);
|
||||
|
||||
// TODO: Move this to Engine
|
||||
engine_.get_ui_server().render();
|
||||
|
||||
render_server.finish_frame();
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
85
src/rutile/game/scenes/game_scene.cppm
Normal file
85
src/rutile/game/scenes/game_scene.cppm
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
module;
|
||||
|
||||
export module rutile.game.scenes.game_scene;
|
||||
|
||||
import std;
|
||||
import rutile.core.drawing.sprite;
|
||||
import rutile.core.drawing.tile_map;
|
||||
import rutile.core.engine;
|
||||
import rutile.core.render_server;
|
||||
import rutile.core.scenes.base_scene;
|
||||
import wrappers.sdl;
|
||||
|
||||
export namespace rutile
|
||||
{
|
||||
class GameScene : public BaseScene
|
||||
{
|
||||
// Sprites and stuff for testing
|
||||
Sprite player_sprite_;
|
||||
std::vector<Sprite> sprites_;
|
||||
TileMap tile_map_;
|
||||
|
||||
public:
|
||||
GameScene()
|
||||
: player_sprite_{
|
||||
Sprite::create_from_texture(
|
||||
Engine::get().get_resource_server().load_texture("assets/sprites/neocat_64.png"),
|
||||
std::nullopt,
|
||||
sdl::FPoint{0, 0},
|
||||
sdl::FPoint{-32, -32}
|
||||
)
|
||||
},
|
||||
tile_map_{
|
||||
Engine::get().get_resource_server().load_tile_set("assets/tilesets/terrain.json"),
|
||||
32, 16, 12, {50, 50}
|
||||
}
|
||||
{
|
||||
// Initialize tile map with example data
|
||||
for (auto x = 0; x < 10; x++) {
|
||||
for (auto y = 0; y < 10; y++) {
|
||||
const auto tile_index = 2 + (x + y) % 2;
|
||||
tile_map_.set_tile(x, y, tile_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handles an SDL event. Returns true if the event has been handled.
|
||||
bool handle_event(const sdl::Event& event) override
|
||||
{
|
||||
if (event.type == sdl::EventTypes::MouseMotion) {
|
||||
player_sprite_.set_position({event.motion.x, event.motion.y});
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event.type == sdl::EventTypes::MouseButtonUp) {
|
||||
sprites_.push_back(
|
||||
Sprite::create_from_texture(
|
||||
Engine::get().get_resource_server().load_texture("assets/sprites/neofox_64.png"),
|
||||
std::nullopt,
|
||||
sdl::FPoint{event.motion.x, event.motion.y},
|
||||
sdl::FPoint{-32, -32}
|
||||
)
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void update() override
|
||||
{
|
||||
}
|
||||
|
||||
void render(const RenderServer& render_server) override
|
||||
{
|
||||
// Render tilemap
|
||||
tile_map_.draw(render_server);
|
||||
|
||||
// Render sprites
|
||||
for (const Sprite& sprite : sprites_) {
|
||||
sprite.draw(render_server);
|
||||
}
|
||||
player_sprite_.draw(render_server);
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue