게임 효과
게임 이펙트 - 같은 그림 찾기
오늘은 같은그림찾기 게임을 만들어보겠습니다. 핑크색 메모리 문서를 클릭해보세요!
결과
HTML 작성
게임판을 만들 틀을 잡아줍니다. 같은사진을 앞뒤로 쓸것이기에 li태그 안에 div태그를 두개를 만들어줍시다.
소스 보기
<div class="memory__wrap">
<div class="memory__inner">
<div class="memory__header">
<h2>같은그림찾기</h2>
<div class="memory__box">
<ul>
<li>1. 기회는 세번입니다.</li>
<li>2. 한번 맞출때 마다 1점씩 올라갑니다.</li>
<li>3. 제한시간은 없으니 천천히 푸시기 바랍니다.</li>
<li>4. 마음의 준비를 하신 뒤 시작버튼을 눌러주세요.</li>
</ul>
<div class="start">시작</div>
</div>
</div>
<div class="memory__card">
<div class="card__header">
<p>틀린 횟수 : <span class="chance">0</span> 맞힌 개수 : <span class="score"> 0 </span>개</p>
</div>
<ul class="cards">
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon01.png" alt="icon1">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon02.png" alt="icon2">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon03.png" alt="icon3">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon04.png" alt="icon4">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon05.png" alt="icon5">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon06.png" alt="icon6">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon07.png" alt="icon7">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon08.png" alt="icon8">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon01.png" alt="icon1">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon02.png" alt="icon2">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon03.png" alt="icon3">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon04.png" alt="icon4">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon05.png" alt="icon5">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon06.png" alt="icon6">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon07.png" alt="icon7">
</div>
</li>
<li>
<div class="view front">
<img src="../assets/img/memory_icon.png" alt="icon">
</div>
<div class="view back">
<img src="../assets/img/memory_icon08.png" alt="icon8">
</div>
</li>
</ul>
<!-- memory__card -->
</div>
<div class="memory__result">
<div class="result">게임 오버</div>
<!-- 맞힌 개수 :<span class="resultScore">개</span> -->
<div class="result__restart">다시 시작하기</div>
</div>
<div class="memory__clear">
<div class="clear">게임 승리</div>
틀린 개수 : <span class="clearScore"> 0개</span>
<!-- <div class="clear__restart">다시 시작하기</div> -->
</div>
</div>
</div>
CSS 작성
같은그림찾기 CSS
소스 보기
.memory__wrap {
position: relative;
}
.memory__inner {
display: none;
width: 600px;
height: 615px;
border: 3px solid #08f;
background: #000;
position: absolute;
left: 300px;
top: 100px;
border-radius: 20px;
animation: flicker 1.5s infinite alternate;
}
.memory__inner.show {
display: block;
overflow: hidden;
}
.memory__header {
width: 100%;
height: 100%;
z-index: 2;
background: linear-gradient( to bottom, rgba(255, 255, 0, 0.5), rgba(0, 0, 255, 0.5));
}
.memory__header h2 {
font-size: 60px;
padding-top: 100px;
text-align: center;
color: #fff;
padding-bottom: 50px;
box-sizing: border-box;
}
.memory__header .memory__box {}
.memory__header .memory__box li {
text-align: center;
color: #fff;
line-height: 1.5;
font-size: 25px;
}
.memory__header .start {
margin-top: 150px;
text-align: center;
font-size: 50px;
cursor: pointer;
box-sizing: border-box;
color: #fff;
}
.memory__header .start:hover {
color: rgba(255, 255, 0, 0.5);
}
.memory__result, .memory__clear {
display: none;
}
.memory__clear.show, .memory__result.show {
display: block;
position: absolute;
left: 25%;
top: 25%;
width: 50%;
height: 50%;
z-index: 100;
background: linear-gradient( to bottom, rgba(255, 255, 0, 1), rgba(0, 0, 255, 1));
border-radius: 15px;
font-size: 20px;
text-align: center;
}
.clearScore {
display: inline-block;
margin-bottom: 15px;
color: blue;
}
.resultScore {
display: inline-block;
margin-bottom: 15px;
color: red;
}
.memory__result .result {
display: block;
text-align: center;
padding-top: 35px;
font-size: 50px;
color: red;
margin-bottom: 70px;
}
.memory__clear .clear {
display: block;
text-align: center;
padding-top: 35px;
font-size: 50px;
color: blue;
margin-bottom: 70px;
}
.memory__result .result__restart, .memory__clear .clear__restart {
text-align: center;
font-size: 20px;
border-radius: 20px;
background: #fff;
color: #000;
padding: 5px 10px;
margin-top: 10px;
width: 150px;
margin: 0 auto;
}
.memory__result .result__restart:hover, .memory__clear .clear__restart:hover {
background: #000;
color: #fff;
}
.card__header {
display: flex;
justify-content: space-between;
}
.card__header .chance {
margin-right: 100px;
}
.time span {
color: #fff;
}
.memory__card {
padding: 40px;
}
.memory__card p {
text-align: center;
color: #fff;
margin-bottom: 15px;
}
.memory__card .cards {
display: flex;
flex-wrap: wrap;
gap: 10px;
padding-bottom: 15px;
box-sizing: border-box;
}
.memory__card .cards li {
list-style: none;
width: 120px;
height: 120px;
position: relative;
transform-style: preserve-3d;
perspective: 500px;
}
.memory__card .cards li img {
width: 100%;
box-sizing: border-box;
padding: 15px;
}
.memory__card .cards li .view {
position: absolute;
width: 100%;
height: 100%;
background: #08f;
backface-visibility: hidden;
padding: 10px;
border-radius: 20px;
transition: all 0.5s;
/* user-select: none; */
pointer-events: none;
}
.memory__card .cards li .front {
transform: rotateY(0deg);
}
.memory__card .cards li.flip .front {
transform: rotateY(180deg);
}
.memory__card .cards li .back {
transform: rotateY(-180deg);
}
.memory__card .cards li.flip .back {
transform: rotateY(0deg);
}
.memory__card .cards li.shakeX {
animation: shakeX 1s 1;
}
.memory__card .cards li.shakeY {
animation: shakeY 1s 1;
}
@keyframes flicker {
0%,
19%,
21%,
23%,
25%,
54%,
56%,
100% {
box-shadow: 0 0 0.5rem #fff, inset 0 0 0.5rem #fff, 0 0 2rem #08f,
inset 0 0 2rem #08f, 0 0 4rem #08f, inset 0 0 4rem #08f;
}
}
@keyframes shakeX {
from,
to {
transform: translate3d(0, 0, 0);
}
10%,
30%,
50%,
70%,
90% {
transform: translate3d(-10px, 0, 0);
}
20%,
40%,
60%,
80% {
transform: translate3d(10px, 0, 0);
}
}
@keyframes shakeY {
from,
to {
transform: translate3d(0, 0, 0);
}
10%,
30%,
50%,
70%,
90% {
transform: translate3d(0, -10px, 0);
}
20%,
40%,
60%,
80% {
transform: translate3d(0, 10px, 0);
}
}
JS 작성
버튼 스크립트
시작버튼, 게임을 클리어했을 때, 게임을 패배했을 때 시작하는 함수를 만들어봅시다
<script>
// 시작버튼 클릭
startBtn.addEventListener("click",() => {
memoryFront.style.display="none";
shuffleCard()
})
let cardOne, cardTwo;
let disableDeck = false;
let matchedCard = 0;
let missedCard = 0;
let sound = [
"../assets/audio/Success.m4a",
"../assets/audio/fail.mp3",
"../assets/audio/up.mp3"
]
// 재시작버튼 클릭
resultRestart.addEventListener("click", ()=>{
memoryResult.classList.remove("show")
shuffleCard()
})
// 재시작버튼 클릭
clearRestart.addEventListener("click", ()=>{
memoryClear.classList.remove("show")
shuffleCard()
})
</script>
카드 뒤집기 함수
카드를 클릭하면 카드의 이미지 src 주소를 가져오도록 만들었습니다. flip이라는 클래스를 추가해서 미리 만들어놓은 css로 카드가 뒤집어지는 효과를 주고, 카드1의 이미지 src와 카드2의 이미지 src를 비교하는 함수는 밑에서 설명드리겠습니다.
<script>
let cardOne, cardTwo;
let disableDeck = false;
let matchedCard = 0;
let missedCard = 0;
let sound = [
"../assets/audio/Success.m4a",
"../assets/audio/fail.mp3",
"../assets/audio/up.mp3"
]
// 카드 뒤집기
function flipCard(e){
let clickedCard = e.target;
if(clickedCard !== cardOne && !disableDeck){
clickedCard.classList.add("flip");
// 카드1이 아니면 카드1값에 clickCard넣기
if(!cardOne){
return cardOne = clickedCard;
}
cardTwo = clickedCard;
disableDeck = true;
// 결국 카드1, 카드2 클릭하면 matchCard로 두개의 이미지 src값만 나오게 설정
let cardOneImg = cardOne.querySelector(".back img ").src;
let cardTwoImg = cardTwo.querySelector(".back img ").src;
matchCards(cardOneImg, cardTwoImg)
}
// console.log(cardOneImg)
// console.log(cardTwoImg)
}
</script>
두개의 이미지 비교하는 함수
img1과 img2가 같은경우 매치카드가 1씩 올라가고 8이되면 게임이 끝나도록 설정했습니다. img1과 img2는 flipcard에서의 cardOneImg, cardTwoimg 를 받아옵니다. img1과 img2가 다를경우 좌우로 움직이는 효과를 주었습니다.
<script>
// 카드 확인(두개의 이미지 비교)
function matchCards(img1, img2){
if(img1 == img2){
// 같을 경우
matchedCard++;
memoryScore.innerText = matchedCard;
// 정답맞춘 오디오
soundMatch.play();
if(matchedCard == 8){
// alert("게임 오버")
soundSuccess.play();
memoryClear.classList.add("show");
}
// 이벤트 제거하고 초기화하는 과정
cardOne.removeEventListener("click", flipCard);
cardTwo.removeEventListener("click", flipCard);
cardOne = cardTwo = "";
disableDeck = false;
} else {
missedCard++;
// 일치하지 않는 경우(틀린음악, 이미지가 좌우로 흔들림)
setTimeout(()=>{
cardOne.classList.add("shakeX");
cardTwo.classList.add("shakeX");
// 틀렸을때 음악재생
soundUnMatch.play();
chance.innerText = missedCard + "회";
}, 500);
setTimeout(()=>{
cardOne.classList.remove("shakeX", "flip");
cardTwo.classList.remove("shakeX", "flip");
cardOne = cardTwo = "";
disableDeck = false;
if(missedCard == 3){
// alert("gameover")
memoryResult.classList.add("show")
}
}, 1500)
}
}
</script>
초기화 하는 함수
설정한 바뀌는값들을 모두 기본값으로 되돌리고, 카드의 셔플하는 위치는 random과 sort메서드를 이용해서 랜덤으로 설정되도록 하였습니다. 또한 settime아웃으로 0.2초 간격으로 카드를 하나씩 보여준뒤 4초후에 모든 카드를 다시 뒤집어줍니다.
<script>
// 카드 섞기
function shuffleCard(){
// 초기화
cardOne = cardTwo = "";
disableDeck = false;
matchedCard = missedCard = 0;
disableDeck = false;
memoryScore.innerText = matchedCard;
chance.innerText = missedCard;
let arr = [1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8];
// 0.5보다 큰경우 1 아닌경우 -1
let result = arr.sort(() => Math.random() > 0.5 ? 1 : -1);
memoryCards.forEach((card, index) => {
card.classList.remove("flip");
setTimeout((e)=>{
card.classList.add("flip");
}, 200 * index);
setTimeout(()=> {
card.classList.remove("flip");
card.classList.remove("shakeX");
}, 4000)
let ImgTag = card.querySelector(".back img");
ImgTag.src = `../assets/img/memory_icon0${arr[index]}.png`
})
}
</script>
'Javascript_Effect' 카테고리의 다른 글
슬라이드 이펙트 - 이미지 슬라이드(버튼, 닷메뉴, 무한) (1) | 2022.10.20 |
---|---|
게임 이펙트 - 스피드 퀴즈 (1) | 2022.10.17 |
게임 이펙트 - 뮤직 플레이어 (0) | 2022.10.17 |
서치 이펙트 - 정렬하기 (0) | 2022.10.17 |
슬라이더 이펙트 - (버튼, 닷메뉴) (3) | 2022.10.14 |
댓글