aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2024-08-05 08:52:04 -0400
committerClyne Sullivan <clyne@bitgloo.com>2024-08-05 08:52:04 -0400
commitb2eb646979b9cdcef4f9edfbcc2e2309b1f57a18 (patch)
tree42d80816a1d2263e87b71e9597d8237416bb4cee
parent7579665e6292c62b35d8365d3fee1b76512547a3 (diff)
very basic thing
-rw-r--r--.gitignore3
-rw-r--r--.gitmodules3
-rw-r--r--Makefile14
m---------entt0
-rw-r--r--img/player.pngbin0 -> 3959 bytes
-rw-r--r--main.cpp184
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
new file mode 100644
index 0000000..810c152
--- /dev/null
+++ b/img/player.png
Binary files differ
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;
+}
+