]> code.bitgloo.com Git - clyne/game.git/commitdiff
very basic thing
authorClyne Sullivan <clyne@bitgloo.com>
Mon, 5 Aug 2024 12:52:04 +0000 (08:52 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Mon, 5 Aug 2024 12:52:04 +0000 (08:52 -0400)
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]
Makefile [new file with mode: 0644]
entt [new submodule]
img/player.png [new file with mode: 0644]
main.cpp [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..b8e5a39
--- /dev/null
@@ -0,0 +1,3 @@
+*.sw*
+*.o
+game
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..3f53ce8
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "entt"]
+       path = entt
+       url = https://github.com/skypjack/entt
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
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 (submodule)
index 0000000..93f7d51
--- /dev/null
+++ b/entt
@@ -0,0 +1 @@
+Subproject commit 93f7d516f21e5f63422df983c02827ab1c8e050e
diff --git a/img/player.png b/img/player.png
new file mode 100644 (file)
index 0000000..810c152
Binary files /dev/null and b/img/player.png differ
diff --git a/main.cpp b/main.cpp
new file mode 100644 (file)
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;
+}
+