diff --git a/_templates/raylib/empty/.gitignore b/_templates/raylib/empty/.gitignore new file mode 100644 index 0000000..4996ad8 --- /dev/null +++ b/_templates/raylib/empty/.gitignore @@ -0,0 +1 @@ +__PROGNAME diff --git a/_templates/raylib/empty/template.toml b/_templates/raylib/empty/template.toml index decab55..ad7a5d7 100644 --- a/_templates/raylib/empty/template.toml +++ b/_templates/raylib/empty/template.toml @@ -1,7 +1,8 @@ name = "Empty Raylib project" templates = [ "Makefile", - "main.c" + "main.c", + ".gitignore" ] [params.WINDOW_WIDTH] diff --git a/sim/cellular/.gitignore b/sim/cellular/.gitignore new file mode 100644 index 0000000..062fad2 --- /dev/null +++ b/sim/cellular/.gitignore @@ -0,0 +1 @@ +cellular diff --git a/sim/cellular/Makefile b/sim/cellular/Makefile new file mode 100755 index 0000000..2f980c6 --- /dev/null +++ b/sim/cellular/Makefile @@ -0,0 +1,12 @@ +CFLAGS += -Wall -Wextra `exec pkg-config --cflags raylib` +LDFLAGS := -lm `pkg-config --libs raylib` + +cellular: main.c + $(CC) $(CFLAGS) main.c $(LDFLAGS) -o cellular + + +clean: + $(RM) cellular + +run: cellular + ./cellular diff --git a/sim/cellular/main.c b/sim/cellular/main.c new file mode 100644 index 0000000..4ad9b22 --- /dev/null +++ b/sim/cellular/main.c @@ -0,0 +1,116 @@ +// x-run: make run +#include +#include +#include + +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; + } +}