분류
javascript
자바스크립트 게임 - 무지개를 찾아라
본문
"일부 CSS와 일반 JavaScript로 약간의 게임을 만들었습니다. 게임은 CSS Grid + Flexbox를 통해 완벽하게 반응합니다. 무지개는 항상 다른 장소에 숨겨져 있기 때문에 원하는 만큼 여러 번 재생할 수 있습니다"– ilithya.
https://codepen.io/ilithya/pen/vodGee
HTML :
<main class="game">
<div class="game__canvas">
<div class="box" id="play-box">
<div class="box__inner">
<h1 class="box__headline">Find the rainbow</h1>
<p class="box__txt">Press (click/tap) the buttons until you find it!</p>
<button class="box__btn p-btn" type="button" id="play-btn">Play now</button>
</div>
</div>
<div class="grid">
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
<div class="grid__cell">
<button class="grid__btn p-btn" type="button"> <span class="grid__btn__rainbow"> </span></button>
</div>
</div>
</div>
</main>
CSS :
html,
body {
height: 100%;
}
body {
min-width: 20em;
background-color: pink;
margin: 0;
padding: 0;
}
::-moz-selection {
background-color: pink;
}
::selection {
background-color: pink;
}
.p-btn {
cursor: pointer;
outline: none;
-webkit-tap-highlight-color: transparent;
}
.game {
width: 100%;
height: 100%;
display: flex;
overflow-y: scroll;
-webkit-overflow-scrolling: touch;
}
.game__canvas {
width: 100%;
height: auto;
max-width: 500px;
margin: auto;
position: relative;
}
.box {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 120;
}
.box__inner {
width: 100%;
height: auto;
background-color: blue;
box-sizing: border-box;
color: yellow;
font-family: 'Overpass Mono', monospace;
padding: 2.2rem 1.5rem;
position: absolute;
top: 22%;
text-align: center;
}
.box__headline {
font-size: 2rem;
line-height: 1;
margin: 0;
}
.box__txt {
font-size: 0.9rem;
}
.box__btn {
background-color: yellow;
color: blue;
font-family: 'Overpass Mono', monospace;
font-size: 1rem;
font-weight: bold;
line-height: 1;
padding: 0.5rem 1rem;
text-transform: lowercase;
}
.grid {
display: grid;
place-items: center;
justify-content: center;
grid-template-columns: repeat(auto-fit, 100px);
}
.grid__cell {
width: 100px;
height: 100px;
}
.grid__btn {
width: 60%;
height: 60%;
background-color: yellow;
border: 4px solid blue;
line-height: 1.5;
margin: 13% 26%;
position: relative;
transition: all 0.05s ease-in;
}
.grid__btn.is-pressed {
background-color: blue;
cursor: default;
-webkit-transform: translate(calc(-10% + 1px), calc(10% - 1px));
transform: translate(calc(-10% + 1px), calc(10% - 1px));
}
.grid__btn.is-pressed::before {
width: 10%;
}
.grid__btn.is-pressed::after {
height: 10%;
}
.grid__btn::before, .grid__btn::after {
border: 4px solid blue;
content: '';
background: yellow;
position: absolute;
transition: all 0.05s ease-in;
}
.grid__btn::before {
width: 20%;
height: calc(100% + 2px);
border-right: 0;
border-bottom-width: 2px;
-webkit-transform: skew(0deg, -45deg) translateX(-4px);
transform: skew(0deg, -45deg) translateX(-4px);
-webkit-transform-origin: top right;
transform-origin: top right;
top: -8px;
right: 99%;
}
.grid__btn::after {
width: calc(100% + 1px);
height: 20%;
border-top: 0;
border-left-width: 3px;
-webkit-transform: skew(-45deg, 0deg) translateY(4px);
transform: skew(-45deg, 0deg) translateY(4px);
-webkit-transform-origin: top right;
transform-origin: top right;
top: 100%;
right: -8px;
}
.grid__btn__rainbow {
position: absolute;
top: 40%;
left: 40%;
z-index: 90;
font-size: 0;
}
.grid__btn__rainbow.has-rainbow {
-webkit-animation: rainbowFound 1s ease-in-out alternate infinite;
animation: rainbowFound 1s ease-in-out alternate infinite;
font-size: 28px;
}
@-webkit-keyframes rainbowFound {
0% {
-webkit-transform: translate(-11.1111111111px, -11.1111111111px);
transform: translate(-11.1111111111px, -11.1111111111px);
}
25% {
font-size: 6rem;
-webkit-transform: translate(-45.4545454545px, -55.5555555556px) rotate(25deg);
transform: translate(-45.4545454545px, -55.5555555556px) rotate(25deg);
}
50% {
font-size: 6rem;
-webkit-transform: translate(-45.4545454545px, -55.5555555556px) rotate(-15deg);
transform: translate(-45.4545454545px, -55.5555555556px) rotate(-15deg);
}
75% {
font-size: 6rem;
-webkit-transform: translate(-45.4545454545px, -55.5555555556px) rotate(25deg);
transform: translate(-45.4545454545px, -55.5555555556px) rotate(25deg);
}
100% {
font-size: 6rem;
-webkit-transform: translate(-45.4545454545px, -55.5555555556px) rotate(-15deg);
transform: translate(-45.4545454545px, -55.5555555556px) rotate(-15deg);
}
}
@keyframes rainbowFound {
0% {
-webkit-transform: translate(-11.1111111111px, -11.1111111111px);
transform: translate(-11.1111111111px, -11.1111111111px);
}
25% {
font-size: 6rem;
-webkit-transform: translate(-45.4545454545px, -55.5555555556px) rotate(25deg);
transform: translate(-45.4545454545px, -55.5555555556px) rotate(25deg);
}
50% {
font-size: 6rem;
-webkit-transform: translate(-45.4545454545px, -55.5555555556px) rotate(-15deg);
transform: translate(-45.4545454545px, -55.5555555556px) rotate(-15deg);
}
75% {
font-size: 6rem;
-webkit-transform: translate(-45.4545454545px, -55.5555555556px) rotate(25deg);
transform: translate(-45.4545454545px, -55.5555555556px) rotate(25deg);
}
100% {
font-size: 6rem;
-webkit-transform: translate(-45.4545454545px, -55.5555555556px) rotate(-15deg);
transform: translate(-45.4545454545px, -55.5555555556px) rotate(-15deg);
}
}
Javascript :
/* FIND THE RAINBOW
* Press (click/tap) the buttons until you find the rainbow!
* Game is fully responsive via CSS Grid + Flexbox.
*
* You can play as many times as you'd like, because the rainbow it's always hidden in a different place.
*
* Feel free to improve this game, or give me feedback.
*
* #006 - #100DaysOfCode
* By ilithya | 2019
*/
let gameOver = false;
const rainbowString = "rainbow";
const btnPressClass = "is-pressed";
const rainbowClass = "has-rainbow";
const dialog = {
hide: function (dialogBox) {
dialogBox.style.display = "none";
},
updateContent: function () {
const boxHeadline = document.querySelector("#play-box .box__headline");
boxHeadline.innerHTML = "Play again?";
const boxText = document.querySelector("#play-box .box__txt");
boxText.innerHTML = "Rainbow is never in the same place.";
},
showPlayAgain: function (dialogBox) {
dialog.updateContent();
dialogBox.style.display = "block";
} };
const getRandomIntInclusive = maxNum => {
const min = 0;
const max = Math.floor(maxNum);
return Math.floor(Math.random() * (max - min + 1)) + min;
};
const rainbow = {
insert: function (el) {
const btnCount = el.length - 1;
const luckyBtn = getRandomIntInclusive(btnCount);
el[luckyBtn].children[0].innerHTML = rainbowString;
el.forEach(function (item) {
game.addBtnClick(item);
});
},
remove: function (el) {
el.forEach(function (item) {
const itemChild = item.children[0];
itemChild.innerHTML = "";
itemChild.classList.remove(rainbowClass);
item.classList.remove(btnPressClass);
});
} };
const game = {
btn: document.querySelectorAll(".grid__btn"),
box: document.getElementById("play-box"),
start: function () {
rainbow.insert(game.btn);
dialog.hide(game.box);
},
run: function () {
if (gameOver) {
rainbow.remove(game.btn);
game.start();
} else {
game.start();
}
},
stop: function () {
gameOver = true;
game.btn.forEach(function (item) {
game.removeBtnClick(item);
});
setTimeout(function () {
dialog.showPlayAgain(game.box);
}, 5000);
},
play: function (e) {
const thisItem = e.target;
thisItem.classList.add(btnPressClass);
game.removeBtnClick(thisItem);
const rainbowEl = thisItem.children[0];
if (rainbowEl.innerHTML === rainbowString) {
rainbowEl.classList.add(rainbowClass);
game.stop();
}
},
addBtnClick: function (el) {
el.addEventListener("click", game.play, false);
},
removeBtnClick: function (el) {
el.removeEventListener("click", game.play, false);
} };
const btnPlay = document.getElementById("play-btn");
btnPlay.addEventListener("click", game.run, false);
- 이전글지뢰찾기게임 - Minesweeper 19.08.14
- 다음글애니메이션 SVG 로더 19.08.14