123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <SDL.h>
- #define STB_IMAGE_IMPLEMENTATION
- #include "stb_image.h"
- const size_t SCREEN_WIDTH = 800;
- const size_t SCREEN_HEIGHT = 600;
- const size_t FPS = 60;
- const float DELTA_TIME = 1.0f / (float) FPS;
- const size_t SPRITE_DIGIT_WIDTH = 300 / 2;
- const size_t SPRITE_DIGIT_HEIGHT = 380 / 2;
- const size_t DIGIT_WIDTH = 300 / 2;
- const size_t DIGIT_HEIGHT = 380 / 2;
- const size_t DIGITS_COUNT = 11;
- const size_t WIGGLE_COUNT = 3;
- const float WIGGLE_DURATION = 0.40 / (float) WIGGLE_COUNT;
- const size_t COLON_INDEX = 10;
- const SDL_Color MAIN_COLOR = {220, 220, 220, 255};
- const SDL_Color PAUSE_COLOR = {220, 120, 120, 255};
- const SDL_Color BACKGROUND_COLOR = {24, 24, 24, 255};
- const float SCALE_FACTOR = 0.15f;
- void sec(int code)
- {
- if (code < 0) {
- fprintf(stderr, "SDL pooped itself: %s\n", SDL_GetError());
- abort();
- }
- }
- template <typename T>
- T *sec(T *ptr)
- {
- if (ptr == nullptr) {
- fprintf(stderr, "SDL pooped itself: %s\n", SDL_GetError());
- abort();
- }
- return ptr;
- }
- SDL_Surface *load_png_file_as_surface(const char *image_filename)
- {
- int width, height;
- uint32_t *image_pixels = (uint32_t *) stbi_load(image_filename, &width, &height, NULL, 4);
- if (image_pixels == NULL) {
- fprintf(stderr, "[ERROR] Could not load `%s` as PNG\n", image_filename);
- abort();
- }
- SDL_Surface* image_surface =
- sec(SDL_CreateRGBSurfaceFrom(
- image_pixels,
- (int) width,
- (int) height,
- 32,
- (int) width * 4,
- 0x000000FF,
- 0x0000FF00,
- 0x00FF0000,
- 0xFF000000));
- return image_surface;
- }
- SDL_Texture *load_png_file_as_texture(SDL_Renderer *renderer,
- const char *image_filename)
- {
- SDL_Surface *image_surface = load_png_file_as_surface(image_filename);
- return sec(SDL_CreateTextureFromSurface(renderer, image_surface));
- }
- void render_digit_at(SDL_Renderer *renderer, SDL_Texture *digits, size_t digit_index,
- size_t wiggle_index, int *pen_x, int *pen_y, float scale)
- {
- const int effective_digit_width = (int) floorf((float) DIGIT_WIDTH * scale);
- const int effective_digit_height = (int) floorf((float) DIGIT_HEIGHT * scale);
- const SDL_Rect src_rect = {
- (int) (digit_index * SPRITE_DIGIT_WIDTH),
- (int) (wiggle_index * SPRITE_DIGIT_HEIGHT),
- SPRITE_DIGIT_WIDTH,
- SPRITE_DIGIT_HEIGHT
- };
- const SDL_Rect dst_rect = {
- *pen_x,
- *pen_y,
- effective_digit_width,
- effective_digit_height
- };
- SDL_RenderCopy(renderer, digits, &src_rect, &dst_rect);
- *pen_x += effective_digit_width;
- }
- void initial_pen(SDL_Window *window, int *pen_x, int *pen_y, float scale)
- {
- int w, h;
- SDL_GetWindowSize(window, &w, &h);
- const int effective_digit_width = (int) floorf((float) DIGIT_WIDTH * scale);
- const int effective_digit_height = (int) floorf((float) DIGIT_HEIGHT * scale);
- *pen_x = w / 2 - effective_digit_width * 8 / 2;
- *pen_y = h / 2 - effective_digit_height / 2;
- }
- int main(int argc, char **argv)
- {
- bool ascending = true;
- float time = 0.0f;
- if (argc > 1) {
- ascending = false;
- time = strtof(argv[1], NULL);
- }
- sec(SDL_Init(SDL_INIT_VIDEO));
- SDL_Window *window =
- sec(SDL_CreateWindow(
- "sowon",
- 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT,
- SDL_WINDOW_RESIZABLE));
- SDL_Renderer *renderer =
- sec(SDL_CreateRenderer(
- window, -1,
- SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED));
- sec(SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"));
- SDL_Texture *digits = load_png_file_as_texture(renderer, "./digits.png");
- sec(SDL_SetTextureColorMod(digits, MAIN_COLOR.r, MAIN_COLOR.g, MAIN_COLOR.b));
- bool quit = false;
- size_t wiggle_index = 0;
- size_t digit_index = 0;
- float wiggle_cooldown = WIGGLE_DURATION;
- float digit_cooldown = 1.0f;
- bool paused = false;
- float scale = 1.0f;
- while (!quit) {
- // INPUT BEGIN //////////////////////////////
- SDL_Event event = {};
- while (SDL_PollEvent(&event)) {
- switch (event.type) {
- case SDL_QUIT: {
- quit = true;
- } break;
- case SDL_KEYDOWN: {
- switch (event.key.keysym.sym) {
- case SDLK_SPACE: {
- paused = !paused;
- if (paused) {
- sec(SDL_SetTextureColorMod(digits, PAUSE_COLOR.r, PAUSE_COLOR.g, PAUSE_COLOR.b));
- } else {
- sec(SDL_SetTextureColorMod(digits, MAIN_COLOR.r, MAIN_COLOR.g, MAIN_COLOR.b));
- }
- } break;
- case SDLK_EQUALS: {
- scale += SCALE_FACTOR * scale;
- } break;
- case SDLK_MINUS: {
- scale -= SCALE_FACTOR * scale;
- } break;
- case SDLK_0: {
- scale = 1.0f;
- } break;
- }
- } break;
- default: {}
- }
- }
- // INPUT END //////////////////////////////
- // RENDER BEGIN //////////////////////////////
- SDL_SetRenderDrawColor(renderer, BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, 255);
- SDL_RenderClear(renderer);
- {
- int pen_x, pen_y;
- initial_pen(window, &pen_x, &pen_y, scale);
- const size_t t = (size_t) floorf(fmaxf(time, 0.0f));
- const size_t hours = t / 60 / 60;
- render_digit_at(renderer, digits, hours / 10, wiggle_index, &pen_x, &pen_y, scale);
- render_digit_at(renderer, digits, hours % 10, wiggle_index, &pen_x, &pen_y, scale);
- render_digit_at(renderer, digits, COLON_INDEX, wiggle_index, &pen_x, &pen_y, scale);
- const size_t minutes = t / 60 % 60;
- render_digit_at(renderer, digits, minutes / 10, wiggle_index, &pen_x, &pen_y, scale);
- render_digit_at(renderer, digits, minutes % 10, wiggle_index, &pen_x, &pen_y, scale);
- render_digit_at(renderer, digits, COLON_INDEX, wiggle_index, &pen_x, &pen_y, scale);
- const size_t seconds = t % 60;
- render_digit_at(renderer, digits, seconds / 10, wiggle_index, &pen_x, &pen_y, scale);
- render_digit_at(renderer, digits, seconds % 10, wiggle_index, &pen_x, &pen_y, scale);
- }
- SDL_RenderPresent(renderer);
- // RENDER END //////////////////////////////
- // UPDATE BEGIN //////////////////////////////
- if (wiggle_cooldown <= 0.0f) {
- wiggle_index = (wiggle_index + 1) % WIGGLE_COUNT;
- wiggle_cooldown = WIGGLE_DURATION;
- }
- wiggle_cooldown -= DELTA_TIME;
- if (!paused) {
- if (ascending) {
- time += DELTA_TIME;
- } else {
- if (time > 1e-6) {
- time -= DELTA_TIME;
- } else {
- time = 0.0f;
- }
- }
- }
- // UPDATE END //////////////////////////////
- SDL_Delay((int) floorf(DELTA_TIME * 1000.0f));
- }
- SDL_Quit();
- return 0;
- }
|