Last active
October 9, 2024 16:23
-
-
Save Theldus/10614722638269fdd0491230ca416f3f to your computer and use it in GitHub Desktop.
Star trails in C+SDL2 (inspired by @rlaneth's code in https://startrail.rlaneth.com/)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <err.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <time.h> | |
#include <inttypes.h> | |
#include <SDL.h> | |
/* | |
* Tuto nice: | |
* https://lazyfoo.net/tutorials/SDL/index.php | |
*/ | |
/* | |
* Build instructions: | |
* | |
* gcc sdl.c -o star -O3 `pkg-config --cflags --libs sdl2` | |
*/ | |
typedef uint8_t u8; | |
#define WIDTH 1920 | |
#define HEIGHT 1080 | |
#define PI 3.141592653589793 | |
static int centerX, centerY; | |
static u8 *buff; | |
#define MAX_STARS 100 | |
static SDL_Window* window; | |
static SDL_Renderer* renderer; | |
static int screen_width = WIDTH; | |
static int screen_height = HEIGHT; | |
static int IsWindowResized = 1; | |
int min_w_h; | |
struct star { | |
double x; | |
double y; | |
double size; | |
double speed; | |
double angle; | |
} stars[MAX_STARS]; | |
static void resize(int width, int height) { | |
if (width > 599) { | |
centerY = height - 250; | |
centerX = width - 250; | |
} else { | |
centerY = height; | |
centerX = width / 2; | |
} | |
if (width <= height) | |
min_w_h = width; | |
else | |
min_w_h = height; | |
} | |
static void create_stars(void) { | |
for (int i = 0; i < MAX_STARS; i++) { | |
double radius = drand48() * (double)min_w_h; | |
double angle = drand48() * PI * 2.0; | |
stars[i].x = (double)centerX + SDL_cos(angle) * radius; | |
stars[i].y = (double)centerY + SDL_sin(angle) * radius; | |
stars[i].size = 2; | |
stars[i].speed = (drand48() * 0.0002) + 0.0002; | |
stars[i].angle = angle; | |
} | |
} | |
void drawcircle(int centerX, int centerY, int radius) | |
{ | |
int x = radius - 1; | |
int y = 0; | |
int dx = 1; | |
int dy = 1; | |
int err = dx - (radius * 2); | |
while (x >= y) { | |
SDL_RenderDrawPoint(renderer, centerX + x, centerY + y); | |
SDL_RenderDrawPoint(renderer, centerX + y, centerY + x); | |
SDL_RenderDrawPoint(renderer, centerX - y, centerY + x); | |
SDL_RenderDrawPoint(renderer, centerX - x, centerY + y); | |
SDL_RenderDrawPoint(renderer, centerX - x, centerY - y); | |
SDL_RenderDrawPoint(renderer, centerX - y, centerY - x); | |
SDL_RenderDrawPoint(renderer, centerX + y, centerY - x); | |
SDL_RenderDrawPoint(renderer, centerX + x, centerY - y); | |
if (err <= 0) { | |
y++; | |
err += dy; | |
dy += 2; | |
} | |
if (err > 0) { | |
x--; | |
dx += 2; | |
err += dx - (radius * 2); | |
} | |
} | |
} | |
static void draw_stars(void) { | |
SDL_SetRenderDrawColor(renderer, 0,4,20, 12); | |
SDL_RenderFillRect(renderer, | |
&(SDL_Rect){ | |
.x = 0, .y = 0, | |
.w = screen_width, .h = screen_height | |
} | |
); | |
SDL_SetRenderDrawColor(renderer, 255,255,255, 255); | |
for (int i = 0; i < MAX_STARS; i++) | |
drawcircle(stars[i].x, stars[i].y, 2); | |
} | |
static void update_stars(void) { | |
double radius; | |
for (int i = 0; i < MAX_STARS; i++) { | |
radius = | |
SDL_sqrt( | |
SDL_pow(stars[i].x - centerX, 2) | |
+ | |
SDL_pow(stars[i].y - centerY, 2) | |
); | |
stars[i].angle += stars[i].speed; | |
stars[i].x = centerX + SDL_cos(stars[i].angle) * radius; | |
stars[i].y = centerY + SDL_sin(stars[i].angle) * radius; | |
} | |
} | |
static void animate(void) { | |
/* Check if resize. */ | |
if (IsWindowResized) { | |
IsWindowResized = 0; | |
resize(screen_width, screen_height); | |
create_stars(); | |
} | |
update_stars(); | |
draw_stars(); | |
/* Render everything. */ | |
SDL_RenderPresent(renderer); | |
} | |
/** | |
* Main game loop. | |
*/ | |
int main(void) | |
{ | |
SDL_Event event; | |
srand48(time(NULL)); | |
/* Initialize. */ | |
if (SDL_Init(SDL_INIT_VIDEO) < 0) | |
errx(1, "SDL could not initialize!: %s\n", SDL_GetError()); | |
window = SDL_CreateWindow("startrail", | |
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, | |
screen_width, screen_height, | |
SDL_WINDOW_SHOWN|SDL_WINDOW_RESIZABLE); | |
if (!window) | |
errx(1, "Unable to create Window, %s\n", SDL_GetError()); | |
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC); | |
if (!renderer) | |
errx(1, "Unable to create Renderer, %s\n", SDL_GetError()); | |
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); | |
while (1) | |
{ | |
while (SDL_PollEvent(&event) != 0) | |
{ | |
if (event.type == SDL_QUIT) | |
goto quit; | |
else if (event.type == SDL_WINDOWEVENT && | |
event.window.event == SDL_WINDOWEVENT_RESIZED) | |
{ | |
IsWindowResized = 1; | |
screen_width = event.window.data1; | |
screen_height = event.window.data2; | |
} | |
} | |
animate(); | |
} | |
quit: | |
if (renderer) | |
SDL_DestroyRenderer(renderer); | |
if (window) | |
SDL_DestroyWindow(window); | |
SDL_Quit(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment