어제까지 ES6를 이용한 클래스를 생성하여 정리를 하였다면, 이제는 배운 클래스를 조잡하지만 적용 해 보는 단계를 가지려고 한다. 그리하여 Enemy Rain이라는 간단한 게임(게임이라고 하기엔 너무 구현이 허접하긴 하다.)을 만들어 보기로 하였다. 조건은 아래와 같다.
- 히어로를 가운데에서 시작하도록.
- 히어로에 좌우로 key event
- 바탕화면 끝에 도달하면 히어로 못 움직이게 하기.
- 귀신이 하늘에서 시작하도록.
- Random한 x 위치에서 나오게 하기.
- setInterval을 활용해 귀신 시작위치에서 y값을 아래로 떨어뜨리기.
얼핏 보면 간단해 보이지만, 클래스를 처음 사용해볼 필자에겐 엄청난 도전이었다!!!
조잡해 보이는 저 애니메이션을 구현하기 위해 하루종일 삽질을 경험했다......갈길이 멀다
처음에는 귀신을 화면 하단으로 떨어뜨리는 방법부터 알아야 했기에, 클래스로 바로 작성하지 않고 함수로 먼저 귀신 한마리를 임의의 x값에서 떨어뜨리도록 코드를 작성했다.
const enemy = (() => {
//귀신 태그 및 CSS 상속을 위한 ID 부여
const creatEnemy = document.createElement('div');
creatEnemy.id = 'enemy';
document.body.insertAdjacentElement('afterbegin',creatEnemy);
document.getElementById('enemy').style.top = '6%';
//임의의 x값에서 시작.
document.getElementById('enemy').style.left = `${15+(Math.random() * 60)}%`
//귀신 떨어뜨리기 시작
const dropEnemy = setInterval(() => {
const getEnemy = document.getElementById('enemy');
let temp = getEnemy.style.top;
let top = temp.slice(0,temp.length-1);
getEnemy.style.top = `${Number(top) +1.5}%`
if(Number(getEnemy.style.top.slice(0,2)) >= 76){
console.log(Number(getEnemy.style.top.slice(0,2)))
//귀신 죽은 이미지 구현
getEnemy.style.background = `url('./images/enemy.png') 46px`;
clearInterval(dropEnemy);
//귀신이 바닥에 닿고 1초뒤에 제거.
setTimeout(() => {
console.log('1',document.getElementById('enemy'))
document.getElementById('enemy').remove();
},1000);
}
},300);
})();
한마리를 떨어뜨리는데 성공하였다!!!!
하지만 상기 함수형으로는 여러마리를 떨어뜨리는데 문제가 있다. 여러마리를 2초마다 떨어뜨리고 싶었던 나는 멘토님의 도움을 받아 마침내 클래스로 완성하였다!!!
//Enemy class 생성자
class Enemy {
//매번 새로운 enemy 생성
constructor(creatEnemy) {
this.creatEnemy = document.createElement('div');
this.className = creatEnemy;
this.creatEnemy.className = creatEnemy;
this.creatEnemy.classList.add('enemy');
}
placeEnemy = () => {
document.body.insertAdjacentElement('afterbegin', this.creatEnemy);
}
setTopDefault = () => {
document.getElementsByClassName(this.className)[0].style.top = '6%';
}
spawnRandom = () => {
const enemyClass = document.getElementsByClassName(this.className);
for (let i = 0; i < enemyClass.length; i++) {
document.getElementsByClassName(this.className)[i].style.left = `${15 + (Math.random() * 60)}%`
}
}
dropEnemy =
setInterval(() => {
for (let i = 0; i < document.getElementsByClassName(this.className).length; i++) {
let getEnemy = document.getElementsByClassName(this.className)[i];
let temp = getEnemy.style.top;
let top = temp.slice(0, temp.length - 1);
getEnemy.style.top = `${Number(top) + 1.5}%`
if (Number(getEnemy.style.top.slice(0, 2)) >= 76) {
console.log(Number(getEnemy.style.top.slice(0, 2)))
getEnemy.style.background = `url('./images/enemy.png') 46px`;
clearInterval(this.dropEnemy);
setTimeout(() => {
console.log('1', getEnemy)
getEnemy.remove();
}, 1000)
}
}
}, 300);
}
//임의의 i값을 부여하여 enemy 투하!!
let i = 0;
const enemyRain = setInterval(() => {
const newEnemy = new Enemy(`new${i}`);
newEnemy.placeEnemy();
newEnemy.setTopDefault();
newEnemy.spawnRandom();
i++;
}, 2000);
사실 클래스로 변환하면서 여러가지 버그를 만들어냈는데, 예리 멘토님이 없었으면 해결하지 못했을 것이다....
아직도 갈길이 멀다는 것을 뼈저리게 깨달으며 이렇게 반성문을 끝내도록 하겠다.