그동안 카드 뒤집어서 짝맞추기, 지뢰찾기 등 게임 몇 개를 만들어봤는데 디자인에는 크게 신경을 쓰지 않았었다. 기능이 중요하지!! 하면서... 그렇지만 오늘은 유튜브에서 본 간단한 점프게임을 만들면서 이쁘게 꾸며보았다. 흡족하다.😊 이미지는 Pixabay에서 다운받았다. 만들면서 든 생각인데 슈퍼마리오 클론코딩하면 엄청 재밌을 것 같다.
호스팅은 파이어베이스를 이용했다.
(클릭 시 새 창에 뜹니다.)
https://jump-game-ac50b.web.app/
만들면서 신경 쓴 부분들을 중점으로 설명해 보겠습니다.
<body>
<div id="game">
<div id="jumpNum" class="hidden">성공 × <span>0</span></div>
<div id="gameover" class="hidden">GAME OVER</div>
<button id="btn">Start</button>
<div id="character"></div>
<div id="bomb"></div>
</div>
</body>
html은 간단하다. 캐릭터와 폭탄은 div에 background-img로 넣어주었다.
#gameover {
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
font-size: 3rem;
font-weight: bolder;
filter: drop-shadow(2px 2px rgb(124, 97, 97));
animation: twinkle 0.5s linear 2;
}
@keyframes twinkle {
0% {
opacity: 0.2;
}
50% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
레딧에서 누군가 말했었다. 본인 프로젝트에 음 뭔가 부족한데.. 싶으면 shadow를 추가해보라고. 그걸 본 뒤로 잘 애용하고 있다.
텍스트가 화면의 가운데에 있어야 하기 때문에 left: 50%
, transforn: translateX(-50%)
를 주었다.
애니메이션을 주어서 게임오버 텍스트가 빤짝빤짝 빛나게 했다.
#character {
position: relative;
top: 203px;
left: -55px;
background: url("./images/pacman.png") -357px -178px no-repeat;
width: 250px;
height: 270px;
transform: scale(0.45);
}
.jump {
animation: jump 1s ease;
}
@keyframes jump {
0% {
top: 203px;
}
50% {
top: 110px;
}
75% {
top: 110px;
}
100% {
top: 203px;
}
}
background position
을 조정해서 이미지 스프라이트를 하였다.
jump 클래스를 넣었다 붙였다 하면서 캐릭터가 점프하도록 만들 것이다.
jump 애니메이션에 50%와 75%를 똑같이 준 이유는 붕~ 뜨고 잠시 있다가 가라앉는 모션을 위해서이다.
startBtn.addEventListener("click", (e) => {
e.stopPropagation();
stopflag = false;
bomb.classList.add("move");
gameoverText.classList.add("hidden");
startBtn.classList.add("hidden");
jumpNum.classList.remove("hidden");
jumpNumCnt.textContent = 0;
});
stopPropagation()
을 줘서 start 버튼을 눌렀을 때 그 이벤트가 부모로 전달이 되지 않게끔 막았다. 이 코드를 삭제한다면 start 버튼을 누르면 캐릭터가 점프한다. 왜냐면 화면 아무 곳이나 누르면 점프하기 때문이다. 이 코드로 시작버튼을 클릭할 때 엄하게 캐릭터가 뛰는 것을 막을 수 있다.
게임오버 글씨나 재시작 버튼은 게임이 끝나면 보이고 시작하면 사라지도록 hidden 클래스를 넣었다 뺐다 한다. hidden 클래스에는 display: none
을 넣어주었다.
game.addEventListener("click", (e) => {
if (!stopflag) {
character.classList.add("jump");
stopflag = true;
jumpNumCnt.textContent++;
} else if (stopflag) {
return;
}
// 연속으로 캐릭터가 뛰지 않도록 조절
setTimeout(() => {
character.classList.remove("jump");
stopflag = false;
}, 1000);
});
클릭! -> 캐릭터 점프 시작 -> 착지. 점프 시작과 착지 사이에 또 클릭이 먹히면 안 된다. 그래서 stopflag 를 주어서 stopflag 가 true 라면 클릭을 무시하도록 return 을 주었다.
setTimeout
으로 1초 뒤에 jump 클래스를 제거했다.
setInterval(() => {
let characterTop = parseInt(
window.getComputedStyle(character).getPropertyValue("top")
);
let bombLeft = parseInt(
window.getComputedStyle(bomb).getPropertyValue("left")
);
// 졌다.
if (characterTop > 180 && bombLeft < -470) {
stopflag = true;
bomb.classList.remove("move");
gameoverText.classList.remove("hidden");
startBtn.textContent = "Replay";
setTimeout(() => {
startBtn.classList.remove("hidden");
}, 1000);
}
}, 100);
setInterval
로 0.1초마다 캐릭터와 폭탄이 닿았는지 확인한다.
window.getComputedStyle()
은 괄호 안의 css style 을 가져온다. 캐릭터의 높이와 폭탄의 좌측거리를 계산해서 충분히 높이 뛰지 않았는데 폭탄이 올 경우 게임이 종료된다.
게임이 종료될 때 바로 성공횟수를 0으로 초기화하면 사용자가 놓칠 수 있어서 재시작버튼을 누를 때 초기화하도록 했다.
Samantha, an avid fan of classic slot machines, decided to explore a new online slot game that featured a retro theme. The game’s nostalgic https://olimpkzcasino.kz/ design and familiar symbols appealed to her, making it a perfect choice for a relaxing evening. She set a budget and started spinning the reels, enjoying the familiar sounds and visuals of the game. Samantha’s approach was casual at first, placing small bets and savoring the simple pleasure of watching the reels spin.
지연님 이거 뭐예요 능력자...👍🏻👍🏻 글구 캐릭터 졸귀탱
!ㅠ