JavaScript로 게임 만들기 - 8

Fantazindy·2022년 4월 12일
1

JSFightGame

목록 보기
8/12

캐릭터 이미지를 넣어보자.
캐릭터는 Fighter클래스로 생성해주고 있는데 캐릭터 애니메이션을 사용하기 위해선 이전 Sprite에 사용했던 프로퍼티들이 필요하다.
Sprite를 extend하고 파라미터를 추가해주고 필요한 프로퍼티들을 추가해 사용할 수 있게 해주자.

class Fighter extends Sprite {
  constructor({
    position,
    velocity,
    color,
    offset,
    imageSrc,
    scale = 1,
    framesMax = 1,
  }) {
    super({
      position,
      imageSrc,
      scale,
      framesMax,
    });

    this.velocity = velocity;
    this.width = 50;
    this.height = 150;
    this.lastKey;
    this.attackBox = {
      position: {
        x: this.position.x,
        y: this.position.y,
      },
      offset,
      width: 100,
      height: 50,
    };
    this.color = color;
    this.isAttacking;
    this.health = 100;
    this.framesCurrent = 0;
    this.framesElapsed = 0;
    this.framesHold = 10;
  }

super의 안에는 Sprite에만 존재하는 프로퍼티들을 써주면 된다(기존 Fighter의 position은 지워줬다).
frame관련 프로퍼티들은 따로 필요하므로 별도 추가하였다.

기존에 사각형을 그려주던 Fighter클래스 내 draw메소드는 필요 없으니 지워주자.

그리고 index.js에서 캐릭터 이미지 경로를 지정해주고 shop과 동일하게 frameMax와 scale을 지정해주면

const player = new Fighter({
  position: {
    x: 0,
    y: 0,
  },
  velocity: {
    x: 0,
    y: 0,
  },
  color: "green",
  offset: {
    x: 0,
    y: 0,
  },
  imageSrc: "./img/samuraiMack/Idle.png",
  framesMax: 8,
  scale: 2.5,
});


캐릭터 이미지가 잘 나타나긴 하지만 위치가 어색한데 캐릭터 이미지 주변에 여백이 있기 때문이다.
이전 캐릭터의 공격범위를 지정했을때와 유사하게 offset을 사용해서 해결할 것이다.
Sprite에 프로퍼티와 아규먼트로 offset을 추가하고 Fighter의 프로퍼티에도 추가한다.

class Sprite {
  constructor({
    ...
    offset = { x: 0, y: 0 },
  }) {
    ...
    this.offset = offset;
  }
...
class Fighter extends Sprite {
  constructor({
    ...
    offset = { x: 0, y: 0 },
  }) {
    super({
      ...
      offset
    });

그리고 offset값을 추가하면

const player = new Fighter({
  ...
  offset: {
    x: 215,
    y: 157,
  },
});


위치가 잘 잡힌듯 하다.
아직 애니메이션이 동작하지 않는데 이를 해결해보자
Sprite의 update의

	this.framesElapsed++;
    if (this.framesElapsed % this.framesHold === 0) {
      if (this.framesCurrent < this.framesMax - 1) {
        this.framesCurrent++;
      } else {
        this.framesCurrent = 0;
      }
    }

이 부분이 애니메이션을 구현하는 조건문이었다.
이걸 추가하면 되는데 좀 더 보기 편하게 animateFrames메소드를 새로 만들어 위 내용을 붙여넣고 animateFrames만 가져다 쓰는 식으로 하면

  animateFrames() {
    this.framesElapsed++;
    if (this.framesElapsed % this.framesHold === 0) {
      if (this.framesCurrent < this.framesMax - 1) {
        this.framesCurrent++;
      } else {
        this.framesCurrent = 0;
      }
    }
  }
  
    update() {
    this.draw();
    this.animateFrames();
  }

더욱 간편하게 코드를 관리할 수 있다.
아래 Fighter클래스의 update에도 해당 메소드를 추가하면

  update() {
    this.draw();
    this.animateFrames();

    this.attackBox.position.x = this.position.x - this.attackBox.offset.x;
    this.attackBox.position.y = this.position.y;

    this.position.x += this.velocity.x;
    this.position.y += this.velocity.y;

    if (this.position.y + this.height + this.velocity.y >= canvas.height - 95) {
      this.velocity.y = 0;
    } else this.velocity.y += gravity;
  }


정지상태일 때 캐릭터가 움직인다.
그런데 조작키가 먹히지 않는데 enemy쪽 코드에 에러가 발생해서 그렇다.
enemy쪽 코드는 나중에 수정하기로 하고 잠시 코멘트 처리 해두자.

function animate() {
  window.requestAnimationFrame(animate);
  c.fillStyle = "black";
  c.fillRect(0, 0, canvas.width, canvas.height);
  background.update();
  shop.update();
  player.update();
  // enemy.update();

지금은 캐릭터의 움직임이 너무 단조로운데 다음 포스팅에선 캐릭터의 다른 동작 애니메이션을 추가해보자

profile
풀스택 개발자를 목표로 성장중입니다!

0개의 댓글