1. top_ui 리팩토링
gameControl.js 파일
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
'use strict';
import * as sound from './sound.js';
import Field from './playField.js';
export const FinishReason = Object.freeze({
win: 'win',
bug: 'bug',
timeout: 'timeout',
finalStageWin: 'finally',
});
export const StopReason = Object.freeze({
start: 'start',
pause: 'pause',
});
export class Game {
constructor(iconCount, gameDuration) {
this.iconCount = iconCount;
this.gameDuration = gameDuration;
this.gameDurationRefresh = gameDuration;
this.playBtn = document.querySelector('.play_button');
this.countSpan = document.querySelector('.count');
this.stage = document.querySelector('.stage');
this.clock = document.querySelector('.clock');
this.timeDisplay = document.querySelector('.time_display');
this.intervalId;
this.veryFirstStart = true;
this.field = new Field();
this.field.setIconClickEvent(this.fieldIconClick);
this.playBtn.addEventListener('click', event => {
if (this.veryFirstStart) {
this.startFromTheVeryFirst();
} else if (!this.veryFirstStart) {
if (this.pressedBtn(event) === 'fa-play') {
this.pauseToStart(StopReason.start);
} else if (this.pressedBtn(event) === 'fa-pause') {
this.startToPause(StopReason.pause);
}
}
});
}
// 여기도 바인딩? yep
startFromTheVeryFirst = () => {
// 와..... 이거이거 오래걸렸다.refresh랑 pausetostart랑 시간타이머가 겹쳐서 계속 오류났는데 이렇게 해결했다.
// 사실 기존에 time을 새로 설정했었는데 그걸 잘 생각했다면 이건 금방 생각해냈을텐데.
// 새로운 신박한걸 생각하지 말고 기존에 있는것을 토대로 어떻게 다시 재구성할지 생각하자.
this.veryFirstStart = false;
this.gameDuration = this.gameDuration;
this.startTimer();
this.showPlayBtn();
this.gameBtnChange('pause');
this.field.displayAllIcon(this.iconCount);
sound.playBgFromTheStart();
this.countCarrotFunc();
};
startToPause(reason) {
this.gameBtnChange('play');
sound.stopBgSound();
this.stopGameTimer();
this.onFinishBanner && this.onFinishBanner(reason);
}
pauseToStart(reason) {
this.gameBtnChange('pause');
sound.playBgSound();
this.startTimer();
//pause에서 start로 넘어갈때는 duration을 초기화하면 안됨
this.onFinishBanner && this.onFinishBanner(reason);
}
finish(reason) {
this.hidePlayBtn();
this.stopGameTimer();
sound.stopBgSound();
this.onFinishBanner && this.onFinishBanner(reason);
}
onFinishBannerEvent(func) {
this.onFinishBanner = func;
}
// 여기도 바인딩? yep
fieldIconClick = icon => {
if (icon === 'carrot') {
this.countCarrotFunc();
} else if (icon === 'bug') {
this.finish(FinishReason.bug);
//여기서도 '왜 배경음악중지가 없는데 배경음악이 중지될까?' 라는 의문이 들면 이전 알고리즘으로 차근차근 올라가보자
}
};
updateTimer(count) {
// let minutes = Math.floor(count / 60);
let seconds = count % 60;
this.timeDisplay.textContent = `00:${
seconds >= 10 ? seconds : `0${seconds}`
}`;
}
startTimer() {
this.updateTimer(this.gameDuration);
this.intervalId = setInterval(() => {
if (this.gameDuration <= 0) {
this.finish(FinishReason.timeout);
return;
} else {
this.updateTimer(--this.gameDuration);
this.clockRing(this.gameDuration);
}
}, 1000);
}
stopGameTimer() {
clearInterval(this.intervalId);
this.stopClockRing();
}
countCarrotFunc() {
const carrotCount = this.field.carrotCount.length;
if (carrotCount < 1) {
this.finish(FinishReason.win);
this.countSpan.innerHTML = carrotCount;
}
} else {
this.countSpan.innerHTML = carrotCount;
}
}
gameBtnChange(btn) {
let button;
switch (btn) {
case StopReason.start:
button = `<i class="fas fa-play"></i>`;
break;
case StopReason.pause:
button = `<i class="fas fa-pause"></i>`;
break;
default:
throw new Error('unvalid button');
}
this.playBtn.innerHTML = button;
}
showPlayBtn() {
this.playBtn.style.visibility = 'visible';
}
hidePlayBtn() {
this.playBtn.style.visibility = 'hidden';
}
pressedBtn(event) {
const whichBtn = event.target.classList[1];
return whichBtn;
}
}
top_ui와 관련된 모든 변수와 함수를 class안에 담았다. field 클래스를 불러와서 setIconClickEvent 함수에 this.fieldIconClick을 넘겨주었다. 넘겨줄때 역시 this는 자동으로 넘어가지 않으므로 arrow funciton 으로 만들어서 념겨주었다.
그리고 맨처음 시작하는 함수 / 시작->일시정지 함수/ 일시정시 -> 시작 함수/ 멈추는 함수 이렇게 나누었다. 그담에 finishReason, stopReason을 immutable한 객체로 만들었다. 말그대로 게임을 중지하는 함수에 string이 아닌 객체를 넘겨주어 직관성을 높이고 오타를 방지하기 위함이다.
그럼 main.js에 최종적으로 게임함수를 만들어 보자.