Facebook
From Criar novo código brave - explor, 3 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 61
  1. const { EventEmitter } = require('events');
  2. const { stdin } = require('process');
  3.  
  4. class Game extends EventEmitter {
  5.     constructor(width, height, sprites) {
  6.         super();
  7.        
  8.         this.width = width;
  9.         this.height = height;
  10.         this.sprites = sprites;
  11.  
  12.         this.goals = 0;
  13.         this.okGoals = 0;
  14.  
  15.         this.on('levelEnd', this.nextLevel);
  16.         this.on('move', this.onMove);
  17.     };
  18.  
  19.     resetLines() {
  20.         this.lines = [];
  21.  
  22.         for(let y = 0; y < this.height; y ++) {
  23.             const line = new Array(this.width).fill('air');
  24.             this.lines.push(line);
  25.         };
  26.     };
  27.  
  28.     nextLevel() {
  29.         this.okGoals = 0;
  30.         this.resetLines();
  31.         this.addBorderWalls();
  32.  
  33.         const walls = 1 + Math.random() * 2;
  34.         for(let i = 0; i < walls; i ++)
  35.             this.spawn('wall');
  36.  
  37.         const boxes = 1 + Math.floor(Math.random() * 2);
  38.         this.goals = boxes;
  39.  
  40.         for(let i = 0; i < boxes; i ++) {
  41.             this.spawn('box', 2);
  42.             this.spawn('goal');
  43.         };
  44.  
  45.         this.spawn('player');
  46.         this.update();
  47.     };
  48.  
  49.     getPlayerPos() {
  50.         const y = this.lines.findIndex((line) => line.includes('player'));
  51.         const line = this.lines[y];
  52.  
  53.         if(!line) {
  54.             this.spawn('player');
  55.             return this.getPlayerPos();
  56.         };
  57.  
  58.         const x = line.indexOf('player');
  59.  
  60.         return { x, y };
  61.     };
  62.  
  63.     setItemPos(x, y, newX, newY) {
  64.         const char = this.lines[y][x];
  65.  
  66.         this.lines[y][x] = 'air';
  67.         this.lines[newY][newX] = char;
  68.     };
  69.  
  70.     moveItem(x, y, side) {
  71.         const sides = {
  72.             left: [ 'x', -1 ],
  73.             up: [ 'y', -1 ],
  74.             down: [ 'y', 1 ],
  75.             right: [ 'x', 1 ]
  76.         };
  77.  
  78.         const [ coord, apply ] = sides[side];
  79.         const newPos = { x, y };
  80.  
  81.         newPos[coord] += apply;
  82.  
  83.         const collide = this.lines[newPos.y][newPos.x];
  84.         const char = this.lines[y][x];
  85.  
  86.         if(collide === 'box') {
  87.             const ok = this.moveItem(newPos.x, newPos.y, side);
  88.  
  89.             if(!ok) return;
  90.         } else {
  91.             if(char === 'box' && collide === 'goal') {
  92.                 this.okGoals ++;
  93.  
  94.                 if(this.okGoals >= this.goals)
  95.                     this.emit('levelEnd');
  96.  
  97.                 this.lines[newPos.y][newPos.x] = 'air';
  98.  
  99.                 return true;
  100.             };
  101.  
  102.             if(collide !== 'air') return;
  103.         };
  104.  
  105.         this.setItemPos(x, y, newPos.x, newPos.y);
  106.  
  107.         return true;
  108.     };
  109.  
  110.     onMove(side) {
  111.         const pos = this.getPlayerPos();
  112.  
  113.         this.moveItem(pos.x, pos.y, side);
  114.         this.update();
  115.     };
  116.  
  117.     spawn(item, offset = 1) {
  118.         const randomPos = (max) => Math.floor(offset + Math.random() * (max - offset * 2));
  119.  
  120.         const x = randomPos(this.width);
  121.         const y = randomPos(this.height);
  122.  
  123.         if(this.lines[y][x] === 'air') {
  124.             this.lines[y][x] = item;
  125.         } else {
  126.             this.spawn(item, offset);
  127.         };
  128.     };
  129.  
  130.     addBorderWalls() {
  131.         for(let x = 0; x < this.width; x ++) {
  132.             this.lines[0][x] = 'wall';
  133.             this.lines[this.height - 1][x] = 'wall';
  134.         };
  135.        
  136.         for(let y = 0; y < this.height; y ++) {
  137.             this.lines[y][0] = 'wall';
  138.             this.lines[y][this.width - 1] = 'wall';
  139.         };
  140.     };
  141.  
  142.     update() {
  143.         const frame = this.lines
  144.             .map((line) => line.map((char) => this.sprites[char]).join(''))
  145.             .join('\n');
  146.  
  147.         this.emit('update', frame);
  148.     };
  149. };
  150.  
  151. const game = new Game(16, 7, {
  152.     player: '@',
  153.     air: ' ',
  154.     wall: '#',
  155.     box: '%',
  156.     goal: '$'
  157. });
  158.  
  159. game.on('update', (state) => {
  160.     console.clear();
  161.     console.log(state);
  162. });
  163.  
  164. game.nextLevel();
  165.  
  166. stdin.setRawMode(true);
  167. stdin.setEncoding('utf-8')
  168. stdin.resume();
  169.  
  170. const sides = {
  171.     a: 'left',
  172.     w: 'up',
  173.     s: 'down',
  174.     d: 'right'
  175. };
  176.  
  177. stdin.on('data', (key) => {
  178.     if(key === '\u0003') process.exit();
  179.  
  180.     const side = sides[key];
  181.  
  182.     if(side) game.emit('move', side);
  183. });