diff --git a/files/zh-cn/games/anatomy/index.html b/files/zh-cn/games/anatomy/index.html index 43f5647f1afff7..06af4d7e7bd8fc 100644 --- a/files/zh-cn/games/anatomy/index.html +++ b/files/zh-cn/games/anatomy/index.html @@ -11,7 +11,7 @@
{{GamesSidebar}}
-

本文从技术角度分析了一般电子游戏的结构和工作流程,就此介绍主循环是如何运行的。它有助于初学者了解在现代游戏开发领域构建游戏时需要什么,以及如何将JavaScript这样的Web标准工具作为自己的工具使用。游戏开发经验丰富但不熟悉Web开发的开发者也能从中受益。

+

本文从技术角度分析了一般电子游戏的结构和工作流程,就此介绍主循环是如何运行的。它有助于初学者了解在现代游戏开发领域构建游戏时需要什么,以及如何将 JavaScript 这样的 Web 标准工具作为自己的工具使用。游戏开发经验丰富但不熟悉 Web 开发的开发者也能从中受益。

呈现,接收,解释,计算,重复

@@ -26,13 +26,13 @@

呈现,接收,解释,

但它也可能不需要逐帧控制。您的游戏循环可能类似找不同的例子,并以输入事件作为基础。它可能需要输入和模拟时间片。它甚至可以基于其他的东西来循环。

-

现代JavaScript - 正如下一节中所描述的 - 它可以轻松开发出一个高效的,逐帧执行的主循环,这很值得庆幸。当然,您的游戏只会按照您所做的那样优化。如果某些东西看起来应该被添加到一个更罕见的事件里,那么将它从主循环中剥离出来通常是个好主意(但并非总是如此)。

+

现代 JavaScript - 正如下一节中所描述的 - 它可以轻松开发出一个高效的,逐帧执行的主循环,这很值得庆幸。当然,您的游戏只会按照您所做的那样优化。如果某些东西看起来应该被添加到一个更罕见的事件里,那么将它从主循环中剥离出来通常是个好主意(但并非总是如此)。

-

在JavaScript中构建一个主循环

+

在 JavaScript 中构建一个主循环

-

JavaScript能很好的处理事件和回调函数。现代浏览器努力在需要的时候调用方法,并在间隙中闲下来(或做其他任务)。将您的代码附加到适合它们的时刻是一个很好的主意。考虑一下你的函数是需要在严格的时间周期内,还是每一帧,或者仅仅是在发生了其他情况之后执行。当您的函数需要被调用时,要更具体地使用浏览器,这样浏览器就可以在调用时进行优化。而且,这可能会让你的工作更轻松。

+

JavaScript 能很好的处理事件和回调函数。现代浏览器努力在需要的时候调用方法,并在间隙中闲下来(或做其他任务)。将您的代码附加到适合它们的时刻是一个很好的主意。考虑一下你的函数是需要在严格的时间周期内,还是每一帧,或者仅仅是在发生了其他情况之后执行。当您的函数需要被调用时,要更具体地使用浏览器,这样浏览器就可以在调用时进行优化。而且,这可能会让你的工作更轻松。

-

有些代码需要逐帧运行,所以应将其附加到浏览器的重绘周期中,没有比这更好的了!在Web 中,通常 window.requestAnimationFrame()方法是大多数良好的逐帧循环的基础。在调用该方法时必须传入一个回调函数,这个回调函数将在下一次重新绘制之前执行。下面是一个简单的主循环的例子。:

+

有些代码需要逐帧运行,所以应将其附加到浏览器的重绘周期中,没有比这更好的了!在 Web 中,通常 window.requestAnimationFrame()方法是大多数良好的逐帧循环的基础。在调用该方法时必须传入一个回调函数,这个回调函数将在下一次重新绘制之前执行。下面是一个简单的主循环的例子。:

window.main = function(){
   window.requestAnimationFrame(main);
@@ -52,9 +52,9 @@ 

在JavaScript中构建一个主

将主循环的时机安排在浏览器每次的绘制显示中,允许您能像浏览器想要绘制的那样频繁的运行您的循环。你能够控制每一帧动画,并且main()是循环中唯一执行的函数,所以这很简单。主视角射击游戏(或类似的游戏)每一帧都会出现一个新的场景。没有比这种方法更平滑并绘制及时的了。

-

但是不要马上认为动画必需要帧帧控制。通过CSS动画或浏览器中的其他工具,可以很容易实现简单的动画,甚至GPU加速。有很多这样的东西,它们会让你的工作更轻松。

+

但是不要马上认为动画必需要帧帧控制。通过 CSS 动画或浏览器中的其他工具,可以很容易实现简单的动画,甚至 GPU 加速。有很多这样的东西,它们会让你的工作更轻松。

-

在Javascript中构建一个更好的主循环

+

在 Javascript 中构建一个更好的主循环

在前面的主循环中有两个明显的问题:main()污染了 window对象(所有全局变量存储的对象),并且示例代码没有给我们留下一个停止循环的方法,除非整个浏览器选项卡被关闭或刷新。对于第一个问题,如果您希望主循环只运行,并且不需要被简单(直接)访问它,您可以将它作为一个立即调用的函数表达式(IIFE)创建。

@@ -72,16 +72,16 @@

在Javascript中构建 main(); //开始循环 })();

-

当浏览器遇到这个IIFE时,它将定义您的主循环,并立即将其加入下一个帧的更新队列中。main(或main()方法)不会被附加到任何对象,在应用程序的其他地方仍是一个有效的未使用的名称,仍可以自由地定义为其他的东西。

+

当浏览器遇到这个 IIFE 时,它将定义您的主循环,并立即将其加入下一个帧的更新队列中。main(或main()方法)不会被附加到任何对象,在应用程序的其他地方仍是一个有效的未使用的名称,仍可以自由地定义为其他的东西。

-

注意:在实践中,更常见的终止下一个requestAnimationFrame()方式是使用if语句,而不是调用cancelAnimationFrame()

+

注意:在实践中,更常见的终止下一个requestAnimationFrame()方式是使用 if 语句,而不是调用cancelAnimationFrame()

-

对于第二个问题,要终止循环,您需要调用 window.cancelAnimationFrame()来取消main()的调用。该方法需要传入你最后一次调用requestAnimationFrame()时返回的ID。让我们假设您的游戏的函数和变量是建立在您称为MyGame的名称空间上。扩展我们的最后一个例子,主循环现在看起来是这样的:

+

对于第二个问题,要终止循环,您需要调用 window.cancelAnimationFrame()来取消main()的调用。该方法需要传入你最后一次调用requestAnimationFrame()时返回的 ID。让我们假设您的游戏的函数和变量是建立在您称为 MyGame 的名称空间上。扩展我们的最后一个例子,主循环现在看起来是这样的:

/*
-* 让我们假设MyGame是之前定义的。
+* 让我们假设 MyGame 是之前定义的。
 */
 
 ;(function(){
@@ -94,45 +94,45 @@ 

在Javascript中构建 main(); //开始循环 })();

-

现在,我们在MyGame名称空间中声明了一个变量stopMain,其值为主循环最后调用requestAnimationFrame()时返回的ID。任何时候,我们可以通过告诉浏览器取消与ID相对应的请求来停止主循环。

+

现在,我们在 MyGame 名称空间中声明了一个变量stopMain,其值为主循环最后调用requestAnimationFrame()时返回的 ID。任何时候,我们可以通过告诉浏览器取消与 ID 相对应的请求来停止主循环。

window.cancelAnimationFrame(MyGame.stopMain);
-

在JavaScript的中编写主循环的关键在于,考虑到任何会驱动你行为的事件,并注意不同的系统是如何相互作用的。您可能拥有多个由多个不同类型的事件驱动的组件。这看起来像是不必要的复杂性,但它可能就是一个很好的优化(当然,不一定是这样的)。问题是,您并不是在编写一个典型的主循环。在Java脚本中,您使用的是浏览器的主循环,并且您正在尝试这样做。

+

在 JavaScript 的中编写主循环的关键在于,考虑到任何会驱动你行为的事件,并注意不同的系统是如何相互作用的。您可能拥有多个由多个不同类型的事件驱动的组件。这看起来像是不必要的复杂性,但它可能就是一个很好的优化(当然,不一定是这样的)。问题是,您并不是在编写一个典型的主循环。在 Java 脚本中,您使用的是浏览器的主循环,并且您正在尝试这样做。

-

用JavaScript构建一个更优化的主循环

+

用 JavaScript 构建一个更优化的主循环

-

基本上,在JavaScript的中,浏览器有它自己的主循环,而你的代码存在于循环某些阶段。上面描述的主循环,试图避免脱离浏览器的控制。这种主循环附着于window.requestAnimationFrame()方法,该方法将在浏览器的下一帧中执行,具体取决于浏览器如何与将其自己的主循环关联起来。W3C规范并没有真正定义什么时候浏览器必须执行requestAnimationFrame回调。这有一个好处,浏览器厂商可以自由地实现他们认为最好的解决方案,并随着时间的推移进行调整。

+

基本上,在 JavaScript 的中,浏览器有它自己的主循环,而你的代码存在于循环某些阶段。上面描述的主循环,试图避免脱离浏览器的控制。这种主循环附着于window.requestAnimationFrame()方法,该方法将在浏览器的下一帧中执行,具体取决于浏览器如何与将其自己的主循环关联起来。W3C 规范并没有真正定义什么时候浏览器必须执行 requestAnimationFrame 回调。这有一个好处,浏览器厂商可以自由地实现他们认为最好的解决方案,并随着时间的推移进行调整。

-

现代版的Firefox和Google Chrome(可能还有其他版本)试图在框架的时间片的开始时将请求AnimationFrame回调与它们的主线程进行连接。因此,浏览器的主线程看起来就像下面这样:

+

现代版的 Firefox 和 Google Chrome(可能还有其他版本)试图在框架的时间片的开始时将请求 AnimationFrame 回调与它们的主线程进行连接。因此,浏览器的主线程看起来就像下面这样:

  1. 启动一个新帧(而之前的帧由显示处理)。
  2. -
  3. 遍历requestAnimationFrame回调并调用它们。
  4. +
  5. 遍历 requestAnimationFrame 回调并调用它们。
  6. 当上面的回调停止控制主线程时,执行垃圾收集和其他帧任务。
  7. 睡眠(除非事件打断了浏览器的小睡),直到显示器准备好你的图像(VSYNC)并重复。
-

您可以考虑开发实时应用程序,因为有时间做工作。所有上述步骤都必须在每16毫秒内进行一次,以保持60赫兹的显示效果。浏览器会尽可能早地调用您的代码,从而给它最大的计算时间。您的主线程通常会启动一些甚至不在主线程上的工作负载(如WebGL的中的光栅化或着色器)。在浏览器使用其主线程管理垃圾收集,其他任务或处理异步事件时,可以在Web Worker或GPU上执行长时间的计算。

+

您可以考虑开发实时应用程序,因为有时间做工作。所有上述步骤都必须在每 16 毫秒内进行一次,以保持 60 赫兹的显示效果。浏览器会尽可能早地调用您的代码,从而给它最大的计算时间。您的主线程通常会启动一些甚至不在主线程上的工作负载(如 WebGL 的中的光栅化或着色器)。在浏览器使用其主线程管理垃圾收集,其他任务或处理异步事件时,可以在 Web Worker 或 GPU 上执行长时间的计算。

-

当我们讨论预算时,许多网络浏览器都有一个称为高分辨率时间的工具.{{ domxref("Date") }} 对象不再是计时事件的识别方法,因为它非常不精确,可以由系统时钟进行修改。另一方面,高分辨率的时间计算自navigationStart(当上一个文档被卸载时)的毫秒数。这个值以小数的精度返回,精确到千分之一毫秒。它被称为{{ domxref("DOMHighResTimeStamp") }},但是,无论出于什么目的和目的,都认为它是一个浮点数。

+

当我们讨论预算时,许多网络浏览器都有一个称为高分辨率时间的工具.{{ domxref("Date") }} 对象不再是计时事件的识别方法,因为它非常不精确,可以由系统时钟进行修改。另一方面,高分辨率的时间计算自 navigationStart(当上一个文档被卸载时)的毫秒数。这个值以小数的精度返回,精确到千分之一毫秒。它被称为{{ domxref("DOMHighResTimeStamp") }},但是,无论出于什么目的和目的,都认为它是一个浮点数。

-

注意:系统(硬件或软件)不能达到微秒精度,可以提供毫秒精度的最小值然而,如果他们能够做到这一点,他们就应该提供0.001的准确性。

+

注意:系统(硬件或软件)不能达到微秒精度,可以提供毫秒精度的最小值然而,如果他们能够做到这一点,他们就应该提供 0.001 的准确性。

-

这个值本身并不太有用,因为它与一个相当无趣的事件相关,但它可以从另一个时间戳中减去,以便准确准确地确定这两个点之间的时间间隔。要获得这些时间戳中的一个,您可以调用window.performance.now()并将结果存储为一个变量。

+

这个值本身并不太有用,因为它与一个相当无趣的事件相关,但它可以从另一个时间戳中减去,以便准确准确地确定这两个点之间的时间间隔。要获得这些时间戳中的一个,您可以调用 window.performance.now()并将结果存储为一个变量。

var tNow = window.performance.now();
 
-

回到主循环的主题。您将经常想知道何时调用主函数。因为这是常见的,window.requestAnimationFrame()总是提供一个DOMHighResTimeStamp执行时回调函数作为参数。这将导致我们之前的主循环的另一个增强。

+

回到主循环的主题。您将经常想知道何时调用主函数。因为这是常见的,window.requestAnimationFrame()总是提供一个 DOMHighResTimeStamp 执行时回调函数作为参数。这将导致我们之前的主循环的另一个增强。

/*
 * 以分号开始,以上例子中的代码行都是这样的
-* 依靠自动分号插入(ASI)。浏览器可能会意外
+* 依靠自动分号插入 (ASI)。浏览器可能会意外
 * 认为这个整个例子从上一行继续。领先分号
 * 标记我们的新行的开始,如果前一个不是空或终止。
 *
-* 我们还假设MyGame是以前定义的。
+* 我们还假设 MyGame 是以前定义的。
 */
 
 ;(function(){
@@ -140,13 +140,13 @@ 

用JavaScript构建一 MyGame.stopMain = window.requestAnimationFrame(main); //你的主循环内容 - // tFrame,来自"function main(tFrame)",现在是由rAF提供的DOMHighResTimeStamp。 + // tFrame,来自"function main(tFrame)",现在是由 rAF 提供的 DOMHighResTimeStamp。 } main(); //开始循环 })();

-

其他一些优化是可能的,这取决于你的游戏想要完成什么。你的游戏类型显然会有所不同,但它甚至可能比这更微妙。您可以在画布上单独绘制每个像素,也可以将DOM元素(包括具有透明背景的多个WebGL的画布)放入复杂的层次结构中。每条路径都将导致不同的机会和约束。

+

其他一些优化是可能的,这取决于你的游戏想要完成什么。你的游戏类型显然会有所不同,但它甚至可能比这更微妙。您可以在画布上单独绘制每个像素,也可以将 DOM 元素(包括具有透明背景的多个 WebGL 的画布)放入复杂的层次结构中。每条路径都将导致不同的机会和约束。

决定......时间

@@ -156,44 +156,44 @@

决定......时间

大多数浏览器游戏应该是什么样的

-

如果你的游戏可以达到你所支持的任何硬件的最大刷新率,那么你的工作就变得相当容易了。 你可以简单地进行更新,渲染,然后在垂直同步之前什么都不用做。

+

如果你的游戏可以达到你所支持的任何硬件的最大刷新率,那么你的工作就变得相当容易了。你可以简单地进行更新,渲染,然后在垂直同步之前什么都不用做。

/*
 * 以分号开始,以上例子中的代码行都是这样的
-* 依靠自动分号插入(ASI)。浏览器可能会意外
+* 依靠自动分号插入 (ASI)。浏览器可能会意外
 * 认为这个整个例子从上一行继续。领先分号
 * 标记我们的新行的开始,如果前一个不是空或终止。
 *
-* 我们还假设MyGame是以前定义的。
+* 我们还假设 MyGame 是以前定义的。
 */
 
 ;(function(){
   function main(tFrame){
     MyGame.stopMain = window.requestAnimationFrame(main);
 
-    update(Frame); //调用update方法。在我们的例子中,我们给它rAF的时间戳。
+    update(Frame); //调用 update 方法。在我们的例子中,我们给它 rAF 的时间戳。
     render();
   }
 
   main(); //开始循环
 })();
-

如果无法达到最大刷新率,可以调整画面质量设置以保持你的时间预算。这个概念最有名的例子是ID Software的RAGE游戏 ,这个游戏取消了用户的控制权,以使其计算时间保持在大约16ms(或大约60fps)。如果计算时间过长,则提交的解析度就降低,纹理和其他资源将无法加载或绘制等。这个(非网络)案例研究做了一些假设和折衷:

+

如果无法达到最大刷新率,可以调整画面质量设置以保持你的时间预算。这个概念最有名的例子是 ID Software 的 RAGE 游戏 ,这个游戏取消了用户的控制权,以使其计算时间保持在大约 16ms(或大约 60fps)。如果计算时间过长,则提交的解析度就降低,纹理和其他资源将无法加载或绘制等。这个(非网络)案例研究做了一些假设和折衷:

处理可变刷新率需求的其他方法

存在其他解决问题的方法。

-

一种常见的技术是以恒定的频率更新模拟,然后绘制尽可能多的(或尽可能少的)实际帧。更新方法可以继续循环,而不用考虑用户看到的内容。绘图方法可以查看最后的更新以及发生的时间。由于绘制知道何时表示,以及上次更新的模拟时间,它可以预测为用户绘制一个合理的框架。这是否比官方更新循环更频繁(甚至更不频繁)无关紧要。更新方法设置检查点,并且像系统允许的那样频繁地,渲染方法画出周围的时间。在Web标准中分离更新方法有很多种方法:

+

一种常见的技术是以恒定的频率更新模拟,然后绘制尽可能多的(或尽可能少的)实际帧。更新方法可以继续循环,而不用考虑用户看到的内容。绘图方法可以查看最后的更新以及发生的时间。由于绘制知道何时表示,以及上次更新的模拟时间,它可以预测为用户绘制一个合理的框架。这是否比官方更新循环更频繁(甚至更不频繁)无关紧要。更新方法设置检查点,并且像系统允许的那样频繁地,渲染方法画出周围的时间。在 Web 标准中分离更新方法有很多种方法:

-
  • 绘制requestAnimationFrame和更新一个setIntervalsetTimeout一个Web工作者。 +
  • 绘制requestAnimationFrame和更新一个setIntervalsetTimeout一个Web 工作者
  • -
  • 绘制requestAnimationFrame并使用它来戳一个包含更新方法的Web Worker,其中包含要计算的刻度数(如果有的话)。 +
  • 绘制requestAnimationFrame并使用它来戳一个包含更新方法的 Web Worker,其中包含要计算的刻度数(如果有的话)。
  • @@ -224,37 +224,37 @@

    处理可变刷新率需求
  • 强制性内插具有性能损失。
  • -

    单独的更新和绘图方法可能如下面的示例。为了演示,该示例基于第三个项目符号,只是不使用Web Workers进行可读性(而且我们诚实地说可写性)。

    +

    单独的更新和绘图方法可能如下面的示例。为了演示,该示例基于第三个项目符号,只是不使用 Web Workers 进行可读性(而且我们诚实地说可写性)。

    注意:这个例子,具体来说,需要进行技术审查。

    /*
     * 以分号开始,以上例子中的代码行都是这样的
    -* 依靠自动分号插入(ASI)。浏览器可能会意外
    +* 依靠自动分号插入 (ASI)。浏览器可能会意外
     * 认为这个整个例子从上一行继续。领先分号
     * 标记我们的新行的开始,如果前一个不是空或终止。
     *
    -* 我们还假设MyGame是以前定义的。
    +* 我们还假设 MyGame 是以前定义的。
     *
    -* MyGame.lastRender跟踪最后提供的requestAnimationFrame时间戳。
    -* MyGame.lastTick跟踪最后更新时间。始终以tickLength递增。
    -* MyGame.tickLength是游戏状态更新的频率。这是20 Hz(50ms)。
    +* MyGame.lastRender 跟踪最后提供的 requestAnimationFrame 时间戳。
    +* MyGame.lastTick 跟踪最后更新时间。始终以 tickLength 递增。
    +* MyGame.tickLength 是游戏状态更新的频率。这是 20 Hz(50ms)。
     *
    -* timeSinceTick是requestAnimationFrame回调和最后一次更新之间的时间。
    -* numTicks是这两个呈现帧之间应该发生的更新次数。
    +* timeSinceTick 是 requestAnimationFrame 回调和最后一次更新之间的时间。
    +* numTicks 是这两个呈现帧之间应该发生的更新次数。
     *
    -* render() 传入tFrame, 因为render方法可能需要计算
    +* render() 传入 tFrame, 因为 render 方法可能需要计算
     * tFrame 距离最近的更新已经过去了多久,通过外推的方式
    -* 来获得场景数据。(对于快速设备,render方法是纯表现性的)。
    +* 来获得场景数据。(对于快速设备,render 方法是纯表现性的)。
     * 用以绘制场景。
     *
    -* update() 根据给定时间点计算游戏状态。通常需要用tickLength
    +* update() 根据给定时间点计算游戏状态。通常需要用 tickLength
     * 作为循环参数,递增更新。来保证游戏状态的严谨。传入 DOMHighResTimeStamp
    -* 格式的当前时间。(除非需要增加暂停功能, 传入的时间应该总是
    -* 最后更新时间 + 游戏的tick间隔。)
    +* 格式的当前时间。(除非需要增加暂停功能,传入的时间应该总是
    +* 最后更新时间 + 游戏的 tick 间隔。)
     *
    -* setInitialState() 执行在运行mainloop之前需要的任何任务。
    -* 它只是一个普通的示例函数,表示您在mainloop前做过的事。
    +* setInitialState() 执行在运行 mainloop 之前需要的任何任务。
    +* 它只是一个普通的示例函数,表示您在 mainloop 前做过的事。
     */
     
     ;(function(){
    @@ -263,9 +263,9 @@ 

    处理可变刷新率需求 var nextTick = MyGame.lastTick + MyGame.tickLength; var numTicks = 0; - //如果tFrame <nextTick,则需要更新0个ticks(对于numTicks,默认为0)。 - //如果tFrame = nextTick,则需要更新1 tick(等等)。 - //注意:正如我们在总结中提到的那样,您应该跟踪numTicks的大小。 + //如果 tFrame <nextTick,则需要更新 0 个 ticks(对于 numTicks,默认为 0)。 + //如果 tFrame = nextTick,则需要更新 1 tick(等等)。 + //注意:正如我们在总结中提到的那样,您应该跟踪 numTicks 的大小。 //如果它很大,那么你的游戏是睡着了,或者机器无法跟上。 if(tFrame> nextTick){ var timeSinceTick = tFrame - MyGame.lastTick; @@ -279,14 +279,14 @@

    处理可变刷新率需求 function queueUpdates(numTicks){ for(var i = 0; i <numTicks; i ++){ - MyGame.lastTick = MyGame.lastTick + MyGame.tickLength; //现在lastTick是这个刻度。 + MyGame.lastTick = MyGame.lastTick + MyGame.tickLength; //现在 lastTick 是这个刻度。 update(MyGame.lastTick); } } MyGame.lastTick = performance.now(); MyGame.lastRender = MyGame.lastTick; //假装第一次绘制是在第一次更新。 - MyGame.tickLength = 50; //这将使您的模拟运行在20Hz(50ms) + MyGame.tickLength = 50; //这将使您的模拟运行在 20Hz(50ms) setInitialState(); main(performance.now()); //开始循环 @@ -298,9 +298,9 @@

    处理可变刷新率需求

    概要

    -

    我知道上述的任何一种,或许没有适合你的游戏。正确的决定完全取决于你愿意(和不愿意)做出的权衡。主要关心的是切换到另一个选项。幸运的是,我没有任何经验,但我听说这是一个令人难以置信的游戏的Whack-a-Mole。

    +

    我知道上述的任何一种,或许没有适合你的游戏。正确的决定完全取决于你愿意(和不愿意)做出的权衡。主要关心的是切换到另一个选项。幸运的是,我没有任何经验,但我听说这是一个令人难以置信的游戏的 Whack-a-Mole。

    -

    像Web这样的受管理平台,要记住的一件重要的事情是,您的循环可能会在相当长的一段时间内停止执行。当用户取消选择您的标签并且浏览器休眠(或减慢)其requestAnimationFrame回调间隔时,可能会发生这种情况。你有很多方法来处理这种情况,这可能取决于你的游戏是单人游戏还是多人游戏。一些选择是:

    +

    像 Web 这样的受管理平台,要记住的一件重要的事情是,您的循环可能会在相当长的一段时间内停止执行。当用户取消选择您的标签并且浏览器休眠(或减慢)其requestAnimationFrame回调间隔时,可能会发生这种情况。你有很多方法来处理这种情况,这可能取决于你的游戏是单人游戏还是多人游戏。一些选择是:

    -

    Web虚拟现实

    +

    Web 虚拟现实

    -

    虚拟现实这一概念并不新鲜,但由于硬件的进步,它大有席卷网络之势,如Oculus Rift和(目前实验性的) WebVR API,它们从VR硬件中捕获信息并使其可在JavaScript中应用。有关的详细信息请阅读 WebVR-Web 虚拟现实

    +

    虚拟现实这一概念并不新鲜,但由于硬件的进步,它大有席卷网络之势,如Oculus Rift和(目前实验性的) WebVR API,它们从 VR 硬件中捕获信息并使其可在 JavaScript 中应用。有关的详细信息请阅读 WebVR-Web 虚拟现实

    -

    还有一篇用A-Frame构建基本demo的文章,向您展示了使用A-Frame框架构建3D环境的虚拟现实是多么的简单。

    +

    还有一篇用 A-Frame 构建基本 demo的文章,向您展示了使用A-Frame框架构建 3D 环境的虚拟现实是多么的简单。

    库和框架的兴起

    -

    编码原生WebGL是相当复杂的,但从长远来看,您需要了解它,如果您的项目变得更加先进(请从参阅我们的WebGL文档开始)。对于现实世界中的项目,您可能还会使用框架来加快开发,并帮助您管理正在处理的项目。使用3D游戏框架还有助于优化性能,因为您使用的工具会处理很多问题,因此您可以专注于构建游戏本身。

    +

    编码原生 WebGL 是相当复杂的,但从长远来看,您需要了解它,如果您的项目变得更加先进(请从参阅我们的WebGL 文档开始)。对于现实世界中的项目,您可能还会使用框架来加快开发,并帮助您管理正在处理的项目。使用 3D 游戏框架还有助于优化性能,因为您使用的工具会处理很多问题,因此您可以专注于构建游戏本身。

    -

    最流行的JavaScript 3D库是Three.js,这是一个多用途工具,它使常见的3D技术更易于实现。还有其他流行的游戏开发库和框架值得检查。A-FramePlayCanvasBabylon.js是最容易辨认的,拥有丰富的文档、在线编辑器和活跃的社区。

    +

    最流行的 JavaScript 3D 库是Three.js,这是一个多用途工具,它使常见的 3D 技术更易于实现。还有其他流行的游戏开发库和框架值得检查。A-FramePlayCanvasBabylon.js是最容易辨认的,拥有丰富的文档、在线编辑器和活跃的社区。

    -

    使用 A-Frame 搭建一个基础Demo

    +

    使用 A-Frame 搭建一个基础 Demo

    -

    A-Frame是一个用于搭建3D和VR体验的Web框架。在内部,它是一个具有已声明的实体组件模式的three.js框架,也就是说我们只需借助HTML即可搭建场景。请参阅Building up a basic demo with A-Frame子页面来了解创建Demo的步骤。

    +

    A-Frame 是一个用于搭建 3D 和 VR 体验的 Web 框架。在内部,它是一个具有已声明的实体组件模式的 three.js 框架,也就是说我们只需借助 HTML 即可搭建场景。请参阅Building up a basic demo with A-Frame子页面来了解创建 Demo 的步骤。

    -

    使用 Babylon.js 搭建一个基础Demo

    +

    使用 Babylon.js 搭建一个基础 Demo

    -

    Babylon.js 是最受开发者欢迎的3D游戏引擎之一。与其他任何3D库一样,它提供了内置函数,帮助您更快地实现常见的3D功能。请参阅 Building up a basic demo with Babylon.js   子页,其中包括建立一个开发环境,构建必要的HTML,以及编写JavaScript代码。

    +

    Babylon.js 是最受开发者欢迎的 3D 游戏引擎之一。与其他任何 3D 库一样,它提供了内置函数,帮助您更快地实现常见的 3D 功能。请参阅 Building up a basic demo with Babylon.js   子页,其中包括建立一个开发环境,构建必要的 HTML,以及编写 JavaScript 代码。

    -

    使用 PlayCanvas  搭建一个基础Demo

    +

    使用 PlayCanvas  搭建一个基础 Demo

    -

    PlayCanvas是一个流行的GitHub开源3D WebGL游戏引擎,有在线编辑器和良好的文档。更多详细信息 请参阅Building up a basic demo with PlayCanvas  ,文章将进一步介绍如何使用PlayCanvas库和联机编辑器搭建例子。

    +

    PlayCanvas 是一个流行的 GitHub 开源 3D WebGL 游戏引擎,有在线编辑器和良好的文档。更多详细信息 请参阅Building up a basic demo with PlayCanvas  ,文章将进一步介绍如何使用 PlayCanvas 库和联机编辑器搭建例子。

    -

    使用 Three.js  搭建一个基础Demo

    +

    使用 Three.js  搭建一个基础 Demo

    -

    Three.js,与任何其他库一样,它给了您一个巨大的便利:不必编写数百行WebGL代码来构建任何有趣的东西,您可以使用内置的helper函数来轻松、快速地完成任务。请参阅 Building up a basic demo with Three.js 子页 逐步创建Demo。

    +

    Three.js,与任何其他库一样,它给了您一个巨大的便利:不必编写数百行 WebGL 代码来构建任何有趣的东西,您可以使用内置的 helper 函数来轻松、快速地完成任务。请参阅 Building up a basic demo with Three.js 子页 逐步创建 Demo。

    -

    使用  Whitestorm.js  搭建一个基础Demo

    +

    使用  Whitestorm.js  搭建一个基础 Demo

    -

    Whitestorm.js 是一个基于 Three.js 技术上的框架。它的主要区别是内置的物理引擎和插件系统 基于NPM。请参阅  Building up a basic demo with Whitestorm.js   了解更多信息、教程和例子制作基本的,甚至配合Three.js 制作更复杂的应用程序或游戏.

    +

    Whitestorm.js 是一个基于 Three.js 技术上的框架。它的主要区别是内置的物理引擎和插件系统 基于 NPM。请参阅  Building up a basic demo with Whitestorm.js   了解更多信息、教程和例子制作基本的,甚至配合 Three.js 制作更复杂的应用程序或游戏。

    其它工具

    -

    Unity 和 Unreal 可以将你的游戏通过 asm.js 输出到WebGL,因此你可以自由地使用这些工具与技术来构建可被输出到Web上的游戏。

    +

    Unity 和 Unreal 可以将你的游戏通过 asm.js 输出到 WebGL,因此你可以自由地使用这些工具与技术来构建可被输出到 Web 上的游戏。

    diff --git a/files/zh-cn/games/techniques/async_scripts/index.html b/files/zh-cn/games/techniques/async_scripts/index.html index 05a1b042fda70b..7fbbdbb812bf20 100644 --- a/files/zh-cn/games/techniques/async_scripts/index.html +++ b/files/zh-cn/games/techniques/async_scripts/index.html @@ -1,17 +1,17 @@ --- -title: asm.js的异步脚本 +title: asm.js 的异步脚本 slug: Games/Techniques/Async_scripts translation_of: Games/Techniques/Async_scripts ---
    {{GamesSidebar}}
    -

    每个中型或大型游戏都应编译asm.js代码作为异步脚本的一部分,以便浏览器能够最大限度地灵活地优化编译过程。 在Gecko中,异步编译允许JavaScript引擎在游戏加载时缓存主线程的asm.js,并缓存生成的机器代码,这样游戏就不需要在随后的加载中编译(从Firefox 28开始)。 要查看差异,请切换javascript.options.parallel_parsing in about:config.

    +

    每个中型或大型游戏都应编译asm.js代码作为异步脚本的一部分,以便浏览器能够最大限度地灵活地优化编译过程。在 Gecko 中,异步编译允许 JavaScript 引擎在游戏加载时缓存主线程的 asm.js,并缓存生成的机器代码,这样游戏就不需要在随后的加载中编译(从 Firefox 28 开始)。要查看差异,请切换javascript.options.parallel_parsing in about:config.

    异步执行

    -

    获取异步编译非常简单:编写JavaScript时,只需使用async属性即可:

    +

    获取异步编译非常简单:编写 JavaScript 时,只需使用async属性即可:

    <script async src="file.js"></script>
    @@ -21,11 +21,11 @@

    异步执行

    script.src = "file.js"; document.body.appendChild(script);
    -

    (从脚本中创建的脚本默认为异步。) 默认的HTML shell Emscripten生成后者。

    +

    (从脚本中创建的脚本默认为异步。) 默认的 HTML shell Emscripten 生成后者。

    -

    什么时候用async或者不用?

    +

    什么时候用 async 或者不用?

    -

    两种常见的情况下是脚本是异步的(由HTML规范定义)

    +

    两种常见的情况下是脚本是异步的(由HTML 规范定义)

    <script async>code</script>
    @@ -37,7 +37,7 @@

    什么时候用async或者不用?

    两者都被视为“内联”脚本,阻塞其余所有任务,进行编译,编译完成后立即执行。

    -

    如果你的代码是一个JS字符串呢? 而不是使用eval或innerHTML,这两者都会触发同步编译,您应该使用Blob和URL对象:

    +

    如果你的代码是一个 JS 字符串呢?而不是使用 eval 或 innerHTML,这两者都会触发同步编译,您应该使用 Blob 和 URL 对象:

    var blob = new Blob([codeString]);
     var script = document.createElement('script');
    diff --git a/files/zh-cn/games/techniques/control_mechanisms/mobile_touch/index.html b/files/zh-cn/games/techniques/control_mechanisms/mobile_touch/index.html
    index 5416becdd12db3..7c2c8ce42b9acf 100644
    --- a/files/zh-cn/games/techniques/control_mechanisms/mobile_touch/index.html
    +++ b/files/zh-cn/games/techniques/control_mechanisms/mobile_touch/index.html
    @@ -8,13 +8,13 @@
     
     

    {{NextMenu("Games/Techniques/Control_mechanisms/Desktop_with_mouse_and_keyboard", "Games/Techniques/Control_mechanisms")}}

    -

    未来手游一定是Web的天下,许多开发在游戏开发过程中首先选择手游 — 既然如此,触摸控制是不可少的。我们将在本教程中了解怎样简单地在移动端H5游戏中实现触摸控制 ,只要移动端支持触摸,你就可以尽情的玩。

    +

    未来手游一定是 Web 的天下,许多开发在游戏开发过程中首先选择手游 — 既然如此,触摸控制是不可少的。我们将在本教程中了解怎样简单地在移动端 H5 游戏中实现触摸控制 ,只要移动端支持触摸,你就可以尽情的玩。

    -

    说明:游戏 Captain Rogers: Battle at Andromeda 是基于Phaser 和Phaser-based管理控制,但它也可以用纯JavaScript实现。使用Phaser的好处它提供了辅助变量和方法可以直接调用,有助于快速的开发游戏,这需要根据项目实际情况选择。

    +

    说明:游戏 Captain Rogers: Battle at Andromeda 是基于Phaser 和 Phaser-based 管理控制,但它也可以用纯 JavaScript 实现。使用 Phaser 的好处它提供了辅助变量和方法可以直接调用,有助于快速的开发游戏,这需要根据项目实际情况选择。

    纯 JavaScript 方式实现

    -

    我们可以实现自己的触摸事件 — 给document添加事件监听,并传入自定义功能的方法,非常简单:

    +

    我们可以实现自己的触摸事件 — 给 document 添加事件监听,并传入自定义功能的方法,非常简单:

    var el = document.getElementsByTagName("canvas")[0];
     el.addEventListener("touchstart", handleStart);
    @@ -22,7 +22,7 @@ 

    纯 JavaScript 方式实现

    el.addEventListener("touchend", handleEnd); el.addEventListener("touchcancel", handleCancel);
    -

    这样, 在移动设备上屏幕上触摸游戏的 {{htmlelement("canvas")}} 将触发这些事件,因为我们就可以随意操控游戏(如:移动太空船)。 事件如下所示:

    +

    这样,在移动设备上屏幕上触摸游戏的 {{htmlelement("canvas")}} 将触发这些事件,因为我们就可以随意操控游戏(如:移动太空船)。 事件如下所示:

    -

    livesTextlifeLostText物体看起来非常相似的scoreText一个-它们定义在屏幕上的位置,显示实际文本和字体样式。前者被锚定在其右上边缘上,与屏幕正确对齐,后者位于中心位置,两者均使用anchor.set()

    +

    livesTextlifeLostText物体看起来非常相似的scoreText一个 - 它们定义在屏幕上的位置,显示实际文本和字体样式。前者被锚定在其右上边缘上,与屏幕正确对齐,后者位于中心位置,两者均使用anchor.set()

    lifeLostText会表示,只有当生命消失,因此其知名度初始设置为false

    diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/game_over/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/game_over/index.html index f48ddd2f011e7f..7e00d4149a0fce 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/game_over/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/game_over/index.html @@ -17,7 +17,7 @@

    {{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Player_paddle_and_controls", "Games/Workflows/2D_Breakout_game_Phaser/Build_the_brick_field")}}

    -

    这是Gamedev Phaser教程 16 的第8步。在Gamedev-Phaser-Content-Kit / demos / lesson08.html完成本课后,您可以找到源代码。

    +

    这是Gamedev Phaser 教程 16 的第 8 步。在Gamedev-Phaser-Content-Kit / demos / lesson08.html完成本课后,您可以找到源代码。

    为了使游戏更有趣,我们可以引入失去的能力 - 如果在到达屏幕底部边缘之前没有击球,那么这个游戏将会结束。

    diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/index.html index 41dff35f3cd286..1d2bebd73a6e3d 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/index.html @@ -1,5 +1,5 @@ --- -title: 使用Phaser开发2D breakout game +title: 使用 Phaser 开发 2D breakout game slug: Games/Tutorials/2D_breakout_game_Phaser tags: - Phaser @@ -11,11 +11,11 @@

    {{Next("Games/Workflows/2D_Breakout_game_Phaser/Initialize_the_framework")}}

    -

    在这个手把手的教程中,我们将使用Phaser框架制作一个使用JavaScript构建简单的MDN消除游戏。

    +

    在这个手把手的教程中,我们将使用 Phaser 框架制作一个使用 JavaScript 构建简单的 MDN 消除游戏。

    -

    教程的每一步骤都会有可供修改的样品来玩,所以你可以看到开发的每一步中间步骤。 您将学到如何使用Phaser框架来实现基础游戏机制的基本知识,诸如渲染和移动图像,碰撞检测,控制机制,框架特定的帮助器功能,动画和补间,以及获胜和失败状态等。

    +

    教程的每一步骤都会有可供修改的样品来玩,所以你可以看到开发的每一步中间步骤。您将学到如何使用 Phaser 框架来实现基础游戏机制的基本知识,诸如渲染和移动图像,碰撞检测,控制机制,框架特定的帮助器功能,动画和补间,以及获胜和失败状态等。

    -

    为了充分理解这一系列的文章,您应该确保已有基本的中级JavaScript知识。学完本教程,您将有能力用Phaser构建简单的Web游戏。

    +

    为了充分理解这一系列的文章,您应该确保已有基本的中级 JavaScript 知识。学完本教程,您将有能力用 Phaser 构建简单的 Web 游戏。

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

    @@ -42,12 +42,12 @@

    教学清单

  • 随机游戏
  • -

    学习路线的小提示 — 最好先熟悉使用原生JavaScript进行网页游戏开发,这样可以打下坚实的基础.如果你还不熟悉原生javascript开发,我们建议你先过一遍这个系列, 使用原生Javascript开发MDN消除游戏.

    +

    学习路线的小提示 — 最好先熟悉使用原生 JavaScript 进行网页游戏开发,这样可以打下坚实的基础。如果你还不熟悉原生 javascript 开发,我们建议你先过一遍这个系列,使用原生 Javascript 开发 MDN 消除游戏.

    -

    在那之后,你就能随意挑选框架并用在你的项目中;我们选择了Phaser这个稳定优越的框架,它有着好的支持和社区环境以及大量优秀的插件. 框架加速了开发并能帮你管理无趣的部分,让你专注于有意思的事务. 然而, 框架也有不好的地方, 所以当一些意想不到的事情发生了或者想实现一些框架没有提供的功能时,你就将需要原生的JavaScript知识了.

    +

    在那之后,你就能随意挑选框架并用在你的项目中;我们选择了 Phaser 这个稳定优越的框架,它有着好的支持和社区环境以及大量优秀的插件。框架加速了开发并能帮你管理无趣的部分,让你专注于有意思的事务。然而,框架也有不好的地方,所以当一些意想不到的事情发生了或者想实现一些框架没有提供的功能时,你就将需要原生的 JavaScript 知识了。

    -

    注意: 本系列文章可用作实际游戏开发的材料。 如果您想要使用Phaser讨论游戏开发,您还可以使用基于本教程的 Gamedev Phaser内容套件.

    +

    注意: 本系列文章可用作实际游戏开发的材料。如果您想要使用 Phaser 讨论游戏开发,您还可以使用基于本教程的 Gamedev Phaser 内容套件.

    Next steps

    diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/initialize_the_framework/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/initialize_the_framework/index.html index f23a9e5d59be06..e7ace4430086f5 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/initialize_the_framework/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/initialize_the_framework/index.html @@ -17,14 +17,14 @@

    {{PreviousNext("Games/Tutorials/2D_Breakout_game_Phaser", "Games/Tutorials/2D_Breakout_game_Phaser/Scaling")}}

    -

    这是Gamedev Phaser教程系列的第一课. 在课程完成之后,你可以在Gamedev-Phaser-Content-Kit/demos/lesson01.html找到源码.

    +

    这是Gamedev Phaser 教程系列的第一课。在课程完成之后,你可以在Gamedev-Phaser-Content-Kit/demos/lesson01.html找到源码。

    -

    在我们开始写游戏的功能之前,我们需要创建一个用来内部渲染游戏的基础架构.使用HTML就能做到 — Parser框架将生成所需的 {{htmlelement("canvas")}} 元素.

    +

    在我们开始写游戏的功能之前,我们需要创建一个用来内部渲染游戏的基础架构。使用 HTML 就能做到 — Parser 框架将生成所需的 {{htmlelement("canvas")}} 元素。

    -

    游戏的HTML

    +

    游戏的 HTML

    -

    HTML文档结构非常的简单,这个游戏将整个被渲染在框架生成的{{htmlelement("canvas")}} 元素上. 拿起你最爱的编辑器,挑一个好目录,创建一个HTML文档,存成index.html,然后写下下面的代码:

    +

    HTML 文档结构非常的简单,这个游戏将整个被渲染在框架生成的{{htmlelement("canvas")}} 元素上。拿起你最爱的编辑器,挑一个好目录,创建一个 HTML 文档,存成 index.html,然后写下下面的代码:

    <!DOCTYPE html>
     <html>
    @@ -47,25 +47,25 @@ 

    游戏的HTML

    </html>
    -

    下载Phaser

    +

    下载 Phaser

    -

    下面我们将下载Phaser的代码,并应用到我们的HTML文档中.

    +

    下面我们将下载 Phaser 的代码,并应用到我们的 HTML 文档中。

    1. 进入 Phaser 下载页面.
    2. -
    3. 选择最适合你的下载项 — 我们建议选择min.js,因为它最小,而且你不太可能想去看它的源码
    4. -
    5. 将Phaser的源码存到一个和index.html同级的 /js 的目录下
    6. -
    7. 在上面第一个 {{htmlelement("script")}} 标签里写下phaser的路径.
    8. +
    9. 选择最适合你的下载项 — 我们建议选择 min.js,因为它最小,而且你不太可能想去看它的源码
    10. +
    11. 将 Phaser 的源码存到一个和 index.html 同级的 /js 的目录下
    12. +
    13. 在上面第一个 {{htmlelement("script")}} 标签里写下 phaser 的路径。

    捋一捋我们干了些啥

    -

    这个时候我们在 {{htmlelement("header")}} 里定义了 {{htmlelement("charset")}} ,{{htmlelement("title")}} 和一些基础的css来重置默认的margin和padding. 我们也用 {{htmlelement("script")}} 标签向页面引入了 Phaser 源码。{{htmlelement("body ")}} 里也有一个 {{htmlelement("script")}} 标签,我们将在里面写 JavaScript 代码来渲染和控制游戏。

    +

    这个时候我们在 {{htmlelement("header")}} 里定义了 {{htmlelement("charset")}} ,{{htmlelement("title")}} 和一些基础的 css 来重置默认的 margin 和 padding. 我们也用 {{htmlelement("script")}} 标签向页面引入了 Phaser 源码。{{htmlelement("body ")}} 里也有一个 {{htmlelement("script")}} 标签,我们将在里面写 JavaScript 代码来渲染和控制游戏。

    {{htmlelement("canvas")}} 元素是由框架自动生成的。我们是通过 Phaser.Game 创建一个对象并赋给了 game 变量来完成初始化的。参数的含义是:

    -

    按键可以使用boolean变量来初始定义。在你的其它变量附近添加下列代码:

    +

    按键可以使用 boolean 变量来初始定义。在你的其它变量附近添加下列代码:

    var rightPressed = false;
     var leftPressed = false;
    -

    这两个变量的默认值都是false,因为在开始时按键没有被按下。为了监听按键的按下动作,我们需要添加两个监听器。把下列代码添加到底部的setInterval()的上一列去:

    +

    这两个变量的默认值都是 false,因为在开始时按键没有被按下。为了监听按键的按下动作,我们需要添加两个监听器。把下列代码添加到底部的setInterval()的上一列去:

    document.addEventListener("keydown", keyDownHandler, false);
     document.addEventListener("keyup", keyUpHandler, false);
    @@ -72,13 +72,13 @@

    允许用户控制球板

    } } -

    当按下一个按键,这个信息会被储存在一个变量中。每种情况下的相关变量都设置为true。 当松开按键时,对应变量被设置回false

    +

    当按下一个按键,这个信息会被储存在一个变量中。每种情况下的相关变量都设置为true。当松开按键时,对应变量被设置回false

    -

    两个函数都以一个事件作为参数,由e(event)变量表示。 从这里你可以得到有用的信息:keyCode属性是被按下的键的信息。 例如,keyCode为37是左箭头键,而39是右箭头键。 如果按下左键,那么leftPressed变量设置为true,当松开时,leftPressed变量设置为false。右键同理。

    +

    两个函数都以一个事件作为参数,由e(event) 变量表示。从这里你可以得到有用的信息:keyCode 属性是被按下的键的信息。例如,keyCode 为 37 是左箭头键,而 39 是右箭头键。如果按下左键,那么 leftPressed 变量设置为 true,当松开时,leftPressed 变量设置为 false。右键同理。

    球拍移动逻辑

    -

    我们现在有用于存储按键,事件监听器和相关功能的信息的变量。 现在我们将看到实际的代码来使用这些变量,并在屏幕上移动球拍。 在draw()函数内部,我们将检查每一帧被渲染的同时是否按下左或右键。 我们的代码如下:

    +

    我们现在有用于存储按键,事件监听器和相关功能的信息的变量。现在我们将看到实际的代码来使用这些变量,并在屏幕上移动球拍。在 draw()函数内部,我们将检查每一帧被渲染的同时是否按下左或右键。我们的代码如下:

    if(rightPressed) {
         paddleX += 7;
    @@ -87,7 +87,7 @@ 

    球拍移动逻辑

    paddleX -= 7; }
    -

    如果按一下左键,球拍将向左移动7个像素,如果按一下右键,球拍将向右移动7个像素。 目前这个功能可以正常工作,但是如果我们按任意一个键的时间太长,球拍就会从画布的边缘消失。 我们可以通过改变代码来改善这种情况,并且只能在画布的边界内移动球拍,如下所示:

    +

    如果按一下左键,球拍将向左移动 7 个像素,如果按一下右键,球拍将向右移动 7 个像素。目前这个功能可以正常工作,但是如果我们按任意一个键的时间太长,球拍就会从画布的边缘消失。我们可以通过改变代码来改善这种情况,并且只能在画布的边界内移动球拍,如下所示:

    if(rightPressed && paddleX < canvas.width-paddleWidth) {
         paddleX += 7;
    @@ -96,11 +96,11 @@ 

    球拍移动逻辑

    paddleX -= 7; }
    -

    我们使用在Canvas左侧的0和右侧的canvas.width-paddleWidth之间的paddleX位置移动,这会让球拍按预期的要求移动。

    +

    我们使用在Canvas左侧的 0 和右侧的canvas.width-paddleWidth之间的paddleX位置移动,这会让球拍按预期的要求移动。

    将上面的代码块添加到底部的draw()函数中,在右大括号的上方。

    -

    现在唯一要做的就是在draw()函数内调用drawPaddle()函数,将其实际渲染在屏幕上。 在draw()函数内添加下面一行,就在调用drawBall()的那一行的下面:

    +

    现在唯一要做的就是在draw()函数内调用drawPaddle()函数,将其实际渲染在屏幕上。在draw()函数内添加下面一行,就在调用drawBall()的那一行的下面:

    drawPaddle();
     
    @@ -117,6 +117,6 @@

    比较你的代码

    下一步

    -

    现在我们有一些类似于游戏的东西。 唯一的麻烦就是无论如何你都可以继续用球拍击球。 这一切都将在第五章中改变,游戏结束时,我们会为游戏添加一个最后的状态。

    +

    现在我们有一些类似于游戏的东西。唯一的麻烦就是无论如何你都可以继续用球拍击球。这一切都将在第五章中改变,游戏结束时,我们会为游戏添加一个最后的状态。

    {{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over")}}

    diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html index c71f426c3c297f..eb89a93a5121c9 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/track_the_score_and_win/index.html @@ -8,14 +8,14 @@

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

    -

    本篇为Gamedev Canvas tutorial10节教程中的第8节。在你完成这篇课程之后,你可以在Gamedev-Canvas-workshop/lesson8.html找到我们的源代码。

    +

    本篇为Gamedev Canvas tutorial10 节教程中的第 8 节。在你完成这篇课程之后,你可以在Gamedev-Canvas-workshop/lesson8.html找到我们的源代码。

    破坏砖块真的很酷,但更酷的是,游戏可以给每个用户击破的砖块奖励分数,并保持总分。

    计算分数

    -

    如果你能在整个游戏中看到你的分数,最终你会给你的朋友留下深刻印象。你需要一个变量来记录分数。在变量的其余部分之后,将下面的内容添加到JavaScript中:

    +

    如果你能在整个游戏中看到你的分数,最终你会给你的朋友留下深刻印象。你需要一个变量来记录分数。在变量的其余部分之后,将下面的内容添加到 JavaScript 中:

    var score = 0;
    @@ -27,7 +27,7 @@

    计算分数

    ctx.fillText("Score: "+score, 8, 20); } -

    在画布上绘制文本类似于绘制形状。字体定义看起来与CSS中的字体定义完全一样——可以在{{domxref("CanvasRenderingContext2D.font","font()")}} 方法中设置大小和字体类型。然后使用{{domxref("CanvasRenderingContext2D.fillStyle()","fillStyle()")}} 来设置字体的颜色,{{domxref("CanvasRenderingContext2D.fillText","fillText()")}} 来设置将放置在画布上的实际文本,和其放置位置。第一个参数是文本本身——上面的代码显示当前点的数量——最后两个参数是文本将放置在画布上的坐标。

    +

    在画布上绘制文本类似于绘制形状。字体定义看起来与 CSS 中的字体定义完全一样——可以在{{domxref("CanvasRenderingContext2D.font","font()")}} 方法中设置大小和字体类型。然后使用{{domxref("CanvasRenderingContext2D.fillStyle()","fillStyle()")}} 来设置字体的颜色,{{domxref("CanvasRenderingContext2D.fillText","fillText()")}} 来设置将放置在画布上的实际文本,和其放置位置。第一个参数是文本本身——上面的代码显示当前点的数量——最后两个参数是文本将放置在画布上的坐标。

    若要在每次击中砖块时评分,则在 collisionDetection()中添加计分规则,以在每次检测到碰撞时增加得分变量的值。将下面突出显示的行添加到代码中:

    @@ -52,7 +52,7 @@

    计算分数

    当所有砖块被破坏时显示获胜消息

    -

    收集这些点很有效,但是你不会永远添加它们-当所有的砖头都被破坏的时候呢?毕竟这是游戏的主要目的,所以如果收集到所有可用的点,你应该显示一个获胜的消息。将下面突出显示的部分添加到 collisionDetection() 函数中:

    +

    收集这些点很有效,但是你不会永远添加它们 - 当所有的砖头都被破坏的时候呢?毕竟这是游戏的主要目的,所以如果收集到所有可用的点,你应该显示一个获胜的消息。将下面突出显示的部分添加到 collisionDetection() 函数中:

    function collisionDetection() {
         for(var c=0; c<brickColumnCount; c++) {
    diff --git a/files/zh-cn/games/tutorials/html5_gamedev_phaser_device_orientation/index.html b/files/zh-cn/games/tutorials/html5_gamedev_phaser_device_orientation/index.html
    index 713992d9ffe21e..0649f260330899 100644
    --- a/files/zh-cn/games/tutorials/html5_gamedev_phaser_device_orientation/index.html
    +++ b/files/zh-cn/games/tutorials/html5_gamedev_phaser_device_orientation/index.html
    @@ -6,32 +6,32 @@
     
    {{GamesSidebar}}
    -

    在本教程中,我们将介绍构建 HTML5 移动游戏的过程。 本游戏使用 Device OrientationVibration APIs 来增强游戏玩法,并使用 Phaser 框架构建。 为了充分理解本教程建议您先学习基础的JavaScript 知识。

    +

    在本教程中,我们将介绍构建 HTML5 移动游戏的过程。本游戏使用 Device OrientationVibration APIs 来增强游戏玩法,并使用 Phaser 框架构建。为了充分理解本教程建议您先学习基础的 JavaScript 知识。

    Example game

    -

    在本教程结束时,您将有一个功能齐全的游戏demo:Cyber Orb 。如下所示:

    +

    在本教程结束时,您将有一个功能齐全的游戏 demo:Cyber Orb 。如下所示:

    A 2D game board featuring a small yellow ball. There is a large black hole for the ball to escape down, and a number of barriers blocking the ball from escaping.

    Phaser framework

    -

    Phaser 是构建桌面和移动 HTML5 游戏的框架。它非常新,但由于热情的社区参与开发过程它同时也是快速增长的。您能够在 GitHub 查看它的开放源代码,阅读 在线文档 并浏览大量 示例 。Phaser 框架为您提供了一组工具,这些工具将加快开发速度,并帮助处理完成游戏所需的一般任务,因此您可以专注于游戏创意本身。

    +

    Phaser 是构建桌面和移动 HTML5 游戏的框架。它非常新,但由于热情的社区参与开发过程它同时也是快速增长的。您能够在 GitHub 查看它的开放源代码,阅读 在线文档 并浏览大量 示例 。Phaser 框架为您提供了一组工具,这些工具将加快开发速度,并帮助处理完成游戏所需的一般任务,因此您可以专注于游戏创意本身。

    Starting with the project

    -

    您能够在GitHub看到它的源代码 Cyber Orb。文件夹结构非常简单:起点是 index.html。 我们在该文件中初始化框架并设置 html 元素 {{htmlelement("canvas")}} 以呈现游戏。

    +

    您能够在 GitHub 看到它的源代码 Cyber Orb。文件夹结构非常简单:起点是 index.html。我们在该文件中初始化框架并设置 html 元素 {{htmlelement("canvas")}} 以呈现游戏。

    Screenshot of the GitHub repository with the Cyber Orb game code, listing the folders and the files in the main structure.

    -

    您可以在您最喜爱的浏览器中打开index文件以启动并尝试游戏。目录中还有三个文件夹:

    +

    您可以在您最喜爱的浏览器中打开 index 文件以启动并尝试游戏。目录中还有三个文件夹: