diff --git a/Makefile b/Makefile index f0ad0d1..88cd5d7 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ CXXFLAGS := -std=c++23 -O0 -g3 -ggdb \ - -Ientt/single_include + -Iinclude -Ientt/single_include LDFLAGS := -lSDL2 -lSDL2_image OBJS := $(subst .cpp,.o,$(wildcard *.cpp)) diff --git a/include/components/player.hpp b/include/components/player.hpp new file mode 100644 index 0000000..0940195 --- /dev/null +++ b/include/components/player.hpp @@ -0,0 +1,9 @@ +#ifndef COMPONENTS_PLAYER_HPP +#define COMPONENTS_PLAYER_HPP + +struct Player { + char unused = 0; +}; + +#endif // COMPONENTS_PLAYER_HPP + diff --git a/include/components/point.hpp b/include/components/point.hpp new file mode 100644 index 0000000..b0d0f35 --- /dev/null +++ b/include/components/point.hpp @@ -0,0 +1,9 @@ +#ifndef COMPONENTS_POINT_HPP +#define COMPONENTS_POINT_HPP + +#include "vec2.hpp" + +struct Point : public Vec2 {}; + +#endif // COMPONENTS_POINT_HPP + diff --git a/include/components/texture.hpp b/include/components/texture.hpp new file mode 100644 index 0000000..f4d414e --- /dev/null +++ b/include/components/texture.hpp @@ -0,0 +1,33 @@ +#ifndef COMPONENTS_TEXTURE_HPP +#define COMPONENTS_TEXTURE_HPP + +#include "window.hpp" + +class Texture +{ +public: + Texture(const char *path) { + tex = sdl2LoadTexture(path); + } + + ~Texture() { + if (tex != nullptr) + SDL_DestroyTexture(tex); + } + + void operator()(SDL_Renderer *rend, Point p) const noexcept { + const int x = static_cast(p.x); + const int y = static_cast(p.y); + SDL_Rect rect {x, y, 0, 0}; + + /* TODO err check */ + SDL_QueryTexture(tex, nullptr, nullptr, &rect.w, &rect.h); + SDL_RenderCopy(rend, tex, nullptr, &rect); + } + +private: + SDL_Texture *tex; +}; + +#endif // COMPONENTS_TEXTURE_HPP + diff --git a/include/components/velocity.hpp b/include/components/velocity.hpp new file mode 100644 index 0000000..2337ebd --- /dev/null +++ b/include/components/velocity.hpp @@ -0,0 +1,10 @@ +#ifndef COMPONENTS_VELOCITY_HPP +#define COMPONENTS_VELOCITY_HPP + +#include "vec2.hpp" + +struct Velocity : public Vec2 {}; + +#endif // COMPONENTS_VELOCITY_HPP + + diff --git a/include/vec2.hpp b/include/vec2.hpp new file mode 100644 index 0000000..dcd4b93 --- /dev/null +++ b/include/vec2.hpp @@ -0,0 +1,15 @@ +#ifndef VEC2_HPP +#define VEC2_HPP + +struct Vec2 { + float x, y; + + auto& operator+=(const Vec2& o) noexcept { + x += o.x; + y += o.y; + return *this; + } +}; + +#endif // VEC2_HPP + diff --git a/include/window.hpp b/include/window.hpp new file mode 100644 index 0000000..d245b33 --- /dev/null +++ b/include/window.hpp @@ -0,0 +1,16 @@ +#ifndef WINDOW_HPP +#define WINDOW_HPP + +#include + +constexpr auto WINDOW_WIDTH = 640; +constexpr auto WINDOW_HEIGHT = 480; + +extern SDL_Window *window; +extern SDL_Renderer *renderer; + +int sdl2Initialize(); +SDL_Texture *sdl2LoadTexture(const char *path); + +#endif // WINDOW_HPP + diff --git a/main.cpp b/main.cpp index 409e66b..09b55f4 100644 --- a/main.cpp +++ b/main.cpp @@ -1,64 +1,18 @@ +#include "components/point.hpp" +#include "components/player.hpp" +#include "components/texture.hpp" +#include "components/velocity.hpp" +#include "window.hpp" + #include -#include -#include -#include #include #include #include -#include - -static constexpr auto WINDOW_WIDTH = 640; -static constexpr auto WINDOW_HEIGHT = 480; - -static SDL_Window *window = nullptr; -static SDL_Renderer *renderer = nullptr; - -static int sdl2Initialize(); -static SDL_Texture *sdl2LoadTexture(const char *path); - -struct Player { - char unused = 0; -}; - -struct Vec2 { - float x, y; - - auto& operator+=(const Vec2& o) noexcept { - x += o.x; - y += o.y; - return *this; - } -}; - -struct Point : public Vec2 {}; -struct Velocity : public Vec2 {}; -class Texture -{ -public: - Texture(const char *path) { - tex = sdl2LoadTexture(path); - } +constexpr std::chrono::microseconds FRAME_TIME (1'000'000 / 60); - ~Texture() { - if (tex != nullptr) - SDL_DestroyTexture(tex); - } - - void operator()(SDL_Renderer *rend, Point p) const noexcept { - const int x = static_cast(p.x); - const int y = static_cast(p.y); - SDL_Rect rect {x, y, 0, 0}; - - /* TODO err check */ - SDL_QueryTexture(tex, nullptr, nullptr, &rect.w, &rect.h); - SDL_RenderCopy(rend, tex, nullptr, &rect); - } - -private: - SDL_Texture *tex; -}; +static bool handleInputs(entt::registry& registry); int main() { @@ -73,112 +27,51 @@ int main() registry.emplace(ent, 0.f, 0.f); registry.emplace(ent, "img/player.png"); - SDL_Event e; - bool quit = false; - while (!quit) { - const auto nextFrame = std::chrono::high_resolution_clock::now() + - std::chrono::microseconds(1'000'000 / 60); + do { + const auto now = std::chrono::high_resolution_clock::now(); SDL_RenderClear(renderer); - registry.view().each( - [](Texture& tex, Point& p) { tex(renderer, p); }); + registry.view().each([](auto& tex, auto& p) { tex(renderer, p); }); SDL_RenderPresent(renderer); - registry.view().each( - [](Velocity& v, Point& p) { p += v; }); - - while (SDL_PollEvent(&e)) { - if (e.type == SDL_QUIT) { - quit = true; - } else if (e.type == SDL_KEYDOWN) { - auto view = registry.view(); - - if (e.key.repeat) { - // do nothing - } else if (e.key.keysym.sym == SDLK_d) { - view.each([](Player& p, Velocity& v) { v.x += 1.5f; }); - } else if (e.key.keysym.sym == SDLK_a) { - view.each([](Player& p, Velocity& v) { v.x -= 1.5f; }); - } - } else if (e.type == SDL_KEYUP) { - auto view = registry.view(); - - if (e.key.repeat) { - // do nothing - } else if (e.key.keysym.sym == SDLK_d) { - view.each([](Player& p, Velocity& v) { v.x -= 1.5f; }); - } else if (e.key.keysym.sym == SDLK_a) { - view.each([](Player& p, Velocity& v) { v.x += 1.5f; }); - } - } - } - - std::this_thread::sleep_until(nextFrame); - } + registry.view().each([](auto& v, auto& p) { p += v; }); - SDL_DestroyWindow(window); - SDL_Quit(); + std::this_thread::sleep_until(now + FRAME_TIME); + } while (handleInputs(registry)); } -int sdl2Initialize() +bool handleInputs(entt::registry& registry) { - if (auto err = SDL_Init(SDL_INIT_VIDEO); err < 0) { - std::cerr << "SDL error: " << SDL_GetError() << std::endl; - return EXIT_FAILURE; - } else { - atexit(SDL_Quit); - } - - if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) { - std::cerr << "IMG error: " << IMG_GetError() << std::endl; - return EXIT_FAILURE; - } else { - atexit(IMG_Quit); - } - - window = SDL_CreateWindow("game", - SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - WINDOW_WIDTH, WINDOW_HEIGHT, - SDL_WINDOW_SHOWN); - - if (window == nullptr) { - std::cerr << "SDL error: " << SDL_GetError() << std::endl; - return EXIT_FAILURE; - } else { - atexit([] { SDL_DestroyWindow(window); }); - } - - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); - - if (renderer == nullptr) { - std::cerr << "SDL error: " << SDL_GetError() << std::endl; - return EXIT_FAILURE; - } else { - atexit([] { SDL_DestroyRenderer(renderer); }); - } - - return 0; -} + bool quit = false; -SDL_Texture *sdl2LoadTexture(const char *path) -{ - SDL_Texture *tex = nullptr; - - auto surface = IMG_Load(path); - if (surface == nullptr) { - std::cerr << "Unable to load image " << path << '!' << std::endl; - std::cerr << "SDL error: " << IMG_GetError() << std::endl; - } else { - tex = SDL_CreateTextureFromSurface(renderer, surface); - - if (tex == nullptr) { - std::cerr << "Unable to create texture for " << path << '!' << std::endl; - std::cerr << "SDL error: " << SDL_GetError() << std::endl; - } else { - SDL_FreeSurface(surface); + for (SDL_Event e; SDL_PollEvent(&e);) { + if (e.type == SDL_QUIT) { + quit = true; + } else if (e.type == SDL_KEYDOWN && !e.key.repeat) { + auto view = registry.view(); + + switch (e.key.keysym.sym) { + case SDLK_d: + view.each([](Player& p, Velocity& v) { v.x += 1.5f; }); + break; + case SDLK_a: + view.each([](Player& p, Velocity& v) { v.x -= 1.5f; }); + break; + } + } else if (e.type == SDL_KEYUP && !e.key.repeat) { + auto view = registry.view(); + + switch (e.key.keysym.sym) { + case SDLK_d: + view.each([](Player& p, Velocity& v) { v.x -= 1.5f; }); + break; + case SDLK_a: + view.each([](Player& p, Velocity& v) { v.x += 1.5f; }); + break; + } } } - return tex; + return !quit; } diff --git a/window.cpp b/window.cpp new file mode 100644 index 0000000..3813a3c --- /dev/null +++ b/window.cpp @@ -0,0 +1,72 @@ +#include "window.hpp" + +#include +#include + +#include + +SDL_Window *window; +SDL_Renderer *renderer; + +int sdl2Initialize() +{ + if (auto err = SDL_Init(SDL_INIT_VIDEO); err < 0) { + std::cerr << "SDL error: " << SDL_GetError() << std::endl; + return EXIT_FAILURE; + } else { + atexit(SDL_Quit); + } + + if (!(IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG)) { + std::cerr << "IMG error: " << IMG_GetError() << std::endl; + return EXIT_FAILURE; + } else { + atexit(IMG_Quit); + } + + window = SDL_CreateWindow("game", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + WINDOW_WIDTH, WINDOW_HEIGHT, + SDL_WINDOW_SHOWN); + + if (window == nullptr) { + std::cerr << "SDL error: " << SDL_GetError() << std::endl; + return EXIT_FAILURE; + } else { + atexit([] { SDL_DestroyWindow(window); }); + } + + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + + if (renderer == nullptr) { + std::cerr << "SDL error: " << SDL_GetError() << std::endl; + return EXIT_FAILURE; + } else { + atexit([] { SDL_DestroyRenderer(renderer); }); + } + + return 0; +} + +SDL_Texture *sdl2LoadTexture(const char *path) +{ + SDL_Texture *tex = nullptr; + + auto surface = IMG_Load(path); + if (surface == nullptr) { + std::cerr << "Unable to load image " << path << '!' << std::endl; + std::cerr << "SDL error: " << IMG_GetError() << std::endl; + } else { + tex = SDL_CreateTextureFromSurface(renderer, surface); + + if (tex == nullptr) { + std::cerr << "Unable to create texture for " << path << '!' << std::endl; + std::cerr << "SDL error: " << SDL_GetError() << std::endl; + } else { + SDL_FreeSurface(surface); + } + } + + return tex; +} +