result.jsλΌλ νμΌμ λ°λ‘ λ§λ€μ΄μ resultμ κ΄λ ¨λ μ½λλ₯Ό μ΄κ³³μ μ μ΄μ€λ€. srcλΌλ ν΄λμ result.jsμ main.jsλ₯Ό ν¨κ» λ£μ΄ κ΄λ¦¬νλ€. HTML νμΌμ script μ½λ λΆλΆμ type="module"μ μ λλ€.
result.jsμμ Result λΌλ classλ₯Ό μ μΈνλ€.
constructor ν¨μ
λ₯Ό ν΅ν΄ result ν΄λμ€μ λ©€λ² λ³μ
λ₯Ό λ§λ€μ΄μ€λ€. νμν DOM μμλ₯Ό κ°μ§κ³ μμ κ·Έ μμ thisλ₯Ό μ μ΄μ€λ€. μ¬κΈ°μ thisλ Result ν΄λμ€ κ°μ²΄λ₯Ό μλ―Ένλ€.
π setClickListener λ©μλλ₯Ό λ±λ‘ν΄μ€λ€. onClickμ΄λΌλ μ½λ°± ν¨μλ₯Ό Result ν΄λμ€μ onClickμ΄λΌλ λ©€λ² λ³μμ ν λΉνλ€.
π onClick λ©€λ² λ³μκ° trueλΌλ©΄(λ±λ‘λ μ½λ°± ν¨μκ° μμΌλ©΄) κ·Έκ²μ μ€ννλ€.
Result ν΄λμ€ μμ export default λ₯Ό μ μ΄μ λ€λ₯Έ νμΌμμλ Result ν΄λμ€λ₯Ό μ½μ μ μλλ‘ ν΄μ€λ€.
'use strict';
export default class Result {
constructor () {
this.gameResult = document.querySelector('.result');
this.replayBtn = document.querySelector('.replayBtn');
this.notice = document.querySelector('.notice');
this.replayBtn.addEventListener('click', () => {
this.onClick && this.onClick(); // π
this.hide();
});
}
setClickListener (onClick) { // π
this.onClick = onClick;
}
show (text) {
this.gameResult.style.display = 'block';
this.notice.innerHTML = text;
}
hide () {
this.gameResult.style.display = 'none';
}
}
νμΌ μμ import Result from './result.js'; λΌκ³ μ μ΄μ€λ€.
Result ν΄λμ€λ₯Ό μ΄μ©ν΄ gameFinishBannerλΌλ κ°μ²΄
λ₯Ό μμ±ν΄μ€λ€. κ·Έλ₯ resultλΌκ³ μ°μ§ λ§κ³ , μ νν μ΄κ² μ΄λ€ κ±΄μ§ μ€λͺ
ν΄μ£Όλ μ΄λ¦μ μ°λλ‘ νλ€.
gameFinishBannerμ setClickListener λ©μλλ₯Ό λ±λ‘ν΄μ€λ€. μ΄λ‘ μΈν΄ ν΄λ¦μ΄ λλ©΄ startGame ν¨μκ° νΈμΆλλ€.
const gameFinishBanner = new Result();
gameFinishBanner.setClickListener(() => {
startGame();
});
/*
gameFinishBanner.setClickListener(() => startGame());
gameFinishBanner.setClickListener(startGame);
λͺ¨λ κ°μ λ»μ΄λ€.
*/
field.jsμμ Field λΌλ classλ₯Ό μ μΈνλ€.
constructor ν¨μλ₯Ό ν΅ν΄ field ν΄λμ€μ λ©€λ² λ³μλ₯Ό λ§λ€μ΄μ€λ€. fieldμ ν΄λ¦ μ΄λ²€νΈλ₯Ό λ±λ‘νμ¬ field ν΄λ¦ μ field ν΄λμ€μ λ©€λ² λ©μλμΈ onClick ν¨μκ° νΈμΆλλλ‘ μ μ΄μ€λ€.
π‘ thisμ λ°μΈλ© νλ λ°©λ²
class λ©€λ² ν¨μ
κ° λ€λ₯Έ ν¨μ μΈμλ‘ μ λ¬λ λλ, thisμ κ·Έ classμ μ λ³΄κ° μ μ§λμ§ μλλ€. λ°λΌμ μλμ κ°μ΄ μμ±νλ©΄, onClick ν¨μ λ³Έλ¬Έ(μλ field.js μ 체 μ½λ μ°Έκ³ )μμ this.onItemClick κ°μ΄ νμ undefinedκ° λμ΄ μ½λκ° μλν λλ‘ μ€νλμ§ μλλ€.this.field.addEventListener('click', this.onClick); // (x)
- μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ μλ 3κ°μ§ λ°©λ²μ μ¬μ©ν μ μλ€.
νμ΄ν ν¨μμμ this
λ μΈμ λ νμ΄ν ν¨μμμ μ€μ½νμ thisλ₯Ό κ°λ¦¬ν€λ
μ μ μ΄μ©ν΄ μμ±ν΄λΌ.β νμ΄ν ν¨μ μ΄μ© β
this.field.addEventListener('click', (event) => this.onClick(event));
β νμ΄ν ν¨μ μ΄μ© β‘
// μ΄λ κ² μ μλ onClick ν¨μλ₯Ό onClick (event) { } // μ΄λ κ² λ°κΎΌλ€ onClick = (event) => { }
β bind λ©μλ μ΄μ©
this.onClick = this.onClick.bind(this); this.field.addEventListener('click', this.onClick);
Field ν΄λμ€λ started, timer, limit λ± κ²μ μ§ν μνμ κ΄ν μ 보λ μ²λ¦¬ν μ μλ€. μλ fieldμμ μΌμ΄λ¬λ μ΄λ―Έμ§ λλ€ λ°°μΉ & ν΄λ¦ μ΄λ²€νΈμ κ΄λ ¨λ λΆλΆλ§
main.js μ½λμμ κ°μ Έμ¨λ€. classμ λ©€λ² λ³μλ λ©€λ² λ©μλλ‘ μ μλ κ²λ€μ΄λΌλ©΄, μμ thisλ₯Ό λΆμΈλ€.
class λ΄μ©κ³Ό μκ΄μλ λ°°κ²½ μμ μ¬μ ν¨μ λ±μ λ©λͺ¨λ¦¬ λλΉλ₯Ό λ§κΈ° μν΄ class λ°μΌλ‘ λΉΌμ μ¨μ€λ€. (μΆν μμ ν λΆλΆ)
onClick ν¨μμ if else if ꡬ문μμ this.onItemClick ν¨μκ° μ€νλ λ κ°κ° carrotκ³Ό bugλ₯Ό μΈμλ‘ μ£Όμ΄ κ΅¬λΆλλλ‘ νλ€.
'use strict';
// μ μ λ³μλ€
const CARROT_SIZE = 120;
const BUG_SIZE = 80;
const carrotSound = new Audio('sound/carrot_pull.mp3');
// field ν΄λμ€
export default class Field {
constructor (carrotCount, bugCount) {
this.carrotCount = carrotCount;
this.bugCount = bugCount;
this.field = document.querySelector('.field');
this.fieldRect = this.field.getBoundingClientRect();
this.field.addEventListener('click', (event) => this.onClick(event));
}
// μ΄λ―Έμ§ λλ€ λ°°μΉ
init () {
this.field.innerHTML = '';
this._makeImg('carrot', this.carrotCount, 'img/carrot.png', CARROT_SIZE);
this._makeImg('bug', this.bugCount, 'img/bug.png', BUG_SIZE);
}
// μ΄λ―Έμ§ μμ±
_makeImg (name, count, src, size) { // μ΄ νμΌμμλ§ λΆλ¦΄ ν¨μ μμ _ νμλ₯Ό λΆμΈλ€
for (let i = 0; i < count; i++) {
const item = document.createElement('img');
item.setAttribute('class', `${name}`);
item.setAttribute('src', `${src}`);
const coord = this._randomCoord(size);
item.style.left = coord[0] + 'px';
item.style.top = coord[1] + 'px';
item.style.width = size + 'px';
this.field.appendChild(item);
}
}
// λλ€ μ’ν μμ±
_randomCoord (size) {
return [ ( this.fieldRect.width - size ) * Math.random(),
( this.fieldRect.height - size ) * Math.random() ];
}
// μ½λ°± ν¨μλ₯Ό class κ°μ²΄μ λ³μμ ν λΉ
setClickListener (onItemClick) {
this.onItemClick = onItemClick;
}
// fieldμ ν΄λ¦ μ΄λ²€νΈ 리μ€λ
onClick (event) {
const target = event.target;
if (target.matches('.carrot')) {
target.remove();
playSound(carrotSound);
this.onItemClick && this.onItemClick('carrot');
} else if (target.matches('.bug')) {
this.onItemClick && this.onItemClick('bug');
}
}
}
// λ°°κ²½ μμ
μ¬μ ν¨μ
function playSound (sound) {
sound.currentTime = 0;
sound.play();
}
field.jsμ onClick ν¨μμ μλ μ΄λ―Έμ§ μμ λ μμ μ¬μμ main.jsμ onFieldItemClick ν¨μμ μ μ§ μμλ€.
initGame ν¨μμ κΈ°μ‘΄μ init() λμ gameField.init()μ μ μ΄μ£Όμλ€.
const gameField = new Field(CARROT_COUNT, BUG_COUNT);
gameField.setClickListener(onFieldItemClick);
function onFieldItemClick (item) {
if (!started) {
return;
}
if (item === 'carrot') {
showGameLimit(--limit);
if (limit === 0) {
finishGame(true);
}
} else if (item === 'bug') {
finishGame(false);
}
}