Home 당근게임 시작!
Post
Cancel

당근게임 시작!

1. 당근게임 시작!

이 게임을 통해서 나는 또다시 한걸음, 아니 두세걸음 성장했다. 이 프로젝트는 겉으로 보기에 보잘것 없이 보이지만 내가 이 프로젝트를 하기 전과 후의 모습사이에 매우 상이한 차이가 존재한다. 우선 코드리뷰의 필요성을 절실히 느꼈고, 끈기와 겸손을 배웠다. 그외에 리팩토링하는 법, 그리고 로직을 구성하는 능력도 조금 오른것 같다. 맨 처음시작해서 완전히 완성되어 지금 이글을 쓰기까지 한달이라는 시간이 걸렸다.

한달간의 긴 여정동안 무엇을 배우고 느꼈는지 여기에 적어보려한다.

우선, 엘리님은 강의를 보기전에 본인 스스로 다 만들어볼것을 매우 권하셨다. 그래서 나혼자 만들기 시작했다. 우선 정적 웹페이지부터 구현하자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<head>
  <script
    src="https://kit.fontawesome.com/579c4d8c64.js"
    crossorigin="anonymous"
  ></script>
  <script src="./src/main.js" defer></script>
</head>
<body>
  <div id="background">
    <img src="./img/background.png" class="bg_image" />
  </div>
  <section class="top_ui">
    <div class="play_button_div">
      <audio src="./sound/calm.mp3" id="audio"></audio>
      <button class="play_button"><i class="fas fa-play"></i></button>
    </div>
    <div class="time_display">00:00</div>
    <span class="count">0</span>
  </section>

  <ul class="play_field"></ul>

  <div class="popup non_display">
    <button class="replay_btn"><i class="fas fa-reply-all"></i></button>
    <span></span>
  </div>
</body>

top_ui 안에 기본적으로 사용자가 컨트롤하고 확인하는 ui를 추가했다. 그리고 play_field를 만들어서 그 안에다가 icon이 display되도록 했다. 그리고 popup창을 non_display한다음 게임에서 졌을때 그리고 pause했을때 이 창이 뜨면서 사용자는 field안에 있는 아이콘을 클릭하지 못하게 했다.

또한, 아이콘을 받아오는 방법을 달리 해봤다. 다운받아서 파일에 넣은다음 src를 불러오는 local의 방식이 아닌, 아이콘을 외부에서 받아와서 바로 쓰는 방식으로 말이다.

fontawesome 이라는 웹사이트를 이용하면 된다. 자세한건 검색을 통해 쉽게 배울 수 있으니 굳이 여기에 서술하지는 않겠다.

2. 동적인 웹 구현하기 위한 로직 적어보기

우선 로직을 글로 쉽게 정리해보자.

  • top_ui 로직

1. 플레이 버튼을 누르면 안에 innerHtml이 바뀌면서 타이머가 시작되고 노래가 나옴.

2. 그리고 ul안에 캐릭터가 출력.

3. count가 나타남.

  • field 로직

1. random 함수를 쓴다음 transform을 이용해서 그 값을 pass하면 아이콘의 위치가 무작위로 배치됨.

  • 성공했을경우

1. 시간이 끝나기 전에 당근을 다 클릭했으면 시간 중지.

2. 재생버튼 없어짐.

3. 팝업창이 나타나면서 이겼다고 나옴.

4. 리플레이를 클릭하면 시작함수로 돌아감.

  • 실패했을경우

1. 타이머가 멈춤.

2. 팝업창이 뜨면서 실패했다고 메세지가 바뀜.

3. 리플레이버튼을 누르면 시작함수로 돌아감.

✨설명팝업도 만들어보기. 니코 홈피보고 만들어보기. 에니메이션도 넣어가면서

2-1. 구현 시작!(시간이 1초씩 줄어드는 함수)

만들면서 유난히 생각을 많이 하게한 함수만 설명하려고 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let count;
let intervalId;
let playFromTheVeryStart = true;

function decreasingCount() {
  if (count < 0) {
    audioBackground.pause();
    const audioLose = new Audio("./sound/game_lose.mp3");
    audioLose.play();
    popUp.classList.remove("non_display");
    playBtnDiv.style.visibility = "hidden";
    clearInterval(intervalId);
    gameResult.innerHTML = `Time out..😅 Wanna play again?`;
    playFromTheVeryStart = true;
    return;
  }
  const timeDisplay = document.querySelector(".time_display");
  timeDisplay.innerHTML = count <i 10 ? `00:0${count}` : `00:${count}`;
  --count;
  // console.log(count);
}

function startAgain() {
  clearInterval(intervalId);
  intervalId = setInterval(decreasingCount, 1000);
}

게임이 시작되면 시간함수가 초기화되고 다시 decreasingCount 함수가 1초마다 실행된다. 실행될때마다 카운트는 10에서 줄어들고, time에 표시된다. 카운트가 0이되면 게임이 종료된다.

2-2. 아이콘을 만들고 랜덤으로 배치하는 함수들

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function getRandomCoor(min, max) {
  var minV = Math.ceil(min);
  var maxV = Math.floor(max);
  return Math.random() * (maxV - minV) + minV;
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random 참고
}

function creatIcon(iconName, iconPath) {
  iconName.src = `./img/${iconPath}.png`;
  iconName.classList.add(`${iconPath}`);
  iconName.addEventListener("click", onIconButton);
  const playCoor = playField.getBoundingClientRect();
  var translateX = getRandomCoor(0, playCoor.right);
  var translateY = getRandomCoor(-35, playCoor.bottom - playCoor.top);
  iconName.style.transform = `translate(${translateX - 10}px,${translateY}px)`;
  return iconName;
}

function createCarrotIcon() {
  const imgCarrot = new Image();
  const carrotItems = creatIcon(imgCarrot, "carrot");
  return carrotItems;
}

function createBugIcon() {
  const imgBug = new Image();
  const bugItems = creatIcon(imgBug, "bug");
  return bugItems;
}

getRandomCoor에 들어가는 인자가 직관적이지 못하다. 그래도 일단 playfield 사이즈안에 아이템이 표시되도록 끼워맞췄다. 그리고 new Image를 creatIcon에 pass하여 하나씩 부품을 추가한 다음 완성된 부품을 리턴하는 방식으로 알고리즘을 짰다.

그럼 다음글에선 top_ui를 구현해보도록 하자.

This post is licensed under CC BY 4.0 by the author.