From 310fd066e91f454b990372ffa30e803cc8120975 Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 12:56:40 +0100 Subject: unslug zh-cn: move --- .../finishing_up/index.html | 113 +++++++++++++++++++++ .../mouse_controls/index.html | 61 +++++++++++ .../index.html" | 113 --------------------- .../index.html" | 61 ----------- 4 files changed, 174 insertions(+), 174 deletions(-) create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html create mode 100644 files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html delete mode 100644 "files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/\346\224\266\345\260\276\345\267\245\344\275\234/index.html" delete mode 100644 "files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/\351\274\240\346\240\207\346\216\247\345\210\266/index.html" (limited to 'files/zh-cn/games/tutorials') diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html new file mode 100644 index 0000000000..baa5a514fc --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/finishing_up/index.html @@ -0,0 +1,113 @@ +--- +title: 收尾工作 +slug: Games/Tutorials/2D_Breakout_game_pure_JavaScript/收尾工作 +tags: + - Canvas + - JavaScript + - requestAnimationFrame + - 入门 + - 教程 + - 游戏 + - 生命 +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节教程中的第10节也是最后一节。完成这篇课程后,你可以在 Gamedev-Canvas-workshop/lesson10.html 找到我们的源代码。

+
+ +

不管我们做什么游戏,它总是存在优化的空间。例如,我们可以为玩家多提供几条命,让他们能在发生一两次失误的情况下顺利完成游戏。或者,我们也可以在渲染代码上下工夫。

+ +

加入生命机制

+ +

在游戏中实现生命机制的思路很直接。让我们先新增一个变量,用来存储其生命值。把下面这行代码和我们声明其它变量的代码放在一起:

+ +
var lives = 3;
+ +

在 canvas 上绘制生命值计数的做法几乎和绘制分数一样——把下面的函数添加到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() 即可。让我们把它加到drawScore() 的下一行:

+ +
drawLives();
+
+ +

用 requestAnimationFrame() 优化渲染

+ +

现在让我们处理一些与游戏机制无关,但与画面渲染相关的东西。和我们目前使用{{domxref("windowTimers.setInterval()", "setInterval()")}} 实现的固定帧率渲染相比,{{domxref("window.requestAnimationFrame", "requestAnimationFrame")}} 能让浏览器更好地渲染画面。让我们把下面这行代码:

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

替换为:

+ +
draw();
+ +

再把代码中的每一处

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

删除。然后,在 draw() 函数的最下方(右花括号之前)加入下面这行代码。 它的作用是使 draw() 函数递归调用自身:

+ +
requestAnimationFrame(draw);
+ +

现在 draw() 函数在 requestAnimationFrame() 的循环中被反复调用,之先前做法最大的不同是,我们将帧率的控制权交给浏览器,而不是固定的 10 毫秒。浏览器会在适当的时机同步帧率,并且只在必要的时候才刷新渲染的图形。这使得我们的动画比之前的 setInterval() 方法更加流畅且高效.

+ +

比较你的代码

+ +

我们的游戏的最终版本已经完成!以上。

+ +

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

+ +
+

练习:试着改变生命的数目和球从球板上反弹的角度。

+
+ +

游戏结束——暂时看来!

+ +

祝贺你——你完成了本教程的所有小节!现在,你应该已经掌握 canvas 操纵的基础和 2D 游戏背后的逻辑了。是时候去学习一些框架,继续你的游戏开发之旅了!你可以看看本系列的姊妹篇:用 Phaser 制作 2D 打砖块游戏 或者 Cyber Orb built in Phaser 。或者,你也可以在 MDN 游戏区 中获得灵感和更多知识。

+ +

你也可以回到本教程的目录页。祝编程愉快!

+ +

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

diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html new file mode 100644 index 0000000000..cb90cb8773 --- /dev/null +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/mouse_controls/index.html @@ -0,0 +1,61 @@ +--- +title: 鼠标控制 +slug: Games/Tutorials/2D_Breakout_game_pure_JavaScript/鼠标控制 +tags: + - Canvas + - 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 元素左边框到视窗左边框的距离 (canvas.offsetLeft) —— 这就得到了 canvas 元素左边框到鼠标的距离。若这个值大于零,且小于 canvas 的宽度,说明鼠标指针落在 canvas 边界内,这时就把 paddleX (等于球板左边缘的坐标)设为 relativeX 减速去球板宽度的一半。这样就确保位移是相对于球板中心进行的。

+ +

现在球板将跟随鼠标指针。不过由于我们将球板移动限制在 canvas 大小范围内,它不会从两边完全消失。

+ +

比较你的代码

+ +

以下是我们的示例代码,以便与您进行比较:

+ +

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

+ +
+

练习:调整球板移动的范围,使得整个球板总是可见,而不是在移动到边缘时被遮住一半。

+
+ +

下一步

+ +

现在我们已经拥有一个完整的游戏。我们的系列教程将以一些细节上的调整作为结束。

+ +

{{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/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/\346\224\266\345\260\276\345\267\245\344\275\234/index.html" "b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/\346\224\266\345\260\276\345\267\245\344\275\234/index.html" deleted file mode 100644 index baa5a514fc..0000000000 --- "a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/\346\224\266\345\260\276\345\267\245\344\275\234/index.html" +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: 收尾工作 -slug: Games/Tutorials/2D_Breakout_game_pure_JavaScript/收尾工作 -tags: - - Canvas - - JavaScript - - requestAnimationFrame - - 入门 - - 教程 - - 游戏 - - 生命 -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节教程中的第10节也是最后一节。完成这篇课程后,你可以在 Gamedev-Canvas-workshop/lesson10.html 找到我们的源代码。

-
- -

不管我们做什么游戏,它总是存在优化的空间。例如,我们可以为玩家多提供几条命,让他们能在发生一两次失误的情况下顺利完成游戏。或者,我们也可以在渲染代码上下工夫。

- -

加入生命机制

- -

在游戏中实现生命机制的思路很直接。让我们先新增一个变量,用来存储其生命值。把下面这行代码和我们声明其它变量的代码放在一起:

- -
var lives = 3;
- -

在 canvas 上绘制生命值计数的做法几乎和绘制分数一样——把下面的函数添加到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() 即可。让我们把它加到drawScore() 的下一行:

- -
drawLives();
-
- -

用 requestAnimationFrame() 优化渲染

- -

现在让我们处理一些与游戏机制无关,但与画面渲染相关的东西。和我们目前使用{{domxref("windowTimers.setInterval()", "setInterval()")}} 实现的固定帧率渲染相比,{{domxref("window.requestAnimationFrame", "requestAnimationFrame")}} 能让浏览器更好地渲染画面。让我们把下面这行代码:

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

替换为:

- -
draw();
- -

再把代码中的每一处

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

删除。然后,在 draw() 函数的最下方(右花括号之前)加入下面这行代码。 它的作用是使 draw() 函数递归调用自身:

- -
requestAnimationFrame(draw);
- -

现在 draw() 函数在 requestAnimationFrame() 的循环中被反复调用,之先前做法最大的不同是,我们将帧率的控制权交给浏览器,而不是固定的 10 毫秒。浏览器会在适当的时机同步帧率,并且只在必要的时候才刷新渲染的图形。这使得我们的动画比之前的 setInterval() 方法更加流畅且高效.

- -

比较你的代码

- -

我们的游戏的最终版本已经完成!以上。

- -

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

- -
-

练习:试着改变生命的数目和球从球板上反弹的角度。

-
- -

游戏结束——暂时看来!

- -

祝贺你——你完成了本教程的所有小节!现在,你应该已经掌握 canvas 操纵的基础和 2D 游戏背后的逻辑了。是时候去学习一些框架,继续你的游戏开发之旅了!你可以看看本系列的姊妹篇:用 Phaser 制作 2D 打砖块游戏 或者 Cyber Orb built in Phaser 。或者,你也可以在 MDN 游戏区 中获得灵感和更多知识。

- -

你也可以回到本教程的目录页。祝编程愉快!

- -

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

diff --git "a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/\351\274\240\346\240\207\346\216\247\345\210\266/index.html" "b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/\351\274\240\346\240\207\346\216\247\345\210\266/index.html" deleted file mode 100644 index cb90cb8773..0000000000 --- "a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/\351\274\240\346\240\207\346\216\247\345\210\266/index.html" +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: 鼠标控制 -slug: Games/Tutorials/2D_Breakout_game_pure_JavaScript/鼠标控制 -tags: - - Canvas - - 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 元素左边框到视窗左边框的距离 (canvas.offsetLeft) —— 这就得到了 canvas 元素左边框到鼠标的距离。若这个值大于零,且小于 canvas 的宽度,说明鼠标指针落在 canvas 边界内,这时就把 paddleX (等于球板左边缘的坐标)设为 relativeX 减速去球板宽度的一半。这样就确保位移是相对于球板中心进行的。

- -

现在球板将跟随鼠标指针。不过由于我们将球板移动限制在 canvas 大小范围内,它不会从两边完全消失。

- -

比较你的代码

- -

以下是我们的示例代码,以便与您进行比较:

- -

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

- -
-

练习:调整球板移动的范围,使得整个球板总是可见,而不是在移动到边缘时被遮住一半。

-
- -

下一步

- -

现在我们已经拥有一个完整的游戏。我们的系列教程将以一些细节上的调整作为结束。

- -

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

-- cgit v1.2.3-54-g00ecf