JSFiddle - React, Tailwind, and code Playground

by kalinin sergey

HTML

<div class="game" id="game"></div>   

			<template id="menuTpl">
			  <div class="wrap-menu">
					<div class="punkt-menu">
						<span class="left">1. Количество врагов: </span>
						<span class="right" id="enemiesCnt"></span>
					</div>

					<div class="punkt-menu">
						<span class="left">2. Прочность стен: </span>
						<span class="right" id="wallsStrength"></span>
					</div>

					<div class="punkt-menu">
						<span class="left">3. старт игры </span>
						<span class="right" id="start"></span>
					</div>										
				</div>
			</template>  

			<template id="infoScreenTpl">
			  <div class="wrap-info-screen" id="wrapInfoScreen">
					<div class="text-top">Уровень <span id="levelCnt"></span></div>
					<div class="text-bottom" id="infoTextBottom">Нажмите любую клавишу для старта</div>								
				</div>
			</template>  

			<template id="gameOverScreenTpl">
			  <div class="wrap-game-over-screen" id="wrapGameOverScreen">
					<div class="game-over-text" id="gameOverText">Игра окончена. Вы проиграли</div>							
				</div>
			</template>  		

			<template id="gameCompleteScreenTpl">
			  <div class="wrap-game-complete-screen" id="wrapGameCompleteScreen">
					<div class="game-complete-text" id="gameCompleteText">Игра окончена. Вы выиграли</div>							
				</div>
			</template>

CSS

html, body {
  height: 100vh;
  width: 100vw;
  margin: 0;
  padding: 0;
  position: relative;
  background: orange;  
  overflow: auto;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;  
}

.game {
	width: 800px;
	height: 800px;
	background: #000;
	overflow: hidden;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;  	
}

.wrap-menu {
	width: 40%;
	border: 1px solid red;
	padding: 10px;
}

	.punkt-menu {
		color: yellow;
		padding: 4px 0;
	}

		.right {
			text-decoration: underline;
		}

.wrap-info-screen { 
  text-align: center;
  transition: 1s;
}

  .text-top {
    font-size: 3em;
    padding-bottom: 4em;
    color: red;
  }

  .text-bottom {
    font-size: 1em;
    color: cyan;
  }

  .hide {
    opacity: 0;
    transition: 1s;
  }


#end,
#next {
	cursor: pointer;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center; 
	width: 100px;
	height: 100px;
	background: lime;	
}
#end {
	background: red;
}
#minus {
  width: 100px;
  height: 100px;
  background: white;
}

.game-over-text {
	font-size: 3em;
	transition: 2s;
	color: blue;
}
	
	.game-over-text.transform {
		font-size: 0em;
	}

.game-complete-text {
	font-size: 3em;
	transition: 2s;
	color: lime;
}
	
	.game-complete-text.transform {
		font-size: 10em;
		opacity: 0;
	}

JavaScript

class Game {

  constructor(initObj) {
    this.initObj = initObj;
    this.gameEl = initObj.gameEl;
    this.levelCnt = 1;
    this.levelCntMax = 3;
    this.playerLife = 100;
    this.menu = new Menu(this);
  }

  reConstructor() {
    this.gameEl = this.initObj.gameEl;
    this.levelCnt = 1;
    this.levelCntMax = 3;
    this.playerLife = 100;
    this.menu = new Menu(this);    
  }

  controller(action) {
    let action_ = this.isGameComplete() ? 'gameCompleteScreen' : action;

    switch(action_) {
      case 'infoScreen':
        new InfoScreen(this);
        break;
      case 'gameCompleteScreen':
        new GameCompleteScreen(this);      
        break;
      case 'level':
        new Level(this);      
        break;
      case 'gameOverScreen':
        new GameOverScreen(this);     
        break;        
    }
  }

  isGameComplete() {
    return this.levelCnt > this.levelCntMax;
  }

}

class Menu {

  constructor(gameObj) {
    this.gameObj = gameObj;

    this.enemiesCntIndex = 2;
    this.enemiesCntLabels = {
      0: 'Много',
      1: 'Средне',
      2: 'Мало'
    };
    
    this.wallsStrengthIndex = 2;
    this.wallsStrengthLabels = {
      0: 'Алмазные',
      1: 'Железобетонные',
      2: 'Кирпичные'
    };

    this.render();
    this.startKeysListen();
  }

  render() {
    this.gameObj.gameEl.innerHTML = '';

    const menuTpl = document.querySelector('#menuTpl');
    const menuTplClone = menuTpl.content.cloneNode(true);
    this.gameObj.gameEl.appendChild(menuTplClone);
    
    const enemiesCntEl = document.getElementById('enemiesCnt');
    if (enemiesCntEl) {
      enemiesCntEl.innerHTML = this.enemiesCntLabels[this.enemiesCntIndex];
    }

    const wallsStrengthEl = document.getElementById('wallsStrength');
    if (wallsStrengthEl) {
      wallsStrengthEl.innerHTML = this.wallsStrengthLabels[this.wallsStrengthIndex];
    }    
  }  

  startKeysListen() {
    this._keysListenHandler = this._keysListen.bind(this);
   ...