[JavaScript] 미니게임 프로젝트 | 가위바위보🖐

승연·2022년 7월 14일
4

Game World

목록 보기
2/6
post-thumbnail

Game World


미니 프로젝트 첫 게임으로 가위바위보 게임을 만들었습니다.

🙋‍♀️ 게임 설명 좀 해주세요

컴퓨터와 가위바위보 게임을 할 수 있습니다.

🤔 어떤 기능이 있나요?

  • 컴퓨터와 가위바위보 대결
    • 컴퓨터는 가위, 바위, 보 중 랜덤으로 하나를 선택한다.
    • 사용자는 가위, 바위, 보 중 하나를 선택해서 낼 수 있다.
    • 사용자가 가위, 바위, 보 중 하나를 선택하는 순간 컴퓨터가 선택한 값과 비교하여 결과를 출력한다.

  • 승리 시 베네핏, 패배 시 페널티
    • 사용자에게는 생명 3개가 기본으로 주어진다.
    • 승리 시 10점과 생명 1개를 얻는다.
    • 패배 시 생명 1개를 잃는다.

  • 게임 종료 후 결과 출력
    • 게임은 사용자의 생명이 0개가 되거나 사용자가 게임 정지 버튼을 눌렀을 때 종료된다.
    • 게임 종료 시 사용자가 획득한 점수와 대전 결과를 출력한다.

🔎 사용 기술은 무엇인가요?

HTML, CSS, JavaScript를 이용하여 만들었습니다.

🙊 어디서 해볼 수 있나요?

https://sypear.github.io/game-world/game-rps.html



Game World - 가위바위보🖐


1. 화면 구성

1-1. 무지성 구성

(무지성으로 화면을 만든 내 모습)

레이아웃을 먼저 잡고 그 안에 요소를 넣자.. 이런 생각 없이

가운데에 게임판을 놓자~~
그 안에 가위, 바위, 보 이미지를 넣자~~
그 밑에 버튼을 넣자~~
뭐야 홈버튼이 빠졌잖아🤔 게임판 위에 올리자~~

이런 식으로 만들었었습니다.

하기 전에 생각했나요?
아뇨 안 했어요.
아, 생각은 했었는데 귀찮아서?
아뇨 그냥 안 했어요.

귀찮아서 안 한게 아니라
레이아웃을 잡고 그 안에 요소를 넣자! 라는 사고 자체를 못했습니다..😅

1-2. 레이아웃을 잡아보자

무지성이었지만 양심은 있던 나,
왠지 찝찝한 마음에..😶 여기저기 기웃거리다

teo님의 CSS 전체 레이아웃 잡는 방법 글을 보고 깨달음을 얻어서 레이아웃을 다시 잡고 화면 구성을 갈아엎었습니다. (감사합니다.)

🎨 Flexbox를 이용해서 레이아웃을 잡아가는 과정

가로 방향으로 네모네모들을 그려가며 레이아웃을 잡아갔습니다.

가로 방향 네모네모들을 전부 그린 후 메뉴 바 안에 요소들을 배치했습니다.

현재 기준 레이아웃입니다.

요소까지 배치 완료!

1-3. 비교

같은 해상도(iPhone 4 사이즈)로 비교해 본 전/후 사진입니다.
아직 어설프긴 해도 확실히 나아진 것 같습니다.



2. 가위바위보 기능을 어떻게 만들까?

2-1. 컴퓨터의 랜덤 선택 값 만들기

⏳ setInterval()을 이용하여 특정 시간마다 선택 값 새로 뽑기

let timer = 0;
let speed = 300; // 게임 기본 스피드 0.3초로 설정

// 가위바위보 게임 자동 시작
window.onload = function() {
  timer = setInterval(changePcSelection, speed);
  ...
}

setInterval()을 이용하여 특정한 시간마다 컴퓨터의 선택 값을 바꾸도록 했습니다. (기본값 0.3초)

🎲 선택 값을 무작위로 뽑아보자

function getRandom() {
    return parseInt(Math.random() * 3); // (max - min) + min : max는 3, min은 0
}

`Math.random()'메소드를 이용하여 0~2 범위의 난수를 생성했습니다. (참고 페이지)


❌ 이전 선택값과 똑같은 값은 뽑지 못하도록

이전 선택 값과 똑같은 값은 뽑지 못하도록 하고 싶었습니다.

그래서 PC의 이전 선택 값을 저장하는 lastPcSelection 이라는 변수를 만들고,
다음 난수 생성 시에 이전 값과 새로운 값을 비교하여 두 값이 동일하면 다시 난수를 생성하도록 구현했습니다.

🔥 스테이지가 진행 될수록 컴퓨터의 선택 속도를 빠르게 하고 싶어요

let speed = 300; // 게임 기본 스피드 0.3초로 설정
let count = 0; // 게임 회차

// 게임을 재시작 하는 함수
function restartGame() {
    ...
    
    // 게임 회차에 따라 스피드 빠르게 조절 (20회차 이상 부턴 속도 고정)
    if (count <= 20) {
        speed = speed - 10;
    }

    // 게임 재시작
    timer = setInterval(changePcSelection, speed);
}

한 회차가 끝난 후 새 회차 시작 시, 컴퓨터의 선택 속도가 10ms씩 빨라지도록 했습니다.
20회차가 넘어가면 컴퓨터의 선택 속도가 더 이상 빨라지지 않도록(0.1초로 고정되도록) 했습니다.

2-2. 가위바위보 결과 비교

🧠 가위바위보 결과 비교를 위한 규칙 찾기

사용자와 컴퓨터의 가위, 바위, 보는 위와 같이 9개의 결과가 나올 수 있습니다.

가위, 바위, 보를 숫자 0, 1, 2로 치환한 후
사용자 선택 값과 PC 선택 값의 차(사용자 선택 값-PC선택 값)로 결과를 다시 정리하면

무승부인 경우는 결과가 0인 경우,
사용자가 승리하는 경우는 결과가 -2 또는 1인 경우,
사용자가 패배하는 경우는 결과가 -1 또는 2인 경우임을 알 수 있었습니다.

위 결과를 이용해서 가위바위보 결과 비교 로직을 구현하였습니다.




3. 승부 결과 출력하기


3-1. 5초 동안 결과 출력 후 모달창 자동으로 닫기

결과 출력 시간을 담는 변수를 선언한 후 setInterval()을 이용해 1초마다 결과 출력 시간을 1씩 감소시켰습니다.

그리고 남은 시간이 0이 되면 모달 창을 닫고 타이머 종료 후 새로운 게임이 시작되도록 했습니다.

3-2. 5초 기다리기 싫어요..💢

모달창 닫기 버튼을 클릭하거나 뒤 검은 배경을 클릭할 때도 모달창이 닫히도록 했습니다.

HTML

<div class="modal modal-layer">
	<div class="modal__content">
		...
		<button class="white-button modal__content-close-button" type="button">
			닫기
		</button>
	</div>
</div>

CSS

  • 모달창 뒤 검은 배경을 만들기 위한 스타일입니다.
.modal-layer {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 10;
    background: rgba(0, 0, 0, 0.5);
}

JavaScript

  • 사용자가 실제 클릭한 요소가 모달창 뒤 검은 배경이거나 모달창 닫기 버튼이면 창을 닫고 게임을 재시작합니다.
// 5초 되기 전에 사용자가 수동으로 모달 창을 종료하는 경우
const modal = document.getElementsByClassName("modal")[0];
const modalCloseButton = document.getElementsByClassName("modal__content-close-button")[0];
const modalLayer = document.getElementsByClassName("modal-layer")[0];

modal.addEventListener('click', function(e) {
    if (e.target === modalLayer || e.target === modalCloseButton) {
        modal.classList.remove("show");
        restartGame(); // 게임을 재 시작 하는 함수
    }
});

3-3. 깜빡이는 하트 애니메이션 💔

결과 출력 시 승리했을 때는 ❤️ 이미지가, 패배했을 때는 💔 이미지가 깜빡거리는 애니메이션을 넣고 싶었습니다.

이유는 두 가지였는데요,

첫 번째 이유는 승리 시 생명 하나를 얻고, 패배 시 생명 하나를 잃도록 구현되어 있는데
결과를 보여줄 때 승/패에 따라 ❤️ 또는 💔 이미지를 보여준다면? 사용자에게 게임의 룰이 좀 더 잘 전달되지 않을까 하는 마음.

두 번째 이유는 왠지 있어 보임. 😎

그래서 넣었습니다.

승/패 결과에 따라 ❤️ 또는 💔 이미지를 삽입하고, 깜빡이 효과를 주는 애니메이션을 적용했습니다.

JavaScript

resultLifeItem.style.animation = "blinkingEffect 400ms 6 alternate";

CSS

@keyframes blinkingEffect {
	from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

3-4. 전체 대전 결과도 출력하고 싶어요

// 게임 회차 및 승패 정보 저장
let count = 0;
let winCount = 0;
let drawCount = 0;
let loseCount = 0;
let playerScore = 0;

게임 회차 및 승패 정보, 사용자 점수를 저장한 뒤 게임 종료 시 출력하도록 했습니다.




깃허브 페이지에 배포해서 친구들에게 보여줬더니 다들 칭찬해줘서 뿌듯했습니다.

그동안 혼자만 보는 프로젝트를 해왔는데
사용자가 있는(..매우 매우 소수지만) 서비스를 만든다는 건 참 재밌는 일이라는 걸 느꼈습니다. 🐣

profile
✈️ https://sypear.tistory.com/

0개의 댓글