반응속도 테스트

.·2021년 8월 1일
0
post-thumbnail

스스로 구현했을 때

  • 강의를 보지 않고 스스로 만들어 봤을 때 구현은 했으나 코드가 깔끔하지 않고 스파게티 처럼 꼬여간다는 것을 느꼈다.
  • 나는 flag변수를 이용해 상태를 구분했지만 강의에서는 class에 따라 구분했는데 아주 깔끔했다 ! 그래서 class를 이용해 순서도를 다시그리고 코드를 짜 보았다.

class를 활용해 핵심로직 분리하기

  1. 대기화면을 클릭했을 때
  2. 준비화면을 클릭했을 때
  3. 클릭화면을 클릭했을 때

1. 대기화면을 클릭했을 때

대기화면은 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);
  • 대기화면을 클릭했을 때(게임시작할 때) progress bar를 보여준다
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로 만들어서 함수에 전달해 주었다.

대망의 setTimeout

const startTimerForNow = () => {
  setTimeOutId = setTimeout(() => {
    $screen.className = "now";
    handleScreenText(message.now.title, message.now.description);
    startTime = new Date();
  }, Math.random() * 1000 + 2000);
};
  1. 클릭시 준비화면으로 바로 바꾸고 타이머를 작동해 준다
  2. 2-3초 사이의 랜덤시간 후 클릭화면으로 바꿔준다
  3. 클릭화면으로 바꿨을 때의 시간을 저장해준다
  • startTime과 endTime은 이곳저곳에서 쓸 것 이기 때문에 전역으로 선언해둔다

2. 준비화면 클릭시

else if (className === "ready") {
    //대기화면 전환 - 성급했다고 보여주기
    clearTimeout(setTimeOutId);
    $screen.className = "waiting";
    $screenTitle.textContent = "준비화면에서는 클릭이 불가합니다";
    $screenDescription.textContent = "클릭하시면 다시 준비화면으로 돌아갑니다";
  } 

준비화면을 실수로 클릭하면 대기화면으로 돌아가는데

!! 실행했던 타이머를 제거해 줘야 버그가 생기지 않는다

그렇지 않으면 대기화면일 때 타이머가 끝나 갑자기 클릭화면으로 넘어가거나
대기화면 - > 준비화면을 거쳐 타이머가 2번 실행될 수 있다

3. 클릭화면 클릭시

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();
  }
  1. progrss-bar를 다뤄주고 게임 종료시켜주기 위해 attempt를 전역으로 선언해 준다
    = > 클릭화면에서 클릭했을 땐 성공한 것이므로 증가시켜주고 = > 화면에 보여준다
  2. 클릭한 시간을 변수(endTime)에 할당해주고 반응속도를 계산해준다
  3. 평균을 구해줘야 하기 때문에 계산값을 전역변수인 배열에 넣어주고 평균을 계산해준다 = > 화면에 보여준다
  4. 준비화면으로 바꾸기 전에 5번을 진행했는지 확인해준다 ===말고 >=를 사용해 버그가 생기지 않게 범위를 넓혀준다
  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();
};
  1. 게임이 끝나면 최종평균을 보여주는 결과화면을 보여준다
  2. progress-bar를 숨기고 replay button을 활성화 시켜준다
  3. 데이터들을 reset시킨다

게임 시작하기

const startGame = () => {
  playing = true;
  $screen.className = "waiting";
  handleScreenText(message.waiting.title, message.waiting.description);
  hideElement($replayBtn);
  updateProgressBar();
};

페이지 로딩했을 때, replay-button을 눌렸을때 게임을 실행시켜줄 함수를 따로 만든다

출처 Let's get it 자바스크립트 프로그래밍

profile
Divde & Conquer

0개의 댓글