things/sim/cellular/main.c

117 lines
3.3 KiB
C

// x-run: make run
#include <raylib.h>
#include <stdlib.h>
#include <string.h>
struct cell {
int origin_x, origin_y;
int random_seed;
enum cell_type {
CELL_VOID,
CELL_LIVING,
CELL_DEAD
} type;
int timer;
};
#define GET_CELL(A, X, Y) (A[((X + width) % width) + ((Y + height) % height) * width])
const int width = 400, height = 300;
Color cell_get_color(struct cell *cells, int x, int y);
void cell_update(struct cell *cells_old, struct cell *cells, int x, int y);
int main(int argc, char **argv) {
InitWindow(width * 2, height * 2, "sim/cellular_NAME");
SetTargetFPS(60);
struct cell *cells = calloc(width * height, sizeof(struct cell));
struct cell *cells_old = calloc(width * height, sizeof(struct cell));
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
cells[x + y * width].origin_x = x;
cells[x + y * width].origin_y = y;
cells[x + y * width].random_seed = rand();
cells[x + y * width].type = rand() % 100 == 0;
cells[x + y * width].timer = 200;
}
}
Image img_out = GenImageColor(width, height, BLANK);
Texture2D tex_out = LoadTextureFromImage(img_out);
while (!WindowShouldClose()) {
memcpy(cells_old, cells, width * height * sizeof(struct cell));
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
cell_update(cells_old, cells, x, y);
}
}
BeginDrawing();
ClearBackground(BLACK);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
struct cell cell = cells[x + y * width];
ImageDrawPixel(&img_out, x, y, cell_get_color(cells, x, y));
}
}
UpdateTexture(tex_out, img_out.data);
DrawTextureEx(tex_out, (Vector2){ 0, 0 }, 0, 2, WHITE);
DrawFPS(10, 10);
EndDrawing();
}
UnloadTexture(tex_out);
UnloadImage(img_out);
}
Color cell_get_color(struct cell *cells, int x, int y) {
Vector3 color = ColorToHSV(WHITE);
struct cell cell = cells[x + y * width];
switch (cell.type) {
case CELL_VOID: color = ColorToHSV(BLACK); break;
case CELL_LIVING: color = ColorToHSV(DARKGREEN); break;
case CELL_DEAD: color = ColorToHSV(RED); break;
}
color.x += (cell.random_seed % 60) - 30;
color.y *= 1.0 - 0.2 * ((float)(cell.random_seed % 100) / 100.0);
/*color.z *= cell.timer / 200.0;*/
return ColorFromHSV(color.x, color.y, color.z);
}
void cell_update(struct cell *cells_old, struct cell *cells, int x, int y) {
struct cell *old_self = &cells_old[x + y * width];
struct cell *self = &cells[x + y * width];
switch (self->type) {
case CELL_LIVING:
{
for (int oy = -1; oy <= 1; oy++) {
for (int ox = -1; ox <= 1; ox++) {
struct cell old_other = GET_CELL(cells_old, x + ox, y + oy);
struct cell *other = &GET_CELL(cells, x + ox, y + oy);
if (old_other.type == CELL_VOID && rand() % 100 == 0) {
other->type = CELL_LIVING;
other->timer = 200;
} else if (old_other.type == CELL_LIVING && rand() % 90 == 0) {
other->type = CELL_DEAD;
other->timer = rand() % 200;
}
}
}
}
break;
case CELL_DEAD:
self->timer -= rand() % 8;
if (self->timer <= 0) {
self->type = CELL_VOID;
}
default:
break;
}
}