#include "log.h" #include "nyan_types.h" #include #include #include static void nyan_sdl_fatal(const char *const msg) { log_fatal("%s: %s", msg, SDL_GetError()); abort(); } static void nyan_sdl_error(const char *const msg) { log_error("%s: %s", msg, SDL_GetError()); } static const float NYAN_PI = 3.14159265358979323846f; static const float NYAN_PI2 = 2.0f * NYAN_PI; template T deg2rad(T deg) { return deg * NYAN_PI / 180.0; } template T rad2deg(T deg) { return 180.0 * deg / NYAN_PI; } struct NyanSpinnyCircle { SDL_Texture *nyanSheet = nullptr; SDL_Point centerPos; float radius = 100.0f; float radiusBounce = 0.0f; float radiusBounceIncrement = 0.4f; float radiusBounceMax = 42.0f; float angle = 0.0f; float angularStep = 0.015f; unsigned animSpeed = 48; unsigned nyanCount = 13; }; void do_circle_nyan_step(SDL_Renderer *renderer, NyanSpinnyCircle &nsc) { static constexpr SDL_Point rotCenter = {NYAN_SPRITE_WIDTH, NYAN_SPRITE_HEIGHT}; const size_t nyanSpriteIndex = (SDL_GetTicks() / nsc.animSpeed) % NYAN_SPRITE_COUNT; const auto sourceRect = nyan_sprite_rect(nyanSpriteIndex); const auto nyanRads = deg2rad(360.0f / nsc.nyanCount); for (auto i=0u; i= NYAN_PI2) nsc.angle -= NYAN_PI2; nsc.radiusBounce += nsc.radiusBounceIncrement; if (nsc.radiusBounce <= -nsc.radiusBounceMax || nsc.radiusBounce > nsc.radiusBounceMax) nsc.radiusBounceIncrement = - nsc.radiusBounceIncrement; } int main(int argc, char *argv[]) { (void) argc; (void) argv; #ifndef NDEBUG log_set_level(LOG_TRACE); #else log_set_level(LOG_DEBUG); #endif if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) nyan_sdl_fatal("SDL_Init"); #ifdef SDL_HINT_IME_SHOW_UI SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1"); #endif const auto windowFlags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_OPENGL; auto window = SDL_CreateWindow("sdl_nyan", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 960, windowFlags); if (!window) nyan_sdl_fatal("SDL_CreateWindow"); auto renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); if (!renderer) nyan_sdl_fatal("SDL_CreateRenderer"); //auto nyanSheet = make_nyan_sprite_sheet_from_files(renderer); auto nyanSheet = make_nyan_sprite_sheet_from_mem(renderer); NyanSpinnyCircle nsc; nsc.nyanSheet = nyanSheet; nsc.centerPos = { 420/2, 420/2 }; bool quit = false; while (!quit) { SDL_Event event; while (SDL_PollEvent(&event)) { if (event.type == SDL_QUIT) quit = true; if (event.type == SDL_KEYDOWN && event.key.keysym.mod & KMOD_CTRL && event.key.keysym.sym == SDLK_q) quit = true; } SDL_SetRenderDrawColor(renderer, 128, 128, 128, 255); SDL_RenderClear(renderer); auto sheetDestRect = nyan_sheet_rect(); sheetDestRect.w *= 3; sheetDestRect.h *= 3; SDL_RenderCopy(renderer, nyanSheet, nullptr, &sheetDestRect); auto ticks = SDL_GetTicks(); size_t nyanSpriteIndex = (ticks / 48) % NYAN_SPRITE_COUNT; auto sourceRect = nyan_sprite_rect(nyanSpriteIndex); auto destRect = nyan_sprite_rect(0); destRect.w *= 3; destRect.h *= 3; destRect.y += sheetDestRect.h; SDL_RenderCopy(renderer, nyanSheet, &sourceRect, &destRect); destRect.x = 420/2; destRect.y = 420/2; SDL_Point centerPoint = {NYAN_SPRITE_WIDTH, NYAN_SPRITE_HEIGHT}; double angle = (ticks / 4) % 360; SDL_RenderCopyEx(renderer, nyanSheet, &sourceRect, &destRect, angle, ¢erPoint, SDL_FLIP_NONE); do_circle_nyan_step(renderer, nsc); SDL_RenderPresent(renderer); } SDL_DestroyTexture(nyanSheet); SDL_DestroyRenderer(renderer); SDL_DestroyWindow(window); SDL_Quit(); return 0; }