|
|
|
@ -1,64 +1,18 @@
|
|
|
|
|
#include "components/point.hpp"
|
|
|
|
|
#include "components/player.hpp"
|
|
|
|
|
#include "components/texture.hpp"
|
|
|
|
|
#include "components/velocity.hpp"
|
|
|
|
|
#include "window.hpp"
|
|
|
|
|
|
|
|
|
|
#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};
|
|
|
|
|
constexpr std::chrono::microseconds FRAME_TIME (1'000'000 / 60);
|
|
|
|
|
|
|
|
|
|
/* TODO err check */
|
|
|
|
|
SDL_QueryTexture(tex, nullptr, nullptr, &rect.w, &rect.h);
|
|
|
|
|
SDL_RenderCopy(rend, tex, nullptr, &rect);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
SDL_Texture *tex;
|
|
|
|
|
};
|
|
|
|
|
static bool handleInputs(entt::registry& registry);
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
|
{
|
|
|
|
@ -73,112 +27,51 @@ int main()
|
|
|
|
|
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);
|
|
|
|
|
do {
|
|
|
|
|
const auto now = std::chrono::high_resolution_clock::now();
|
|
|
|
|
|
|
|
|
|
SDL_RenderClear(renderer);
|
|
|
|
|
registry.view<Texture, Point>().each(
|
|
|
|
|
[](Texture& tex, Point& p) { tex(renderer, p); });
|
|
|
|
|
registry.view<Texture, Point>().each([](auto& tex, auto& p) { tex(renderer, p); });
|
|
|
|
|
SDL_RenderPresent(renderer);
|
|
|
|
|
|
|
|
|
|
registry.view<Velocity, Point>().each(
|
|
|
|
|
[](Velocity& v, Point& p) { p += v; });
|
|
|
|
|
registry.view<Velocity, Point>().each([](auto& v, auto& p) { p += v; });
|
|
|
|
|
|
|
|
|
|
std::this_thread::sleep_until(now + FRAME_TIME);
|
|
|
|
|
} while (handleInputs(registry));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool handleInputs(entt::registry& registry)
|
|
|
|
|
{
|
|
|
|
|
bool quit = false;
|
|
|
|
|
|
|
|
|
|
while (SDL_PollEvent(&e)) {
|
|
|
|
|
for (SDL_Event e; SDL_PollEvent(&e);) {
|
|
|
|
|
if (e.type == SDL_QUIT) {
|
|
|
|
|
quit = true;
|
|
|
|
|
} else if (e.type == SDL_KEYDOWN) {
|
|
|
|
|
} else if (e.type == SDL_KEYDOWN && !e.key.repeat) {
|
|
|
|
|
auto view = registry.view<Player, Velocity>();
|
|
|
|
|
|
|
|
|
|
if (e.key.repeat) {
|
|
|
|
|
// do nothing
|
|
|
|
|
} else if (e.key.keysym.sym == SDLK_d) {
|
|
|
|
|
switch (e.key.keysym.sym) {
|
|
|
|
|
case SDLK_d:
|
|
|
|
|
view.each([](Player& p, Velocity& v) { v.x += 1.5f; });
|
|
|
|
|
} else if (e.key.keysym.sym == SDLK_a) {
|
|
|
|
|
break;
|
|
|
|
|
case SDLK_a:
|
|
|
|
|
view.each([](Player& p, Velocity& v) { v.x -= 1.5f; });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else if (e.type == SDL_KEYUP) {
|
|
|
|
|
} else if (e.type == SDL_KEYUP && !e.key.repeat) {
|
|
|
|
|
auto view = registry.view<Player, Velocity>();
|
|
|
|
|
|
|
|
|
|
if (e.key.repeat) {
|
|
|
|
|
// do nothing
|
|
|
|
|
} else if (e.key.keysym.sym == SDLK_d) {
|
|
|
|
|
switch (e.key.keysym.sym) {
|
|
|
|
|
case SDLK_d:
|
|
|
|
|
view.each([](Player& p, Velocity& v) { v.x -= 1.5f; });
|
|
|
|
|
} else if (e.key.keysym.sym == SDLK_a) {
|
|
|
|
|
break;
|
|
|
|
|
case SDLK_a:
|
|
|
|
|
view.each([](Player& p, Velocity& v) { v.x += 1.5f; });
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
return !quit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|