[Vanilla JS Project] 타자게임 클론코딩

SeokHun·2021년 1월 8일
0

Projects

목록 보기
1/3
post-thumbnail

참조 영상
Vanilla 자바스크립트 타자게임 만들기! 실전코스 - Code Scalper

코드
GitHub : pyo-sh


1. Main Features

1-1. Random Word API

random-word-api

타이핑 게임에서 사용될 단어를 API를 통해 불러옵니다.
홈페이지 로딩 시 API를 통해 단어들을 요청하고 데이터를 무사히 받으면 게임 시작 버튼을 누를 수 있게 됩니다.

Axios 를 통한 HTTP 통신

index.html에서 jsDelivr CDN을 통해 axios를 사용을 선언하고 api를 통해 데이터를 받습니다.

<head>
    ...
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>

받은 단어들 중에서 길이가 10 미만인 단어들만 저장합니다.
단어들을 무사히 전달받아 저장하였다면 게임 시작 버튼을 누를 수 있게 상태를 변경합니다.

let words = [];

const getWords = async () => {
    try{
        const url = 'https://random-word-api.herokuapp.com/word?number=100';
        const response = await axios.get(url);
        response.data.forEach(word => {
            if(word.length < 10){
                words.push(word);
            }
        });
        buttonChange('게임시작');
    }
    catch (error){
        console.error(error);
    }
}

1-2. Game Start

1) 게임시작 버튼

게임을 시작할 때에는 버튼을 클릭해야 합니다.
게임시작 버튼이 작동되어야 할 상황은 게임시작할 때 밖에 없습니다.
따라서 버튼은 두 가지의 상태만을 고려하여 만들어줍니다.

<body>
    ...
    <button class="button loading">게임을 불러오는 중...</button>
</body>
.button {
    width: 200px;
    height: 35px;
    background: #3b5999;
    color: #ffffff;
    border: none;
    margin-top: 3rem;
    cursor: pointer;
}
.loading{
    background: #cccccc;
    cursor: not-allowed;
}

Javascript에서는 버튼을 클릭할 수 있는 상태로 만들지 말지만 정해주면 됩니다.

const button = document.querySelector('.button');

const buttonChange = (text) => {
    button.innerText = text;
    text === '게임시작' ? button.classList.remove('loading')
        : button.classList.add('loading');
}

2) 버튼 클릭

게임시작 버튼을 클릭하면 게임에 대한 정보를 초기화할 필요가 있습니다.
아래와 같은 정보들을 초기화 합니다.

  1. 게임 플레이 중인지에 대한 여부 ( + setInterval을 통해 상시 확인 )
  2. 입력받는 input창에 focus
  3. 점수 0점
  4. 시간 초기화 ( + setInterval을 통해 CountDown 시작 )
  5. 버튼의 상태 변경
const wordInput = document.querySelector('.word-input');
const wordDisplay = document.querySelector('.word-display');
const scoreDisplay = document.querySelector('.score');
const timeDisplay = document.querySelector('.time');

const GAME_TIME = 9;
let time = GAME_TIME;
let isPlaying = false;
let timeInterval;
let checkInterval;

const run = () => {
    if(!isPlaying){
        isPlaying = true;
        wordInput.focus();
        scoreDisplay.innerText = 0;
        time = GAME_TIME;
        timeDisplay.innerText = time;
        timeInterval = setInterval(countDown, 1000);
        checkInterval = setInterval(checkStatus, 50);
        buttonChange('게임중');
    }
}

해당 기능을 실행하는 함수를 버튼의 클릭 이벤트에 추가하여 줍니다.

button.addEventListener('click', run);

CountDown을 할 때에는 1초마다 시간을 줄이고 사용자에게 디스플레이하며 시간이 다되면 플레이를 멈추고 clearInterval을 통해 CountDown을 멈춥니다.

const countDown = () => {
    time > 0 ? time-- : isPlaying = false;
    timeDisplay.innerText = time;
    if(!isPlaying){
        clearInterval(timeInterval);
    }
}

현재 게임을 플레이 중인지에 대한 여부를 확인하는 함수도 시간이 다 됐거나 플레이 하지 않는다면 clearInterval을 통해 멈추며 버튼의 상태를 플레이할 수 있는 상태로 바꿉니다.
CountDown과 checkStatus를 분리하여 작동시키면 후에 기능을 추가할 때 유리할 수 있다고 합니다.

const checkStatus = () => {
    if(!isPlaying && time === 0){
        buttonChange("게임시작");
        clearInterval(checkInterval);
    }
}

1-3. Check Word

<body>
    ...
    <div class="word-display">
        Hello
    </div>
    <div class="word-input-box">
        <input type="text" class="word-input">
    </div>
    ...
</body>
.word-display {
    margin-top: 3rem;
    font-size: 80px;
    color: #3b5999;
}
.word-input-box{
    margin-top: 2rem;
}
.word-input{
    padding: 0.5rem;
    width: 300px;
}

단어를 입력받는 창에서 입력이 확인이 되면 게임 플레이중인지에 대한 여부와 현재 디스플레이 중인 단어와 같은지 확인하고 점수를 올릴지 말지 결정합니다.

단어의 대소문자 구별하지 않고 같음을 구별하기 위해 String의 toLowerCase() 함수를 사용하여 소문자로 만든 뒤 비교하는 방식을 사용하였습니다.

const checkWordMatch = () => {
    if(wordInput.value.toLowerCase() === wordDisplay.innerText.toLowerCase()){
        wordInput.value = "";
        // 게임 실행 중일 때 점수 관련 실행
        if(isPlaying){
            score++;
            scoreDisplay.innerText = score;
            time = GAME_TIME;
            const randomIndex = Math.floor(Math.random() * words.length);
            wordDisplay.innerText = words[randomIndex];
        }
    }
}

이를 입력 받을 때 마다 작동하도록 합니다.

wordInput.addEventListener('input', checkWordMatch);

0개의 댓글