diff --git a/img/level.png b/img/level.png new file mode 100644 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 index 0000000..d02d229 --- /dev/null +++ b/include/components/solid.hpp @@ -0,0 +1,56 @@ +#ifndef COMPONENTS_SOLID_HPP +#define COMPONENTS_SOLID_HPP + +#include "components/point.hpp" +#include "window.hpp" + +#include +#include + +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(bitmap->pixels); + const int x = std::clamp(static_cast(p.x), 0, bitmap->w); + const int y = std::clamp(static_cast(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 + diff --git a/include/components/texture.hpp b/include/components/texture.hpp index f4d414e..14253f1 100644 --- a/include/components/texture.hpp +++ b/include/components/texture.hpp @@ -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(p.x); const int y = static_cast(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(w), static_cast(h)}; + } + private: SDL_Texture *tex; + int w, h; }; #endif // COMPONENTS_TEXTURE_HPP diff --git a/include/vec2.hpp b/include/vec2.hpp index dcd4b93..6b3c30a 100644 --- a/include/vec2.hpp +++ b/include/vec2.hpp @@ -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; diff --git a/include/window.hpp b/include/window.hpp index d245b33..ad8392c 100644 --- a/include/window.hpp +++ b/include/window.hpp @@ -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 diff --git a/main.cpp b/main.cpp index 09b55f4..c137cc1 100644 --- 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 +#include #include #include @@ -21,11 +23,20 @@ int main() entt::registry registry; - const auto ent = registry.create(); - registry.emplace(ent); - registry.emplace(ent, 0.f, WINDOW_HEIGHT - 100.f); - registry.emplace(ent, 0.f, 0.f); - registry.emplace(ent, "img/player.png"); + { + const auto ent = registry.create(); + registry.emplace(ent); + registry.emplace(ent, 0.f, WINDOW_HEIGHT - 200.f); + registry.emplace(ent, 0.f, 0.f); + registry.emplace(ent, "img/player.png"); + } + + { + const auto ent = registry.create(); + registry.emplace(ent, 0.f, 0.f); + registry.emplace(ent, "img/level.png"); + registry.emplace(ent, "img/level.png"); + } do { const auto now = std::chrono::high_resolution_clock::now(); @@ -36,6 +47,23 @@ int main() registry.view().each([](auto& v, auto& p) { p += v; }); + registry.view().each( + [®istry](auto& s, auto& p) { + registry.view().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(); diff --git a/window.cpp b/window.cpp index 3813a3c..e8677a8 100644 --- a/window.cpp +++ b/window.cpp @@ -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; +} +