Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env node
- const MIN_DROP_LENGTH = 12;
- const MAX_DROP_LENGTH = 25;
- const CHAR_MIN_RANGE = 0x21;
- const CHAR_MAX_RANGE = 0x7E;
- const DROP_MIN_SPEED = 80;
- const DROP_MAX_SPEED = 20;
- const DROP_SPAWN_INTERVAL = 40;
- const colors = [46, 40, 34, 28, 22, 16].map(index => `\x1b[38;5;${index}m`);
- const terminal = {
- clear: () => write('\033[2J'),
- hide: () => write('\x1b[?25l'),
- moveTo: (x, y) => write(`\x1b[${y + 1};${x + 1}H`)
- }
- function write(data) {
- process.stdout.write(data);
- }
- function random(min, max) {
- return min + Math.floor((max - min) * Math.random());
- }
- class Drop {
- constructor() {
- this.length = random(Math.min(MIN_DROP_LENGTH, process.stdout.rows), Math.min(MAX_DROP_LENGTH, process.stdout.rows));
- this.speed = random(DROP_MAX_SPEED, DROP_MIN_SPEED);
- this.chars = new Array(process.stdout.rows).fill(0).map(() => String.fromCharCode(random(CHAR_MIN_RANGE, CHAR_MAX_RANGE)));
- this.head = new Head();
- }
- update() {
- this.draw();
- this.head.slide();
- if(this.head.y - this.length === process.stdout.rows) {
- this.clean();
- }
- }
- draw() {
- for(let y = Math.max(0, this.head.y - process.stdout.rows); y < Math.min(this.length, this.length + (this.head.y - this.length)); y++) {
- terminal.moveTo(this.head.x, this.head.y - y - 1);
- write(colors[Math.floor(y * colors.length / this.length)]);
- write(this.chars[this.head.y - y - 1]);
- }
- if(this.head.y - this.length >= 0) {
- terminal.moveTo(this.head.x, this.head.y - this.length);
- write(' ');
- }
- }
- clean() {
- removeDrop(this);
- }
- }
- class Head {
- constructor() {
- this.x = random(0, process.stdout.columns);
- this.y = 0;
- }
- slide() {
- this.y += 1;
- }
- }
- terminal.clear();
- terminal.hide();
- const drops = [];
- const speedIntervals = [];
- function addDrop() {
- const drop = new Drop();
- if(!drops[drop.speed]) drops[drop.speed] = [];
- drops[drop.speed].push(drop);
- if(!speedIntervals[drop.speed]) {
- speedIntervals[drop.speed] = setInterval(() => {
- drops[drop.speed].forEach(drop => drop.update());
- }, drop.speed);
- }
- }
- function removeDrop(drop) {
- drops[drop.speed].splice(drops[drop.speed].indexOf(drop), 1);
- if(!drops[drop.speed].length) {
- clearInterval(speedIntervals[drop.speed]);
- speedIntervals[drop.speed] = null;
- }
- }
- setInterval(addDrop, DROP_SPAWN_INTERVAL);
Add Comment
Please, Sign In to add comment