You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
228 lines
8.9 KiB
228 lines
8.9 KiB
<!--
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
{
|
|
"original_hash": "41be8d35e7f30aa9dad10773c35e89c4",
|
|
"translation_date": "2025-08-23T22:59:28+00:00",
|
|
"source_file": "6-space-game/2-drawing-to-canvas/README.md",
|
|
"language_code": "ko"
|
|
}
|
|
-->
|
|
# 우주 게임 만들기 Part 2: 캔버스에 영웅과 몬스터 그리기
|
|
|
|
## 강의 전 퀴즈
|
|
|
|
[강의 전 퀴즈](https://ff-quizzes.netlify.app/web/quiz/31)
|
|
|
|
## 캔버스
|
|
|
|
캔버스는 기본적으로 내용이 없는 HTML 요소로, 빈 도화지와 같습니다. 여기에 무언가를 그려넣어야 합니다.
|
|
|
|
✅ [캔버스 API에 대해 더 알아보기](https://developer.mozilla.org/docs/Web/API/Canvas_API) (MDN).
|
|
|
|
일반적으로 페이지의 본문에 다음과 같이 선언됩니다:
|
|
|
|
```html
|
|
<canvas id="myCanvas" width="200" height="100"></canvas>
|
|
```
|
|
|
|
위 코드에서는 `id`, `width`, `height`를 설정하고 있습니다.
|
|
|
|
- `id`: 캔버스와 상호작용할 때 참조할 수 있도록 설정합니다.
|
|
- `width`: 요소의 너비를 설정합니다.
|
|
- `height`: 요소의 높이를 설정합니다.
|
|
|
|
## 간단한 도형 그리기
|
|
|
|
캔버스는 데카르트 좌표계를 사용하여 그림을 그립니다. 따라서 x축과 y축을 사용하여 위치를 표현합니다. 좌표 `0,0`은 왼쪽 상단을 나타내며, 오른쪽 하단은 캔버스의 너비와 높이에 따라 결정됩니다.
|
|
|
|

|
|
> 이미지 출처: [MDN](https://developer.mozilla.org/docs/Web/API/Canvas_API/Tutorial/Drawing_shapes)
|
|
|
|
캔버스 요소에 그림을 그리려면 다음 단계를 따라야 합니다:
|
|
|
|
1. **캔버스 요소에 대한 참조**를 가져옵니다.
|
|
2. **캔버스 요소 위에 있는 컨텍스트 요소에 대한 참조**를 가져옵니다.
|
|
3. **컨텍스트 요소를 사용하여 그리기 작업**을 수행합니다.
|
|
|
|
위 단계를 코드로 작성하면 다음과 같습니다:
|
|
|
|
```javascript
|
|
// draws a red rectangle
|
|
//1. get the canvas reference
|
|
canvas = document.getElementById("myCanvas");
|
|
|
|
//2. set the context to 2D to draw basic shapes
|
|
ctx = canvas.getContext("2d");
|
|
|
|
//3. fill it with the color red
|
|
ctx.fillStyle = 'red';
|
|
|
|
//4. and draw a rectangle with these parameters, setting location and size
|
|
ctx.fillRect(0,0, 200, 200) // x,y,width, height
|
|
```
|
|
|
|
✅ 캔버스 API는 주로 2D 도형에 초점을 맞추고 있지만, 웹사이트에 3D 요소를 그릴 수도 있습니다. 이를 위해 [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API)를 사용할 수 있습니다.
|
|
|
|
캔버스 API를 사용하면 다음과 같은 다양한 작업을 할 수 있습니다:
|
|
|
|
- **기하학적 도형**: 사각형을 그리는 방법을 이미 보여드렸지만, 그 외에도 다양한 도형을 그릴 수 있습니다.
|
|
- **텍스트**: 원하는 폰트와 색상으로 텍스트를 그릴 수 있습니다.
|
|
- **이미지**: .jpg나 .png 같은 이미지 자산을 기반으로 이미지를 그릴 수 있습니다.
|
|
|
|
✅ 해보세요! 사각형을 그리는 방법을 배웠으니, 이번에는 페이지에 원을 그려보세요. CodePen에서 흥미로운 캔버스 그림들을 확인해보세요. [특히 인상적인 예제](https://codepen.io/dissimulate/pen/KrAwx)를 하나 소개합니다.
|
|
|
|
## 이미지 자산 로드 및 그리기
|
|
|
|
이미지 자산을 로드하려면 `Image` 객체를 생성하고 `src` 속성을 설정합니다. 그런 다음 `load` 이벤트를 통해 이미지가 준비되었는지 확인합니다. 코드는 다음과 같습니다:
|
|
|
|
### 자산 로드
|
|
|
|
```javascript
|
|
const img = new Image();
|
|
img.src = 'path/to/my/image.png';
|
|
img.onload = () => {
|
|
// image loaded and ready to be used
|
|
}
|
|
```
|
|
|
|
### 자산 로드 패턴
|
|
|
|
위 코드를 다음과 같은 구조로 감싸는 것이 좋습니다. 이렇게 하면 사용하기 더 쉬워지고, 이미지가 완전히 로드된 후에만 조작할 수 있습니다:
|
|
|
|
```javascript
|
|
function loadAsset(path) {
|
|
return new Promise((resolve) => {
|
|
const img = new Image();
|
|
img.src = path;
|
|
img.onload = () => {
|
|
// image loaded and ready to be used
|
|
resolve(img);
|
|
}
|
|
})
|
|
}
|
|
|
|
// use like so
|
|
|
|
async function run() {
|
|
const heroImg = await loadAsset('hero.png')
|
|
const monsterImg = await loadAsset('monster.png')
|
|
}
|
|
|
|
```
|
|
|
|
게임 자산을 화면에 그리려면 코드는 다음과 같습니다:
|
|
|
|
```javascript
|
|
async function run() {
|
|
const heroImg = await loadAsset('hero.png')
|
|
const monsterImg = await loadAsset('monster.png')
|
|
|
|
canvas = document.getElementById("myCanvas");
|
|
ctx = canvas.getContext("2d");
|
|
ctx.drawImage(heroImg, canvas.width/2,canvas.height/2);
|
|
ctx.drawImage(monsterImg, 0,0);
|
|
}
|
|
```
|
|
|
|
## 이제 게임을 만들어봅시다
|
|
|
|
### 무엇을 만들 것인가
|
|
|
|
캔버스 요소가 포함된 웹 페이지를 만듭니다. 이 페이지는 `1024*768` 크기의 검은 화면을 렌더링해야 합니다. 두 개의 이미지를 제공합니다:
|
|
|
|
- 영웅 우주선
|
|
|
|

|
|
|
|
- 5*5 몬스터
|
|
|
|

|
|
|
|
### 개발 시작을 위한 추천 단계
|
|
|
|
`your-work` 하위 폴더에 생성된 파일을 찾으세요. 이 폴더에는 다음 파일이 포함되어 있어야 합니다:
|
|
|
|
```bash
|
|
-| assets
|
|
-| enemyShip.png
|
|
-| player.png
|
|
-| index.html
|
|
-| app.js
|
|
-| package.json
|
|
```
|
|
|
|
Visual Studio Code에서 이 폴더의 복사본을 엽니다. 로컬 개발 환경이 설정되어 있어야 하며, Visual Studio Code와 NPM, Node가 설치되어 있는 것이 좋습니다. 컴퓨터에 `npm`이 설정되어 있지 않다면, [설치 방법](https://www.npmjs.com/get-npm)을 참고하세요.
|
|
|
|
`your_work` 폴더로 이동하여 프로젝트를 시작합니다:
|
|
|
|
```bash
|
|
cd your-work
|
|
npm start
|
|
```
|
|
|
|
위 명령은 `http://localhost:5000` 주소에서 HTTP 서버를 시작합니다. 브라우저를 열고 해당 주소를 입력하세요. 현재는 빈 페이지지만, 곧 바뀔 것입니다.
|
|
|
|
> 참고: 화면에서 변경 사항을 확인하려면 브라우저를 새로고침하세요.
|
|
|
|
### 코드 추가
|
|
|
|
`your-work/app.js`에 필요한 코드를 추가하여 아래 작업을 해결하세요:
|
|
|
|
1. **캔버스**를 검은 배경으로 그리기
|
|
> 팁: `/app.js`의 적절한 TODO 아래에 두 줄을 추가하여 `ctx` 요소를 검은색으로 설정하고, 좌표를 0,0으로, 높이와 너비를 캔버스 크기와 동일하게 설정하세요.
|
|
2. **텍스처 로드**
|
|
> 팁: `await loadTexture`를 사용하여 이미지 경로를 전달하며 플레이어와 적 이미지를 추가하세요. 아직 화면에는 보이지 않을 것입니다!
|
|
3. **화면 하단 중앙에 영웅 그리기**
|
|
> 팁: `drawImage` API를 사용하여 `heroImg`를 화면에 그리세요. 좌표는 `canvas.width / 2 - 45`와 `canvas.height - canvas.height / 4`로 설정하세요.
|
|
4. **5*5 몬스터 그리기**
|
|
> 팁: 이제 적을 화면에 그리는 코드를 주석 해제하세요. 그런 다음 `createEnemies` 함수로 이동하여 이를 완성하세요.
|
|
|
|
먼저 몇 가지 상수를 설정합니다:
|
|
|
|
```javascript
|
|
const MONSTER_TOTAL = 5;
|
|
const MONSTER_WIDTH = MONSTER_TOTAL * 98;
|
|
const START_X = (canvas.width - MONSTER_WIDTH) / 2;
|
|
const STOP_X = START_X + MONSTER_WIDTH;
|
|
```
|
|
|
|
그런 다음, 몬스터 배열을 화면에 그리는 루프를 생성합니다:
|
|
|
|
```javascript
|
|
for (let x = START_X; x < STOP_X; x += 98) {
|
|
for (let y = 0; y < 50 * 5; y += 50) {
|
|
ctx.drawImage(enemyImg, x, y);
|
|
}
|
|
}
|
|
```
|
|
|
|
## 결과
|
|
|
|
완성된 결과는 다음과 같아야 합니다:
|
|
|
|

|
|
|
|
## 솔루션
|
|
|
|
먼저 스스로 해결해보세요. 하지만 막히면 [솔루션](../../../../6-space-game/2-drawing-to-canvas/solution/app.js)을 참고하세요.
|
|
|
|
---
|
|
|
|
## 🚀 도전 과제
|
|
|
|
2D 중심의 캔버스 API에 대해 배웠습니다. [WebGL API](https://developer.mozilla.org/docs/Web/API/WebGL_API)를 살펴보고 3D 객체를 그려보세요.
|
|
|
|
## 강의 후 퀴즈
|
|
|
|
[강의 후 퀴즈](https://ff-quizzes.netlify.app/web/quiz/32)
|
|
|
|
## 복습 및 자습
|
|
|
|
[캔버스 API에 대해 읽어보며](https://developer.mozilla.org/docs/Web/API/Canvas_API) 더 알아보세요.
|
|
|
|
## 과제
|
|
|
|
[캔버스 API로 실습하기](assignment.md)
|
|
|
|
**면책 조항**:
|
|
이 문서는 AI 번역 서비스 [Co-op Translator](https://github.com/Azure/co-op-translator)를 사용하여 번역되었습니다. 정확성을 위해 최선을 다하고 있지만, 자동 번역에는 오류나 부정확성이 포함될 수 있습니다. 원본 문서를 해당 언어로 작성된 상태에서 권위 있는 자료로 간주해야 합니다. 중요한 정보의 경우, 전문적인 인간 번역을 권장합니다. 이 번역 사용으로 인해 발생하는 오해나 잘못된 해석에 대해 당사는 책임을 지지 않습니다. |