level solid; basic collision/gravity

main
Clyne 3 months ago
parent 66991ce9b8
commit 456ef37653
Signed by: clyne
GPG Key ID: 3267C8EBF3F9AFC7

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

@ -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

@ -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

@ -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;

@ -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

@ -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>();

@ -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;
}

Loading…
Cancel
Save