Skip to content

Instantly share code, notes, and snippets.

@tan86
Last active October 10, 2023 19:18
Show Gist options
  • Save tan86/c731df7786e0a94a0a78c9cadaccf505 to your computer and use it in GitHub Desktop.
Save tan86/c731df7786e0a94a0a78c9cadaccf505 to your computer and use it in GitHub Desktop.
draft-001 💩
#include<SDL2/SDL.h>
#include<math.h>
#include<stdio.h>
#include<time.h>
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
struct Vec2 {
double x{};
double y{};
};
typedef struct Vec2 Vec2;
SDL_Rect winDim {
.x = 100,
.y = 100,
.w = 800,
.h = 800,
};
static const int w = 640;
static const int h = 480;
static const int n = 50; // no fields per row.
static const int pn = 500; // no. of particles.
static const int fieldSize = w / n;
static const int hfs = fieldSize / 2;
static const int maxLifeTime = 60 * 5;
Vec2 fields[n * n] {};
Vec2 particles[pn] {};
int lifetimes[pn] {};
SDL_Window *win = NULL;
SDL_Renderer *ren = NULL;
SDL_Event event;
bool isRunning = false;
void sdl_messup() {
SDL_Init(SDL_INIT_VIDEO);
win = SDL_CreateWindow("Flow Field", winDim.x, winDim.y, winDim.w, winDim.h, SDL_WINDOW_ALLOW_HIGHDPI);
ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
}
void sdl_cleanup() {
SDL_DestroyRenderer(ren);
SDL_DestroyWindow(win);
SDL_Quit();
}
void handle_events() {
while (SDL_PollEvent(&event)) {
switch (event.type) {
case SDL_QUIT:
isRunning = false;
break;
case SDL_KEYDOWN: {
if (event.key.keysym.sym == SDLK_ESCAPE)
isRunning = false;
} break;
}
}
}
///
Vec2 randomParticle() {
return Vec2{
.x = fieldSize + rand() % w,
.y = fieldSize + rand() % h,
};
}
Vec2 angleVec2(double radian) {
return Vec2 {
.x = cos(radian),
.y = sin(radian),
};
}
Vec2 computeFieldValue(double x, double y) {
double sins[3] {
sin(x * 0.1 + y * 0.1),
sin(x * .08 * y * .15),
};
// final avgSin = sins.fold(0.0, (a, b) => a + b) / sins.length;
double sum{};
for(int i = 0; i != 3; ++i) {
sum += sins[i];
}
double avgSin = sum / 3;
return angleVec2(((avgSin + 1) / 2) * M_PI * 2);
}
int clamp(int x, int min, int max) {
return MIN(MAX(x, min), max);
}
Vec2 clampVec2(Vec2 v, int min, int max) {
return Vec2{
clamp((int)v.x, min, max),
clamp((int)v.y, min, max),
};
}
Vec2 windowToField(Vec2 v) {
Vec2 f = Vec2{
.x = floor(v.x / fieldSize),
.y = floor(v.y / fieldSize),
};
return clampVec2(f, 0, n - 1);
}
void on_tick() {
for (int i = 0; i != pn; ++i) {
Vec2 p = particles[i];
Vec2 fp = windowToField(p);
Vec2 fv = fields[(int)fp.x * (int)fp.y];
particles[i] = Vec2{
.x = fv.x + p.x,
.y = fv.y + p.y,
};
if(lifetimes[i]-- <= 0) {
particles[i] = randomParticle();
lifetimes[i] = rand() % maxLifeTime;
}
}
}
int main(int argc, char** argv) {
srand(time(NULL));
sdl_messup();
// Populate the fields
for (int i = 0, nn = n * n; i != nn; ++i)
fields[i] = computeFieldValue(i % n, i / n);
// Populate the particles.
for (int i = 0; i != pn; ++i) {
particles[i] = randomParticle();
lifetimes[i] = rand() % maxLifeTime;
}
bool shouldRerender = true;
for (isRunning = true; isRunning;) {
handle_events();
if (shouldRerender) {
///
//SDL_SetRenderDrawColor(ren, 0x00, 0x00, 0x00, 0x0F);
//SDL_RenderClear(ren);
SDL_SetRenderDrawBlendMode(ren, SDL_BLENDMODE_BLEND);
/*/ Draw Lines
SDL_SetRenderDrawColor(ren, 0xFF, 0xFF, 0xFF, 0xFF);
for (int y = 0; y < n; ++y) {
for (int x = 0; x < n; ++x) {
double dx = fieldSize * x + fieldSize;
double dy = fieldSize * y + fieldSize;
Vec2 f = fields[x * y];
int x1 = (hfs * f.x) + dx;
int y1 = (hfs * f.y) + dy;
int x2 = (-hfs * f.x) + dx;
int y2 = (-hfs * f.y) + dy;
SDL_RenderDrawLine(ren, x1, y1, x2, y2);
SDL_Rect rect{.x = x1, .y = y1, .w = 3, .h = 3};
SDL_RenderDrawRect(ren, &rect);
}
}
//*/
//*/ Draw Particles
SDL_SetRenderDrawColor(ren, 0xFF, 0xFF, 0xFF, 0x0F);
for (int i = 0; i != pn; ++i) {
Vec2 p = particles[i];
SDL_RenderDrawPoint(ren, p.x, p.y);
}
//*/
SDL_RenderPresent(ren);
//shouldRerender = false;
}
on_tick();
}
sdl_cleanup();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment