]> code.bitgloo.com Git - clyne/game.git/commitdiff
level solid; basic collision/gravity
authorClyne Sullivan <clyne@bitgloo.com>
Mon, 5 Aug 2024 19:47:55 +0000 (15:47 -0400)
committerClyne Sullivan <clyne@bitgloo.com>
Mon, 5 Aug 2024 19:47:55 +0000 (15:47 -0400)
img/level.png [new file with mode: 0644]
include/components/solid.hpp [new file with mode: 0644]
include/components/texture.hpp
include/vec2.hpp
include/window.hpp
main.cpp
window.cpp

diff --git a/img/level.png b/img/level.png
new file mode 100644 (file)
index 0000000..bb28633
Binary files /dev/null and b/img/level.png differ
diff --git a/include/components/solid.hpp b/include/components/solid.hpp
new file mode 100644 (file)
index 0000000..d02d229
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef COMPONENTS_SOLID_HPP
+#define COMPONENTS_SOLID_HPP
+
+#include "components/point.hpp"
+#include "window.hpp"
+
+#include <algorithm>
+#include <cstdint>
+
+class Solid {
+public:
+    Solid(const char *path) {
+        bitmap = sdl2LoadSolid(path);
+    }
+
+    ~Solid() {
+        if (bitmap != nullptr)
+            SDL_FreeSurface(bitmap);
+    }
+
+    float collision(Vec2 p) const noexcept {
+        float dy = 0.f;
+
+        if (at(p)) {
+            auto up = p;
+            while (up.y > 0 && at(up))
+                up.y--;
+
+            auto down = p;
+            while (down.y < bitmap->h && at(down))
+                down.y++;
+
+            if (down.y - p.y > p.y - up.y)
+                dy = -(p.y - up.y);
+            else
+                dy = down.y - p.y;
+        }
+
+        return dy;
+    }
+
+private:
+    SDL_Surface *bitmap;
+
+    bool at(Vec2 p) const noexcept {
+        const auto bm = reinterpret_cast<std::uint8_t *>(bitmap->pixels);
+        const int x = std::clamp(static_cast<int>(p.x), 0, bitmap->w);
+        const int y = std::clamp(static_cast<int>(p.y), 0, bitmap->h);
+        const int i = y * bitmap->w + x;
+        const auto val = bm[i * bitmap->format->BytesPerPixel];
+        return val > 0;
+    }
+};
+
+#endif // COMPONENTS_SOLID_HPP
+
index f4d414ea4896824a77d4726ba699ac20dde1f565..14253f12141b094eac720bff39ae025c94b3d9c1 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef COMPONENTS_TEXTURE_HPP
 #define COMPONENTS_TEXTURE_HPP
 
+#include "components/point.hpp"
 #include "window.hpp"
 
 class Texture
@@ -8,6 +9,8 @@ class Texture
 public:
     Texture(const char *path) {
         tex = sdl2LoadTexture(path);
+        if (tex)
+            SDL_QueryTexture(tex, nullptr, nullptr, &w, &h);
     }
 
     ~Texture() {
@@ -18,15 +21,18 @@ public:
     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};
+        SDL_Rect rect {x, y, w, h};
 
-        /* TODO err check */
-        SDL_QueryTexture(tex, nullptr, nullptr, &rect.w, &rect.h);
         SDL_RenderCopy(rend, tex, nullptr, &rect);
     }
 
+    Point dim() const noexcept {
+        return Point {static_cast<float>(w), static_cast<float>(h)};
+    }
+
 private:
     SDL_Texture *tex;
+    int w, h;
 };
 
 #endif // COMPONENTS_TEXTURE_HPP
index dcd4b935d2c196aed8b835afe117a0238fcad743..6b3c30ad510ba75c4cf31b8885af7b9dadb4c4db 100644 (file)
@@ -4,6 +4,10 @@
 struct Vec2 {
     float x, y;
 
+    auto operator+(const Vec2& o) const noexcept {
+        return Vec2 {x + o.x, y + o.y};
+    }
+
     auto& operator+=(const Vec2& o) noexcept {
         x += o.x;
         y += o.y;
index d245b33ebc1a801cad2a8621215112107656f16e..ad8392c532c90e8082f7e914f6097ac1fc0aff0a 100644 (file)
@@ -11,6 +11,7 @@ extern SDL_Renderer *renderer;
 
 int sdl2Initialize();
 SDL_Texture *sdl2LoadTexture(const char *path);
+SDL_Surface *sdl2LoadSolid(const char *path);
 
 #endif // WINDOW_HPP
 
index 09b55f4bb7ede86c1db24d11644650623f40164c..c137cc15b2572d425453b1363b3a7b8249581f65 100644 (file)
--- a/main.cpp
+++ b/main.cpp
@@ -1,10 +1,12 @@
 #include "components/point.hpp"
 #include "components/player.hpp"
+#include "components/solid.hpp"
 #include "components/texture.hpp"
 #include "components/velocity.hpp"
 #include "window.hpp"
 
 #include <chrono>
+#include <iostream>
 #include <thread>
 
 #include <entt/entt.hpp>
@@ -21,11 +23,20 @@ int main()
 
     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");
+    {
+        const auto ent = registry.create();
+        registry.emplace<Player>(ent);
+        registry.emplace<Point>(ent, 0.f, WINDOW_HEIGHT - 200.f);
+        registry.emplace<Velocity>(ent, 0.f, 0.f);
+        registry.emplace<Texture>(ent, "img/player.png");
+    }
+
+    {
+        const auto ent = registry.create();
+        registry.emplace<Point>(ent, 0.f, 0.f);
+        registry.emplace<Texture>(ent, "img/level.png");
+        registry.emplace<Solid>(ent, "img/level.png");
+    }
 
     do {
         const auto now = std::chrono::high_resolution_clock::now();
@@ -36,6 +47,23 @@ int main()
 
         registry.view<Velocity, Point>().each([](auto& v, auto& p) { p += v; });
 
+        registry.view<Solid, Point>().each(
+            [&registry](auto& s, auto& p) {
+                registry.view<Player, Point, Velocity, Texture>().each(
+                    [&s, &p](auto& _, auto& pp, auto& pv, auto& t) {
+                        const auto c = s.collision(pp + t.dim());
+
+                        if (c) {
+                            if (std::abs(c) > 1.f)
+                                pv.y = c * 0.5f;
+                            else
+                                pv.y = 0.f;
+                        } else {
+                            pv.y += 0.1f;
+                        }
+                    });
+            });
+
         std::this_thread::sleep_until(now + FRAME_TIME);
     } while (handleInputs(registry));
 }
@@ -57,6 +85,9 @@ bool handleInputs(entt::registry& registry)
             case SDLK_a:
                 view.each([](Player& p, Velocity& v) { v.x -= 1.5f; });
                 break;
+            case SDLK_SPACE:
+                view.each([](Player& p, Velocity& v) { if (v.y <= 0.f) v.y -= 3.f; });
+                break;
             }
         } else if (e.type == SDL_KEYUP && !e.key.repeat) {
             auto view = registry.view<Player, Velocity>();
index 3813a3cd57286e4606d245d1ebf546a6848a37e8..e8677a8552bce7d8bee30469d06b0717b2a10ce2 100644 (file)
@@ -70,3 +70,15 @@ SDL_Texture *sdl2LoadTexture(const char *path)
     return tex;
 }
 
+SDL_Surface *sdl2LoadSolid(const char *path)
+{
+    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;
+    }
+
+    return surface;
+}
+