Skip to content

Instantly share code, notes, and snippets.

@cyrillsemenov
Created January 3, 2025 23:27
Show Gist options
  • Save cyrillsemenov/8a8a4405fa9216c92d719918e7152968 to your computer and use it in GitHub Desktop.
Save cyrillsemenov/8a8a4405fa9216c92d719918e7152968 to your computer and use it in GitHub Desktop.
7 days visual - SDL Version
// BUILD_ARGS: -Wall $(pkg-config --libs --cflags sdl2)
#include <SDL2/SDL.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#define SCREEN_WIDTH 400
#define SCREEN_HEIGHT 240
#define OUTER_RADIUS 100.0f
#define INNER_RADIUS 90.0f
float pseudo_random_noise(int x, int y, int seed) {
unsigned int n = x + y * 57 + seed * 131;
n = (n << 13) ^ n;
return (1.0f -
(float)((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) /
1073741824.0f);
}
int dither_pattern(int x, int y, float value) {
int threshold[8][8] = {{0, 64, 32, 96, 16, 80, 48, 112},
{192, 128, 224, 160, 208, 144, 240, 176},
{48, 112, 16, 80, 32, 96, 64, 128},
{240, 176, 224, 160, 208, 144, 192, 128},
{24, 88, 56, 120, 8, 72, 40, 104},
{216, 152, 184, 120, 200, 136, 168, 104},
{72, 136, 104, 168, 8, 72, 40, 104},
{200, 136, 168, 104, 184, 120, 152, 88}};
int tx = x % 8;
int ty = y % 8;
int threshold_value = threshold[ty][tx];
return value * 256 > threshold_value ? 0xff : 0x0;
}
static inline int compute_local_x_offset(int x, int y, int seed) {
return pseudo_random_noise(x >> 4, y, seed) *
(2 - pseudo_random_noise(0, 0, seed << 2));
}
static inline int compute_displacement(int x, int y, int seed) {
return pseudo_random_noise(x, y >> 1, seed >> 2) *
(3 + pseudo_random_noise(0, 0, seed >> 4));
}
static inline float generate_walls(int x, int y, int seed) {
float dx = x - SCREEN_WIDTH / 2.0f;
float dy = y - SCREEN_HEIGHT / 2.0f;
float distance_1 =
sqrt(dx * dx + dy * dy) + sin(dy / 20.0f + (seed >> 4)) * 10.0f;
float ring_1 = fabs(sin(distance_1 * 0.18f)) * exp(-distance_1 * 0.005f);
float distance_2 = sqrt(dx * dx + dy * dy) +
cos(dx / 20.0f - dy / 40.0f + (seed >> 8)) * 10.0f;
float ring_2 = fabs(sin(distance_2 * 0.25f)) * exp(-distance_2 * 0.005f);
return ring_1 * ring_2;
}
static inline float generate_ring_value(int x, int y, float global_x_offset,
int local_x_offset, int displacement,
int seed) {
float dx_1 = x - SCREEN_WIDTH / 2.0f - local_x_offset * 2.0f;
float dx_2 =
x - SCREEN_WIDTH / 2.0f + global_x_offset + local_x_offset * 3.0f;
float dy = y - SCREEN_HEIGHT / 2.0f;
float dist_1 = sqrt(dx_1 * dx_1 + dy * dy) + displacement;
float dist_2 = sqrt(dx_2 * dx_2 + dy * dy) - displacement;
float fade = exp(-dist_1 / SCREEN_HEIGHT);
float ring_1 = (dist_1 < OUTER_RADIUS) ? 1.0f : fade / 2.0f;
float ring_2 = (dist_2 > INNER_RADIUS) ? 1.0f : 0.0f;
float walls = generate_walls(x, y, seed);
return (ring_1 + (walls * fade * 1.2f)) * ring_2 +
(1.0f - ring_2) * (1.0f - fade) * 2.0f;
}
void render_ring_with_effects(SDL_Renderer *renderer) {
SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING,
SCREEN_WIDTH, SCREEN_HEIGHT);
void *pixels;
int pitch;
if (SDL_LockTexture(texture, NULL, &pixels, &pitch) < 0) {
fprintf(stderr, "Failed to lock texture: %s\n", SDL_GetError());
return;
}
Uint32 *pixel_data = (Uint32 *)pixels;
int seed = SDL_GetTicks();
float global_x_offset = pseudo_random_noise(0, 0, seed >> 4) * 3;
for (int y = 0; y < SCREEN_HEIGHT; y++) {
for (int x = 0; x < SCREEN_WIDTH; x++) {
int local_x_offset = compute_local_x_offset(x, y, seed);
int displacement = compute_displacement(x, y, seed);
float ring = generate_ring_value(
x, y, global_x_offset, local_x_offset, displacement, seed);
float noise = pseudo_random_noise(x >> 1, y >> 1, seed);
float pixels = pseudo_random_noise(x >> 4, y >> 2, seed);
float pixel_value = ring + noise * 0.2f - 0.25f - pixels * 0.1f;
int color = dither_pattern(x, y, pixel_value);
pixel_data[y * (pitch / 4) + x] =
(color << 16) | (color << 8) | color;
}
}
SDL_UnlockTexture(texture);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_DestroyTexture(texture);
}
int main(int argc, char *argv[]) {
int success = EXIT_FAILURE;
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
fprintf(stderr, "SDL_Init(): %s\n", SDL_GetError());
goto finish;
}
window = SDL_CreateWindow("7 days", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
if (!window) {
fprintf(stderr, "SDL_CreateWindow(): %s\n", SDL_GetError());
goto finish;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
fprintf(stderr, "SDL_CreateRenderer(): %s\n", SDL_GetError());
goto finish;
}
int running = 1;
SDL_Event event;
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = 0;
}
}
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
render_ring_with_effects(renderer);
usleep(100000);
SDL_RenderPresent(renderer);
}
success = EXIT_SUCCESS;
finish:
if (renderer)
SDL_DestroyRenderer(renderer);
if (window)
SDL_DestroyWindow(window);
SDL_Quit();
return success;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment