-
Notifications
You must be signed in to change notification settings - Fork 0
/
code.js
123 lines (102 loc) · 2.5 KB
/
code.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const ctx = document.getElementById("cnv").getContext("2d");
let simPlaying = false;
let interval = 0;
let sliceSize = 0;
class Map {
constructor() {
this.automata = (_, x, y) => this.getPixel(x, y);
this.palette = ["#000000"];
this.size = 0;
this.buffer = null;
this.backBuffer = null;
}
update(start, end) {
for (let x = start; x < Math.min(end, this.size); x++) {
for (let y = 0; y < this.size; y++) {
this.buffer[x + y * this.size] = this.automata(this, x, y);
}
}
}
resize(size) {
this.buffer = new Array(size ** 2).fill(0);
let offset = (this.size - size) >> 1;
for (let x = 0; x < size; x++) {
for (let y = 0; y < size; y++) {
this.buffer[x + y * size] = this.getPixel(x + offset, y + offset);
}
}
this.backBuffer = new Array(size ** 2).fill(0);
this.swapBuffers();
this.size = size;
}
swapBuffers() {
let aux = this.buffer;
this.buffer = this.backBuffer;
this.backBuffer = aux;
}
clear() {
this.buffer.fill(0);
this.backBuffer.fill(0);
}
setPixel = (x, y, value) => this.backBuffer[x + y * this.size] = value;
getPixel = (x, y) => {
if (x >= 0 && x < this.size && y >= 0 && y < this.size) {
return this.backBuffer[x + y * this.size];
}
return 0;
}
}
let leftColor = 1;
let rightColor = 0;
function paint(x, y, right) {
if (!simPlaying && x >= 0 && x < map.size && y >= 0 && y < map.size) {
map.setPixel(x, y, right ? rightColor : leftColor);
render();
}
}
function resizeMap(size) {
map.resize(size);
updateSliceSize();
render();
}
function clearMap() {
map.clear();
render();
}
function updateSliceSize() {
sliceSize = Math.ceil(map.size / interval);
frame = 0;
}
function updateSpeed(speed) {
interval = 60 - speed;
updateSliceSize();
}
function render() {
let imgData = ctx.createImageData(map.size, map.size);
for (let i = 0; i < map.buffer.length; i++) {
let p = i << 2;
let c = map.palette[map.backBuffer[i]];
if (!c) console.log(map.backBuffer[i]);
imgData.data[p] = c[0];
imgData.data[p + 1] = c[1];
imgData.data[p + 2] = c[2];
imgData.data[p + 3] = 255;
}
ctx.putImageData(imgData, 0, 0);
}
let frame = 0;
function loop() {
if (!simPlaying) {
frame = 0;
requestAnimationFrame(loop);
return;
}
map.update(frame * sliceSize, (frame + 1) * sliceSize);
frame++;
if (frame % interval == 0) {
frame = 0;
map.swapBuffers();
render();
}
requestAnimationFrame(loop);
}