From ee778d6eea54935fd05022e0ba8c49456003381a Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 14:48:24 +0100 Subject: unslug ko: move --- .../2d_breakout_game_phaser/the_score/index.html | 73 +++++++++++ .../\353\223\235\354\240\220/index.html" | 73 ----------- .../bounce_off_the_walls/index.html | 99 ++++++++++++++ .../build_the_brick_field/index.html | 112 ++++++++++++++++ .../collision_detection/index.html | 128 ++++++++++++++++++ .../create_the_canvas_and_draw_on_it/index.html | 114 ++++++++++++++++ .../finishing_up/index.html | 111 ++++++++++++++++ .../game_over/index.html | 77 +++++++++++ .../2d_breakout_game_pure_javascript/index.html | 55 ++++++++ .../mouse_controls/index.html | 57 ++++++++ .../move_the_ball/index.html | 145 +++++++++++++++++++++ .../paddle_and_keyboard_controls/index.html | 122 +++++++++++++++++ .../track_the_score_and_win/index.html | 100 ++++++++++++++ .../bounce_off_the_walls/index.html" | 99 -------------- .../build_the_brick_field/index.html" | 112 ---------------- .../collision_detection/index.html" | 128 ------------------ .../finishing_up/index.html" | 111 ---------------- .../game_over/index.html" | 77 ----------- .../index.html" | 55 -------- .../mouse_controls/index.html" | 57 -------- .../paddle_and_keyboard_controls/index.html" | 122 ----------------- .../track_the_score_and_win/index.html" | 100 -------------- .../index.html" | 145 --------------------- .../index.html" | 114 ---------------- 24 files changed, 1193 insertions(+), 1193 deletions(-) create mode 100644 files/ko/games/tutorials/2d_breakout_game_phaser/the_score/index.html delete mode 100644 "files/ko/games/tutorials/2d_breakout_game_phaser/\353\223\235\354\240\220/index.html" create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html create mode 100644 files/ko/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/bounce_off_the_walls/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/build_the_brick_field/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/collision_detection/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/finishing_up/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/game_over/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/mouse_controls/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/paddle_and_keyboard_controls/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/track_the_score_and_win/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/\352\263\265_\354\233\200\354\247\201\354\235\264\352\270\260/index.html" delete mode 100644 "files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/\354\272\224\353\262\204\354\212\244_\354\203\235\354\204\261\352\263\274_\352\267\270\353\246\254\352\270\260/index.html" (limited to 'files/ko/games') diff --git a/files/ko/games/tutorials/2d_breakout_game_phaser/the_score/index.html b/files/ko/games/tutorials/2d_breakout_game_phaser/the_score/index.html new file mode 100644 index 0000000000..ca79e665a1 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_phaser/the_score/index.html @@ -0,0 +1,73 @@ +--- +title: 득점 +slug: Games/Tutorials/2D_breakout_game_Phaser/득점 +tags: + - 게임 + - 게임제작 + - 득점 + - 득점시스템 + - 튜토리얼 +translation_of: Games/Tutorials/2D_breakout_game_Phaser/The_score +--- +
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Collision_detection", "Games/Workflows/2D_Breakout_game_Phaser/Win_the_game")}}

+ +
+

이것은 Gamedev Phaser tutorial의 16단계중 11번째 과정입니다. 이 과정의 소스코드를 얻고자 한다면 이 강좌를 수강한 후 Gamedev-Phaser-Content-Kit/demos/lesson11.html를 통해 얻으세요.

+
+ +

점수를 얻는 방식의 게임은 좀더 재미있을 것 입니다.— 당신 또는, 친구의 최고 기록을 갈아치울수도 있습니다. 이 글에서는 우리의 게임에 득점 시스템을 추가해 보려고 합니다.

+ +

우리는 점수를 저장해두기 위해 여러 변수를 사용하고, 점수를 화면에 출력하기 위해 내부의 text() 메소드를 사용합니다.

+ +

새로운 변수들

+ +

이전 정의되었던 변수들 바로 다음에 다음과 같이 새로운 변수 두개를 추가해 주세요:

+ +
// ...
+var scoreText;
+var score = 0;
+
+ +

게임 화면에 점수가 표시 되도록 해보자

+ +

지금 create() 함수 뒤에 다음과 같은 코드를 추가해봅시다:

+ +
scoreText = game.add.text(5, 5, 'Points: 0', { font: '18px Arial', fill: '#0095DD' });
+
+ +

text() 메소드는 4개의 변수를 가질수 있습니다:

+ + + +

마지막 변수는 CSS와 매우 비슷해 보입니다. 우리의 점수는 파란색에, 18픽셀 크기이며, Arial 폰트를 사용하여 나타날 것입니다.

+ +

블록이 무너지면 점수를 갱신합니다.

+ +

우리는 공이 블록을 칠때마다 점수를 증가시킵니다 그리고 공이 블록을 칠때마다 동시에 점수판을 갱신하여 화면에 현재 점수를 나타낼 것입니다. 이건 setText()매소드를 써서 해결 할수 있습니다 — ballHitBrick() 함수 아래로 다음과 같은 새로운 코드 두 줄을 추가하세요:

+ +
function ballHitBrick(ball, brick) {
+    brick.kill();
+    score += 10;
+    scoreText.setText('Points: '+score);
+}
+
+ +

됬습니다, — index.html 을 다시 새로고침 해주고 공이 블록을 칠때마다 점수가 갱신되는지 확인해줍니다.

+ +

코드를 비교해보세요

+ +

이번 강좌에서 배운 득점 시스템이 어떻게 작동하는지 이해하고자 한다면, 다음 아래를 이용해 시연해보세요.:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/n8o6rhrf/","","400")}}

+ +

다음 단계

+ +

우리는 이제 득점 시스템을 게임에 추가했습니다. 그러나 게임에서 이길 수 없다면, 게임하면서 득점하는게 무슨 소용일까요? 그래서 승리 상태를 추가해보려고 합니다. 게임에서 이기게 하고 싶다면 다음으로 넘어갑시다: win the game.

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Collision_detection", "Games/Workflows/2D_Breakout_game_Phaser/Win_the_game")}}

diff --git "a/files/ko/games/tutorials/2d_breakout_game_phaser/\353\223\235\354\240\220/index.html" "b/files/ko/games/tutorials/2d_breakout_game_phaser/\353\223\235\354\240\220/index.html" deleted file mode 100644 index ca79e665a1..0000000000 --- "a/files/ko/games/tutorials/2d_breakout_game_phaser/\353\223\235\354\240\220/index.html" +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: 득점 -slug: Games/Tutorials/2D_breakout_game_Phaser/득점 -tags: - - 게임 - - 게임제작 - - 득점 - - 득점시스템 - - 튜토리얼 -translation_of: Games/Tutorials/2D_breakout_game_Phaser/The_score ---- -
{{GamesSidebar}}
{{IncludeSubnav("/en-US/docs/Games")}}
- -

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Collision_detection", "Games/Workflows/2D_Breakout_game_Phaser/Win_the_game")}}

- -
-

이것은 Gamedev Phaser tutorial의 16단계중 11번째 과정입니다. 이 과정의 소스코드를 얻고자 한다면 이 강좌를 수강한 후 Gamedev-Phaser-Content-Kit/demos/lesson11.html를 통해 얻으세요.

-
- -

점수를 얻는 방식의 게임은 좀더 재미있을 것 입니다.— 당신 또는, 친구의 최고 기록을 갈아치울수도 있습니다. 이 글에서는 우리의 게임에 득점 시스템을 추가해 보려고 합니다.

- -

우리는 점수를 저장해두기 위해 여러 변수를 사용하고, 점수를 화면에 출력하기 위해 내부의 text() 메소드를 사용합니다.

- -

새로운 변수들

- -

이전 정의되었던 변수들 바로 다음에 다음과 같이 새로운 변수 두개를 추가해 주세요:

- -
// ...
-var scoreText;
-var score = 0;
-
- -

게임 화면에 점수가 표시 되도록 해보자

- -

지금 create() 함수 뒤에 다음과 같은 코드를 추가해봅시다:

- -
scoreText = game.add.text(5, 5, 'Points: 0', { font: '18px Arial', fill: '#0095DD' });
-
- -

text() 메소드는 4개의 변수를 가질수 있습니다:

- - - -

마지막 변수는 CSS와 매우 비슷해 보입니다. 우리의 점수는 파란색에, 18픽셀 크기이며, Arial 폰트를 사용하여 나타날 것입니다.

- -

블록이 무너지면 점수를 갱신합니다.

- -

우리는 공이 블록을 칠때마다 점수를 증가시킵니다 그리고 공이 블록을 칠때마다 동시에 점수판을 갱신하여 화면에 현재 점수를 나타낼 것입니다. 이건 setText()매소드를 써서 해결 할수 있습니다 — ballHitBrick() 함수 아래로 다음과 같은 새로운 코드 두 줄을 추가하세요:

- -
function ballHitBrick(ball, brick) {
-    brick.kill();
-    score += 10;
-    scoreText.setText('Points: '+score);
-}
-
- -

됬습니다, — index.html 을 다시 새로고침 해주고 공이 블록을 칠때마다 점수가 갱신되는지 확인해줍니다.

- -

코드를 비교해보세요

- -

이번 강좌에서 배운 득점 시스템이 어떻게 작동하는지 이해하고자 한다면, 다음 아래를 이용해 시연해보세요.:

- -

{{JSFiddleEmbed("https://jsfiddle.net/end3r/n8o6rhrf/","","400")}}

- -

다음 단계

- -

우리는 이제 득점 시스템을 게임에 추가했습니다. 그러나 게임에서 이길 수 없다면, 게임하면서 득점하는게 무슨 소용일까요? 그래서 승리 상태를 추가해보려고 합니다. 게임에서 이기게 하고 싶다면 다음으로 넘어갑시다: win the game.

- -

{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Collision_detection", "Games/Workflows/2D_Breakout_game_Phaser/Win_the_game")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html new file mode 100644 index 0000000000..2df00b91b9 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html @@ -0,0 +1,99 @@ +--- +title: 공을 벽에 튕기기 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games")}}
+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls")}}

+ +
+

이 글은 Gamedev Canvas 튜토리얼에 포함된 10단계 중 3단계 글입니다. 이 글을 다 읽고 난 뒤 완성된 소스코드는 Gamedev-Canvas-workshop/lesson3.html에서 확인해볼 수 있습니다.

+
+ +

공이 움직이는 걸 보니 기쁩니다! 하지만 기쁨을 즐길 틈도 없이 공이 스크린 밖으로 사라져버리네요. 이 문제를 해결하기 위해 공이 캔버스의 4군데 모서리에 다달았을 때 튕겨나올 수 있도록 간단한 충돌 감지 기능(더 자세한 내용은 다음 글에서 다시 설명할 예정입니다)을 구현해야 합니다.

+ +

간단한 충돌 감지

+ +

충돌을 감지하기 위해서는 공이 벽에 닿았는지를 확인하고 그에 따라 움직이는 방향을 수정해야 합니다.

+ +

보다 계산을 쉽게 하기 위하여 ballRadius 변수를 만든 뒤 원의 반지름 값을 대입하여 계산하는데 사용합니다. 아래의 코드를 기존의 변수들 아래에 삽입하세요:

+ +
var ballRadius = 10;
+ +

이제drawBall() func기능 안에 볼을 그리는 코드를 아래와 같이 수정하세요:

+ +
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
+ +

위 아래 방향으로 튕기기

+ +

캔버스에는 총 4개의 모서리 즉, 4개의 벽이 있습니다. 일단 상단의 벽에 집중해 보겠습니다. 공을 그리는 매 프레임마다 우리는 볼이 상단 모서리에 닿았는지 확인해야합니다 — 닿았다면 볼이 움직이는 방향을 반대로 바꾸어 캔버스 안에 여전히 공이 보이도록 만들어주어야 합니다. 캔버스 내 위치 구조는 좌상단으로 부터 시작하는 것을 잊지마세요:

+ +
if(y + dy < 0) {
+    dy = -dy;
+}
+ +

만약 공의 위치에서 y값이 0보다 작은 경우 음/양수를 반대로 바꾸어주어 y 축의 방향을 바꾸어 줍니다. 공이 매 프레임마다 2픽셀만큼 움직이고 있었다면, 이제는 매 프레임마다 2픽셀만큼 "아래 방향으로" 이동할 것입니다.

+ +

위 코드는 상단 모서리를 튕기도록 해주기 때문에 이번엔 하단 모서리를 튕기도록 해보겠습니다:

+ +
if(y + dy > canvas.height) {
+    dy = -dy;
+}
+ +

공의 위치에서 y값이 캔버스의 높이보다 큰 경우(좌상단으로부터 y값을 측정하기 때문에 상단모서리에서의 y값은 0, 하단모서리에서의 y값은 480, 즉 캔버서의 높이값임을 잊지마세요) y축 움직임의 반대 방향으로 튕겨냅니다.

+ +

위의 두가지 코드를 하나로 합칠 수 있습니다:

+ +
if(y + dy > canvas.height || y + dy < 0) {
+    dy = -dy;
+}
+ +

둘 중 하나의 조건이라도 만족한다면, 공의 방향은 반대로 바뀝니다.

+ +

좌우로 튕겨내기

+ +

우리는 방금 상, 하단 모서리를 인식했으므로 이번엔 좌우 모서리를 생각해봅시다. 거의 같은 문제이므로 우리는 y 대신 x값을 대입하여 그대로 반복해주기만 하면 됩니다:

+ +
if(x + dx > canvas.width || x + dx < 0) {
+    dx = -dx;
+}
+
+if(y + dy > canvas.height || y + dy < 0) {
+    dy = -dy;
+}
+ +

이 후 위 코드를 draw() 함수블럭이 끝나는 중괄호 바로 전에 삽입합니다.

+ +

공이 여전히 벽 밖으로 사라져요!

+ +

코드를 테스트해보세요. — 아마 캔버스 모서리에서 튕겨나오는 볼이 인상적이지 않나요? 하지만 또 다른 문제가 생겼습니다. — 공이 벽을 튕겨나와 방향이 바뀌기 전에 살짝 벽 안으로 숨어버리네요:

+ +

+ +

이 문제는 우리가 충돌을 감지할 때 그 기준을 공의 원점에 두고 계산했지만, 원의 둘레를 기준으로 계산을 해야 하기 때문입니다. 벽에 공이 절반쯤 지난 뒤가 아니라 닿자마자 튕겨나와야 합니다. 이에 맞게 코드를 조금 수정해봅시다. 여러분이 삽입한 코드를 아래와 같이 수정해보세요:

+ +
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
+    dx = -dx;
+}
+if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
+    dy = -dy;
+}
+ +

공의 원점과 벽 사이의 거리가 공의 반지름과 같아졌을 때 공의 움직임이 바뀌도록 만들었습니다. 이제야 볼이 정확히 튕겨나오고 있네요.

+ +

여러분의 코드를 비교해보세요

+ +

자, 다시 여러분이 작성한 코드를 완성된 코드와 비교해보고 게임을 실행해보세요:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/redj37dc/","","370")}}

+ +
+

Exercise: 공이 벽에 부딪힐 때마다 공의 색을 무작위로 변화시켜보세요.

+
+ +

다음 단계

+ +

이제 우리는 공이 게임판 안에서 어디서 어떻게 움직이고 있는지 파악했습니다. 네번째 챕터에서는 조작 가능한 배드를 구현해볼 것입니다. — 패드와 키보드 조작.

+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html new file mode 100644 index 0000000000..9560da25e9 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html @@ -0,0 +1,112 @@ +--- +title: 벽돌 만들기 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Build_the_brick_field +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임")}}
+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Collision_detection")}}

+ +
+

이번 단계는 Gamedev Canvas tutorial의 여섯 번째 학습입니다. Gamedev-Canvas-workshop/lesson6.html에서 이번 학습의 소스코드를 확인할 수 있습니다.

+
+ +

게임플레이 원리를 수정한 후에, 우리는 게임에서 패배할 수 있게 되었습니다. 이것은 실제 게임에 보다 가까운 느낌이기 때문에 훌륭합니다. 하지만 벽과 패들에 공이 튀기는 것 말고 할 수 있는 것이 없기 때문에 금방 지루해집니다. 벽돌깨기 게임에서 진정으로 필요로 한 것은 공으로 파괴할 벽돌입니다. 이 것이 지금 우리가 만들 것입니다!

+ +

벽돌에 대한 변수 설정하기

+ +

이번 학습의 모든 목표는 벽돌들을 위한 코드를 2차원 배열로 동작하는 반복문을 통해 제공하는 것입니다. 그러나 먼저 우리는 가로, 세로, 행, 열 등 벽돌에 대한 값을 정의할 몇몇 변수들을 설정해야 합니다. 지난 학습에서 작성한 코드에 아래 코드를 추가해봅시다.

+ +
var brickRowCount = 3;
+var brickColumnCount = 5;
+var brickWidth = 75;
+var brickHeight = 20;
+var brickPadding = 10;
+var brickOffsetTop = 30;
+var brickOffsetLeft = 30;
+ +

우리는 벽돌 배열 행과 열의 수, 그것들의 가로, 세로길이, 각 벽돌이 서로 닿지 않을 정도의 간격과 벽돌이 캔버스의 모서리에 닿지 않게 할 오프셋 변수들을 정의했습니다.

+ +

우리는 2차원 배열에 벽돌을 담았습니다. 배열은 열 c, 행 r, 그리고 배열의 각 객체엔 화면에 벽돌을 그릴 위치를 나타낼 x, y 위치를 가지고 있습니다. 위에서 변수를 선언한 코드 뒤에 아래 코드를 추가해봅시다.

+ +
var bricks = [];
+for(var c=0; c<brickColumnCount; c++) {
+    bricks[c] = [];
+    for(var r=0; r<brickRowCount; r++) {
+        bricks[c][r] = { x: 0, y: 0 };
+    }
+}
+ +

위 코드는 행과 열 수만큼 반복되면서 새로운 벽돌을 만듭니다. 각 벽돌 객체는 이후에 충돌감지에 사용됩니다.

+ +

벽돌을 그리는 방법

+ +

이제 배열안의 모든 벽돌을 반복해서 화면에 그려줄 함수를 만들어봅시다. 코드는 아래와 같습니다.

+ +
function drawBricks() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            bricks[c][r].x = 0;
+            bricks[c][r].y = 0;
+            ctx.beginPath();
+            ctx.rect(0, 0, brickWidth, brickHeight);
+            ctx.fillStyle = "#0095DD";
+            ctx.fill();
+            ctx.closePath();
+        }
+    }
+}
+ +

다시 행, 열 반복을 통해 각 벽돌의 x, y 값을 설정하고, 캔버스에 brickWidth * brickHeight 크기의 벽돌들을 그립니다. 문제는 모든 벽돌들이 좌표 (0, 0) 위치해있다는 것입니다. 우리는 약간의 연산을 통해 각 벽돌의 x, y 값을 계산해야 합니다.

+ +
var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
+var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
+ +

 

+ +

brickXbrickWidth + brickPaddingc를 곱하고, brickOffsetLeft를 더한 값입니다. brickY는 변수 r, brickHeight, brickOffsetTop 변수를 사용한다는 것을 제외하곤 동일합니다. 이제 모든 벽돌들을 올바른 위치에, 알맞은 간격을 두고, 캔버스 모서리로부터 오프셋 값만큼의 거리를 둔 상태로 그릴수 있게되었습니다.

+ +

brickXbrickY 값을 (0, 0) 대신에 좌표 값으로 할당한 후에 drawBricks 함수의 마지막 버전은 아래와 같을 것입니다. 이 코드는 drawpaddle 함수 아래에 추가해봅시다.

+ +
function drawBricks() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
+            var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
+            bricks[c][r].x = brickX;
+            bricks[c][r].y = brickY;
+            ctx.beginPath();
+            ctx.rect(brickX, brickY, brickWidth, brickHeight);
+            ctx.fillStyle = "#0095DD";
+            ctx.fill();
+            ctx.closePath();
+        }
+    }
+}
+ +

실제 벽돌을 그리기

+ +

이 학습에서 마지막으로 할 일은 drawBrick함수를 호출하는 코드를 draw함수 어딘가에, 되도록이면 시작하는 부분에, 캔버스를 초기화하는 부분과 공을 그리는 사이에 추가하는 것입니다.  아래 코드를 drawBall() 코드 위에 추가해봅시다.

+ +
drawBricks();
+
+ +

코드 비교해보기

+ +

이 부분에서 게임은 조금 더 흥미로워졌습니다.

+ +

{{JSFiddleEmbed("https://jsfiddle.net/yumetodo/t1zqmzLp/","","395")}}

+ +
+

연습하기: 행과 열의 수를 바꿔서 벽돌의 수를 변경해보거나, 위치를 변경해봅시다.

+
+ +

다음 단계

+ +

이제 우리에겐 벽돌이 있습니다! 하지만 공은 벽돌들과의 반응이 없습니다. 우리는 다음 단계에서 이 문제에 대해 다룰 것입니다: 충돌 감지

+ +

 

+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Collision_detection")}}

+ +

 

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html new file mode 100644 index 0000000000..f312374938 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html @@ -0,0 +1,128 @@ +--- +title: 충돌 감지 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Collision_detection +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Collision_detection +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/ko/docs/Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임")}}
+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win")}}

+ +
+

이 학습은 Gamedev Canvas tutorial의 일곱 번째 단계입니다. Gamedev-Canvas-workshop/lesson7.html에서 이번 학습에서 완성된 코드를 확인할 수 있습니다.

+
+ +

지난 학습에서 우린 화면에 벽돌을 표현했습니다. 그러나 공은 벽돌은 그냥 지나가버리고 게임은 아직 흥미로워지려면 멀어보입니다. 우린 공이 벽돌을 파괴하고 튕겨져 나올 수 있도록 충돌 감지 기능을 고려해봐야 합니다.

+ +

물론 어떻게 적용할지는 우리가 결정할 문제입니다. 그러나 공이 벽돌에 닿았는지 계산하는 일은 꽤나 까다로울 수 있습니다. 왜냐하면 캔버스엔 이를 위한 기능이 없기 때문입니다.  이번 학습은 가능한 쉬운 방법으로 진행될 것입니다. 우린 공의 중앙이 어느 벽돌과 충돌하는지 확인할 것입니다. 이는 항상 완벽한 결과를 주진 않지만, 충돌 감지를 위한 정교한 방법은 무궁무진합니다. 그러나 이 방법 역시 기본적인 개념을 학습하기에 꽤 괜찮습니다.

+ +

충돌 감지 함수

+ +

이 모든 것을 시작하기 위해 우리는 모든 벽돌들을 순회하고 각 벽돌의 좌표를 공의 위치와 비교하는 충돌 감지 함수를 만들어야 합니다. 코드의 가독성을 향상시키기 위해 충돌 감지의 반복에서 사용할 벽돌 객체를 저장하는 b 변수를 정의할 것입니다.

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            // calculations
+        }
+    }
+}
+ +

만약 공의 중앙이 어떤 벽돌의 범위 내에 있을 경우, 공의 방향을 바꾸게 됩니다. 공이 벽돌 안에 존재하려면, 아래 4가지 조건이 참이어야 합니다.

+ + + +

이 조건을 코드로 작성해봅시다.

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
+                dy = -dy;
+            }
+        }
+    }
+}
+ +

위 코드를 keyUpHandler() 함수 아래에 추가해봅시다.

+ +

충돌 후에 벽돌을 사라지게 만들기

+ +

위의 코드는 우리가 의도한대로 작동할 것이고 공은 방향을 바꿀 것입니다. 문제는 벽돌이 그대로 있다는 것입니다. 우린 이미 공이 부딪힌 벽돌을 제거하기 위한 방법을 고민해봐야 합니다. 우리는 화면에 있는 벽돌을 그릴지 결정하는 변수를 추가해서 이 문제를 해결할 수 있습니다, 벽돌을 초기화하는 코드에, status 속성을 각 벽돌 객체에 추가해봅시다. 아래와 같이 말입니다.

+ +
var bricks = [];
+for(var c=0; c<brickColumnCount; c++) {
+    bricks[c] = [];
+    for(var r=0; r<brickRowCount; r++) {
+        bricks[c][r] = { x: 0, y: 0, status: 1 };
+    }
+}
+ +

다음으로 drawBricks 함수에서 벽돌들을 그리기 전에 status 속성을 확인해야 합니다. 만약 status가 1이라면 벽돌을 그리고, 만약 0이라면 이미 공이 치고간 벽돌이므로 우린 더이상 화면에 그릴 필요가 없습니다. 아래와 같이 drawBricks 함수를 수정해봅시다,

+ +
function drawBricks() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            if(bricks[c][r].status == 1) {
+                var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
+                var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
+                bricks[c][r].x = brickX;
+                bricks[c][r].y = brickY;
+                ctx.beginPath();
+                ctx.rect(brickX, brickY, brickWidth, brickHeight);
+                ctx.fillStyle = "#0095DD";
+                ctx.fill();
+                ctx.closePath();
+            }
+        }
+    }
+}
+ +

충돌 감지함수에서 상태 추적 및 업데이트

+ +

이제 collisonDectection 함수에 벽돌 status 속성을 포함시켜야 합니다. 만약 벽돌이 활성 상태(status 1)이라면 충돌이 일어났는지 확인해야 합니다. 만약 충돌이 발생했다면 다시 그리지 않게 벽돌의 속성을 0으로 변경해야 합니다. collisionDetection 함수를 아래와 같이 수정합시다.

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            if(b.status == 1) {
+                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
+                    dy = -dy;
+                    b.status = 0;
+                }
+            }
+        }
+    }
+}
+ +

충돌 감지 활성화하기

+ +

마지막으로 할일은 draw함수에서 collisionDetection 함수를 호출하는 것입니다. 아래 코드를 draw 함수에, drawPaddle() 아래에 추가해봅시다.

+ +
collisionDetection();
+
+ +

코드 비교하기

+ +

이제 매 프레임마다 충돌 감지를 확인할 것입니다. 이제 우린 별돌을 파괴할 수 있습니다!

+ +

{{JSFiddleEmbed("https://jsfiddle.net/yumetodo/mkwtxgc3/3/","","395")}}

+ +
+

연습하기: 벽돌이 부딪힐 때마다 색깔을 바꿔보세요.

+
+ +

다음 단계

+ +

우리는 충분히 여기까지 왔습니다! 이제 어덟 번째 장에서는 점수를 추가와 승패 판정 방법을 알아 볼 것입니다.

+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html new file mode 100644 index 0000000000..a7f1ed4130 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html @@ -0,0 +1,114 @@ +--- +title: 캔버스 생성과 그리기 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기 +tags: + - 2D + - 게임 + - 비기너 + - 자바스크립트 + - 캔버스 + - 튜토리얼 +translation_of: >- + Games/Tutorials/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games")}}
+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기")}}

+ +
+

이 강의는 게임 개발 캔버스 튜토리얼의 10단계 중 첫 번째 과정입니다. Gamedev-Canvas-workshop/lesson1.html에서 이 강의의 완성된 코드를 볼 수 있습니다.

+
+ +

게임의 기능들을 작성하기 전에, 게임 내부에 렌더링 하기 위한 기본 구조들을 HTML과 {{htmlelement("canvas")}} 엘리먼트를 사용하여 만들어야 합니다.

+ +

게임의 HTML

+ +

HTML문서 구조는 꽤 간단합니다. 게임은 {{htmlelement("canvas")}} 엘리먼트에 렌더링됩니다. 여러분이 좋아하는 텍스트 에디터로 새로운 HTML 문서를 생성하여 index.html로 저장하고, 아래 코드를 추가하세요.

+ +
<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <title>Gamedev Canvas Workshop</title>
+    <style>
+    	* { padding: 0; margin: 0; }
+    	canvas { background: #eee; display: block; margin: 0 auto; }
+    </style>
+</head>
+<body>
+
+<canvas id="myCanvas" width="480" height="320"></canvas>
+
+<script>
+	// JavaScript 코드가 여기에 들어갈 것입니다.
+</script>
+
+</body>
+</html>
+
+ +

{{htmlelement("head")}} 에는 문자셋이 정의되어 있고, {{htmlelement("title")}}과 몇가지 기본적인 CSS가 있습니다. {{htmlelement("body")}}는 {{htmlelement("canvas")}} 와 {{htmlelement("script")}}를 포함하고 있습니다. {{htmlelement("canvas")}}에는 게임이 렌더되고, {{htmlelement("script")}}에는 JavaScript가 들어갑니다. {{htmlelement("canvas")}}엘리먼트는 쉽게 참조하기 위해 id로 myCanvas를 갖고 있고, 480픽셀의 길이와 320픽셀의 높이를 갖도록 되어있습니다. 우리가 이 튜토리얼에서 작성하게될 모든 JavaScript 코드는 <script>와  </script> 태그 사이에 들어가게 됩니다.

+ +

캔버스 기본

+ +

실제로 {{htmlelement("canvas")}}엘리먼트 위에 그래픽을 렌더링하기 위해서는 JavaScript로 참조할 수 있게 만들어야 합니다. 다음 코드를 여러분의 <script> 태그 다음에 추가하세요..

+ +
var canvas = document.getElementById("myCanvas");
+var ctx = canvas.getContext("2d");
+ +

{{htmlelement("canvas")}} 엘리먼트에 대한 참조를 canvas 변수에 저장하였습니다. 그러고 나서는 캔버스에 그리기 위해 실질적으로 사용되는 도구인 2D rendering context를 ctx 변수에 저장하고 있습니다.

+ +

캔버스에 빨간색 네모를 그리는 짧은 예제 코드를 작성해봅시다. 바로 직전의 JavaScript 코드 아래에 다음 코드를 추가하고 index.html을 브라우저에서 열어 보세요.

+ +
ctx.beginPath();
+ctx.rect(20, 40, 50, 50);
+ctx.fillStyle = "#FF0000";
+ctx.fill();
+ctx.closePath();
+ +

{{domxref("CanvasRenderingContext2D.beginPath()","beginPath()")}}와 {{domxref("CanvasRenderingContext2D.closePath()","closePath()")}}메소드 사이에 모든 명령어가 들어갑니다. 우리는 {{domxref("CanvasRenderingContext2D.rect()","rect()")}}를 이용해서 직사각형을 정의했는데, 처음 두 값들은 캔버스의 좌상단 모서리로 부터의 좌표를 의미하고, 나머지 두 값은 직사각형의 너비와 높이를 의미합니다. 위 코드에서 직사각형은 캔버스 좌측에서 20픽셀 떨어져있고, 캔버스 상단에서 40픽셀만큼 아래로 떨어져 있습니다. 그리고 너비와 높이는 각각 50픽셀로 설정되어 완벽한 정사각형으로 그려지고 있습니다. {{domxref("CanvasRenderingContext2D.fillStyle","fillStyle")}}은  {{domxref("CanvasRenderingContext2D.fill()","fill()")}}메소드에서 칠해질 색상 값을 갖게 됩니다. 위 코드에서는 사각형을 빨간색으로 칠하고 있습니다.

+ +

직사각형만 그릴 수 있는 것은 아닙니다. 이번에는 초록색 원을 그려보겠습니다. 아래의 코드를 여러분의 JavaScript의 마지막에 추가하고, 저장한 이후에 페이지를 새로고침 해보세요.

+ +
ctx.beginPath();
+ctx.arc(240, 160, 20, 0, Math.PI*2, false);
+ctx.fillStyle = "green";
+ctx.fill();
+ctx.closePath();
+ +

위 코드에서 볼 수 있듯이{{domxref("CanvasRenderingContext2D.beginPath()","beginPath()")}}와 {{domxref("CanvasRenderingContext2D.closePath()","closePath()")}}메소드가 다시 나왔습니다. 그 사이에, 가장 중요한 부분인 {{domxref("CanvasRenderingContext2D.arc()","arc()")}} 메소드가 있습니다. 이 메소드는 6개의 파라미터를 갖습니다.

+ + + +

{{domxref("CanvasRenderingContext2D.fillStyle","fillStyle")}}속성은 이전과 조금 달라 보이는데, 이는 CSS에서 색상을 표현하는 여러가지 방법 중 하나입니다. 색상을 표현할 때, 16진수로 색상값을 표현하거나, 색상 키워드를 사용하거나, rgba() 함수를 사용하거나 그외에 다른 색상 메소드를 사용할 수 있습니다.

+ +

{{domxref("CanvasRenderingContext2D.fill()","fill()")}}을 사용해서 원에 색상을 채울 수 있다면,{{domxref("CanvasRenderingContext2D.stroke()","stroke()")}}를 이용하면 원의 외곽선에 색상을 부여할 수 있습니다. 아래의 코드들도 여러분의 JavaScript에 추가해보세요.

+ +
ctx.beginPath();
+ctx.rect(160, 10, 100, 40);
+ctx.strokeStyle = "rgba(0, 0, 255, 0.5)";
+ctx.stroke();
+ctx.closePath();
+ +

위 코드는 비어있는 파란색 외곽선으로 된 원을 그립니다. rgba() 함수의 알파 채널 값 때문에 파란색은 반투명하게 표현됩니다.

+ +

여러분의 코드와 비교해 보세요

+ +

 JSFiddle에서 라이브로 실행되는 전체 코드입니다.

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/x62h15e2/","","370")}}

+ +
+

연습해보기: 주어진 모양들의 크기와 색상을 변경해보세요.

+
+ +

다음 단계로

+ +

이제 우리는 기본적인 HTML을 설정하고, canvas에 대해 조금 배웠습니다. 두 번째 챕터로 넘어가서 게임에서 공을 움직이기위해 어떻게 해야 하는지 계속 알아봅시다.

+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html new file mode 100644 index 0000000000..b23a4b6b33 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html @@ -0,0 +1,111 @@ +--- +title: 개발 마무리 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Finishing_up +tags: + - Canvas + - Games + - JavaScript +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Finishing_up +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{Previous("Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

+ +
+

Gamedev Canvas tutorial.의 10 개의 레슨 중 마지막 단계 입니다. 이 수업을 마친 후 비교하여 살펴 볼 소스코드는 Gamedev-Canvas-workshop/lesson10.html. 여기서 찾아 볼 수 있습니다.

+
+ +

우리가 쓰는 모든 게임에 항상 개선해야 할 것이 있습니다. 예를 들어 이 게임에 2인용 플레이어를 추가할 수 있습니다. 한두 번 잘못 만들어 경기를 끝낼 수도 있습니다. 그러나 우리는 코드 렌더링을 향상시켜 발전할 수 있습니다.

+ +

플레이어에게 생명을 부여하기

+ +

생명을 구현하는 방법은 아주 간단하다. 먼저 변수를 선언했던 곳과 같은 장소에서  변수를 추가하여 생명 수를 저장합니다.

+ +
var lives = 3; //남은 생명 수
+ +

남은 생명 수를 표시하는 방법은 점수 카운터가 그려지는 것과 같은 형태 입니다. drawScore()함수 아래에 다음 기능을 추가 하십시오.

+ +
function drawLives() {
+    ctx.font = "16px Arial";
+    ctx.fillStyle = "#0095DD";
+    ctx.fillText("Lives: "+lives, canvas.width-65, 20);
+}
+ +

지금까지 바닥에 닿으면 바로 게임을 끝내는 형식이였습니다. 이제 우리는 더 이상 게임을 이용할 수 없게 될 때까지 남은 생명 수를 줄일 것입니다. 또한 플레이어가 게임 오버되면 다시 생명과 블럭들을 리셋하여 공과 패들 위치를 재설정할 수 있습니다. draw() 함수는 다음 세 줄로 대체합니다:

+ +
alert("GAME OVER");
+document.location.reload();
+clearInterval(interval); // Needed for Chrome to end game
+
+ +

 

+ +

 

+ +

이를 통해 아래와 같이 약간 복잡한 논리를 추가할 수 있습니다:

+ +
lives--;
+if(!lives) {
+    alert("GAME OVER");
+    document.location.reload();
+    clearInterval(interval); // Needed for Chrome to end game
+}
+else {
+    x = canvas.width/2;
+    y = canvas.height-30;
+    dx = 2;
+    dy = -2;
+    paddleX = (canvas.width-paddleWidth)/2;
+}
+ +

자, 이제 공이 화면의 맨아래 가장자리에 맞으면 생명(lives)을 하나 뺍니다. 생명이 없다면 게임이 끝나고 아직 남아있다면 공의 위치와 패들의 위치가 재설정 됩니다.

+ +

남은 생명 표시 렌더링하기

+ +

이제 draw()함수 내에서 drawLives()에 생명 수를 추가하고 drawLives() 아래에 생명 수를 추가해야 합니다.

+ +
drawLives();
+
+ +

requestAnimationFrame()을 사용하여 랜더링 개선하기

+ +

이제 게임 역학과 연결이 되지 않고, 그것이 렌더링되는 방식에 대해 연구해 봅시다. {{domxref("window.requestAnimationFrame", "requestAnimationFrame")}} 브라우저가 현재 Replace를 사용하여 구현한 고정 프레임보다 게임을 더 잘 랜더링할 수 있도록 {{domxref("windowTimers.setInterval()", "setInterval()")}} 도와줍니다:

+ +
var interval = setInterval(draw, 10);
+ +

간단하게:

+ +
draw();
+ +

다음 각 인스턴스를 제거합니다:

+ +
clearInterval(interval); // Needed for Chrome to end game
+
+ +

그 다음, draw()함수의 맨 아래 (닫는 '}'바로 전에) 다음 줄을 추가하여 draw()함수가 반복적으로 자신을 호출하게 합니다:

+ +
requestAnimationFrame(draw);
+ +

이 draw() 함수는 현재 requestAnimationFrame() 루프 내에서 반복적으로 실행되고 있지만, 고정된 10ms 프레임 대신 프레임의 제어권을 브라우저에 다시 부여 합니다. 이는 프레임과 적절하게 일치하고 필요할 때만 모양을 만들 것입니다. 이것은 이전의 setInterval() 방법보다 더 효율적이고 부드럽게 애니메이션 루프를 만듭니다.

+ +

코드 비교하기

+ +

그것이 이 레슨의 전부입니다. 게임의 최종버전이 준비되 있고 시작할 준비가 되어 있습니다!

+ +

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/dfh2tpu1/","","395")}}

+ +
+

Exercise: 남은 생명에 따라 공이 패들에서 튕겨나가는 각도를 변경합니다.

+
+ +

게임 오버 - 마무리!

+ +

축하합니다! 당신은 모든 수업을 완수하였습니다! 이쯤 되면 이제 캔버스의 조작 기초와 간단한 2D 게임 구현 방법을 알게 되었을 것 입니다. 이제 몇 가지 프레임워크를 배우고 게임 개발을 해 본 좋은 시간이였습니다.

+ +

이 시리즈의 2D breakout game using Phaser 또는 Cyber Orb built in Phaser 튜토리얼을 확인해 볼 수 있습니다. Games section on MDN의 섹션에서 더 많은 지식과 영감을 얻으십시오.

+ +

 

+ +

{{Previous("Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html new file mode 100644 index 0000000000..d0c72fb8b3 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html @@ -0,0 +1,77 @@ +--- +title: 게임 오버 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over +tags: + - 게임 + - 게임 오버 + - 그래픽 + - 자바스크립트 + - 초심자 + - 캔버스 + - 튜토리얼 +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Game_over +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임")}}
+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field")}}

+ +
+

이것은 Gamedev Canvas tutorial 의 다섯 번째 학습입니다. 이 학습을 통해 완성된 코드는 Gamedev-Canvas-workshop/lesson5.html 에서 확인할 수 있습니다.

+
+ +

공이 벽에서 튕겨져 나오는 것과 패들을 움직이는 것을 보는건 재밌지만, 더 진전이 필요합니다. 게임에서 질 수 있다면 좋겠습니다. 벽돌 깨기 게임에서 패배하는 구조는 꽤 단순합니다. 만약 패들이 공을 놓친다면, 공은 캔버스의 아래 면에 닿을 것이고, 그대로 게임은 끝납니다.

+ +

게임 오버 기능 적용하기

+ +

'게임 오버' 기능을 만들어봅시다. 아래에 세 번째 학습에서 작성한, 벽에서 공을 반사시키는 코드의 일부가 있습니다.

+ +
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
+    dx = -dx;
+}
+
+if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
+    dy = -dy;
+}
+ +

사면 모두에서 공을 튕겨내지 말고 왼쪽, 위쪽, 오른쪽, 세 면에만 적용해봅시다. 아래쪽 면에 닿는 순간 게임은 끝납니다. 우리는 공이 밑면에 충돌하는 순간 "게임 오버" 상태로 바뀌게 하기 위해 두 번째 if 블록을 수정할 것입니다. 우선 경고 메시지를 보여주고 페이지를 리로딩해서 게임을 다시 시작하게 할 것입니다. 두번째 if 블록을 아래와 같이 수정해봅시다.

+ +
if(y + dy < ballRadius) {
+    dy = -dy;
+} else if(y + dy > canvas.height-ballRadius) {
+    alert("GAME OVER");
+    document.location.reload();
+}
+ +

Paddle은 공을 튕겨내야지

+ +

이번 학습에서 할 마지막 일은 공과 패들 사이의 충돌 감지같은, 공을 게임 화면으로 되돌아가게 튕겨내는 기능을 만드는 것입니다. 가장 쉬운 방법은 공의 중심이 패들의 내부에 있는지 확인하는 것이다. 위에서 수정한 코드를 약간 고쳐봅시다.

+ +
if(y + dy < ballRadius) {
+    dy = -dy;
+} else if(y + dy > canvas.height-ballRadius) {
+    if(x > paddleX && x < paddleX + paddleWidth) {
+        dy = -dy;
+    }
+    else {
+        alert("GAME OVER");
+        document.location.reload();
+    }
+}
+ +

공이 캔버스의 밑면에 닿는 순간, 공이 패들의 안쪽에 있는지 확인해야 합니다. 만약 그렇다면, 우리가 기대하는대로 공은 튕겨져야 합니다. 그게 아니라면, 게임의 전과 같이 끝나야 합니다.

+ +

코드 비교하기

+ +

여기 완성된 코드가 있으니 작성한 코드와 비교해봅시다.

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/z4zy79fo/","","395")}}

+ +
+

연습: 공이 패들에 닿았을 때 공의 속도를 빠르게 만들어봅시다.

+
+ +

다음 단계

+ +

지금까지 아주 잘 하고 있습니다. 게임은 플레이 할 가치가 생겼고 이젠 게임이 끝날 수도 있습니다. 하지만 뭔가가 빠졌습니다. 여섯 번째 학습 — 벽돌 영역을 만들어보기 — 로 이동해서 몇 개의 벽돌을 만들어 봅시다.

+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/index.html new file mode 100644 index 0000000000..8b0e4da888 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/index.html @@ -0,0 +1,55 @@ +--- +title: 순수한 자바스크립트를 이용한 2D 벽돌깨기 게임 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임 +tags: + - 2D + - 게임 + - 자바스크립트 + - 캔버스 + - 튜토리얼 +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games")}}
+ +

{{Next("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기")}}

+ +

이 튜토리얼을 차례차례 진행하면서 우리는 HTML5 {{htmlelement("canvas")}} 로 렌더되는 순수하게 JavaScript로만 쓰여진 간단한 MDN 벽돌깨기 게임을 만들 것입니다.

+ +

모든 과정은 플레이 가능하고 편집가능한 라이브 샘플을 포함하고 있습니다. 이 샘플을 통해, 여러분은 중간 스테이지들이 어떻게 보여져야 하는지 확인할 수 있습니다. 여러분은 이미지의 렌더링과 움직임, 충돌 감지, 컨트롤 메카니즘들과 승리와 패배 상태와 같은 기본적인 게임 원리들을 구현하기 위해서, {{htmlelement("canvas")}}엘리먼트의 기본적인 사용 방법을  배우게 될 것입니다.

+ +

이 시리즈를 최대한 활용하려면 중급의 JavaScript 지식이 있어야 합니다. 이 튜토리얼을 끝낸 후에는 여러분은 스스로 간단한 웹 게임들을 만들 수 있게 될 것입니다.

+ +

Gameplay screen from the game MDN Breakout where you can use your paddle to bounce the ball and destroy the brick field, with keeping the score and lives.

+ +

강의 내용

+ +

모든 강의 내용과 우리가 함께 만드는 MDN 벽돌깨기 게임의 다른 버전들은 GitHub에서 찾을 수 있습니다.:

+ +
    +
  1. 캔버스 생성과 그리기
  2. +
  3. 공 움직이기
  4. +
  5. 벽으로 부터 튕겨나오기
  6. +
  7. 패들과 키보드 컨트롤
  8. +
  9. 게임 오버
  10. +
  11. 벽돌 필드 만들기
  12. +
  13. 충돌 감지
  14. +
  15. 점수 추적과 승리
  16. +
  17. 마우스 컨트롤
  18. +
  19. 마무리
  20. +
+ +

웹 게임 개발의 확고한 지식을 얻기 위한 최고의 방법은 순수하게 JavaScript만 이용해서 시작하는 것입니다. 이후에, 여러분은 프로젝트에 프레임워크를 골라서 사용할 수도 있습니다.  프레임워크들은 JavaScript로 만들어진 도구일 뿐입니다. 따라서 여러분이 프레임워크를 사용하더라도, 프레임워크 밑에서 정확히 어떤 일이 일어나는지 알기 위해 언어를 배우는것이 좋습니다. 프레임워크들은 개발 속도를 올려주고, 게임의 지루한 부분들을 해결하는데 도움을 줍니다. 하지만 어떤 일들이 기대한대로 일어나지 않는다면, 여러분은 디버그를 시도하거나 여러분 스스로 순수하게 JavaScript만 이용한 솔루션을 작성할 수 도 있습니다.

+ +
+

노트: 만약 여러분이 게임 라이브러리를 이용한 2D 웹 게임 개발의 학습에 흥미가 있다면,  이 시리즈의 대응 파트인 2D breakout game using Phaser를 살펴보시기 바랍니다.

+
+ +
+

노트: 이 시리즈의 내용들은 게임개발 워크숍의 재료로 쓰일 수 있습니다. 또한, 만약 여러분이 게임개발에 있어 강연을 원한다면 이 튜토리얼에 기초한 Gamedev Canvas Content Kit를 활용할 수 있습니다.

+
+ +

다음 단계

+ +

좋습니다, 이제 시작하도록 합시다. 첫 번째 챕터인 캔버스 생성과 그리기 부터 시작합니다.

+ +

{{Next("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기")}} 

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html new file mode 100644 index 0000000000..e05faf32e8 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html @@ -0,0 +1,57 @@ +--- +title: 마우스로 패들 조종하기 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Mouse_controls +tags: + - Canvas + - Games + - JavaScript +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Mouse_controls +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Finishing_up")}}

+ +
+

이 레슨은 Gamedev Canvas tutorial.의 10개 중 9 번째 단계입니다. 당신은 Gamedev-Canvas-workshop/lesson9.html. 이 소스코드에서 이 수업의 교훈을 찾을 수 있습니다.

+
+ +

경기 자체가 사실상 끝났으므로, 이를 다듬는 작업을 해봅시다. 우리는 이미 키보드로 조종하는 코드를 추가했지만 마우스 조종하는 코드를 쉽게 추가할 수 있습니다.

+ +

마우스 이동 감지하기

+ +

마우스 움직임을 감지하기 위해 감지를 하는 것은 키 감지를 하는 것보다 훨씬 더 쉽습니다. 우리가 필요한 것은 {{event("mousemove")}} 이 이벤트 감지입니다. 이 keyup event 바로 아래에 이 행을 추가하십시오.

+ +
document.addEventListener("mousemove", mouseMoveHandler, false);
+ +

마우스 움직임에 따라 패들 이동 하기

+ +

포인터 좌표에 따라 패들 위치를 업데이트를 할 수 있습니다. 다음과 같은 핸들러 기능을 정확하게 할 것입니다. 추가한 이전 줄 아래에 다음 함수를 추가하십시오:

+ +
function mouseMoveHandler(e) {
+    var relativeX = e.clientX - canvas.offsetLeft;
+    if(relativeX > 0 && relativeX < canvas.width) {
+        paddleX = relativeX - paddleWidth/2;
+    }
+}
+ +

이 함수에서 우리는 먼저 상대적인 relativeX 를 구합니다. 이 값은 뷰포트(e.clientX)와 캔버스 왼쪽 가장자리 (canvas.offsetLeft) 사이의 거리에 마우스 위치를 뺀 값입니다. 상대적인 X 포인터 위치가 0보다 크고 캔버스 폭보다 적으면 포인터가 경계 내에 있게 되고, paddleX의 위치(패들 왼쪽 가장자리에 배치되어 있다)는 패들 width의 반을 뺀 relativeX의 값으로 설정되므로 이동은 실제로 패들 가운데 상대적으로 이동이 됩니다.

+ +

이제 패들은 마우스 커서의 움직임을 따르겠지만, 움직임을 캔버스 크기로 제한하고 있기 때문에 어느 쪽에서도 완전히 사라지지 않을 것입니다.

+ +

코드 비교하기

+ +

지금까지 해왔던 코드를 한번 비교해보세요.

+ +

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/vt7y5hcp/","","395")}}

+ +
+

Exercise: 패들이 캔버스 양쪽 가장자리에서 반만 잘려나가 보일 것 입니다. 패들 이동 제한 경계를 조정해 보세요.

+
+ +

다음 단계

+ +

이제 우리는 완전한 게임을 할 수 있게 되었습니다. 우리는 몇 가지 작은 코드만으로 이 레슨을 마치게 될 것 입니다! — Finishing up. (마지막)

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Finishing_up")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html new file mode 100644 index 0000000000..5a8b02904e --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html @@ -0,0 +1,145 @@ +--- +title: 공 움직이기 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기 +tags: + - 2D + - 게임 + - 루프 + - 비기너 + - 움직임 + - 자바스크립트 + - 캔버스 + - 튜토리얼 +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Move_the_ball +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games")}}
+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls")}}

+ +
+

이 강의는 게임 개발 캔버스 튜토리얼의 10단계 중 두 번째 과정입니다.  Gamedev-Canvas-workshop/lesson2.html에서 이 강의의 완성된 코드를 볼 수 있습니다.

+
+ +

여러분은 이전 과정에서 어떻게 공이 그려지는지 배웠습니다. 이젠 공을 움직이게 만들어보죠! 기술적으로는 화면에 공을 그렸다가 지우는 과정을 반복하게 되는데, 매 프레임마다 공의 위치를 조금씩 다르게 해서 그리면 공이 움직이는것 처럼 보이게 됩니다. 마치 영화 화면이 움직이는 방식처럼 말이죠!

+ +

드로잉 루프를 정의하기

+ +

매 프레임마다 캔버스에 그리는것을 지속적으로 갱신하기 위해서는, 계속해서 그리는 것을 반복하게 만들어주는 함수가 필요합니다. 이 함수는 매 프레임마다 위치를 바꿔주기 위한 몇가지 변수들을 포함합니다.  JavaScript 타이밍 함수인 {{domxref("WindowTimers.setInterval()", "setInterval()")}}나 {{domxref("window.requestAnimationFrame()", "requestAnimationFrame()")}}를 이용하면 함수를 몇번이고 계속 반복해서 실행할 수 있습니다..

+ +

현재 여러분의 HTML파일 안에 있는 JavaScript중에 처음 두 줄만 제외하고 나머지는 모두 지워주세요. 지운 후에는 아래에 있는 코드를 추가해주세요. draw()함수는 setInterval를 통해서 10밀리초마다 실행됩니다.

+ +
function draw() {
+    // drawing code
+}
+setInterval(draw, 10);
+ +

무한히 작동하는 setInterval 함수 덕에, draw() 함수는 우리가 멈추기 전 까지 10밀리초마다 영원히 호출됩니다. 이제 공을 그려봅시다! 다음 코드를 여러분의 draw() 함수 안에 추가해주세요.

+ +
ctx.beginPath();
+ctx.arc(50, 50, 10, 0, Math.PI*2);
+ctx.fillStyle = "#0095DD";
+ctx.fill();
+ctx.closePath();
+
+ +

이제 바뀐 코드를 실행해 보세요. 공은 매 프레임마다 다시 그려지게 됩니다.

+ +

움직이게 만들기

+ +

공이 움직이지 않고 있기 때문에, 여러분은 공이 다시 그려지고 있다는 사실을 알아챌 수 는 없었을 것입니다. 이제 공을 움직이게 바꿔봅시다. 첫 번째로, (50,50)이라는 지정된 좌표 대신에, x와 y라는 변수를 이용해서 화면 하단 중앙에서 그려지도록 하겠습니다. 

+ +

x와 y를 정의하기 위해서 다음 두 줄을 여러분의 draw() 함수위에 추가해주세요.

+ +
var x = canvas.width/2;
+var y = canvas.height-30;
+
+ +

그 다음에는 draw() 함수를 갱신할 것입니다. 아래 코드에서 강조된 줄에서 처럼, {{domxref("CanvasRenderingContext2D.arc()","arc()")}}메소드안에서 x와 y 변수를 사용하게 됩니다.

+ +
function draw() {
+    ctx.beginPath();
+    ctx.arc(x, y, 10, 0, Math.PI*2);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+}
+
+ +

이제 중요한 부분입니다. 공을 움직이는 것을 표현하기 위해 x와 y에 작은 값을 매 프레임마다 더해줄 것입니다. 그 작은 값을 dx와 dy라 정의하고, 각각 2와 -2로 그 값을 정해보겠습니다. 다음 코드를 여러분의 x와 y변수가 정의된 코드 아래에 추가하세요.

+ +
var dx = 2;
+var dy = -2;
+
+ +

마지막으로 할 일은 dx와 dy변수를 이용해서 매 프레임마다 x와 y변수를 갱신해 주는 것입니다. 그렇게 하면 매 갱신마다 공은 새 위치에 그려지게 됩니다. 다음 코드에 표시된 새로운 두 줄의 코드를 여러분의 draw() 함수에 추가해주세요.

+ +
function draw() {
+    ctx.beginPath();
+    ctx.arc(x, y, 10, 0, Math.PI*2);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+    x += dx;
+    y += dy;
+}
+ +

여러분의 코드를 다시 저장하고, 브라우저를 열어 실행해보세요. 공은 잘 움직이는군요. 뒤에 흔적이 남기는 하지만 말이죠.

+ +

+ +

다음 프레임 전에 캔버스를 지우기

+ +

공이 흔적을 남기는 것은, 매 프레임마다 공을 그릴 때 이전 프레임을 지워주지 않았기 때문입니다. 하지만 걱정할 것은 없습니다. 캔버스의 내용들을 지워주기 위한 메소드인 {{domxref("CanvasRenderingContext2D.clearRect()","clearRect()")}}가 있으니까요. 이 메소드는 네 개의 파라미터가 필요합니다. 직사각형의 좌상단 모서리를 표시할 x와 y좌표, 그리고 직사각형의 우하단 모서리를 표시할 x와 y좌표가 바로 그것이죠. 이 좌표들로 생기는 사각형 안에 있는 것들은 전부 지워지게 될 것입니다.

+ +

다음 코드에서 강조된 새로운 한줄의 코드를 draw() 함수에 추가하세요.

+ +
function draw() {
+    ctx.clearRect(0, 0, canvas.width, canvas.height);
+    ctx.beginPath();
+    ctx.arc(x, y, 10, 0, Math.PI*2);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+    x += dx;
+    y += dy;
+}
+
+ +

여러분의 코드를 저장하고, 다시 실행해보세요. 이번에는 흔적없이 공이 움직이는 것을 보실 수 있을 것입니다. 매 10밀리초마다 캔버스는 지워지고, 새로운 x와 y값의 좌표를 가지는 공이 다음 프레임에 그려지게 되는 것이죠.

+ +

코드 정리하기

+ +

다음 강좌에서도 계속해서 몇가지 명령들을 draw() 함수에다 추가해야 합니다. 그렇기 때문에 코드를 최대한 간단하고 깨끗하게 유지하는 것이 좋습니다. 공을 움직이는 코드를 분리된 함수로 옮기는 것 부터 시작해보죠!

+ +

현재의 draw() 함수를 다음의 분리된 두 함수로 바꿔주세요.

+ +
function drawBall() {
+    ctx.beginPath();
+    ctx.arc(x, y, 10, 0, Math.PI*2);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+}
+
+function draw() {
+    ctx.clearRect(0, 0, canvas.width, canvas.height);
+    drawBall();
+    x += dx;
+    y += dy;
+}
+ +

여러분의 코드와 비교해보세요

+ +

아래의 라이브 데모에서 이 강의의 완성된 코드를 확인할 수 있습니다. 어떻게 작동하는지 더 잘 이해하기 위해 플레이 해보세요.

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/3x5foxb1/","","415")}}

+ +
+

연습해보기: 움직이는 공의 속도를 바꾸거나, 움직이는 방향을 바꿔보세요.

+
+ +

다음 단계로

+ +

우리는 공을 그리고 움직이게 만들었지만, 캔버스 모서리 밖으로 사라져버립니다. 세 번째 챕터에서는 공이 벽으로부터 튕겨 나오기 위한 방법을 알아볼 것입니다.

+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html new file mode 100644 index 0000000000..47cde1be4e --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html @@ -0,0 +1,122 @@ +--- +title: Paddle과 키보드 컨트롤 +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls +--- +
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/")}}
+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over")}}

+ +
+

이 글은 Gamedev Canvas tutorial의 10단계 중 4단계 입니다. 이 글을 다 읽고 난 뒤 완성된 소스코드는 Gamedev-Canvas-workshop/lesson4.html 에서 확인할 수 있습니다.

+
+ +

공이 계속해서 벽을 튕기며 이동하는 모습을 볼 수 있지만, 현재로서는 그것을 컨트롤 할 방법이 없습니다. 컨트롤 할 수 없으면 게임이 아니죠! paddle을 컨트롤 할 수 있는 몇가지 상호작용을 추가해 봅시다.

+ +

공을 치기 위한 paddle 정의

+ +

먼저, 우리는 공을 치기 위한 paddle이 필요합니다. 이를 위해 몇가지 변수들을 정의합시다. 코드 상단에 다른 변수들과 함께 아래 변수들을 추가하세요:

+ +
var paddleHeight = 10;
+var paddleWidth = 75;
+var paddleX = (canvas.width-paddleWidth)/2;
+ +

여기에서 paddle의 높이와 너비, 그리고  x 축 위에 시작 지점을 정의합니다. paddle을 스크린에 그리는 함수를 만듭시다. drawBall() 함수 아래에 다음 코드를 추가하세요:

+ +
function drawPaddle() {
+    ctx.beginPath();
+    ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
+    ctx.fillStyle = "#0095DD";
+    ctx.fill();
+    ctx.closePath();
+}
+ +

유저의 paddle 컨트롤

+ +

paddle은 우리가 원하는 곳 어디든 그릴 수 있지만, 사용자의 컨트롤에 반응해야 합니다. — 키보드 컨트롤을 구현합시다. 다음 내용이 필요합니다.:

+ + + +

버튼을 누르는 것은 boolean 변수로 정의하고 초기화 합니다. 아래 코드를 변수 선언 부분에 추가하세요. :

+ +
var rightPressed = false;
+var leftPressed = false;
+ +

처음에는 컨트롤 버튼이 눌려지지 않은 상태이므로 두개의 기본값은 false 입니다. 키가 눌렸음을 인식하기 위해, 이벤트 리스너를 설정합니다. 자바스크립트 하단에 setInterval() 바로 위에 아래 코드를 추가합니다.:

+ +
document.addEventListener("keydown", keyDownHandler, false);
+document.addEventListener("keyup", keyUpHandler, false);
+ +

키보드 중 어떤 키 하나가 눌려서 keydown 이벤트가 발생하면, keyDownHandler() 함수가 실행됩니다. 두번째 리스너에도 같은 패턴이 적용됩니다: 키에서 손을 때면 keyup 이벤트가 keyUpHandler() 함수를 실행합니다 . addEventListener() 아래에 다음 코드를 추가하세요:

+ +
function keyDownHandler(e) {
+    if(e.keyCode == 39) {
+        rightPressed = true;
+    }
+    else if(e.keyCode == 37) {
+        leftPressed = true;
+    }
+}
+
+function keyUpHandler(e) {
+    if(e.keyCode == 39) {
+        rightPressed = false;
+    }
+    else if(e.keyCode == 37) {
+        leftPressed = false;
+    }
+}
+ +

키를 누르면 변수에 정보가 저장됩니다. 각 경우에 관련된 변수가 true 로 설정됩니다. 키에서 손을 때면, 변수값은 false로 되돌아갑니다.

+ +

두 함수 모두 e 변수로 표시되는 이벤트를 파라미터로 사용합니다. 이것으로 유용한 정보를 얻을 수 있습니다: keyCode 는 눌려진 키에 대한 정보를 가지고 있습니다. 예를 들어 키 코드 37 은 왼쪽 방향키이고 39 는 오른쪽 방향키 입니다. 만약에 왼쪽 방향키를 누르면, leftPressed 변수가 true 로 설정되고, 왼쪽 방향키에서 손을 때면 leftPressed 변수가 false로 설정됩니다. 오른쪽 방향키와 rightPressed 변수에도 동일한 패턴이 적용됩니다.

+ +

Paddle 이동 로직

+ +

이제 우리는 눌려진 키, 이벤트 리스너, 관련된 함수에 대한 정보를 저장할 변수를 가지고 있습니다. 이제 실제 코드를 사용하여 이것들을 사용하고 paddle을 화면에서 움직여봅시다. draw() 함수에서, 각각의 프레임이 렌더링 될때마다 왼쪽이나 오른쪽 방향키가 눌려졌는지 확인합니다. 코드는 아래와 같습니다:

+ +
if(rightPressed) {
+    paddleX += 7;
+}
+else if(leftPressed) {
+    paddleX -= 7;
+}
+ +

만약 왼쪽 방향키를 누르면, paddle은 좌측으로 7픽셀 움직이고, 오른쪽 방향키를 누르면, 우측으로 7픽셀 움직입니다. 잘 작동하지만, 키를 너무 오래 누르고 있으면 paddle이 캔버스 밖으로 사라집니다. 아래처럼 코드를 수정해서 paddle이 캔버스 안에서만 움직이도록 개선합니다:

+ +
if(rightPressed && paddleX < canvas.width-paddleWidth) {
+    paddleX += 7;
+}
+else if(leftPressed && paddleX > 0) {
+    paddleX -= 7;
+}
+ +

paddleX 의 위치는 캔버스 왼쪽 끝 0 위치와 오른쪽 canvas.width-paddleWidth 에서 움직입니다.

+ +

위의 코드를 draw() 함수 아래쪽에 추가합니다.

+ +

이제 paddle이 화면에서 실제로 그려지도록 draw() 함수 안에서 drawPaddle() 을 호출합니다.  draw() 함수 안에  drawBall() 아래에 다음 코드를 추가합니다:

+ +
drawPaddle();
+
+ +

여러분의 코드와 비교해보세요

+ +

여기 움직이는 코드를 확인해보세요:

+ +

{{JSFiddleEmbed("https://jsfiddle.net/end3r/tgn3zscj/","","395")}}

+ +
+

Exercise: paddle의 움직임을 빠르거나 느리게, 혹은 사이즈를 변경해보세요.

+
+ +

다음 단계

+ +

게임과 비슷해지긴 했지만 한가지 문제는 게임이 끝나지 않는다는 것입니다. 5단계에서 Game over를 추가할 것입니다.

+ +

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over")}}

diff --git a/files/ko/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html new file mode 100644 index 0000000000..76883a1655 --- /dev/null +++ b/files/ko/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html @@ -0,0 +1,100 @@ +--- +title: Track the score and win +slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Track_the_score_and_win +tags: + - Canvas + - Games + - JavaScript +translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win +--- +
{{GamesSidebar}}
+ +
{{IncludeSubnav("/en-US/docs/Games")}}
+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

+ +
+

이번 단계는  Gamedev Canvas tutorial 의 8번째 단계입니다.  Gamedev-Canvas-workshop/lesson8.html 에서 이번 단계의 소스 코드를 확인할 수 있습니다.

+
+ +

벽돌 깨기 기능은 잘 작동한다. 하지만 더 나은 게임이 되기 위해서, 유저가 벽돌을 깰 때마다 점수를 얻고, 그 점수를 기록하는 Score 기능을 만든다.

+ +

점수 계산하기

+ +

게임 안에 점수 기능이 있다면, 친구들이 더 좋아할 것이다. 그러기 위해서는 점수를 기록할 변수가 필요합니다. 작성중인 JS파일의 변수 영역의 하단에, 아래 코드를 추가하자.

+ +
var score = 0;
+ +

점수 화면을 만들고, 업데이트를 하기 위해서 drawScore() 함수가 필요하다. 아래 코드를 collisionDetection() 함수 아래에 추가하자.

+ +
function drawScore() {
+    ctx.font = "16px Arial";
+    ctx.fillStyle = "#0095DD";
+    ctx.fillText("Score: "+score, 8, 20);
+}
+ +

텍스트를 캔버스 안에 그리는 것은 도형을 그리는 작업과 비슷하다. 폰트를 정의하는 것은 CSS에서의 작업과 같다. — {{domxref("CanvasRenderingContext2D.font","font()")}} 함수에서 크기와 타입을 설정할 수 있다. 그런 다음 {{domxref("CanvasRenderingContext2D.fillStyle()","fillStyle()")}} 함수를 사용하여 글꼴의 색상을 설정하고 {{domxref("CanvasRenderingContext2D.fillText","fillText()")}} 함수를 이용해서 캔버스에 배치 될 실제 텍스트와 배치 위치를 설정하는 데 사용한다. 첫 번째 매개 변수는 텍스트 자체다. 위의 코드는 현재 점의 수를 나타내며 마지막 두 매개 변수는 텍스트가 캔버스에 배치 될 좌표이다.

+ +

벽돌이 깨질 때마다 점수 변수의 값을 증가 시키기 위해서 collisionDetection() 함수에 강조 표시된 코드를 입력하여 수정한다.

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            if(b.status == 1) {
+                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
+                    dy = -dy;
+                    b.status = 0;
+                    score++;
+                }
+            }
+        }
+    }
+}
+ +

draw() 함수 안에서 위 함수를 호출하면 호출 될 때마다 다시 그리기 때문에 점수 변동을 확인할 수 있다. draw() 아래 코드를  drawPaddle() 아래에서 호출한다.

+ +
drawScore();
+ +

모든 벽돌이 파괴되었을 때 승리 메시지 표시

+ +

점수가 오르는 것은 좋지만, 평생 점수가 올라가진 않을 것이다. 모든 벽돌의 파괴가 결국 게임의 주된 목적이기 때문에 모든 점수를 얻는다면  승리 메시지를 표시해야한다.  collisionDetection()함수에 강조된 코드를 붙여넣는다.

+ +
function collisionDetection() {
+    for(var c=0; c<brickColumnCount; c++) {
+        for(var r=0; r<brickRowCount; r++) {
+            var b = bricks[c][r];
+            if(b.status == 1) {
+                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
+                    dy = -dy;
+                    b.status = 0;
+                    score++;
+                    if(score == brickRowCount*brickColumnCount) {
+                        alert("YOU WIN, CONGRATULATIONS!");
+                        document.location.reload();
+                    }
+                }
+            }
+        }
+    }
+}
+ +

결국 사용자는 모든 벽돌을 파괴 한 순간, 실제로 게임에서 승리 할 수 ​​있다. 이는 게임과 관련하여 굉장히 중요하다. document.location.reload()기능은 페이지를 다시로드하고 경고를 클릭하면 게임을 다시 시작한다.

+ +

코드 비교

+ +

최종 코드는 아래와 같다. 지금까지 작성한 코드와 비교해보자.

+ +

 

+ +

{{JSFiddleEmbed("https://jsfiddle.net/yumetodo/2m74vr9r/1/","","395")}}

+ +
+

추가학습: 벽돌을 깰 때마다 얻는 점수를 늘리고,  게임 클리어 시 최종 점수를 경고창에 표시해보자.

+
+ +

다음 단계

+ +

게임은 현재 꽤 멋지게 보인다. 다음 단계에서는,  Mouse controls (마우스로 패들 조종하는 방법) 을 통해서 게임을 즐길 수 있습니다.

+ +

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/bounce_off_the_walls/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/bounce_off_the_walls/index.html" deleted file mode 100644 index 2df00b91b9..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/bounce_off_the_walls/index.html" +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: 공을 벽에 튕기기 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls ---- -
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games")}}
- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls")}}

- -
-

이 글은 Gamedev Canvas 튜토리얼에 포함된 10단계 중 3단계 글입니다. 이 글을 다 읽고 난 뒤 완성된 소스코드는 Gamedev-Canvas-workshop/lesson3.html에서 확인해볼 수 있습니다.

-
- -

공이 움직이는 걸 보니 기쁩니다! 하지만 기쁨을 즐길 틈도 없이 공이 스크린 밖으로 사라져버리네요. 이 문제를 해결하기 위해 공이 캔버스의 4군데 모서리에 다달았을 때 튕겨나올 수 있도록 간단한 충돌 감지 기능(더 자세한 내용은 다음 글에서 다시 설명할 예정입니다)을 구현해야 합니다.

- -

간단한 충돌 감지

- -

충돌을 감지하기 위해서는 공이 벽에 닿았는지를 확인하고 그에 따라 움직이는 방향을 수정해야 합니다.

- -

보다 계산을 쉽게 하기 위하여 ballRadius 변수를 만든 뒤 원의 반지름 값을 대입하여 계산하는데 사용합니다. 아래의 코드를 기존의 변수들 아래에 삽입하세요:

- -
var ballRadius = 10;
- -

이제drawBall() func기능 안에 볼을 그리는 코드를 아래와 같이 수정하세요:

- -
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
- -

위 아래 방향으로 튕기기

- -

캔버스에는 총 4개의 모서리 즉, 4개의 벽이 있습니다. 일단 상단의 벽에 집중해 보겠습니다. 공을 그리는 매 프레임마다 우리는 볼이 상단 모서리에 닿았는지 확인해야합니다 — 닿았다면 볼이 움직이는 방향을 반대로 바꾸어 캔버스 안에 여전히 공이 보이도록 만들어주어야 합니다. 캔버스 내 위치 구조는 좌상단으로 부터 시작하는 것을 잊지마세요:

- -
if(y + dy < 0) {
-    dy = -dy;
-}
- -

만약 공의 위치에서 y값이 0보다 작은 경우 음/양수를 반대로 바꾸어주어 y 축의 방향을 바꾸어 줍니다. 공이 매 프레임마다 2픽셀만큼 움직이고 있었다면, 이제는 매 프레임마다 2픽셀만큼 "아래 방향으로" 이동할 것입니다.

- -

위 코드는 상단 모서리를 튕기도록 해주기 때문에 이번엔 하단 모서리를 튕기도록 해보겠습니다:

- -
if(y + dy > canvas.height) {
-    dy = -dy;
-}
- -

공의 위치에서 y값이 캔버스의 높이보다 큰 경우(좌상단으로부터 y값을 측정하기 때문에 상단모서리에서의 y값은 0, 하단모서리에서의 y값은 480, 즉 캔버서의 높이값임을 잊지마세요) y축 움직임의 반대 방향으로 튕겨냅니다.

- -

위의 두가지 코드를 하나로 합칠 수 있습니다:

- -
if(y + dy > canvas.height || y + dy < 0) {
-    dy = -dy;
-}
- -

둘 중 하나의 조건이라도 만족한다면, 공의 방향은 반대로 바뀝니다.

- -

좌우로 튕겨내기

- -

우리는 방금 상, 하단 모서리를 인식했으므로 이번엔 좌우 모서리를 생각해봅시다. 거의 같은 문제이므로 우리는 y 대신 x값을 대입하여 그대로 반복해주기만 하면 됩니다:

- -
if(x + dx > canvas.width || x + dx < 0) {
-    dx = -dx;
-}
-
-if(y + dy > canvas.height || y + dy < 0) {
-    dy = -dy;
-}
- -

이 후 위 코드를 draw() 함수블럭이 끝나는 중괄호 바로 전에 삽입합니다.

- -

공이 여전히 벽 밖으로 사라져요!

- -

코드를 테스트해보세요. — 아마 캔버스 모서리에서 튕겨나오는 볼이 인상적이지 않나요? 하지만 또 다른 문제가 생겼습니다. — 공이 벽을 튕겨나와 방향이 바뀌기 전에 살짝 벽 안으로 숨어버리네요:

- -

- -

이 문제는 우리가 충돌을 감지할 때 그 기준을 공의 원점에 두고 계산했지만, 원의 둘레를 기준으로 계산을 해야 하기 때문입니다. 벽에 공이 절반쯤 지난 뒤가 아니라 닿자마자 튕겨나와야 합니다. 이에 맞게 코드를 조금 수정해봅시다. 여러분이 삽입한 코드를 아래와 같이 수정해보세요:

- -
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
-    dx = -dx;
-}
-if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
-    dy = -dy;
-}
- -

공의 원점과 벽 사이의 거리가 공의 반지름과 같아졌을 때 공의 움직임이 바뀌도록 만들었습니다. 이제야 볼이 정확히 튕겨나오고 있네요.

- -

여러분의 코드를 비교해보세요

- -

자, 다시 여러분이 작성한 코드를 완성된 코드와 비교해보고 게임을 실행해보세요:

- -

{{JSFiddleEmbed("https://jsfiddle.net/end3r/redj37dc/","","370")}}

- -
-

Exercise: 공이 벽에 부딪힐 때마다 공의 색을 무작위로 변화시켜보세요.

-
- -

다음 단계

- -

이제 우리는 공이 게임판 안에서 어디서 어떻게 움직이고 있는지 파악했습니다. 네번째 챕터에서는 조작 가능한 배드를 구현해볼 것입니다. — 패드와 키보드 조작.

- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/build_the_brick_field/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/build_the_brick_field/index.html" deleted file mode 100644 index 9560da25e9..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/build_the_brick_field/index.html" +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: 벽돌 만들기 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Build_the_brick_field ---- -
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임")}}
- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Collision_detection")}}

- -
-

이번 단계는 Gamedev Canvas tutorial의 여섯 번째 학습입니다. Gamedev-Canvas-workshop/lesson6.html에서 이번 학습의 소스코드를 확인할 수 있습니다.

-
- -

게임플레이 원리를 수정한 후에, 우리는 게임에서 패배할 수 있게 되었습니다. 이것은 실제 게임에 보다 가까운 느낌이기 때문에 훌륭합니다. 하지만 벽과 패들에 공이 튀기는 것 말고 할 수 있는 것이 없기 때문에 금방 지루해집니다. 벽돌깨기 게임에서 진정으로 필요로 한 것은 공으로 파괴할 벽돌입니다. 이 것이 지금 우리가 만들 것입니다!

- -

벽돌에 대한 변수 설정하기

- -

이번 학습의 모든 목표는 벽돌들을 위한 코드를 2차원 배열로 동작하는 반복문을 통해 제공하는 것입니다. 그러나 먼저 우리는 가로, 세로, 행, 열 등 벽돌에 대한 값을 정의할 몇몇 변수들을 설정해야 합니다. 지난 학습에서 작성한 코드에 아래 코드를 추가해봅시다.

- -
var brickRowCount = 3;
-var brickColumnCount = 5;
-var brickWidth = 75;
-var brickHeight = 20;
-var brickPadding = 10;
-var brickOffsetTop = 30;
-var brickOffsetLeft = 30;
- -

우리는 벽돌 배열 행과 열의 수, 그것들의 가로, 세로길이, 각 벽돌이 서로 닿지 않을 정도의 간격과 벽돌이 캔버스의 모서리에 닿지 않게 할 오프셋 변수들을 정의했습니다.

- -

우리는 2차원 배열에 벽돌을 담았습니다. 배열은 열 c, 행 r, 그리고 배열의 각 객체엔 화면에 벽돌을 그릴 위치를 나타낼 x, y 위치를 가지고 있습니다. 위에서 변수를 선언한 코드 뒤에 아래 코드를 추가해봅시다.

- -
var bricks = [];
-for(var c=0; c<brickColumnCount; c++) {
-    bricks[c] = [];
-    for(var r=0; r<brickRowCount; r++) {
-        bricks[c][r] = { x: 0, y: 0 };
-    }
-}
- -

위 코드는 행과 열 수만큼 반복되면서 새로운 벽돌을 만듭니다. 각 벽돌 객체는 이후에 충돌감지에 사용됩니다.

- -

벽돌을 그리는 방법

- -

이제 배열안의 모든 벽돌을 반복해서 화면에 그려줄 함수를 만들어봅시다. 코드는 아래와 같습니다.

- -
function drawBricks() {
-    for(var c=0; c<brickColumnCount; c++) {
-        for(var r=0; r<brickRowCount; r++) {
-            bricks[c][r].x = 0;
-            bricks[c][r].y = 0;
-            ctx.beginPath();
-            ctx.rect(0, 0, brickWidth, brickHeight);
-            ctx.fillStyle = "#0095DD";
-            ctx.fill();
-            ctx.closePath();
-        }
-    }
-}
- -

다시 행, 열 반복을 통해 각 벽돌의 x, y 값을 설정하고, 캔버스에 brickWidth * brickHeight 크기의 벽돌들을 그립니다. 문제는 모든 벽돌들이 좌표 (0, 0) 위치해있다는 것입니다. 우리는 약간의 연산을 통해 각 벽돌의 x, y 값을 계산해야 합니다.

- -
var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
-var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
- -

 

- -

brickXbrickWidth + brickPaddingc를 곱하고, brickOffsetLeft를 더한 값입니다. brickY는 변수 r, brickHeight, brickOffsetTop 변수를 사용한다는 것을 제외하곤 동일합니다. 이제 모든 벽돌들을 올바른 위치에, 알맞은 간격을 두고, 캔버스 모서리로부터 오프셋 값만큼의 거리를 둔 상태로 그릴수 있게되었습니다.

- -

brickXbrickY 값을 (0, 0) 대신에 좌표 값으로 할당한 후에 drawBricks 함수의 마지막 버전은 아래와 같을 것입니다. 이 코드는 drawpaddle 함수 아래에 추가해봅시다.

- -
function drawBricks() {
-    for(var c=0; c<brickColumnCount; c++) {
-        for(var r=0; r<brickRowCount; r++) {
-            var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
-            var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
-            bricks[c][r].x = brickX;
-            bricks[c][r].y = brickY;
-            ctx.beginPath();
-            ctx.rect(brickX, brickY, brickWidth, brickHeight);
-            ctx.fillStyle = "#0095DD";
-            ctx.fill();
-            ctx.closePath();
-        }
-    }
-}
- -

실제 벽돌을 그리기

- -

이 학습에서 마지막으로 할 일은 drawBrick함수를 호출하는 코드를 draw함수 어딘가에, 되도록이면 시작하는 부분에, 캔버스를 초기화하는 부분과 공을 그리는 사이에 추가하는 것입니다.  아래 코드를 drawBall() 코드 위에 추가해봅시다.

- -
drawBricks();
-
- -

코드 비교해보기

- -

이 부분에서 게임은 조금 더 흥미로워졌습니다.

- -

{{JSFiddleEmbed("https://jsfiddle.net/yumetodo/t1zqmzLp/","","395")}}

- -
-

연습하기: 행과 열의 수를 바꿔서 벽돌의 수를 변경해보거나, 위치를 변경해봅시다.

-
- -

다음 단계

- -

이제 우리에겐 벽돌이 있습니다! 하지만 공은 벽돌들과의 반응이 없습니다. 우리는 다음 단계에서 이 문제에 대해 다룰 것입니다: 충돌 감지

- -

 

- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Collision_detection")}}

- -

 

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/collision_detection/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/collision_detection/index.html" deleted file mode 100644 index f312374938..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/collision_detection/index.html" +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: 충돌 감지 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Collision_detection -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Collision_detection ---- -
{{GamesSidebar}}
- -
{{IncludeSubnav("/ko/docs/Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임")}}
- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win")}}

- -
-

이 학습은 Gamedev Canvas tutorial의 일곱 번째 단계입니다. Gamedev-Canvas-workshop/lesson7.html에서 이번 학습에서 완성된 코드를 확인할 수 있습니다.

-
- -

지난 학습에서 우린 화면에 벽돌을 표현했습니다. 그러나 공은 벽돌은 그냥 지나가버리고 게임은 아직 흥미로워지려면 멀어보입니다. 우린 공이 벽돌을 파괴하고 튕겨져 나올 수 있도록 충돌 감지 기능을 고려해봐야 합니다.

- -

물론 어떻게 적용할지는 우리가 결정할 문제입니다. 그러나 공이 벽돌에 닿았는지 계산하는 일은 꽤나 까다로울 수 있습니다. 왜냐하면 캔버스엔 이를 위한 기능이 없기 때문입니다.  이번 학습은 가능한 쉬운 방법으로 진행될 것입니다. 우린 공의 중앙이 어느 벽돌과 충돌하는지 확인할 것입니다. 이는 항상 완벽한 결과를 주진 않지만, 충돌 감지를 위한 정교한 방법은 무궁무진합니다. 그러나 이 방법 역시 기본적인 개념을 학습하기에 꽤 괜찮습니다.

- -

충돌 감지 함수

- -

이 모든 것을 시작하기 위해 우리는 모든 벽돌들을 순회하고 각 벽돌의 좌표를 공의 위치와 비교하는 충돌 감지 함수를 만들어야 합니다. 코드의 가독성을 향상시키기 위해 충돌 감지의 반복에서 사용할 벽돌 객체를 저장하는 b 변수를 정의할 것입니다.

- -
function collisionDetection() {
-    for(var c=0; c<brickColumnCount; c++) {
-        for(var r=0; r<brickRowCount; r++) {
-            var b = bricks[c][r];
-            // calculations
-        }
-    }
-}
- -

만약 공의 중앙이 어떤 벽돌의 범위 내에 있을 경우, 공의 방향을 바꾸게 됩니다. 공이 벽돌 안에 존재하려면, 아래 4가지 조건이 참이어야 합니다.

- - - -

이 조건을 코드로 작성해봅시다.

- -
function collisionDetection() {
-    for(var c=0; c<brickColumnCount; c++) {
-        for(var r=0; r<brickRowCount; r++) {
-            var b = bricks[c][r];
-            if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
-                dy = -dy;
-            }
-        }
-    }
-}
- -

위 코드를 keyUpHandler() 함수 아래에 추가해봅시다.

- -

충돌 후에 벽돌을 사라지게 만들기

- -

위의 코드는 우리가 의도한대로 작동할 것이고 공은 방향을 바꿀 것입니다. 문제는 벽돌이 그대로 있다는 것입니다. 우린 이미 공이 부딪힌 벽돌을 제거하기 위한 방법을 고민해봐야 합니다. 우리는 화면에 있는 벽돌을 그릴지 결정하는 변수를 추가해서 이 문제를 해결할 수 있습니다, 벽돌을 초기화하는 코드에, status 속성을 각 벽돌 객체에 추가해봅시다. 아래와 같이 말입니다.

- -
var bricks = [];
-for(var c=0; c<brickColumnCount; c++) {
-    bricks[c] = [];
-    for(var r=0; r<brickRowCount; r++) {
-        bricks[c][r] = { x: 0, y: 0, status: 1 };
-    }
-}
- -

다음으로 drawBricks 함수에서 벽돌들을 그리기 전에 status 속성을 확인해야 합니다. 만약 status가 1이라면 벽돌을 그리고, 만약 0이라면 이미 공이 치고간 벽돌이므로 우린 더이상 화면에 그릴 필요가 없습니다. 아래와 같이 drawBricks 함수를 수정해봅시다,

- -
function drawBricks() {
-    for(var c=0; c<brickColumnCount; c++) {
-        for(var r=0; r<brickRowCount; r++) {
-            if(bricks[c][r].status == 1) {
-                var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
-                var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
-                bricks[c][r].x = brickX;
-                bricks[c][r].y = brickY;
-                ctx.beginPath();
-                ctx.rect(brickX, brickY, brickWidth, brickHeight);
-                ctx.fillStyle = "#0095DD";
-                ctx.fill();
-                ctx.closePath();
-            }
-        }
-    }
-}
- -

충돌 감지함수에서 상태 추적 및 업데이트

- -

이제 collisonDectection 함수에 벽돌 status 속성을 포함시켜야 합니다. 만약 벽돌이 활성 상태(status 1)이라면 충돌이 일어났는지 확인해야 합니다. 만약 충돌이 발생했다면 다시 그리지 않게 벽돌의 속성을 0으로 변경해야 합니다. collisionDetection 함수를 아래와 같이 수정합시다.

- -
function collisionDetection() {
-    for(var c=0; c<brickColumnCount; c++) {
-        for(var r=0; r<brickRowCount; r++) {
-            var b = bricks[c][r];
-            if(b.status == 1) {
-                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
-                    dy = -dy;
-                    b.status = 0;
-                }
-            }
-        }
-    }
-}
- -

충돌 감지 활성화하기

- -

마지막으로 할일은 draw함수에서 collisionDetection 함수를 호출하는 것입니다. 아래 코드를 draw 함수에, drawPaddle() 아래에 추가해봅시다.

- -
collisionDetection();
-
- -

코드 비교하기

- -

이제 매 프레임마다 충돌 감지를 확인할 것입니다. 이제 우린 별돌을 파괴할 수 있습니다!

- -

{{JSFiddleEmbed("https://jsfiddle.net/yumetodo/mkwtxgc3/3/","","395")}}

- -
-

연습하기: 벽돌이 부딪힐 때마다 색깔을 바꿔보세요.

-
- -

다음 단계

- -

우리는 충분히 여기까지 왔습니다! 이제 어덟 번째 장에서는 점수를 추가와 승패 판정 방법을 알아 볼 것입니다.

- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/finishing_up/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/finishing_up/index.html" deleted file mode 100644 index b23a4b6b33..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/finishing_up/index.html" +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: 개발 마무리 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Finishing_up -tags: - - Canvas - - Games - - JavaScript -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Finishing_up ---- -
{{GamesSidebar}}
- -
{{IncludeSubnav("/en-US/docs/Games")}}
- -

{{Previous("Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

- -
-

Gamedev Canvas tutorial.의 10 개의 레슨 중 마지막 단계 입니다. 이 수업을 마친 후 비교하여 살펴 볼 소스코드는 Gamedev-Canvas-workshop/lesson10.html. 여기서 찾아 볼 수 있습니다.

-
- -

우리가 쓰는 모든 게임에 항상 개선해야 할 것이 있습니다. 예를 들어 이 게임에 2인용 플레이어를 추가할 수 있습니다. 한두 번 잘못 만들어 경기를 끝낼 수도 있습니다. 그러나 우리는 코드 렌더링을 향상시켜 발전할 수 있습니다.

- -

플레이어에게 생명을 부여하기

- -

생명을 구현하는 방법은 아주 간단하다. 먼저 변수를 선언했던 곳과 같은 장소에서  변수를 추가하여 생명 수를 저장합니다.

- -
var lives = 3; //남은 생명 수
- -

남은 생명 수를 표시하는 방법은 점수 카운터가 그려지는 것과 같은 형태 입니다. drawScore()함수 아래에 다음 기능을 추가 하십시오.

- -
function drawLives() {
-    ctx.font = "16px Arial";
-    ctx.fillStyle = "#0095DD";
-    ctx.fillText("Lives: "+lives, canvas.width-65, 20);
-}
- -

지금까지 바닥에 닿으면 바로 게임을 끝내는 형식이였습니다. 이제 우리는 더 이상 게임을 이용할 수 없게 될 때까지 남은 생명 수를 줄일 것입니다. 또한 플레이어가 게임 오버되면 다시 생명과 블럭들을 리셋하여 공과 패들 위치를 재설정할 수 있습니다. draw() 함수는 다음 세 줄로 대체합니다:

- -
alert("GAME OVER");
-document.location.reload();
-clearInterval(interval); // Needed for Chrome to end game
-
- -

 

- -

 

- -

이를 통해 아래와 같이 약간 복잡한 논리를 추가할 수 있습니다:

- -
lives--;
-if(!lives) {
-    alert("GAME OVER");
-    document.location.reload();
-    clearInterval(interval); // Needed for Chrome to end game
-}
-else {
-    x = canvas.width/2;
-    y = canvas.height-30;
-    dx = 2;
-    dy = -2;
-    paddleX = (canvas.width-paddleWidth)/2;
-}
- -

자, 이제 공이 화면의 맨아래 가장자리에 맞으면 생명(lives)을 하나 뺍니다. 생명이 없다면 게임이 끝나고 아직 남아있다면 공의 위치와 패들의 위치가 재설정 됩니다.

- -

남은 생명 표시 렌더링하기

- -

이제 draw()함수 내에서 drawLives()에 생명 수를 추가하고 drawLives() 아래에 생명 수를 추가해야 합니다.

- -
drawLives();
-
- -

requestAnimationFrame()을 사용하여 랜더링 개선하기

- -

이제 게임 역학과 연결이 되지 않고, 그것이 렌더링되는 방식에 대해 연구해 봅시다. {{domxref("window.requestAnimationFrame", "requestAnimationFrame")}} 브라우저가 현재 Replace를 사용하여 구현한 고정 프레임보다 게임을 더 잘 랜더링할 수 있도록 {{domxref("windowTimers.setInterval()", "setInterval()")}} 도와줍니다:

- -
var interval = setInterval(draw, 10);
- -

간단하게:

- -
draw();
- -

다음 각 인스턴스를 제거합니다:

- -
clearInterval(interval); // Needed for Chrome to end game
-
- -

그 다음, draw()함수의 맨 아래 (닫는 '}'바로 전에) 다음 줄을 추가하여 draw()함수가 반복적으로 자신을 호출하게 합니다:

- -
requestAnimationFrame(draw);
- -

이 draw() 함수는 현재 requestAnimationFrame() 루프 내에서 반복적으로 실행되고 있지만, 고정된 10ms 프레임 대신 프레임의 제어권을 브라우저에 다시 부여 합니다. 이는 프레임과 적절하게 일치하고 필요할 때만 모양을 만들 것입니다. 이것은 이전의 setInterval() 방법보다 더 효율적이고 부드럽게 애니메이션 루프를 만듭니다.

- -

코드 비교하기

- -

그것이 이 레슨의 전부입니다. 게임의 최종버전이 준비되 있고 시작할 준비가 되어 있습니다!

- -

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/dfh2tpu1/","","395")}}

- -
-

Exercise: 남은 생명에 따라 공이 패들에서 튕겨나가는 각도를 변경합니다.

-
- -

게임 오버 - 마무리!

- -

축하합니다! 당신은 모든 수업을 완수하였습니다! 이쯤 되면 이제 캔버스의 조작 기초와 간단한 2D 게임 구현 방법을 알게 되었을 것 입니다. 이제 몇 가지 프레임워크를 배우고 게임 개발을 해 본 좋은 시간이였습니다.

- -

이 시리즈의 2D breakout game using Phaser 또는 Cyber Orb built in Phaser 튜토리얼을 확인해 볼 수 있습니다. Games section on MDN의 섹션에서 더 많은 지식과 영감을 얻으십시오.

- -

 

- -

{{Previous("Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/game_over/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/game_over/index.html" deleted file mode 100644 index d0c72fb8b3..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/game_over/index.html" +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: 게임 오버 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over -tags: - - 게임 - - 게임 오버 - - 그래픽 - - 자바스크립트 - - 초심자 - - 캔버스 - - 튜토리얼 -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Game_over ---- -
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임")}}
- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field")}}

- -
-

이것은 Gamedev Canvas tutorial 의 다섯 번째 학습입니다. 이 학습을 통해 완성된 코드는 Gamedev-Canvas-workshop/lesson5.html 에서 확인할 수 있습니다.

-
- -

공이 벽에서 튕겨져 나오는 것과 패들을 움직이는 것을 보는건 재밌지만, 더 진전이 필요합니다. 게임에서 질 수 있다면 좋겠습니다. 벽돌 깨기 게임에서 패배하는 구조는 꽤 단순합니다. 만약 패들이 공을 놓친다면, 공은 캔버스의 아래 면에 닿을 것이고, 그대로 게임은 끝납니다.

- -

게임 오버 기능 적용하기

- -

'게임 오버' 기능을 만들어봅시다. 아래에 세 번째 학습에서 작성한, 벽에서 공을 반사시키는 코드의 일부가 있습니다.

- -
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) {
-    dx = -dx;
-}
-
-if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) {
-    dy = -dy;
-}
- -

사면 모두에서 공을 튕겨내지 말고 왼쪽, 위쪽, 오른쪽, 세 면에만 적용해봅시다. 아래쪽 면에 닿는 순간 게임은 끝납니다. 우리는 공이 밑면에 충돌하는 순간 "게임 오버" 상태로 바뀌게 하기 위해 두 번째 if 블록을 수정할 것입니다. 우선 경고 메시지를 보여주고 페이지를 리로딩해서 게임을 다시 시작하게 할 것입니다. 두번째 if 블록을 아래와 같이 수정해봅시다.

- -
if(y + dy < ballRadius) {
-    dy = -dy;
-} else if(y + dy > canvas.height-ballRadius) {
-    alert("GAME OVER");
-    document.location.reload();
-}
- -

Paddle은 공을 튕겨내야지

- -

이번 학습에서 할 마지막 일은 공과 패들 사이의 충돌 감지같은, 공을 게임 화면으로 되돌아가게 튕겨내는 기능을 만드는 것입니다. 가장 쉬운 방법은 공의 중심이 패들의 내부에 있는지 확인하는 것이다. 위에서 수정한 코드를 약간 고쳐봅시다.

- -
if(y + dy < ballRadius) {
-    dy = -dy;
-} else if(y + dy > canvas.height-ballRadius) {
-    if(x > paddleX && x < paddleX + paddleWidth) {
-        dy = -dy;
-    }
-    else {
-        alert("GAME OVER");
-        document.location.reload();
-    }
-}
- -

공이 캔버스의 밑면에 닿는 순간, 공이 패들의 안쪽에 있는지 확인해야 합니다. 만약 그렇다면, 우리가 기대하는대로 공은 튕겨져야 합니다. 그게 아니라면, 게임의 전과 같이 끝나야 합니다.

- -

코드 비교하기

- -

여기 완성된 코드가 있으니 작성한 코드와 비교해봅시다.

- -

{{JSFiddleEmbed("https://jsfiddle.net/end3r/z4zy79fo/","","395")}}

- -
-

연습: 공이 패들에 닿았을 때 공의 속도를 빠르게 만들어봅시다.

-
- -

다음 단계

- -

지금까지 아주 잘 하고 있습니다. 게임은 플레이 할 가치가 생겼고 이젠 게임이 끝날 수도 있습니다. 하지만 뭔가가 빠졌습니다. 여섯 번째 학습 — 벽돌 영역을 만들어보기 — 로 이동해서 몇 개의 벽돌을 만들어 봅시다.

- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Build_the_brick_field")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/index.html" deleted file mode 100644 index 8b0e4da888..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/index.html" +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: 순수한 자바스크립트를 이용한 2D 벽돌깨기 게임 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임 -tags: - - 2D - - 게임 - - 자바스크립트 - - 캔버스 - - 튜토리얼 -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript ---- -
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games")}}
- -

{{Next("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기")}}

- -

이 튜토리얼을 차례차례 진행하면서 우리는 HTML5 {{htmlelement("canvas")}} 로 렌더되는 순수하게 JavaScript로만 쓰여진 간단한 MDN 벽돌깨기 게임을 만들 것입니다.

- -

모든 과정은 플레이 가능하고 편집가능한 라이브 샘플을 포함하고 있습니다. 이 샘플을 통해, 여러분은 중간 스테이지들이 어떻게 보여져야 하는지 확인할 수 있습니다. 여러분은 이미지의 렌더링과 움직임, 충돌 감지, 컨트롤 메카니즘들과 승리와 패배 상태와 같은 기본적인 게임 원리들을 구현하기 위해서, {{htmlelement("canvas")}}엘리먼트의 기본적인 사용 방법을  배우게 될 것입니다.

- -

이 시리즈를 최대한 활용하려면 중급의 JavaScript 지식이 있어야 합니다. 이 튜토리얼을 끝낸 후에는 여러분은 스스로 간단한 웹 게임들을 만들 수 있게 될 것입니다.

- -

Gameplay screen from the game MDN Breakout where you can use your paddle to bounce the ball and destroy the brick field, with keeping the score and lives.

- -

강의 내용

- -

모든 강의 내용과 우리가 함께 만드는 MDN 벽돌깨기 게임의 다른 버전들은 GitHub에서 찾을 수 있습니다.:

- -
    -
  1. 캔버스 생성과 그리기
  2. -
  3. 공 움직이기
  4. -
  5. 벽으로 부터 튕겨나오기
  6. -
  7. 패들과 키보드 컨트롤
  8. -
  9. 게임 오버
  10. -
  11. 벽돌 필드 만들기
  12. -
  13. 충돌 감지
  14. -
  15. 점수 추적과 승리
  16. -
  17. 마우스 컨트롤
  18. -
  19. 마무리
  20. -
- -

웹 게임 개발의 확고한 지식을 얻기 위한 최고의 방법은 순수하게 JavaScript만 이용해서 시작하는 것입니다. 이후에, 여러분은 프로젝트에 프레임워크를 골라서 사용할 수도 있습니다.  프레임워크들은 JavaScript로 만들어진 도구일 뿐입니다. 따라서 여러분이 프레임워크를 사용하더라도, 프레임워크 밑에서 정확히 어떤 일이 일어나는지 알기 위해 언어를 배우는것이 좋습니다. 프레임워크들은 개발 속도를 올려주고, 게임의 지루한 부분들을 해결하는데 도움을 줍니다. 하지만 어떤 일들이 기대한대로 일어나지 않는다면, 여러분은 디버그를 시도하거나 여러분 스스로 순수하게 JavaScript만 이용한 솔루션을 작성할 수 도 있습니다.

- -
-

노트: 만약 여러분이 게임 라이브러리를 이용한 2D 웹 게임 개발의 학습에 흥미가 있다면,  이 시리즈의 대응 파트인 2D breakout game using Phaser를 살펴보시기 바랍니다.

-
- -
-

노트: 이 시리즈의 내용들은 게임개발 워크숍의 재료로 쓰일 수 있습니다. 또한, 만약 여러분이 게임개발에 있어 강연을 원한다면 이 튜토리얼에 기초한 Gamedev Canvas Content Kit를 활용할 수 있습니다.

-
- -

다음 단계

- -

좋습니다, 이제 시작하도록 합시다. 첫 번째 챕터인 캔버스 생성과 그리기 부터 시작합니다.

- -

{{Next("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기")}} 

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/mouse_controls/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/mouse_controls/index.html" deleted file mode 100644 index e05faf32e8..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/mouse_controls/index.html" +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: 마우스로 패들 조종하기 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Mouse_controls -tags: - - Canvas - - Games - - JavaScript -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Mouse_controls ---- -
{{GamesSidebar}}
- -
{{IncludeSubnav("/en-US/docs/Games")}}
- -

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Finishing_up")}}

- -
-

이 레슨은 Gamedev Canvas tutorial.의 10개 중 9 번째 단계입니다. 당신은 Gamedev-Canvas-workshop/lesson9.html. 이 소스코드에서 이 수업의 교훈을 찾을 수 있습니다.

-
- -

경기 자체가 사실상 끝났으므로, 이를 다듬는 작업을 해봅시다. 우리는 이미 키보드로 조종하는 코드를 추가했지만 마우스 조종하는 코드를 쉽게 추가할 수 있습니다.

- -

마우스 이동 감지하기

- -

마우스 움직임을 감지하기 위해 감지를 하는 것은 키 감지를 하는 것보다 훨씬 더 쉽습니다. 우리가 필요한 것은 {{event("mousemove")}} 이 이벤트 감지입니다. 이 keyup event 바로 아래에 이 행을 추가하십시오.

- -
document.addEventListener("mousemove", mouseMoveHandler, false);
- -

마우스 움직임에 따라 패들 이동 하기

- -

포인터 좌표에 따라 패들 위치를 업데이트를 할 수 있습니다. 다음과 같은 핸들러 기능을 정확하게 할 것입니다. 추가한 이전 줄 아래에 다음 함수를 추가하십시오:

- -
function mouseMoveHandler(e) {
-    var relativeX = e.clientX - canvas.offsetLeft;
-    if(relativeX > 0 && relativeX < canvas.width) {
-        paddleX = relativeX - paddleWidth/2;
-    }
-}
- -

이 함수에서 우리는 먼저 상대적인 relativeX 를 구합니다. 이 값은 뷰포트(e.clientX)와 캔버스 왼쪽 가장자리 (canvas.offsetLeft) 사이의 거리에 마우스 위치를 뺀 값입니다. 상대적인 X 포인터 위치가 0보다 크고 캔버스 폭보다 적으면 포인터가 경계 내에 있게 되고, paddleX의 위치(패들 왼쪽 가장자리에 배치되어 있다)는 패들 width의 반을 뺀 relativeX의 값으로 설정되므로 이동은 실제로 패들 가운데 상대적으로 이동이 됩니다.

- -

이제 패들은 마우스 커서의 움직임을 따르겠지만, 움직임을 캔버스 크기로 제한하고 있기 때문에 어느 쪽에서도 완전히 사라지지 않을 것입니다.

- -

코드 비교하기

- -

지금까지 해왔던 코드를 한번 비교해보세요.

- -

{{JSFiddleEmbed("https://jsfiddle.net/raymondjplante/vt7y5hcp/","","395")}}

- -
-

Exercise: 패들이 캔버스 양쪽 가장자리에서 반만 잘려나가 보일 것 입니다. 패들 이동 제한 경계를 조정해 보세요.

-
- -

다음 단계

- -

이제 우리는 완전한 게임을 할 수 있게 되었습니다. 우리는 몇 가지 작은 코드만으로 이 레슨을 마치게 될 것 입니다! — Finishing up. (마지막)

- -

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Finishing_up")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/paddle_and_keyboard_controls/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/paddle_and_keyboard_controls/index.html" deleted file mode 100644 index 47cde1be4e..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/paddle_and_keyboard_controls/index.html" +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Paddle과 키보드 컨트롤 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Paddle_and_keyboard_controls -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls ---- -
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/")}}
- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over")}}

- -
-

이 글은 Gamedev Canvas tutorial의 10단계 중 4단계 입니다. 이 글을 다 읽고 난 뒤 완성된 소스코드는 Gamedev-Canvas-workshop/lesson4.html 에서 확인할 수 있습니다.

-
- -

공이 계속해서 벽을 튕기며 이동하는 모습을 볼 수 있지만, 현재로서는 그것을 컨트롤 할 방법이 없습니다. 컨트롤 할 수 없으면 게임이 아니죠! paddle을 컨트롤 할 수 있는 몇가지 상호작용을 추가해 봅시다.

- -

공을 치기 위한 paddle 정의

- -

먼저, 우리는 공을 치기 위한 paddle이 필요합니다. 이를 위해 몇가지 변수들을 정의합시다. 코드 상단에 다른 변수들과 함께 아래 변수들을 추가하세요:

- -
var paddleHeight = 10;
-var paddleWidth = 75;
-var paddleX = (canvas.width-paddleWidth)/2;
- -

여기에서 paddle의 높이와 너비, 그리고  x 축 위에 시작 지점을 정의합니다. paddle을 스크린에 그리는 함수를 만듭시다. drawBall() 함수 아래에 다음 코드를 추가하세요:

- -
function drawPaddle() {
-    ctx.beginPath();
-    ctx.rect(paddleX, canvas.height-paddleHeight, paddleWidth, paddleHeight);
-    ctx.fillStyle = "#0095DD";
-    ctx.fill();
-    ctx.closePath();
-}
- -

유저의 paddle 컨트롤

- -

paddle은 우리가 원하는 곳 어디든 그릴 수 있지만, 사용자의 컨트롤에 반응해야 합니다. — 키보드 컨트롤을 구현합시다. 다음 내용이 필요합니다.:

- - - -

버튼을 누르는 것은 boolean 변수로 정의하고 초기화 합니다. 아래 코드를 변수 선언 부분에 추가하세요. :

- -
var rightPressed = false;
-var leftPressed = false;
- -

처음에는 컨트롤 버튼이 눌려지지 않은 상태이므로 두개의 기본값은 false 입니다. 키가 눌렸음을 인식하기 위해, 이벤트 리스너를 설정합니다. 자바스크립트 하단에 setInterval() 바로 위에 아래 코드를 추가합니다.:

- -
document.addEventListener("keydown", keyDownHandler, false);
-document.addEventListener("keyup", keyUpHandler, false);
- -

키보드 중 어떤 키 하나가 눌려서 keydown 이벤트가 발생하면, keyDownHandler() 함수가 실행됩니다. 두번째 리스너에도 같은 패턴이 적용됩니다: 키에서 손을 때면 keyup 이벤트가 keyUpHandler() 함수를 실행합니다 . addEventListener() 아래에 다음 코드를 추가하세요:

- -
function keyDownHandler(e) {
-    if(e.keyCode == 39) {
-        rightPressed = true;
-    }
-    else if(e.keyCode == 37) {
-        leftPressed = true;
-    }
-}
-
-function keyUpHandler(e) {
-    if(e.keyCode == 39) {
-        rightPressed = false;
-    }
-    else if(e.keyCode == 37) {
-        leftPressed = false;
-    }
-}
- -

키를 누르면 변수에 정보가 저장됩니다. 각 경우에 관련된 변수가 true 로 설정됩니다. 키에서 손을 때면, 변수값은 false로 되돌아갑니다.

- -

두 함수 모두 e 변수로 표시되는 이벤트를 파라미터로 사용합니다. 이것으로 유용한 정보를 얻을 수 있습니다: keyCode 는 눌려진 키에 대한 정보를 가지고 있습니다. 예를 들어 키 코드 37 은 왼쪽 방향키이고 39 는 오른쪽 방향키 입니다. 만약에 왼쪽 방향키를 누르면, leftPressed 변수가 true 로 설정되고, 왼쪽 방향키에서 손을 때면 leftPressed 변수가 false로 설정됩니다. 오른쪽 방향키와 rightPressed 변수에도 동일한 패턴이 적용됩니다.

- -

Paddle 이동 로직

- -

이제 우리는 눌려진 키, 이벤트 리스너, 관련된 함수에 대한 정보를 저장할 변수를 가지고 있습니다. 이제 실제 코드를 사용하여 이것들을 사용하고 paddle을 화면에서 움직여봅시다. draw() 함수에서, 각각의 프레임이 렌더링 될때마다 왼쪽이나 오른쪽 방향키가 눌려졌는지 확인합니다. 코드는 아래와 같습니다:

- -
if(rightPressed) {
-    paddleX += 7;
-}
-else if(leftPressed) {
-    paddleX -= 7;
-}
- -

만약 왼쪽 방향키를 누르면, paddle은 좌측으로 7픽셀 움직이고, 오른쪽 방향키를 누르면, 우측으로 7픽셀 움직입니다. 잘 작동하지만, 키를 너무 오래 누르고 있으면 paddle이 캔버스 밖으로 사라집니다. 아래처럼 코드를 수정해서 paddle이 캔버스 안에서만 움직이도록 개선합니다:

- -
if(rightPressed && paddleX < canvas.width-paddleWidth) {
-    paddleX += 7;
-}
-else if(leftPressed && paddleX > 0) {
-    paddleX -= 7;
-}
- -

paddleX 의 위치는 캔버스 왼쪽 끝 0 위치와 오른쪽 canvas.width-paddleWidth 에서 움직입니다.

- -

위의 코드를 draw() 함수 아래쪽에 추가합니다.

- -

이제 paddle이 화면에서 실제로 그려지도록 draw() 함수 안에서 drawPaddle() 을 호출합니다.  draw() 함수 안에  drawBall() 아래에 다음 코드를 추가합니다:

- -
drawPaddle();
-
- -

여러분의 코드와 비교해보세요

- -

여기 움직이는 코드를 확인해보세요:

- -

{{JSFiddleEmbed("https://jsfiddle.net/end3r/tgn3zscj/","","395")}}

- -
-

Exercise: paddle의 움직임을 빠르거나 느리게, 혹은 사이즈를 변경해보세요.

-
- -

다음 단계

- -

게임과 비슷해지긴 했지만 한가지 문제는 게임이 끝나지 않는다는 것입니다. 5단계에서 Game over를 추가할 것입니다.

- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Game_over")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/track_the_score_and_win/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/track_the_score_and_win/index.html" deleted file mode 100644 index 76883a1655..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/track_the_score_and_win/index.html" +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Track the score and win -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Track_the_score_and_win -tags: - - Canvas - - Games - - JavaScript -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win ---- -
{{GamesSidebar}}
- -
{{IncludeSubnav("/en-US/docs/Games")}}
- -

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

- -
-

이번 단계는  Gamedev Canvas tutorial 의 8번째 단계입니다.  Gamedev-Canvas-workshop/lesson8.html 에서 이번 단계의 소스 코드를 확인할 수 있습니다.

-
- -

벽돌 깨기 기능은 잘 작동한다. 하지만 더 나은 게임이 되기 위해서, 유저가 벽돌을 깰 때마다 점수를 얻고, 그 점수를 기록하는 Score 기능을 만든다.

- -

점수 계산하기

- -

게임 안에 점수 기능이 있다면, 친구들이 더 좋아할 것이다. 그러기 위해서는 점수를 기록할 변수가 필요합니다. 작성중인 JS파일의 변수 영역의 하단에, 아래 코드를 추가하자.

- -
var score = 0;
- -

점수 화면을 만들고, 업데이트를 하기 위해서 drawScore() 함수가 필요하다. 아래 코드를 collisionDetection() 함수 아래에 추가하자.

- -
function drawScore() {
-    ctx.font = "16px Arial";
-    ctx.fillStyle = "#0095DD";
-    ctx.fillText("Score: "+score, 8, 20);
-}
- -

텍스트를 캔버스 안에 그리는 것은 도형을 그리는 작업과 비슷하다. 폰트를 정의하는 것은 CSS에서의 작업과 같다. — {{domxref("CanvasRenderingContext2D.font","font()")}} 함수에서 크기와 타입을 설정할 수 있다. 그런 다음 {{domxref("CanvasRenderingContext2D.fillStyle()","fillStyle()")}} 함수를 사용하여 글꼴의 색상을 설정하고 {{domxref("CanvasRenderingContext2D.fillText","fillText()")}} 함수를 이용해서 캔버스에 배치 될 실제 텍스트와 배치 위치를 설정하는 데 사용한다. 첫 번째 매개 변수는 텍스트 자체다. 위의 코드는 현재 점의 수를 나타내며 마지막 두 매개 변수는 텍스트가 캔버스에 배치 될 좌표이다.

- -

벽돌이 깨질 때마다 점수 변수의 값을 증가 시키기 위해서 collisionDetection() 함수에 강조 표시된 코드를 입력하여 수정한다.

- -
function collisionDetection() {
-    for(var c=0; c<brickColumnCount; c++) {
-        for(var r=0; r<brickRowCount; r++) {
-            var b = bricks[c][r];
-            if(b.status == 1) {
-                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
-                    dy = -dy;
-                    b.status = 0;
-                    score++;
-                }
-            }
-        }
-    }
-}
- -

draw() 함수 안에서 위 함수를 호출하면 호출 될 때마다 다시 그리기 때문에 점수 변동을 확인할 수 있다. draw() 아래 코드를  drawPaddle() 아래에서 호출한다.

- -
drawScore();
- -

모든 벽돌이 파괴되었을 때 승리 메시지 표시

- -

점수가 오르는 것은 좋지만, 평생 점수가 올라가진 않을 것이다. 모든 벽돌의 파괴가 결국 게임의 주된 목적이기 때문에 모든 점수를 얻는다면  승리 메시지를 표시해야한다.  collisionDetection()함수에 강조된 코드를 붙여넣는다.

- -
function collisionDetection() {
-    for(var c=0; c<brickColumnCount; c++) {
-        for(var r=0; r<brickRowCount; r++) {
-            var b = bricks[c][r];
-            if(b.status == 1) {
-                if(x > b.x && x < b.x+brickWidth && y > b.y && y < b.y+brickHeight) {
-                    dy = -dy;
-                    b.status = 0;
-                    score++;
-                    if(score == brickRowCount*brickColumnCount) {
-                        alert("YOU WIN, CONGRATULATIONS!");
-                        document.location.reload();
-                    }
-                }
-            }
-        }
-    }
-}
- -

결국 사용자는 모든 벽돌을 파괴 한 순간, 실제로 게임에서 승리 할 수 ​​있다. 이는 게임과 관련하여 굉장히 중요하다. document.location.reload()기능은 페이지를 다시로드하고 경고를 클릭하면 게임을 다시 시작한다.

- -

코드 비교

- -

최종 코드는 아래와 같다. 지금까지 작성한 코드와 비교해보자.

- -

 

- -

{{JSFiddleEmbed("https://jsfiddle.net/yumetodo/2m74vr9r/1/","","395")}}

- -
-

추가학습: 벽돌을 깰 때마다 얻는 점수를 늘리고,  게임 클리어 시 최종 점수를 경고창에 표시해보자.

-
- -

다음 단계

- -

게임은 현재 꽤 멋지게 보인다. 다음 단계에서는,  Mouse controls (마우스로 패들 조종하는 방법) 을 통해서 게임을 즐길 수 있습니다.

- -

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/\352\263\265_\354\233\200\354\247\201\354\235\264\352\270\260/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/\352\263\265_\354\233\200\354\247\201\354\235\264\352\270\260/index.html" deleted file mode 100644 index 5a8b02904e..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/\352\263\265_\354\233\200\354\247\201\354\235\264\352\270\260/index.html" +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: 공 움직이기 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기 -tags: - - 2D - - 게임 - - 루프 - - 비기너 - - 움직임 - - 자바스크립트 - - 캔버스 - - 튜토리얼 -translation_of: Games/Tutorials/2D_Breakout_game_pure_JavaScript/Move_the_ball ---- -
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games")}}
- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls")}}

- -
-

이 강의는 게임 개발 캔버스 튜토리얼의 10단계 중 두 번째 과정입니다.  Gamedev-Canvas-workshop/lesson2.html에서 이 강의의 완성된 코드를 볼 수 있습니다.

-
- -

여러분은 이전 과정에서 어떻게 공이 그려지는지 배웠습니다. 이젠 공을 움직이게 만들어보죠! 기술적으로는 화면에 공을 그렸다가 지우는 과정을 반복하게 되는데, 매 프레임마다 공의 위치를 조금씩 다르게 해서 그리면 공이 움직이는것 처럼 보이게 됩니다. 마치 영화 화면이 움직이는 방식처럼 말이죠!

- -

드로잉 루프를 정의하기

- -

매 프레임마다 캔버스에 그리는것을 지속적으로 갱신하기 위해서는, 계속해서 그리는 것을 반복하게 만들어주는 함수가 필요합니다. 이 함수는 매 프레임마다 위치를 바꿔주기 위한 몇가지 변수들을 포함합니다.  JavaScript 타이밍 함수인 {{domxref("WindowTimers.setInterval()", "setInterval()")}}나 {{domxref("window.requestAnimationFrame()", "requestAnimationFrame()")}}를 이용하면 함수를 몇번이고 계속 반복해서 실행할 수 있습니다..

- -

현재 여러분의 HTML파일 안에 있는 JavaScript중에 처음 두 줄만 제외하고 나머지는 모두 지워주세요. 지운 후에는 아래에 있는 코드를 추가해주세요. draw()함수는 setInterval를 통해서 10밀리초마다 실행됩니다.

- -
function draw() {
-    // drawing code
-}
-setInterval(draw, 10);
- -

무한히 작동하는 setInterval 함수 덕에, draw() 함수는 우리가 멈추기 전 까지 10밀리초마다 영원히 호출됩니다. 이제 공을 그려봅시다! 다음 코드를 여러분의 draw() 함수 안에 추가해주세요.

- -
ctx.beginPath();
-ctx.arc(50, 50, 10, 0, Math.PI*2);
-ctx.fillStyle = "#0095DD";
-ctx.fill();
-ctx.closePath();
-
- -

이제 바뀐 코드를 실행해 보세요. 공은 매 프레임마다 다시 그려지게 됩니다.

- -

움직이게 만들기

- -

공이 움직이지 않고 있기 때문에, 여러분은 공이 다시 그려지고 있다는 사실을 알아챌 수 는 없었을 것입니다. 이제 공을 움직이게 바꿔봅시다. 첫 번째로, (50,50)이라는 지정된 좌표 대신에, x와 y라는 변수를 이용해서 화면 하단 중앙에서 그려지도록 하겠습니다. 

- -

x와 y를 정의하기 위해서 다음 두 줄을 여러분의 draw() 함수위에 추가해주세요.

- -
var x = canvas.width/2;
-var y = canvas.height-30;
-
- -

그 다음에는 draw() 함수를 갱신할 것입니다. 아래 코드에서 강조된 줄에서 처럼, {{domxref("CanvasRenderingContext2D.arc()","arc()")}}메소드안에서 x와 y 변수를 사용하게 됩니다.

- -
function draw() {
-    ctx.beginPath();
-    ctx.arc(x, y, 10, 0, Math.PI*2);
-    ctx.fillStyle = "#0095DD";
-    ctx.fill();
-    ctx.closePath();
-}
-
- -

이제 중요한 부분입니다. 공을 움직이는 것을 표현하기 위해 x와 y에 작은 값을 매 프레임마다 더해줄 것입니다. 그 작은 값을 dx와 dy라 정의하고, 각각 2와 -2로 그 값을 정해보겠습니다. 다음 코드를 여러분의 x와 y변수가 정의된 코드 아래에 추가하세요.

- -
var dx = 2;
-var dy = -2;
-
- -

마지막으로 할 일은 dx와 dy변수를 이용해서 매 프레임마다 x와 y변수를 갱신해 주는 것입니다. 그렇게 하면 매 갱신마다 공은 새 위치에 그려지게 됩니다. 다음 코드에 표시된 새로운 두 줄의 코드를 여러분의 draw() 함수에 추가해주세요.

- -
function draw() {
-    ctx.beginPath();
-    ctx.arc(x, y, 10, 0, Math.PI*2);
-    ctx.fillStyle = "#0095DD";
-    ctx.fill();
-    ctx.closePath();
-    x += dx;
-    y += dy;
-}
- -

여러분의 코드를 다시 저장하고, 브라우저를 열어 실행해보세요. 공은 잘 움직이는군요. 뒤에 흔적이 남기는 하지만 말이죠.

- -

- -

다음 프레임 전에 캔버스를 지우기

- -

공이 흔적을 남기는 것은, 매 프레임마다 공을 그릴 때 이전 프레임을 지워주지 않았기 때문입니다. 하지만 걱정할 것은 없습니다. 캔버스의 내용들을 지워주기 위한 메소드인 {{domxref("CanvasRenderingContext2D.clearRect()","clearRect()")}}가 있으니까요. 이 메소드는 네 개의 파라미터가 필요합니다. 직사각형의 좌상단 모서리를 표시할 x와 y좌표, 그리고 직사각형의 우하단 모서리를 표시할 x와 y좌표가 바로 그것이죠. 이 좌표들로 생기는 사각형 안에 있는 것들은 전부 지워지게 될 것입니다.

- -

다음 코드에서 강조된 새로운 한줄의 코드를 draw() 함수에 추가하세요.

- -
function draw() {
-    ctx.clearRect(0, 0, canvas.width, canvas.height);
-    ctx.beginPath();
-    ctx.arc(x, y, 10, 0, Math.PI*2);
-    ctx.fillStyle = "#0095DD";
-    ctx.fill();
-    ctx.closePath();
-    x += dx;
-    y += dy;
-}
-
- -

여러분의 코드를 저장하고, 다시 실행해보세요. 이번에는 흔적없이 공이 움직이는 것을 보실 수 있을 것입니다. 매 10밀리초마다 캔버스는 지워지고, 새로운 x와 y값의 좌표를 가지는 공이 다음 프레임에 그려지게 되는 것이죠.

- -

코드 정리하기

- -

다음 강좌에서도 계속해서 몇가지 명령들을 draw() 함수에다 추가해야 합니다. 그렇기 때문에 코드를 최대한 간단하고 깨끗하게 유지하는 것이 좋습니다. 공을 움직이는 코드를 분리된 함수로 옮기는 것 부터 시작해보죠!

- -

현재의 draw() 함수를 다음의 분리된 두 함수로 바꿔주세요.

- -
function drawBall() {
-    ctx.beginPath();
-    ctx.arc(x, y, 10, 0, Math.PI*2);
-    ctx.fillStyle = "#0095DD";
-    ctx.fill();
-    ctx.closePath();
-}
-
-function draw() {
-    ctx.clearRect(0, 0, canvas.width, canvas.height);
-    drawBall();
-    x += dx;
-    y += dy;
-}
- -

여러분의 코드와 비교해보세요

- -

아래의 라이브 데모에서 이 강의의 완성된 코드를 확인할 수 있습니다. 어떻게 작동하는지 더 잘 이해하기 위해 플레이 해보세요.

- -

{{JSFiddleEmbed("https://jsfiddle.net/end3r/3x5foxb1/","","415")}}

- -
-

연습해보기: 움직이는 공의 속도를 바꾸거나, 움직이는 방향을 바꿔보세요.

-
- -

다음 단계로

- -

우리는 공을 그리고 움직이게 만들었지만, 캔버스 모서리 밖으로 사라져버립니다. 세 번째 챕터에서는 공이 벽으로부터 튕겨 나오기 위한 방법을 알아볼 것입니다.

- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/Bounce_off_the_walls")}}

diff --git "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/\354\272\224\353\262\204\354\212\244_\354\203\235\354\204\261\352\263\274_\352\267\270\353\246\254\352\270\260/index.html" "b/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/\354\272\224\353\262\204\354\212\244_\354\203\235\354\204\261\352\263\274_\352\267\270\353\246\254\352\270\260/index.html" deleted file mode 100644 index a7f1ed4130..0000000000 --- "a/files/ko/games/tutorials/\354\210\234\354\210\230\355\225\234_\354\236\220\353\260\224\354\212\244\355\201\254\353\246\275\355\212\270\353\245\274_\354\235\264\354\232\251\355\225\234_2d_\353\262\275\353\217\214\352\271\250\352\270\260_\352\262\214\354\236\204/\354\272\224\353\262\204\354\212\244_\354\203\235\354\204\261\352\263\274_\352\267\270\353\246\254\352\270\260/index.html" +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: 캔버스 생성과 그리기 -slug: Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/캔버스_생성과_그리기 -tags: - - 2D - - 게임 - - 비기너 - - 자바스크립트 - - 캔버스 - - 튜토리얼 -translation_of: >- - Games/Tutorials/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it ---- -
{{GamesSidebar}}
{{IncludeSubnav("/ko/docs/Games")}}
- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기")}}

- -
-

이 강의는 게임 개발 캔버스 튜토리얼의 10단계 중 첫 번째 과정입니다. Gamedev-Canvas-workshop/lesson1.html에서 이 강의의 완성된 코드를 볼 수 있습니다.

-
- -

게임의 기능들을 작성하기 전에, 게임 내부에 렌더링 하기 위한 기본 구조들을 HTML과 {{htmlelement("canvas")}} 엘리먼트를 사용하여 만들어야 합니다.

- -

게임의 HTML

- -

HTML문서 구조는 꽤 간단합니다. 게임은 {{htmlelement("canvas")}} 엘리먼트에 렌더링됩니다. 여러분이 좋아하는 텍스트 에디터로 새로운 HTML 문서를 생성하여 index.html로 저장하고, 아래 코드를 추가하세요.

- -
<!DOCTYPE html>
-<html>
-<head>
-    <meta charset="utf-8" />
-    <title>Gamedev Canvas Workshop</title>
-    <style>
-    	* { padding: 0; margin: 0; }
-    	canvas { background: #eee; display: block; margin: 0 auto; }
-    </style>
-</head>
-<body>
-
-<canvas id="myCanvas" width="480" height="320"></canvas>
-
-<script>
-	// JavaScript 코드가 여기에 들어갈 것입니다.
-</script>
-
-</body>
-</html>
-
- -

{{htmlelement("head")}} 에는 문자셋이 정의되어 있고, {{htmlelement("title")}}과 몇가지 기본적인 CSS가 있습니다. {{htmlelement("body")}}는 {{htmlelement("canvas")}} 와 {{htmlelement("script")}}를 포함하고 있습니다. {{htmlelement("canvas")}}에는 게임이 렌더되고, {{htmlelement("script")}}에는 JavaScript가 들어갑니다. {{htmlelement("canvas")}}엘리먼트는 쉽게 참조하기 위해 id로 myCanvas를 갖고 있고, 480픽셀의 길이와 320픽셀의 높이를 갖도록 되어있습니다. 우리가 이 튜토리얼에서 작성하게될 모든 JavaScript 코드는 <script>와  </script> 태그 사이에 들어가게 됩니다.

- -

캔버스 기본

- -

실제로 {{htmlelement("canvas")}}엘리먼트 위에 그래픽을 렌더링하기 위해서는 JavaScript로 참조할 수 있게 만들어야 합니다. 다음 코드를 여러분의 <script> 태그 다음에 추가하세요..

- -
var canvas = document.getElementById("myCanvas");
-var ctx = canvas.getContext("2d");
- -

{{htmlelement("canvas")}} 엘리먼트에 대한 참조를 canvas 변수에 저장하였습니다. 그러고 나서는 캔버스에 그리기 위해 실질적으로 사용되는 도구인 2D rendering context를 ctx 변수에 저장하고 있습니다.

- -

캔버스에 빨간색 네모를 그리는 짧은 예제 코드를 작성해봅시다. 바로 직전의 JavaScript 코드 아래에 다음 코드를 추가하고 index.html을 브라우저에서 열어 보세요.

- -
ctx.beginPath();
-ctx.rect(20, 40, 50, 50);
-ctx.fillStyle = "#FF0000";
-ctx.fill();
-ctx.closePath();
- -

{{domxref("CanvasRenderingContext2D.beginPath()","beginPath()")}}와 {{domxref("CanvasRenderingContext2D.closePath()","closePath()")}}메소드 사이에 모든 명령어가 들어갑니다. 우리는 {{domxref("CanvasRenderingContext2D.rect()","rect()")}}를 이용해서 직사각형을 정의했는데, 처음 두 값들은 캔버스의 좌상단 모서리로 부터의 좌표를 의미하고, 나머지 두 값은 직사각형의 너비와 높이를 의미합니다. 위 코드에서 직사각형은 캔버스 좌측에서 20픽셀 떨어져있고, 캔버스 상단에서 40픽셀만큼 아래로 떨어져 있습니다. 그리고 너비와 높이는 각각 50픽셀로 설정되어 완벽한 정사각형으로 그려지고 있습니다. {{domxref("CanvasRenderingContext2D.fillStyle","fillStyle")}}은  {{domxref("CanvasRenderingContext2D.fill()","fill()")}}메소드에서 칠해질 색상 값을 갖게 됩니다. 위 코드에서는 사각형을 빨간색으로 칠하고 있습니다.

- -

직사각형만 그릴 수 있는 것은 아닙니다. 이번에는 초록색 원을 그려보겠습니다. 아래의 코드를 여러분의 JavaScript의 마지막에 추가하고, 저장한 이후에 페이지를 새로고침 해보세요.

- -
ctx.beginPath();
-ctx.arc(240, 160, 20, 0, Math.PI*2, false);
-ctx.fillStyle = "green";
-ctx.fill();
-ctx.closePath();
- -

위 코드에서 볼 수 있듯이{{domxref("CanvasRenderingContext2D.beginPath()","beginPath()")}}와 {{domxref("CanvasRenderingContext2D.closePath()","closePath()")}}메소드가 다시 나왔습니다. 그 사이에, 가장 중요한 부분인 {{domxref("CanvasRenderingContext2D.arc()","arc()")}} 메소드가 있습니다. 이 메소드는 6개의 파라미터를 갖습니다.

- - - -

{{domxref("CanvasRenderingContext2D.fillStyle","fillStyle")}}속성은 이전과 조금 달라 보이는데, 이는 CSS에서 색상을 표현하는 여러가지 방법 중 하나입니다. 색상을 표현할 때, 16진수로 색상값을 표현하거나, 색상 키워드를 사용하거나, rgba() 함수를 사용하거나 그외에 다른 색상 메소드를 사용할 수 있습니다.

- -

{{domxref("CanvasRenderingContext2D.fill()","fill()")}}을 사용해서 원에 색상을 채울 수 있다면,{{domxref("CanvasRenderingContext2D.stroke()","stroke()")}}를 이용하면 원의 외곽선에 색상을 부여할 수 있습니다. 아래의 코드들도 여러분의 JavaScript에 추가해보세요.

- -
ctx.beginPath();
-ctx.rect(160, 10, 100, 40);
-ctx.strokeStyle = "rgba(0, 0, 255, 0.5)";
-ctx.stroke();
-ctx.closePath();
- -

위 코드는 비어있는 파란색 외곽선으로 된 원을 그립니다. rgba() 함수의 알파 채널 값 때문에 파란색은 반투명하게 표현됩니다.

- -

여러분의 코드와 비교해 보세요

- -

 JSFiddle에서 라이브로 실행되는 전체 코드입니다.

- -

{{JSFiddleEmbed("https://jsfiddle.net/end3r/x62h15e2/","","370")}}

- -
-

연습해보기: 주어진 모양들의 크기와 색상을 변경해보세요.

-
- -

다음 단계로

- -

이제 우리는 기본적인 HTML을 설정하고, canvas에 대해 조금 배웠습니다. 두 번째 챕터로 넘어가서 게임에서 공을 움직이기위해 어떻게 해야 하는지 계속 알아봅시다.

- -

{{PreviousNext("Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임", "Games/Tutorials/순수한_자바스크립트를_이용한_2D_벽돌깨기_게임/공_움직이기")}}

-- cgit v1.2.3-54-g00ecf