─━ IT ━─

Vue.js로 벽돌깨기 게임 개발하기 - 단계별 가이드

DKel 2024. 10. 31. 23:29
반응형

Vue.js를 사용하여 간단한 벽돌깨기 게임을 개발하는 방법을 상세히 설명하겠습니다. 벽돌깨기 게임은 사용자가 패들을 움직여 공을 튀겨 벽돌을 깨는 고전적인 아케이드 게임입니다. 이 게임을 구현하면서 Vue.js의 기본 기능과 HTML5 Canvas API를 활용하는 방법도 배울 수 있습니다.

 

## 1. 프로젝트 설정

 

우선, Vue CLI를 사용하여 새로운 Vue 프로젝트를 생성합니다. 

 

```bash

vue create brick-breaker

cd brick-breaker

npm run serve

```

 

프로젝트가 생성되고 서버가 시작되면 브라우저에서 기본 페이지를 볼 수 있습니다.

 

## 2. 컴포넌트 구조 설계

 

우리는 단일 파일 컴포넌트 구조를 사용하여 앱을 구성할 것입니다. 먼저 `src/components` 디렉토리에 `Game.vue` 파일을 생성합니다. 이 컴포넌트는 게임의 기본 뷰가 될 것입니다.

 

**Game.vue**

 

```html

<template>

  <div id="game" ref="gameContainer">

    <canvas ref="gameCanvas"></canvas>

  </div>

</template>

 

<script>

export default {

  name: 'Game',

  mounted() {

    this.initializeGame();

  },

  methods: {

    initializeGame() {

      const canvas = this.$refs.gameCanvas;

      const context = canvas.getContext('2d');

      canvas.width = 480;

      canvas.height = 320;

      

      // 초기 공, 패들 및 벽돌 설정

      // 예: 공의 위치, 패들을 그리기 위한 코드 추가

    }

  }

}

</script>

 

<style>

#game {

  display: flex;

  justify-content: center;

  align-items: center;

  height: 100vh;

}

canvas {

  background-color: #eee;

}

</style>

```

 

## 3. 게임 로직 구현

 

공과 패들, 벽돌의 이동 및 충돌을 처리하는 게임 로직을 구현합니다. 여기서는 간단한 물리 법칙과 충돌 감지를 설정합니다.

 

**Example Code for Ball Movement**

 

```js

data() {

  return {

    ball: {

      x: 240, // canvas의 가운데

      y: 160,

      dx: 2,

      dy: -2,

      radius: 10

    }

  };

},

methods: {

  drawBall(context) {

    context.beginPath();

    context.arc(this.ball.x, this.ball.y, this.ball.radius, 0, Math.PI * 2);

    context.fillStyle = '#0095DD';

    context.fill();

    context.closePath();

  },

  updateBall() {

    // 충돌 확인 및 위치 업데이트

    if (this.ball.x + this.ball.dx > 480 - this.ball.radius || this.ball.x + this.ball.dx < this.ball.radius) {

      this.ball.dx = -this.ball.dx;

    }

    if (this.ball.y + this.ball.dy < this.ball.radius) {

      this.ball.dy = -this.ball.dy;

    } else if (this.ball.y + this.ball.dy > 320 - this.ball.radius) {

      // 패들과의 충돌 또는 게임 오버 체크

    }

    

    this.ball.x += this.ball.dx;

    this.ball.y += this.ball.dy;

  }

}

```

 

## 4. 패들 동작 추가

 

사용자 입력을 받아 패들이 좌우로 움직이도록 구현합니다. 이는 키보드 이벤트를 사용하여 조작할 수 있습니다.

 

**Example Code for Paddle Movement**

 

```js

data() {

  return {

    paddle: {

      width: 75,

      height: 10,

      x: (480 - 75) / 2,

      speed: 7,

      rightPressed: false,

      leftPressed: false

    }

  };

},

mounted() {

  document.addEventListener('keydown', this.keyDownHandler);

  document.addEventListener('keyup', this.keyUpHandler);

},

methods: {

  keyDownHandler(e) {

    if (e.key === 'Right' || e.key === 'ArrowRight') {

      this.paddle.rightPressed = true;

    } else if (e.key === 'Left' || e.key === 'ArrowLeft') {

      this.paddle.leftPressed = true;

    }

  },

  keyUpHandler(e) {

    if (e.key === 'Right' || e.key === 'ArrowRight') {

      this.paddle.rightPressed = false;

    } else if (e.key === 'Left' || e.key === 'ArrowLeft') {

      this.paddle.leftPressed = false;

    }

  },

  movePaddle() {

    if (this.paddle.rightPressed && this.paddle.x < 480 - this.paddle.width) {

      this.paddle.x += this.paddle.speed;

    } else if (this.paddle.leftPressed && this.paddle.x > 0) {

      this.paddle.x -= this.paddle.speed;

    }

  }

}

```

 

## 5. 벽돌 구현 및 충돌 감지

 

벽돌을 배열로 설정하여 화면에 나타낸 후, 공과의 충돌 여부를 감지합니다.

 

**Example Brick Setup and Collision Detection**

 

```js

data() {

  return {

    bricks: [],

    brickRowCount: 3,

    brickColumnCount: 5,

    brickWidth: 75,

    brickHeight: 20,

    brickPadding: 10,

    brickOffsetTop: 30,

    brickOffsetLeft: 30

  };

},

methods: {

  initializeBricks() {

    for (let c = 0; c < this.brickColumnCount; c++) {

      this.bricks[c] = [];

      for (let r = 0; r < this.brickRowCount; r++) {

        this.bricks[c][r] = { x: 0, y: 0, status: 1 };

      }

    }

  },

  drawBricks(context) {

    for (let c = 0; c < this.brickColumnCount; c++) {

      for (let r = 0; r < this.brickRowCount; r++) {

        if (this.bricks[c][r].status === 1) {

          const brickX = c * (this.brickWidth + this.brickPadding) + this.brickOffsetLeft;

          const brickY = r * (this.brickHeight + this.brickPadding) + this.brickOffsetTop;

          this.bricks[c][r].x = brickX;

          this.bricks[c][r].y = brickY;

          context.beginPath();

          context.rect(brickX, brickY, this.brickWidth, this.brickHeight);

          context.fillStyle = '#0095DD';

          context.fill();

          context.closePath();

        }

      }

    }

  },

  collisionDetection() {

    for (let c = 0; c < this.brickColumnCount; c++) {

      for (let r = 0; r < this.brickRowCount; r++) {

        const b = this.bricks[c][r];

        if (b.status === 1) {

          if (this.ball.x > b.x && this.ball.x < b.x + this.brickWidth &&

              this.ball.y > b.y && this.ball.y < b.y + this.brickHeight) {

            this.ball.dy = -this.ball.dy;

            b.status = 0; // 벽돌을 깨면 status를 0으로 변경

          }

        }

      }

    }

  }

}

```

 

## 6. 게임 루프 설정

 

게임을 실제로 움직이게 하기 위해 애니메이션 루프를 설정합니다. `requestAnimationFrame`을 사용하여 매 프레임마다 캔버스를 갱신합니다.

 

**Example Animation Loop**

 

```js

mounted() {

  this.initializeBricks();

  this.initializeGame();

  this.gameLoop();

},

methods: {

  gameLoop() {

    const canvas = this.$refs.gameCanvas;

    const context = canvas.getContext('2d');

    context.clearRect(0, 0, canvas.width, canvas.height);

    this.drawBricks(context);

    this.drawBall(context);

    this.updateBall();

    this.drawPaddle(context);

    this.movePaddle();

    this.collisionDetection();

 

    requestAnimationFrame(this.gameLoop);

  },

  drawPaddle(context) {

    context.beginPath();

    context.rect(this.paddle.x, canvas.height - this.paddle.height, this.paddle.width, this.paddle.height);

    context.fillStyle = "#0095DD";

    context.fill();

    context.closePath();

  }

}

```

 

이렇게 각 단계별로 구현하면 Vue.js를 활용한 간단한 벽돌깨기 게임이 완성됩니다. 개발을 진행하며 Vue의 반응성 시스템과 HTML5 캔버스를 통한 그래픽 처리 방법에 대한 이해가 높아질 것입니다. 이를 게임의 기초로 삼아 자신의 아이디어를 추가하고, 더 다양한 기능과 시각 효과를 추가해보세요.

반응형