Show code
```html
<!DOCTYPE html>
<html><head><title>Gray-Scott Simulation</title></head><body style="background:#000;margin:0;"><canvas id="c"></canvas><script>
const c = document.getElementById('c');
const ctx = c.getContext('2d');
let S, G, A, B;
let r, s, d_a, d_b, k;
let bufferA, bufferB, nextA, nextB;
let step = 0;
function init(size) {
S = size;
G = size;
c.width = c.height = S * 2; // Higher resolution for visual quality
const scaleFactor = Math.floor(c.width / (S * 1.5)); // Scale down slightly to fit step counter
c.style.width = `${Math.min(800, S*2)}px`;
c.style.height = `${Math.min(600, S*2)}px`;
bufferA = new Float32Array(S * S);
bufferB = new Float32Array(S * S);
nextA = new Float32Array(S * S);
nextB = new Float32Array(S * S);
// Parameters (Standard values for patterns)
r = 0.055; // Reactant rate A consumption
s = 1.0; // Source strength B replacement
d_a = 1.0; // Diffusion A
d_b = 0.5; // Diffusion B
k = 1.8; // Reaction coefficient
step = 0;
// Seeding the initial state (Center area)
for (let y = 0; y < S; y++) {
for (let x = 0; x < S; x++) {
const i = y * S + x;
bufferA[i] = 1.0;
bufferB[i] = 1.0;
}
}
// Create a central 'seed' blob (B=0, A slightly higher)
let startX = Math.floor(S * 0.3);
let startY = Math.floor(S * 0.5);
let radius = Math.floor(S * 0.15);
for (let y = -radius; y <= radius; y++) {
for (let x = -radius; x <= radius; x++) {
const nx = startX + x;
const ny = startY + y;
if (nx >= 0 && nx < S && ny >= 0 && ny < S) {
const i = ny * S + nx;
bufferA[i] = 1.0; // High A
bufferB[i] = 0.0; // Low B
}
}
}
// Initialize the rendering background (black/dark)
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, c.width, c.height);
}
function diffuse(p, buffer, nextBuffer, rate) {
let sum = 0;
for (let i = -1; i <= 1; i++) {
for (let j = -1; j <= 1; j++) {
if (i === 0 && j === 0) continue;
const x = p[0] + i;
const y = p[1] + j;
if (x >= 0 && x < S && y >= 0 && y < S) {
sum += buffer[(y * S + x)];
}
}
}
return sum / 8.0;
}
function stepSimulation() {
for (let y = 0; y < S; y++) {
for (let x = 0; x < S; x++) {
const i = y * S + x;
// Calculate new A concentration (Diffusion and Reaction)
let nextAVal = d_a * diffuse(p, bufferA, nextA, d_a);
nextAVal = (bufferA[i] + 2.0 * d_a / 8.0 * (diffuse(p, bufferA, nextA, 0) - bufferA[i])) - r * bufferA[i] * bufferB[i] * bufferB[i];
nextAVal = Math.max(0, Math.min(1, nextAVal));
// Calculate new B concentration (Diffusion and Reaction)
let nextBVal = d_b * diffuse(p, bufferB, nextB, d_b);
nextBVal = (bufferB[i] + 2.0 * d_b / 8.0 * (diffuse(p, bufferB, nextB, 0) - bufferB[i])) + r * bufferA[i] * bufferB[i] * bufferB[i] - s * bufferB[i];
nextBVal = Math.max(0, Math.min(1, nextBVal));
// Store results in the 'next' buffers
nextA[i] = nextAVal;
nextB[i] = nextBVal;
}
}
// Swap buffers (Next becomes Current)
let temp = bufferA; bufferA = nextA; nextA = temp;
temp = bufferB; bufferB = nextB; nextB = temp;
step++;
}
function draw() {
const imageData = ctx.getImageData(0, 0, c.width, c.height);
const data = imageData.data;
for (let y = 0; y < S; y++) {
for (let x = 0; x < S; x++) {
const i = y * S + x;
// Normalize values to [0, 1] and scale them for color mapping.
// A: Blue/Cyan component (e.g., higher A -> more blue)
// B: Green component (e.g., higher B -> more green)
// The combination creates the coral structure visualization.
let a = bufferA[i];
let b = bufferB[i];
// Simple color mapping based on concentration ratio
let rVal = Math.pow(Math.max(0, (1 - a)), 2); // Red intensity decreases with A
let gVal = b * 2; // Green intensity proportional to B
let bVal = a * 2; // Blue intensity proportional to A
// Scale colors and apply to the ImageData array
const dataIndex = (y * c.width + x) * 4;
data[dataIndex] = Math.floor(rVal * 255); // R
data[dataIndex + 1] = Math.floor(gVal * 255); // G
data[dataIndex + 2] = Math.floor(bVal * 255); // B
data[dataIndex + 3] = 255; // A (Alpha)
}
}
ctx.putImageData(imageData, 0, 0);
}
function loop() {
stepSimulation();
draw();
requestAnimationFrame(loop);
}
init(160); // Use 160x160 grid for better detail while staying efficient
loop();
</script></body></html>
```