more component stuff

This commit is contained in:
Josh Lyon
2025-08-13 22:21:37 -06:00
parent f6de0ed9f3
commit 7259d9307b
8 changed files with 151 additions and 43 deletions

View File

@@ -1,18 +1,39 @@
#pragma once #pragma once
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_rect.h>
#include <memory> #include <memory>
#include "GameState.h"
#include "Graphics.h" #include "Graphics.h"
#include "components/GraphicsComponent.h" #include "components/GraphicsComponent.h"
#include "components/InputComponent.h"
class GameObject : std::enable_shared_from_this<GameObject> { constexpr int HORIZONTAL_SPEED = 10;
class GameObject {
public: public:
GameObject(std::unique_ptr<GraphicsComponent> graphics) GameObject(
: m_graphics(std::move(graphics)) {} std::unique_ptr<GraphicsComponent> graphics,
std::unique_ptr<InputComponent> input)
: m_graphics(std::move(graphics))
, m_input(std::move(input))
{ /* Intentionally empty */ }
void update(Graphics &graphics) { void update(Graphics &graphics) {
if (m_input->moveUp) {
speed.x = HORIZONTAL_SPEED;
}
m_graphics->update(graphics); m_graphics->update(graphics);
} }
GameState processInput(SDL_Event const* event) {
return m_input->update(event);
}
private: private:
std::unique_ptr<GraphicsComponent> m_graphics; std::unique_ptr<GraphicsComponent> m_graphics;
std::unique_ptr<InputComponent> m_input;
SDL_Point speed;
}; };

5
include/GameState.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
enum class GameState {
STOPPING=0,
RUNNING
};

View File

@@ -1,8 +1,32 @@
#pragma once #pragma once
#include <SDL3/SDL_rect.h>
#include <SDL3/SDL_render.h>
#include <SDL3/SDL_video.h>
#include <format>
#include <stdexcept>
#include <string_view>
class Graphics { class Graphics {
public: public:
Graphics(){} Graphics(std::string_view title){
// TODO Don't hardcode resolution
if (!SDL_CreateWindowAndRenderer(title.data(), 2560, 1440, SDL_WINDOW_FULLSCREEN, &window, &renderer)) {
throw std::runtime_error(std::format("Couldn't create window and renderer: {}", SDL_GetError()));
}
}
void drawRect(SDL_FRect const& rect, SDL_Color const& color) {
SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
SDL_RenderFillRect(renderer, &rect);
}
void show() {
SDL_RenderPresent(renderer);
}
private: private:
SDL_Renderer *renderer = nullptr;
SDL_Window *window = nullptr;
}; };

View File

@@ -2,12 +2,13 @@
#include "Graphics.h" #include "Graphics.h"
class GameObject;
class GraphicsComponent { class GraphicsComponent {
public: public:
virtual ~GraphicsComponent() {} virtual ~GraphicsComponent() {}
virtual void update(Graphics &graphics) = 0; virtual void update(Graphics &graphics) = 0;
private:
}; };

View File

@@ -0,0 +1,17 @@
#pragma once
#include <SDL3/SDL_events.h>
#include "GameState.h"
struct InputComponent {
public:
virtual ~InputComponent() {};
virtual GameState update(SDL_Event const* event) = 0;
bool moveUp;
bool moveDown;
bool moveLeft;
bool moveRight;
};

View File

@@ -1,11 +1,31 @@
#pragma once #pragma once
#include "GameObject.h"
#include "Graphics.h" #include "Graphics.h"
#include "GraphicsComponent.h" #include "GraphicsComponent.h"
#include <print> #include <SDL3/SDL_pixels.h>
#include <SDL3/SDL_rect.h>
#include <SDL3/SDL_stdinc.h>
class PlayerGraphics : public GraphicsComponent { class PlayerGraphics : public GraphicsComponent {
void update(Graphics &graphics) { public:
std::print("Updating player graphics"); void setPos(int x, int y) {
hitbox.x = x;
hitbox.y = y;
} }
void update(GameObject const& object, Graphics &graphics) {
SDL_Color color = { .r = 0, .g = 255, .b = 0, .a = 255};
graphics.drawRect(hitbox, color);
}
private:
SDL_FRect hitbox = {
.x = 40,
.y = 40,
.w = 300,
.h = 300,
};
}; };

View File

@@ -0,0 +1,30 @@
#include "components/InputComponent.h"
#include "GameState.h"
#include <SDL3/SDL_keycode.h>
class PlayerInput : public InputComponent {
GameState update(SDL_Event const* event) {
if (SDL_EVENT_QUIT == event->type || SDLK_ESCAPE == event->key.key) {
return GameState::STOPPING;
}
// currently dont care about anything other than down
if (SDL_EVENT_KEY_DOWN != event->type) {
return GameState::RUNNING;
}
if (SDLK_W == event->key.key) {
moveUp = event->key.type == SDL_EVENT_KEY_DOWN;
}
if (SDLK_S == event->key.key) {
moveDown = event->key.type == SDL_EVENT_KEY_DOWN;
}
if (SDLK_A == event->key.key) {
moveLeft = event->key.type == SDL_EVENT_KEY_DOWN;
}
if (SDLK_D == event->key.key) {
moveRight = event->key.type == SDL_EVENT_KEY_DOWN;
}
return GameState::RUNNING;
}
};

View File

@@ -9,6 +9,8 @@
including commercial applications, and to alter it and redistribute it including commercial applications, and to alter it and redistribute it
freely. freely.
*/ */
#include "GameState.h"
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_rect.h> #include <SDL3/SDL_rect.h>
#include <SDL3/SDL_render.h> #include <SDL3/SDL_render.h>
#include <string> #include <string>
@@ -20,66 +22,54 @@
#include <memory> #include <memory>
#include "components/PlayerGraphics.h" #include "components/PlayerGraphics.h"
#include "components/PlayerInput.h"
#include "Graphics.h" #include "Graphics.h"
#include "GameObject.h" #include "GameObject.h"
static SDL_Window *window = nullptr; static SDL_Window *window = nullptr;
static SDL_Renderer *renderer = nullptr; static SDL_Renderer *renderer = nullptr;
GameObject player(std::make_unique<PlayerGraphics>()); GameObject player(
Graphics graphics; std::make_unique<PlayerGraphics>(),
std::make_unique<PlayerInput>()
);
struct state {
Graphics graphics;
/* Physics physics */
};
/* This function runs once at startup. */ /* This function runs once at startup. */
SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[]) SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{ {
static struct state state {
Graphics("My Game")
};
*appstate = &state;
/* Create the window */ /* Create the window */
if (!SDL_CreateWindowAndRenderer("Hello World", 800, 600, SDL_WINDOW_FULLSCREEN, &window, &renderer)) {
SDL_Log("Couldn't create window and renderer: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
/* This function runs when a new event (mouse input, keypresses, etc) occurs. */ /* This function runs when a new event (mouse input, keypresses, etc) occurs. */
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event)
{ {
if (event->type == SDL_EVENT_KEY_DOWN ||
event->type == SDL_EVENT_QUIT) { auto state = player.processInput(event);
return SDL_APP_SUCCESS; /* end the program, reporting success to the OS. */ if (GameState::STOPPING == state) {
return SDL_APP_SUCCESS;
} }
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }
/* This function runs once per frame, and is the heart of the program. */ /* This function runs once per frame, and is the heart of the program. */
SDL_AppResult SDL_AppIterate(void *appstate) SDL_AppResult SDL_AppIterate(void *appstate)
{ {
std::string message("Hello World!"); auto game = static_cast<state*>(appstate);
int w = 0, h = 0;
float x, y;
const float scale = 4.0f;
/* Center the message and scale it up */ player.update(game->graphics);
SDL_GetRenderOutputSize(renderer, &w, &h); game->graphics.show();
SDL_SetRenderScale(renderer, scale, scale);
x = ((w / scale) - SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE * message.length()) / 2;
y = ((h / scale) - SDL_DEBUG_TEXT_FONT_CHARACTER_SIZE) / 2;
SDL_FRect rect {
.x = 30,
.y = 30,
.w = 100,
.h = 100
};
/* Draw the message */
SDL_SetRenderDrawColor(renderer, 0, 0, 200, 255);
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
SDL_RenderFillRect(renderer, &rect);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderDebugText(renderer, x, y, message.c_str());
SDL_RenderPresent(renderer);
return SDL_APP_CONTINUE; return SDL_APP_CONTINUE;
} }