renderiranje - nazaj na singlethreaded ker me SDL ne mara :(
This commit is contained in:
14
src/game/player.cpp
Normal file
14
src/game/player.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include <game/player.hpp>
|
||||
|
||||
namespace Game::AGame {
|
||||
void Player::start() {
|
||||
LOG("Created the Player");
|
||||
}
|
||||
|
||||
void Player::update() {
|
||||
if (!mIsActive) return;
|
||||
//LOG("Updated Player");
|
||||
mTransform.x += 0.5f; // Move right at a constant speed for testing
|
||||
mTransform.rotation += 1.f; // Rotate clockwise for testing
|
||||
}
|
||||
}
|
||||
11
src/main.cpp
11
src/main.cpp
@@ -1,11 +1,20 @@
|
||||
#include <iostream>
|
||||
#include <window/window.hpp>
|
||||
#include <state/gamestate.hpp>
|
||||
#include <object/entity.hpp>
|
||||
#include <object/transform.hpp>
|
||||
#include <game/player.hpp>
|
||||
#include <renderer/renderer.hpp>
|
||||
#include <renderer/texture.hpp>
|
||||
|
||||
using namespace Game;
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int main() {
|
||||
Window::Window window = Window::Window();
|
||||
window.init(1280, 720, "Game Window");
|
||||
|
||||
State::GameState::getInstance().addEntity(std::make_unique<AGame::Player>("Player", std::make_shared<Game::Renderer::Texture>("../resources/missing_texture.png", window.getRenderer()->getSDLRenderer()), Object::DEFAULT_TRANSFORM));
|
||||
|
||||
window.run();
|
||||
|
||||
return 0;
|
||||
|
||||
68
src/object/entity.cpp
Normal file
68
src/object/entity.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <object/entity.hpp>
|
||||
#include <renderer/renderer.hpp>
|
||||
#include <renderer/texture.hpp>
|
||||
|
||||
namespace Game::Object {
|
||||
Entity::~Entity() {
|
||||
LOG("Destroyed Entity: " << mName);
|
||||
}
|
||||
|
||||
Entity::Entity(const Entity& other) : mName(other.mName), mTex(other.mTex), mTransform(other.mTransform), mIsActive(other.mIsActive) {
|
||||
LOG("Copied Entity: " << mName);
|
||||
}
|
||||
|
||||
Entity& Entity::operator=(const Entity& other) {
|
||||
if (this != &other) {
|
||||
mName = other.mName;
|
||||
mTex = other.mTex;
|
||||
mTransform = other.mTransform;
|
||||
mIsActive = other.mIsActive;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Entity::Entity(Entity&& other) noexcept : mName(std::move(other.mName)), mTex(other.mTex), mTransform(other.mTransform), mIsActive(other.mIsActive) {
|
||||
other.mTex = nullptr;
|
||||
LOG("Moved Entity: " << mName);
|
||||
}
|
||||
|
||||
Entity& Entity::operator=(Entity&& other) noexcept {
|
||||
if (this != &other) {
|
||||
mName = std::move(other.mName);
|
||||
mTex = other.mTex;
|
||||
mTransform = other.mTransform;
|
||||
mIsActive = other.mIsActive;
|
||||
other.mTex = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Entity::render(Game::Renderer::Renderer* renderer) {
|
||||
if (!mIsActive || !mTex) return; // Don't render if not active or if there's no texture
|
||||
|
||||
float w, h;
|
||||
SDL_GetTextureSize(mTex->getSDLTexture(), &w, &h);
|
||||
|
||||
SDL_FRect dst;
|
||||
dst.w = w * mTransform.scaleX * mScaleConstant; // 1.f is HUGE, so this is just a constant to make the default scale more reasonable
|
||||
dst.h = h * mTransform.scaleY * mScaleConstant;
|
||||
|
||||
// Top-left origin
|
||||
dst.x = mTransform.x;
|
||||
dst.y = mTransform.y;
|
||||
|
||||
SDL_FPoint center;
|
||||
center.x = dst.w / 2.f;
|
||||
center.y = dst.h / 2.f;
|
||||
|
||||
SDL_RenderTextureRotated(
|
||||
renderer->getSDLRenderer(),
|
||||
mTex->getSDLTexture(),
|
||||
nullptr,
|
||||
&dst,
|
||||
mTransform.rotation,
|
||||
¢er,
|
||||
SDL_FLIP_NONE
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
#include <renderer/renderer.hpp>
|
||||
#include <utils.hpp>
|
||||
#include <state/gamestate.hpp>
|
||||
#include <object/entity.hpp>
|
||||
|
||||
namespace Game::Renderer {
|
||||
Renderer::Renderer() : mRenderer(nullptr) {}
|
||||
@@ -34,12 +36,18 @@ namespace Game::Renderer {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Renderer::run(std::stop_token stoken) {
|
||||
while (!stoken.stop_requested()) {
|
||||
mClear();
|
||||
// Get gamestate mutex and render the objects here; GameState::getState().objects or something, idk
|
||||
mPresent();
|
||||
void Renderer::renderFrame() {
|
||||
mClear();
|
||||
|
||||
// Get gamestate and render the objects here; GameState::getState().objects or something, idk
|
||||
auto entities = Game::State::GameState::getInstance().getEntitiesRef();
|
||||
//LOG("Entity count: " << entities->size());
|
||||
|
||||
for (auto& entity : *entities) {
|
||||
entity->render(this);
|
||||
}
|
||||
|
||||
mPresent();
|
||||
}
|
||||
|
||||
void Renderer::mClear() {
|
||||
|
||||
@@ -1,33 +1,38 @@
|
||||
#include <renderer/texture.hpp>
|
||||
|
||||
namespace Game::Renderer {
|
||||
Texture::Texture(std::string& path, Renderer* renderer, std::string id)
|
||||
: mTex(nullptr), mId(id) {
|
||||
SDL_Surface* surf = IMG_Load(path.c_str());
|
||||
if (!surf) {
|
||||
ERROR("Failed to load image at " << path);
|
||||
return;
|
||||
}
|
||||
|
||||
mTex = SDL_CreateTextureFromSurface(renderer->getSDLRenderer(), surf);
|
||||
SDL_DestroySurface(surf);
|
||||
|
||||
Game::Renderer::Texture::Texture(const std::string& path, SDL_Renderer* renderer, std::string id)
|
||||
: mTex(nullptr), mId(id) {
|
||||
SDL_Surface* surf = IMG_Load(path.c_str());
|
||||
if (!surf) {
|
||||
ERROR("Failed to load image at " << path);
|
||||
return;
|
||||
}
|
||||
|
||||
Texture::Texture(const Texture& other) {
|
||||
// Copy the references, since copying memory would require re-initing a bunch of things - for now
|
||||
this->mTex = other.mTex;
|
||||
}
|
||||
mTex = SDL_CreateTextureFromSurface(renderer, surf);
|
||||
SDL_DestroySurface(surf);
|
||||
}
|
||||
|
||||
Texture& Texture::operator=(const Texture& other) {
|
||||
// Same reasoning
|
||||
this->mTex = other.mTex;
|
||||
return *this;
|
||||
}
|
||||
Game::Renderer::Texture::Texture(const Texture& other) {
|
||||
// Copy the references, since copying memory would require re-initing a bunch of things - for now
|
||||
this->mTex = other.mTex;
|
||||
}
|
||||
|
||||
Texture::~Texture() {
|
||||
if (mTex)
|
||||
SDL_DestroyTexture(mTex);
|
||||
LOG("Destroyed texture '" << mId << "'")
|
||||
}
|
||||
Game::Renderer::Texture& Game::Renderer::Texture::operator=(const Texture& other) {
|
||||
// Same reasoning
|
||||
this->mTex = other.mTex;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Game::Renderer::Texture::~Texture() {
|
||||
if (mTex)
|
||||
SDL_DestroyTexture(mTex);
|
||||
LOG("Destroyed texture '" << mId << "'")
|
||||
}
|
||||
|
||||
SDL_Texture* Game::Renderer::Texture::getSDLTexture() {
|
||||
return mTex;
|
||||
}
|
||||
|
||||
std::string Game::Renderer::Texture::getId() {
|
||||
return mId;
|
||||
}
|
||||
@@ -2,24 +2,22 @@
|
||||
#include <iostream>
|
||||
|
||||
namespace Game::State {
|
||||
// TODO: Caller should also hold these locks
|
||||
const std::vector<Object::Entity>& GameState::getEntities() {
|
||||
std::shared_lock lock(mMutex);
|
||||
return mEntities;
|
||||
}
|
||||
|
||||
std::vector<Object::Entity>* GameState::getEntitiesRef() {
|
||||
std::shared_lock lock(mMutex);
|
||||
std::vector<std::unique_ptr<Object::Entity>>* GameState::getEntitiesRef() {
|
||||
return &mEntities;
|
||||
}
|
||||
|
||||
Object::Entity* GameState::getAtIndex(size_t at) {
|
||||
std::shared_lock lock(mMutex);
|
||||
try {
|
||||
return &mEntities.at(at);
|
||||
return mEntities.at(at).get();
|
||||
} catch (const std::out_of_range& e) {
|
||||
WARN("Tried to access entity from GameState out of range!");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GameState::addEntity(std::unique_ptr<Object::Entity> entity) {
|
||||
mEntities.push_back(std::move(entity));
|
||||
GameState::getInstance().getAtIndex(mEntities.size() - 1)->start(); // Call start() on the newly added entity
|
||||
LOG("Added entity '" << GameState::getInstance().getAtIndex(mEntities.size() - 1)->getName() << "' to GameState");
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,9 @@
|
||||
#include <window/window.hpp>
|
||||
|
||||
namespace Game::Window {
|
||||
Window::Window() : mWindow(nullptr), mRunning(false) {
|
||||
}
|
||||
Window::Window() : mWindow(nullptr), mRenderer(), mRunning(false) { }
|
||||
|
||||
Window::~Window() {
|
||||
// Stop render thread
|
||||
if (mRenderThread.joinable()) {
|
||||
mRenderThread.request_stop();
|
||||
mRenderThread.join();
|
||||
}
|
||||
|
||||
mRenderer.destroy();
|
||||
|
||||
if (mWindow) {
|
||||
@@ -36,14 +29,12 @@ namespace Game::Window {
|
||||
|
||||
LOG("Window created successfully");
|
||||
|
||||
// Spawn new thread for renderer
|
||||
if (!mRenderer.init(mWindow)) {
|
||||
SDL_DestroyWindow(mWindow);
|
||||
mWindow = nullptr;
|
||||
SDL_Quit();
|
||||
return false;
|
||||
}
|
||||
mRenderThread = std::jthread(std::bind_front(&Renderer::Renderer::run, &mRenderer));
|
||||
|
||||
mRunning = true;
|
||||
|
||||
@@ -60,6 +51,14 @@ namespace Game::Window {
|
||||
|
||||
// Handle other events (e.g., keyboard, mouse) here
|
||||
}
|
||||
|
||||
auto entities = State::GameState::getInstance().getEntitiesRef();
|
||||
for (auto& entity : *entities) {
|
||||
entity->update();
|
||||
}
|
||||
|
||||
mRenderer.renderFrame();
|
||||
SDL_Delay(16); // ~60 FPS target, maybe make dynamic based on avg. frame time - TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user