Skip to content

Commit 60641c1

Browse files
authored
GFX: Belousov–Zhabotinsky reaction as cellular automaton (#157)
* gfx_belou_zhabo_ca * add belou_zhabo_ca to makefile
1 parent 839af35 commit 60641c1

File tree

2 files changed

+146
-2
lines changed

2 files changed

+146
-2
lines changed

GNUmakefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ GFXMODS_AVAILABLE += gfx_no13 gfx_candyswarm gfx_ursuppe2 gfx_rule90
1515
GFXMODS_AVAILABLE += gfx_maze gfx_invfourier gfx_colorwheel gfx_snek
1616
GFXMODS_AVAILABLE += gfx_autoterminal gfx_wator gfx_noisewarp gfx_test
1717
GFXMODS_AVAILABLE += gfx_multicell gfx_pheromones
18-
GFXMODS_AVAILABLE += gfx_attractor
18+
GFXMODS_AVAILABLE += gfx_attractor gfx_belou_zhabo_ca
1919
GFXMODS_AVAILABLE += gfx_lorenz gfx_pickover gfx_voronoi
2020

2121
BGMMODS_AVAILABLE += bgm_fish bgm_opc bgm_xyscope bgm_pixelflut
@@ -37,7 +37,7 @@ GFXMODS_DEFAULT += gfx_ghostery gfx_ursuppe gfx_afterglow gfx_fire
3737
GFXMODS_DEFAULT += gfx_candyswarm gfx_ursuppe2 gfx_invfourier gfx_colorwheel
3838
GFXMODS_DEFAULT += gfx_snek gfx_wator gfx_noisewarp
3939
GFXMODS_DEFAULT += gfx_multicell gfx_pheromones
40-
GFXMODS_DEFAULT += gfx_attractor
40+
GFXMODS_DEFAULT += gfx_attractor gfx_belou_zhabo_ca
4141
GFXMODS_DEFAULT += gfx_lorenz gfx_pickover gfx_voronoi gfx_voronoi2
4242

4343
BGMMODS_DEFAULT += bgm_fish bgm_pixelflut

src/modules/gfx_belou_zhabo_ca.c

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#include <math.h>
2+
#include <stdint.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
6+
#include <types.h>
7+
#include <matrix.h>
8+
#include <timers.h>
9+
10+
#define FPS 18
11+
#define FRAMETIME (T_SECOND / FPS)
12+
#define FRAMES (1.5 * TIME_LONG * FPS)
13+
14+
#define V 12
15+
#define G 3
16+
#define SEEDS 6
17+
18+
static RGB cols[V + 1];
19+
20+
static uint8_t *cdat;
21+
uint8_t *ndat;
22+
23+
static int screenW;
24+
static int screenH;
25+
26+
int urand(int max)
27+
{
28+
return rand() % max;
29+
}
30+
31+
void sim(void)
32+
{
33+
for (int y = 0; y < screenH; y++)
34+
{
35+
for (int x = 0; x < screenW; x++)
36+
{
37+
int sum = 0;
38+
int ill = 0;
39+
int infected = 0;
40+
int self = cdat[y * screenW + x];
41+
for (int dy = -1; dy <= 1; dy++)
42+
{
43+
for (int dx = -1; dx <= 1; dx++)
44+
{
45+
if (dx == 0 && dy == 0) continue;
46+
int mx = (x + dx + screenW) % screenW;
47+
int my = (y + dy + screenH) % screenH;
48+
int n = cdat[my * screenW + mx];
49+
sum += n;
50+
if (n >= V) ill++;
51+
else if (n > 0) infected++;
52+
}
53+
}
54+
if (self >= V)
55+
{
56+
ndat[y * screenW + x] = 0;
57+
}
58+
else if (self > 0)
59+
{
60+
ndat[y * screenW + x] = MIN(sum / 8 + G, V);
61+
}
62+
else
63+
{
64+
ndat[y * screenW + x] = infected + ill;
65+
}
66+
}
67+
}
68+
69+
uint8_t *tmp = ndat;
70+
ndat = cdat;
71+
cdat = tmp;
72+
}
73+
74+
int init(int moduleid, char* argstr)
75+
{
76+
screenW = matrix_getx();
77+
screenH = matrix_gety();
78+
return 0;
79+
}
80+
81+
void reset(int moduleid)
82+
{
83+
if (cdat) free(cdat);
84+
if (ndat) free(ndat);
85+
86+
cdat = malloc(screenH * screenW);
87+
ndat = malloc(screenH * screenW);
88+
89+
memset(cdat, 0, screenH * screenW);
90+
91+
for (int i = 0; i < SEEDS; i++)
92+
{
93+
int y = urand(screenH);
94+
int x = urand(screenW);
95+
cdat[y * screenW + x] = 1;
96+
}
97+
98+
int scheme = urand(6);
99+
for (int i = 0; i <= V; i++)
100+
{
101+
double d = (double)i / (V + 2);
102+
uint8_t a = 255 * pow(d, 6.0);
103+
uint8_t b = 255 * pow(d, 2.5);
104+
uint8_t c = 255 * pow(d, 1.0);
105+
switch(scheme)
106+
{
107+
case 0: cols[i] = RGB(a, b, c); break;
108+
case 1: cols[i] = RGB(a, c, b); break;
109+
case 2: cols[i] = RGB(b, a, c); break;
110+
case 3: cols[i] = RGB(b, c, a); break;
111+
case 4: cols[i] = RGB(c, a, b); break;
112+
case 5: cols[i] = RGB(c, b, a); break;
113+
}
114+
}
115+
}
116+
117+
int draw(int moduleid, int argc, char* argv[])
118+
{
119+
static int frame = 0;
120+
oscore_time now = udate();
121+
122+
sim();
123+
for (int y = 0; y < screenH; y++)
124+
{
125+
for (int x = 0; x < screenW; x++)
126+
{
127+
matrix_set(x, y, cols[cdat[y * screenW + x]]);
128+
}
129+
}
130+
matrix_render();
131+
132+
if (frame++ >= FRAMES)
133+
{
134+
frame = 0;
135+
return 1;
136+
}
137+
oscore_time nexttick = now + T_SECOND / FPS;
138+
timer_add(nexttick, moduleid, 0, NULL);
139+
return 0;
140+
}
141+
142+
void deinit(int moduleid)
143+
{
144+
}

0 commit comments

Comments
 (0)