- 강의를 보지 않고 스스로 만들어 봤을 때 구현은 했으나 코드가 깔끔하지 않고 스파게티 처럼 꼬여간다는 것을 느꼈다.
- 나는 flag변수를 이용해 상태를 구분했지만 강의에서는 class에 따라 구분했는데 아주 깔끔했다 ! 그래서 class를 이용해 순서도를 다시그리고 코드를 짜 보았다.
대기화면은 2가지 경우인데
1. 게임시작 전 처음 시작화면과
2. 준비화면을 실수로 클릭했을 때 다시 대기화면으로 돌아간다
$screen.addEventListener("click", (e) => {
const className = $screen.className;
if (className === "waiting") {
showElement($progressBarContainer);
$screen.className = "ready";
startTimerForNow();
handleScreenText(message.ready.title, message.ready.description);
const showElement = (element) => {
element.style.opacity = "1";
};
const hideElement = (element) => {
element.style.opacity = "0";
};
element를 보여줬다 사라졌다 하는게 꽤 있어서 따로 함수로 빼 주었다
const message = {
waiting: {
title: "시작",
description: ` 총 기회는 5회 주어집니다.<br />다음 준비 화면에서 배경화면이 초록색이
되었을 때 클릭하시면 됩니다.<br />시작하시려면 현재 화면을
클릭해주세요.`,
},
ready: { title: "준비", description: "배경이 초록색이 되면 클릭해 주세요" },
now: { title: "클릭", description: "클릭해주세요" },
};
handleScreenText(message.ready.title, message.ready.description);
object를 사용해 보고 싶어서 화면에 따라(class에 따라) 보여줘야 될 title과 descripttion을 object로 만들어서 함수에 전달해 주었다.
const startTimerForNow = () => {
setTimeOutId = setTimeout(() => {
$screen.className = "now";
handleScreenText(message.now.title, message.now.description);
startTime = new Date();
}, Math.random() * 1000 + 2000);
};
- 클릭시 준비화면으로 바로 바꾸고 타이머를 작동해 준다
- 2-3초 사이의 랜덤시간 후 클릭화면으로 바꿔준다
- 클릭화면으로 바꿨을 때의 시간을 저장해준다
- startTime과 endTime은 이곳저곳에서 쓸 것 이기 때문에 전역으로 선언해둔다
else if (className === "ready") {
//대기화면 전환 - 성급했다고 보여주기
clearTimeout(setTimeOutId);
$screen.className = "waiting";
$screenTitle.textContent = "준비화면에서는 클릭이 불가합니다";
$screenDescription.textContent = "클릭하시면 다시 준비화면으로 돌아갑니다";
}
준비화면을 실수로 클릭하면 대기화면으로 돌아가는데
!! 실행했던 타이머를 제거해 줘야 버그가 생기지 않는다
그렇지 않으면 대기화면일 때 타이머가 끝나 갑자기 클릭화면으로 넘어가거나
대기화면 - > 준비화면을 거쳐 타이머가 2번 실행될 수 있다
else if (className === "now") {
attempt++;
endTime = new Date();
const result = endTime - startTime;
reactionRates.push(result);
const average = Math.floor(
reactionRates.reduce((pre, cur) => pre + cur, 0) / reactionRates.length
);
showResultAndAverage(result, average);
updateProgressBar();
if (attempt >= opportunity) {
finishGame(average);
return;
}
handleScreenText(message.ready.title, message.ready.description);
$screen.className = "ready";
startTimerForNow();
}
- progrss-bar를 다뤄주고 게임 종료시켜주기 위해 attempt를 전역으로 선언해 준다
= > 클릭화면에서 클릭했을 땐 성공한 것이므로 증가시켜주고 = > 화면에 보여준다- 클릭한 시간을 변수(endTime)에 할당해주고 반응속도를 계산해준다
- 평균을 구해줘야 하기 때문에 계산값을 전역변수인 배열에 넣어주고 평균을 계산해준다 = > 화면에 보여준다
- 준비화면으로 바꾸기 전에 5번을 진행했는지 확인해준다 ===말고 >=를 사용해 버그가 생기지 않게 범위를 넓혀준다
- 전역에서 const 로 설정한 횟수(const opportunity=5)보다 작으면 다시 준비화면으로 돌아가고 타이머를 작동시켜준다
const startGame = () => {
playing = true;
$screen.className = "waiting";
handleScreenText(message.waiting.title, message.waiting.description);
hideElement($replayBtn);
updateProgressBar();
};
const reset = () => {
reactionRates = [];
$result.textContent = "";
attempt = 0;
};
const finishGame = (average) => {
playing = false;
$screen.className = "finished";
const title = "결과";
const description = `평균 ${average}ms`;
handleScreenText(title, description);
showElement($replayBtn);
hideElement($progressBarContainer);
reset();
};
- 게임이 끝나면 최종평균을 보여주는 결과화면을 보여준다
- progress-bar를 숨기고 replay button을 활성화 시켜준다
- 데이터들을 reset시킨다
const startGame = () => {
playing = true;
$screen.className = "waiting";
handleScreenText(message.waiting.title, message.waiting.description);
hideElement($replayBtn);
updateProgressBar();
};
페이지 로딩했을 때, replay-button을 눌렸을때 게임을 실행시켜줄 함수를 따로 만든다
출처 Let's get it 자바스크립트 프로그래밍