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);
...