Recent Posts
Recent Comments
«   2024/07   »
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
Today
Total
관리 메뉴

DH의 개발 공부로그

[TypeScript] JavaScript 슈팅게임에 TypeScript 적용하기! #4 - 이미지 부분 변환하기! 본문

TypeScript

[TypeScript] JavaScript 슈팅게임에 TypeScript 적용하기! #4 - 이미지 부분 변환하기!

DeveloperDH 2023. 2. 24. 22:18
728x90

타입스크립트로 변환하기!

// 기존 코드
loadImage() {
    this.backgroundImage = new Image();
    this.backgroundImage.src = "./images/background.gif";

    this.bulletImage = new Image();
    this.bulletImage.src = "./images/bullet.png";

    this.spaceShipImage = new Image();
    this.spaceShipImage.src = "./images/space-ship.png";

    this.monsterImage = new Image();
    this.monsterImage.src = `./images/meteor.png`;

    this.gameOverImage = new Image();
    this.gameOverImage.src = "./images/gameover.png";
  }
  renderImage() {
    const { ctx, spaceShip, canvas } = this;
    ctx.drawImage(this.backgroundImage, 0, 0, canvas.width, canvas.height);

    for (let i = 0; i < bulletList.length; i++) {
      if (bulletList[i].alive) {
        ctx.drawImage(this.bulletImage, bulletList[i].x, bulletList[i].y);
      }
    }

    ctx.drawImage(this.spaceShipImage, spaceShip.x, spaceShip.y);

    for (let i = 0; i < monsterList.length; i++) {
      ctx.drawImage(this.monsterImage, monsterList[i].x, monsterList[i].y);
    }

    ctx.fillText(`Score : ${score}`, 20, 30);
    ctx.fillStyle = "white";
    ctx.font = "1rem 맑은 고딕";
  }

loadImage()

loadImage()renderImage()로 이루어진 자바스크립트 코드로 슈팅게임에 필요한 이미지들을 구현을 했었는데,
이 코드를 타입스크립트로 옮기면 오류가 발생하게 됩니다.

우선 오류의 내용들은 Property 'backgroundImage' does not exist on type 'Game'와 같이
backgroundImage, bulletImage, spaceShipImage, monsterImage, gameOverImageGame에 선언되어있는 속성이 아니라는 것이었고,
그래서 선언을 해주는 것으로 문제를 간단하게 해결했습니다.

class Game {
  private canvas: HTMLCanvasElement;
  private ctx: CanvasRenderingContext2D;
  private spaceShip?: SpaceShip | null 
  private backgroundImage?: HTMLImageElement
  private bulletImage?: HTMLImageElement
  private spaceShipImage?: HTMLImageElement
  private meteorImage?: HTMLImageElement
  private gameOverImage?: HTMLImageElement

  constructor() {...}
}

renderImage()

위의 코드를 선언을 하고 나면 loadimage에서는 오류가 해결이 되지만 renderImage에서는 오류가 해결이 되지 않습니다.
바로 다음과 같은 오류입니다.

Argument of type 'HTMLImageElement | undefined' is not assignable to parameter of type 'CanvasImageSource'.
Type 'undefined' is not assignable to type 'CanvasImageSource'

이 오류는 위의 이미지들을 optional로 선언했기 때문에 이미지들이 HTMLImageElement일 수도 있지만,
undefined일 수도 있기 때문에 코드의 실행을 못한다고 해석을 할 수 있습니다.

따라서 Narrowing해주어야 합니다.
Narrowing의 방법에는 여러가지가 있지만 이번 코드에서는 instanceof를 사용을 했습니다.

renderImage() {
  const { ctx, spaceShip, canvas, backgroundImage, bulletImage, spaceShipImage, meteorImage } = this;

  if (backgroundImage instanceof HTMLImageElement) {
    ctx.drawImage(backgroundImage, 0, 0, canvas.width, canvas.height);
  }

  for (let i = 0; i < bulletList.length; i++) {
    if (!bulletList[i].alive) {
      return;
    }
    if (bulletImage instanceof HTMLImageElement) {
      ctx.drawImage(bulletImage, bulletList[i].x, bulletList[i].y);
    }
  }

  if (spaceShipImage instanceof HTMLImageElement
      && spaceShip instanceof SpaceShip) {
    ctx.drawImage(spaceShipImage, spaceShip.x, spaceShip.y);
  }

  for (let i = 0; i < meteorList.length; i++) {
    if (meteorImage instanceof HTMLImageElement) {
      ctx.drawImage(meteorImage, meteorList[i].x, meteorList[i].y);
    }
  }

  ctx.fillText(`Score : ${score}`, 20, 30);
  ctx.fillStyle = "white";
  ctx.font = "1rem 맑은 고딕";
}
728x90
Comments