#include #include #include #include #include #include #include #include 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(p.x); const int y = static_cast(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(ent); registry.emplace(ent, 0.f, WINDOW_HEIGHT - 100.f); registry.emplace(ent, 0.f, 0.f); registry.emplace(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().each( [](Texture& tex, Point& p) { tex(renderer, p); }); SDL_RenderPresent(renderer); registry.view().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(); 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(); 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; }