Enemy Rain

SeungMin·2022년 7월 21일
0

WECODE

목록 보기
3/19

WWECODE 과정중에서 처음으로 개인 프로젝트를 해봤다.
솔직히 기본적인 파일셋이나 이미지는 WECODE 에서 제공하는
GIT REPOSITORY 에서 CLONE 으로 받아왔기 때문에
내가 특별히 한 것이라고는 JS 코딩밖에 없다.

필요 조건

  • Hero 클래스와 Ghost 클래스를 이용할 것
  • Ghost 클래스의 객체는 #bg의 최상단 , 영역 내 무작위 X축에서 등장.
  • Ghost 클래스의 객체는 일정 주기마다 생성됨.
  • Ghost 클래스의 모든 객체는 생성된 지점에서 시간이 지날수록 내려옴.
  • Hero 클래스의 객체와 Ghost 클래스의 객체가 부딫히면 1점을 얻고
    Ghost 클래스의 객체는 동시에 사망처리.
  • Hero 클래스의 객체와 Ghost 클래스의 객체가 부딫히지 않고,
    Ghost 클래스의 객체가 #bg 최하단에 닿는다면 점수발생 없이 사망처리.

추가한 조건

  • START 버튼을 누르면 게임이 시작되며 버튼이 비활성화됨.
  • 작성한 코드

// init.js
const bg = document.querySelector("#bg");
const start = document.querySelector("#start");
const superMan = new Hero("hero");

// START 를 누르면 시작 버튼이 비활성화 되며 게임 시작.
start.addEventListener("click", () => {
  document.querySelector("#score").innerHTML = 0;
  start.disabled = true;
  start.style.backgroundColor = "gray";
  start.style.color = "black";
  start.innerHTML = "RUNNING";

  // Hero Class의 객체를 통해 해당 클래스의 Method를 호출하여 클래스객체를 움직임.
  window.addEventListener("keydown", function (e) {
    if (e.key == "a") {
      superMan.moveHeroLeft();
    }
    if (e.key == "d") {
      superMan.moveHeroRight();
    }
    if (e.key == "w") {
      superMan.HeroTop();
    }
    if (e.key == "s") {
      superMan.HeroBottom();
    }
  });

  // 게임이 시작되자마자 첫번째 유령이 생성
  new Ghost("ghost");

  // 이후 5초마다 지속적으로 유령이 생성됨.
  const game = setInterval(() => {
    new Ghost("ghost");
  }, 5000);
});

//enemy.js
let killCount = 0;

class Ghost {
  constructor(id) {
    this.id = id;
    this.randomX = Math.ceil(Math.random() * 740);
    this.topXPosition = this.randomX;

    // Ghost Class 객체가 선언되며 생성자가 동작하면 동시에 ghost가등장.
    this.createGhost();

    // 생성된 ghost는 setInterval로 인해 지속적으로 아래로 내려감.
    this.Raining(superMan);
  }

  // 생성한 Ghost객체의 정보를 받아서 게임의 스테이지인 #bg에 append하는 함수.
  createGhost() {
    this.div = document.createElement("div");
    this.div.className = this.id;
    this.div.style.left = this.topXPosition + "px";
    bg.appendChild(this.div);
  }

  // ghost가 죽고나서 일정시간이 지나면 삭제하는 함수.
  cleaning() {
    setTimeout(() => (this.div.style.display = "none"), 1200);
  }

  // ghost가 지속적으로 떨어지게 만드는 함수
  // setinterval이 동작하며 반복적으로 각 객체의 top Value를 수정 , 적용한다.
  // ghost 와 hero 의 픽셀이 곂치게되면 (첫번째 if문의 조건), 
  // ghost의 background-position을 dead기준으로 변경하고 
  // Raining setInterval을 종료한다.
  Raining(heroName) {
    this.raining = 0;
    const intervalY = setInterval(() => {
      this.raining += 30;
      this.div.style.top = this.raining + "px";
      if (
        this.raining > 475 &&
        this.topXPosition <= heroName.moveLeft + 35 &&
        this.topXPosition >= heroName.moveLeft - 35
      ) {
        this.div.style.backgroundPosition = "-45px";
        clearInterval(intervalY);
        killCount++;
        document.querySelector("#score").innerHTML = killCount;
        this.cleaning();
      } else if (this.raining > 510) {
        this.div.style.backgroundPosition = "-45px";
        clearInterval(intervalY);
        this.cleaning();
      }
    }, 500);
  }
}

// hero.js
class Hero {
  constructor(name) {
    this.zeroPoint = 382.5;
    this.moveLeft = this.zeroPoint;
    this.name = name;
    this.faceup = -35;
    this.facedown = 0;
    this.faceleft = -70;
    this.faceright = -105;

    // Hero Class 객체가 선언되며 생성자가 동작하면 동시에 Hero가 등장.
    this.createHero();
  }

  // 생성한 Hero객체의 정보를 받아서 게임의 스테이지인 #bg에 append하는 함수.
  createHero() {
    this.hero = document.createElement("div");
    this.hero.className = this.name;
    this.hero.style.left = this.zeroPoint + "px";
    bg.appendChild(this.hero);
  }

  // A를 누르면 왼쪽으로 10px 움직이며 캐릭터가 왼쪽으로 회전.
  // 부모 요소인 #bg와의 좌측 거리가 0이되면 (left : 0px;) 조건 미달성으로 
  // 캐릭터의 방향만 변경되고 더이상 왼쪽으로 움직이지 않음.
  moveHeroLeft() {
    this.hero.style.backgroundPosition = this.faceleft + "px";
    if (this.moveLeft > 0) {
      this.moveLeft -= 10;
      this.hero.style.backgroundPosition = this.faceleft + "px";
      this.hero.style.left = this.moveLeft + "px";
    }
  }

  // D를 누르면 오른쪽으로 10px 움직이며 캐릭터가 오른쪽으로 회전.
  // 부모 요소인 #bg와의 우측 거리가 0이되면 (left : (800 - 45)px;) 조건 미달성으로 
  // 캐릭터의 방향만 변경되고 더이상 오른쪽으로 움직이지 않음.
  moveHeroRight() {
    this.hero.style.backgroundPosition = this.faceright + "px";
    if (this.moveLeft < 755) {
      this.moveLeft += 10;
      this.hero.style.backgroundPosition = this.faceright + "px";
      this.hero.style.left = this.moveLeft + "px";
    }
  }

  // 위 아래 움직임은 구현하지 않았음
  // W를 누르면 캐릭터가 위쪽을 바라봄.
  HeroTop() {
    this.hero.style.backgroundPosition = this.faceup + "px";
  }

  // 위 아래 움직임은 구현하지 않았음
  // S를 누르면 캐릭터가 아래쪽을 바라봄.
  HeroBottom() {
    this.hero.style.backgroundPosition = this.facedown + "px";
  }
}

이번 프로젝트로 새롭게 알게된 사실을 정리해보자

  • 사실 대부분의 웹사이트 이미지는 이미지를 불러오는 로딩시간을 단축하기 위해서
    여러가지 이미지가 하나의 파일로 되어있는 상태로 사용한다.
    그리고 해당 이미지의 크기는 부모 div 의 크기로 조절하며
    사용하고자 하는 이미지의 위치는 background-position 으로 조절한다.

  • class 의 생성자에 내부 함수를 this.method 의 형태로 삽입하여
    객체 생성과 동시에 함수를 실행시키는것이 가능하다.

  • setInterval 함수와 setTimeOut 함수를 사용해 봤다.
    내가 사용한 방법, 목적은 아주 단순하고 사용중에 있음에도 함수의 처리방식과 작동원리를 제대로 알지 못했다. 프로젝트 이후에 다시 곰곰히 이해해 봐야겠다.
    참고 - https://ko.javascript.info/settimeout-setinterval

  • 처음으로 나의 깃허브 저장소가 아닌 다른 저장소에서 CLONE 을 통해
    파일을 복사했다. 앞으로 깃을 자주 사용해서 점차 사용이 자연스러워지길
    기대해본다.

GIT HUB - https://github.com/pmb087/Enemy_Rain
HOSTING GAME - https://pmb087.github.io/Enemy_Rain/

profile
공부기록

0개의 댓글