diff options
author | Clyne Sullivan <clyne@bitgloo.com> | 2024-08-05 08:52:04 -0400 |
---|---|---|
committer | Clyne Sullivan <clyne@bitgloo.com> | 2024-08-05 08:52:04 -0400 |
commit | b2eb646979b9cdcef4f9edfbcc2e2309b1f57a18 (patch) | |
tree | 42d80816a1d2263e87b71e9597d8237416bb4cee | |
parent | 7579665e6292c62b35d8365d3fee1b76512547a3 (diff) |
very basic thing
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | Makefile | 14 | ||||
m--------- | entt | 0 | ||||
-rw-r--r-- | img/player.png | bin | 0 -> 3959 bytes | |||
-rw-r--r-- | main.cpp | 184 |
6 files changed, 204 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b8e5a39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.sw* +*.o +game diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..3f53ce8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "entt"] + path = entt + url = https://github.com/skypjack/entt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f0ad0d1 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +CXXFLAGS := -std=c++23 -O0 -g3 -ggdb \ + -Ientt/single_include +LDFLAGS := -lSDL2 -lSDL2_image + +OBJS := $(subst .cpp,.o,$(wildcard *.cpp)) + +all: game + +clean: + rm -f game $(OBJS) + +game: $(OBJS) + $(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS) + diff --git a/entt b/entt new file mode 160000 +Subproject 93f7d516f21e5f63422df983c02827ab1c8e050 diff --git a/img/player.png b/img/player.png Binary files differnew file mode 100644 index 0000000..810c152 --- /dev/null +++ b/img/player.png diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..409e66b --- /dev/null +++ b/main.cpp @@ -0,0 +1,184 @@ +#include <chrono> +#include <cstdlib> +#include <iostream> +#include <string_view> +#include <thread> + +#include <entt/entt.hpp> +#include <SDL2/SDL.h> +#include <SDL2/SDL_image.h> + +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); + } + + ~Texture() { + if (tex != nullptr) + SDL_DestroyTexture(tex); + } + + void operator()(SDL_Renderer *rend, Point p) const noexcept { + const int x = static_cast<int>(p.x); + const int y = static_cast<int>(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; +}; + +int main() +{ + if (auto err = sdl2Initialize(); err) + return err; + + entt::registry registry; + + const auto ent = registry.create(); + registry.emplace<Player>(ent); + registry.emplace<Point>(ent, 0.f, WINDOW_HEIGHT - 100.f); + registry.emplace<Velocity>(ent, 0.f, 0.f); + registry.emplace<Texture>(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); + + SDL_RenderClear(renderer); + registry.view<Texture, Point>().each( + [](Texture& tex, Point& p) { tex(renderer, p); }); + SDL_RenderPresent(renderer); + + registry.view<Velocity, Point>().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<Player, Velocity>(); + + 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<Player, Velocity>(); + + 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); + } + + SDL_DestroyWindow(window); + SDL_Quit(); +} + +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; +} + |