Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
FogNetwork
GitHub Repository: FogNetwork/Tsunami
Path: blob/main/public/games/files/garbage-collector/js/zoo.js
1036 views
1
(function( window, document, undefined ) {
2
'use strict';
3
4
var PI2 = 2 * Math.PI;
5
6
var running = false;
7
8
var el = document.querySelector( '.container' );
9
10
var tickFns = [];
11
12
function createCanvas( size ) {
13
var canvas = document.createElement( 'canvas' ),
14
ctx = canvas.getContext( '2d' );
15
16
var width = size,
17
height = size;
18
19
canvas.width = width;
20
canvas.height = height;
21
22
el.appendChild( canvas );
23
24
return {
25
canvas: canvas,
26
ctx: ctx,
27
width: width,
28
height: height
29
};
30
}
31
32
/**
33
* TODO:
34
* - Wires,
35
* - Teleporter?
36
* - Emitter.
37
* - Trash?
38
*/
39
40
tickFns.push((function drawHero() {
41
var element = createCanvas( 128 );
42
43
var canvas = element.canvas,
44
ctx = element.ctx,
45
width = element.width,
46
height = element.height;
47
48
canvas.style.backgroundColor = 'black';
49
50
var t = 0;
51
52
function draw() {
53
ctx.clearRect( 0, 0, ctx.canvas.width, ctx.canvas.height );
54
55
ctx.save();
56
ctx.translate( 0.5 * width, 0.5 * height );
57
58
// Draw casing.
59
ctx.lineWidth = 0.05 * width;
60
61
// Top left.
62
ctx.beginPath();
63
ctx.arc( 0, 0, 0.22 * width, -Math.PI, -0.5 * Math.PI );
64
ctx.strokeStyle = '#fef';
65
ctx.stroke();
66
67
// Top right.
68
ctx.beginPath();
69
ctx.arc( 0, 0, 0.22 * width, -0.5 * Math.PI, 0 );
70
ctx.strokeStyle = '#cbe';
71
ctx.stroke();
72
73
// Bottom right.
74
ctx.beginPath();
75
ctx.arc( 0, 0, 0.22 * width, 0, 0.5 * Math.PI );
76
ctx.strokeStyle = '#98b';
77
ctx.stroke();
78
79
// Bottom left.
80
ctx.beginPath();
81
ctx.arc( 0, 0, 0.22 * width, 0.5 * Math.PI, Math.PI );
82
ctx.strokeStyle = '#658';
83
ctx.stroke();
84
85
// Draw main body.
86
ctx.beginPath();
87
ctx.arc( 0, 0, 0.2 * width, 0, PI2 );
88
ctx.fillStyle = '#ecf';
89
ctx.fill();
90
91
// Strokes.
92
ctx.lineWidth = 0.02 * width;
93
ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)';
94
ctx.stroke();
95
96
ctx.beginPath();
97
ctx.arc( 0, 0, 0.18 * width, 0, PI2 );
98
ctx.strokeStyle = '#fff';
99
ctx.stroke();
100
101
// Draw eyes.
102
if ( t % 240 < 160 ) {
103
// Draw left eye.
104
ctx.beginPath();
105
ctx.rect( -0.1 * width, -0.06 * height, 0.04 * width, 0.08 * width );
106
ctx.fillStyle = '#448';
107
ctx.fill();
108
109
// Draw right eye.
110
ctx.beginPath();
111
ctx.rect( 0.06 * width, -0.06 * height, 0.04 * width, 0.08 * width );
112
ctx.fillStyle = '#448';
113
ctx.fill();
114
} else {
115
// Draw X.
116
ctx.beginPath();
117
ctx.moveTo( -0.1 * width, -0.06 * height );
118
ctx.lineTo( 0.1 * width, 0.02 * height );
119
ctx.moveTo( -0.1 * width, 0.02 * height );
120
ctx.lineTo( 0.1 * width, -0.06 * height );
121
ctx.lineWidth = 0.03 * width;
122
ctx.strokeStyle = '#448';
123
ctx.stroke();
124
}
125
126
// Draw mouth.
127
if ( t % 240 < 80 ) {
128
// Draw smile.
129
ctx.beginPath();
130
ctx.arc( 0, 0.02 * height, 0.1 * width, 0.25 * Math.PI, 0.75 * Math.PI );
131
132
ctx.lineWidth = 0.03 * width;
133
ctx.strokeStyle = '#448';
134
ctx.stroke();
135
} else if ( t % 240 < 160 ) {
136
// Draw line.
137
ctx.beginPath();
138
ctx.rect( -0.06 * width, 0.08 * height, 0.12 * width, 0.02 * width );
139
ctx.fillStyle = '#448';
140
ctx.fill();
141
} else {
142
// Draw square.
143
ctx.beginPath();
144
ctx.rect( -0.03 * width, 0.06 * height, 0.06 * width, 0.06 * width );
145
ctx.fillStyle = '#448';
146
ctx.fill();
147
}
148
149
// Draw ring.
150
ctx.beginPath();
151
ctx.arc( 0, 0, 0.35 * width, 0, PI2 );
152
153
ctx.shadowColor = '#fff';
154
ctx.shadowBlur = 0.05 * width + Math.random() * 0.05 * width;
155
156
ctx.lineWidth = 0.07 * width;
157
ctx.strokeStyle = '#fff';
158
ctx.stroke();
159
160
ctx.shadowBlur = 0;
161
162
ctx.restore();
163
}
164
165
return function() {
166
t++;
167
draw();
168
};
169
}) ());
170
171
tickFns.push((function drawEmitter() {
172
var element = createCanvas( 128 );
173
174
var canvas = element.canvas,
175
ctx = element.ctx,
176
width = element.width,
177
height = element.height;
178
179
canvas.style.backgroundColor = '#333';
180
181
var beamWidth = 0.4 * width,
182
beamHeight = 0.3 * height;
183
184
var baseWidth = 0.1 * beamWidth,
185
baseHeight = beamHeight;
186
187
function yRandom() {
188
return Math.random() - 0.5;
189
}
190
191
var t = 0;
192
193
var particles = [];
194
var particleCount = 10;
195
var radius;
196
while ( particleCount-- ) {
197
radius = ( 0.02 + Math.random() * 0.01 ) * width;
198
particles.push({
199
x: Math.random() * beamWidth,
200
y: yRandom() * ( beamHeight - radius ),
201
radius: radius,
202
vx: 2 * beamHeight,
203
vy: 0
204
});
205
}
206
207
var redPrefix = 'rgba(255, 128, 128, ',
208
bluePrefix = 'rgba(128, 128, 255, ';
209
210
var colorPrefix = redPrefix;
211
212
function draw() {
213
if ( t % 120 < 60 ) {
214
colorPrefix = redPrefix;
215
} else {
216
colorPrefix = bluePrefix;
217
}
218
219
ctx.clearRect( 0, 0, width, height );
220
221
ctx.save();
222
ctx.translate( 0.5 * width, 0.5 * height );
223
224
// Draw beam.
225
ctx.beginPath();
226
ctx.rect( 0, -0.5 * beamHeight, beamWidth, beamHeight );
227
var grad = ctx.createLinearGradient( 0, 0, beamWidth, 0 );
228
grad.addColorStop( 0, colorPrefix + '0.8)' );
229
grad.addColorStop( 1, colorPrefix + '0.0)' );
230
ctx.fillStyle = grad;
231
ctx.fill();
232
233
// Draw particles.
234
particles.forEach(function( particle ) {
235
var alpha = 1 - particle.x / beamWidth;
236
237
ctx.beginPath();
238
ctx.arc( particle.x, particle.y, particle.radius, 0, PI2 );
239
ctx.fillStyle = 'rgba(255, 255, 255, ' + alpha + ')';
240
ctx.fill();
241
});
242
243
// Draw base.
244
ctx.shadowBlur = 0.02 * width;
245
ctx.shadowColor = colorPrefix + '1.0)';
246
247
ctx.beginPath();
248
ctx.moveTo( 0, -0.5 * baseHeight );
249
ctx.lineTo( 0, 0.5 * baseHeight );
250
251
ctx.lineCap = 'round';
252
ctx.lineWidth = baseWidth;
253
ctx.strokeStyle = '#fff';
254
ctx.stroke();
255
256
ctx.lineCap = 'butt';
257
ctx.shadowBlur = 0;
258
259
ctx.restore();
260
}
261
262
return function( dt ) {
263
t++;
264
265
particles.forEach(function( particle ) {
266
particle.x += particle.vx * dt;
267
particle.y += particle.vy * dt;
268
269
if ( particle.x - particle.radius > beamWidth ) {
270
particle.x = particle.radius;
271
particle.y = yRandom() * ( beamHeight - radius );
272
}
273
});
274
275
draw();
276
};
277
}) ());
278
279
tickFns.push((function drawTrash() {
280
var element = createCanvas( 128 );
281
282
var canvas = element.canvas,
283
ctx = element.ctx,
284
width = element.width,
285
height = element.height;
286
287
canvas.style.backgroundColor = '#222';
288
289
var t = 0;
290
291
var angle = 0;
292
var va = 60 * Math.PI / 180;
293
294
var hue = 240;
295
296
function draw() {
297
ctx.clearRect( 0, 0, width, height );
298
299
if ( t % 240 < 120 ) {
300
hue = 240;
301
} else {
302
hue = 0;
303
}
304
305
ctx.save();
306
ctx.translate( 0.5 * width, 0.5 * height );
307
ctx.rotate( -angle );
308
309
ctx.beginPath();
310
ctx.rect( -0.32 * width, -0.2 * height, 0.64 * width, 0.4 * height );
311
ctx.fillStyle = 'hsl(' + hue + ', 30%, 60%)';
312
ctx.fill();
313
314
// Draw outline.
315
ctx.shadowBlur = 0.1 * width;
316
ctx.shadowColor = 'hsl(' + hue + ', 70%, 70%)';
317
318
ctx.lineJoin = 'round';
319
ctx.lineWidth = 0.03 * width;
320
ctx.strokeStyle = '#fff';
321
ctx.stroke();
322
323
ctx.shadowBlur = 0;
324
ctx.lineJoin = 'butt';
325
326
ctx.restore();
327
}
328
329
return function( dt ) {
330
t++;
331
332
angle += va * dt;
333
if ( angle > PI2 ) {
334
angle -= PI2;
335
}
336
337
draw();
338
};
339
}) ());
340
341
// Based off of https://github.com/soulwire/sketch.js/blob/master/examples/particles.html
342
tickFns.push((function drawExplosion() {
343
var element = createCanvas( 128 );
344
345
var canvas = element.canvas,
346
ctx = element.ctx,
347
width = element.width,
348
height = element.height;
349
350
canvas.style.backgroundColor = '#555';
351
352
var particles = [];
353
354
var shrink = 0.95;
355
var t = 0;
356
357
function generateParticles() {
358
var particleCount = 10;
359
var angle, force;
360
361
while ( particleCount-- ) {
362
angle = Math.random() * PI2;
363
force = Math.random() * 50 + 100;
364
365
particles.push({
366
x: 0.5 * width,
367
y: 0.5 * height,
368
radius: ( Math.random() * 0.1 + 0.05 ) * width,
369
angle: angle,
370
vx: Math.cos( angle ) * force,
371
vy: Math.sin( angle ) * force,
372
drag: Math.random() * 0.05 + 0.9,
373
deviation: Math.random() * 1.5 + 0.5
374
});
375
}
376
}
377
378
generateParticles();
379
380
function draw() {
381
ctx.clearRect( 0, 0, width, height );
382
383
if ( t % 240 < 120 ) {
384
ctx.fillStyle = 'rgba(64, 32, 32, 1)';
385
} else {
386
ctx.fillStyle = 'rgba(32, 32, 64, 1)';
387
}
388
389
ctx.globalCompositeOperation = 'lighter';
390
391
particles.forEach(function( particle ) {
392
ctx.beginPath();
393
ctx.arc( particle.x, particle.y, particle.radius, 0, PI2 );
394
ctx.fill();
395
});
396
397
ctx.globalCompositeOperation = 'source-over';
398
}
399
400
return function( dt ) {
401
t++;
402
403
var removed = [];
404
particles.forEach(function( particle, index ) {
405
particle.x += particle.vx * dt;
406
particle.y += particle.vy * dt;
407
408
particle.vx *= particle.drag;
409
particle.vy *= particle.drag;
410
411
particle.angle += ( Math.random() - 0.5 ) * particle.deviation;
412
413
particle.vx += Math.cos( particle.angle ) * 0.1;
414
particle.vy += Math.sin( particle.angle ) * 0.1;
415
416
particle.radius *= shrink;
417
if ( particle.radius < 0.5 ) {
418
removed.push( index );
419
}
420
});
421
422
var index = removed.length;
423
while ( index-- ) {
424
particles.splice( removed[ index ], 1 );
425
}
426
427
if ( !particles.length ) {
428
generateParticles();
429
}
430
431
draw();
432
};
433
}) ());
434
435
tickFns.push((function drawBackground() {
436
var element = createCanvas( 512 );
437
438
var canvas = element.canvas,
439
ctx = element.ctx,
440
width = element.width,
441
height = element.height;
442
443
var hue = 240;
444
var hueSpread = 20;
445
446
var t = 0;
447
448
var rects = [];
449
450
function generateRects() {
451
rects = [];
452
453
var rectCount = 100;
454
while ( rectCount-- ) {
455
rects.push({
456
x: Math.random() * width,
457
y: Math.random() * height,
458
width: ( Math.random() * 0.25 + 0.05 ) * width,
459
height: ( Math.random() * 0.25 + 0.05 ) * height,
460
saturation: Math.round( Math.random() * 30 + 25 ) + '%',
461
lightness: Math.round( Math.random() * 50 + 25 ) + '%'
462
});
463
}
464
}
465
466
function draw() {
467
if ( t % 240 < 120 ) {
468
hue = 240;
469
} else {
470
hue = 0;
471
}
472
473
canvas.style.backgroundColor = 'hsla(' + hue + ', 30%, 50%, 1.0)';
474
475
ctx.clearRect( 0, 0, width, height );
476
477
generateRects();
478
rects.forEach(function( rect ) {
479
ctx.save();
480
ctx.translate( rect.x, rect.y );
481
ctx.beginPath();
482
ctx.rect( -0.5 * rect.width, -0.5 * rect.height, rect.width, rect.height );
483
ctx.fillStyle = 'hsla(' +
484
( hue + Math.round( hueSpread * ( Math.random() - 0.5 ) ) ) + ', ' +
485
rect.saturation + ', ' +
486
rect.lightness + ', ' +
487
Math.random() +
488
')';
489
ctx.fill();
490
491
ctx.restore();
492
});
493
}
494
495
var isDrawn = false;
496
497
return function() {
498
t++;
499
if ( t % 120 === 0 ) {
500
isDrawn = false;
501
}
502
503
if ( !isDrawn ) {
504
draw();
505
isDrawn = true;
506
}
507
};
508
}) ());
509
510
var prevTime = Date.now(),
511
currTime;
512
513
function tick() {
514
currTime = Date.now();
515
var dt = currTime - prevTime;
516
prevTime = currTime;
517
518
if ( dt > 1e2 ) {
519
dt = 1e2;
520
}
521
522
dt *= 1e-3;
523
524
tickFns.forEach(function( tickFn ) {
525
tickFn( dt );
526
});
527
528
if ( !running ) {
529
return;
530
}
531
532
window.requestAnimationFrame( tick );
533
}
534
535
tick();
536
537
var runCheckbox = document.getElementById( 'run-checkbox' );
538
539
function play() {
540
if ( !running ) {
541
running = true;
542
tick();
543
runCheckbox.checked = true;
544
}
545
}
546
547
function pause() {
548
running = false;
549
runCheckbox.checked = false;
550
}
551
552
function toggleContinuousRendering() {
553
if ( !runCheckbox.checked ) {
554
play();
555
} else {
556
pause();
557
}
558
}
559
560
runCheckbox.addEventListener( 'click', function() {
561
runCheckbox.checked = !runCheckbox.checked;
562
toggleContinuousRendering();
563
});
564
565
document.addEventListener( 'keydown', function( event ) {
566
// ESC.
567
if ( event.which === 27 ) {
568
pause();
569
}
570
571
// Space.
572
if ( event.which === 32 ) {
573
event.preventDefault();
574
toggleContinuousRendering();
575
}
576
});
577
578
window.addEventListener( 'blur', function() {
579
pause();
580
});
581
}) ( window, document );
582
583