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 @@
本文从技术角度分析了一般电子游戏的结构和工作流程,就此介绍主循环是如何运行的。它有助于初学者了解在现代游戏开发领域构建游戏时需要什么,以及如何将JavaScript这样的Web标准工具作为自己的工具使用。游戏开发经验丰富但不熟悉Web开发的开发者也能从中受益。
+本文从技术角度分析了一般电子游戏的结构和工作流程,就此介绍主循环是如何运行的。它有助于初学者了解在现代游戏开发领域构建游戏时需要什么,以及如何将 JavaScript 这样的 Web 标准工具作为自己的工具使用。游戏开发经验丰富但不熟悉 Web 开发的开发者也能从中受益。
但它也可能不需要逐帧控制。您的游戏循环可能类似找不同的例子,并以输入事件作为基础。它可能需要输入和模拟时间片。它甚至可以基于其他的东西来循环。
-现代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 中构建一个更好的主循环
在前面的主循环中有两个明显的问题:
@@ -72,16 +72,16 @@main()
污染了window
对象
(所有全局变量存储的对象),并且示例代码没有给我们留下一个停止循环的方法,除非整个浏览器选项卡被关闭或刷新。对于第一个问题,如果您希望主循环只运行,并且不需要被简单(直接)访问它,您可以将它作为一个立即调用的函数表达式(IIFE)创建。在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的中,浏览器有它自己的主循环,而你的代码存在于循环某些阶段。上面描述的主循环,试图避免脱离浏览器的控制。这种主循环附着于window.requestAnimationFrame()
方法,该方法将在浏览器的下一帧中执行,具体取决于浏览器如何与将其自己的主循环关联起来。W3C规范并没有真正定义什么时候浏览器必须执行requestAnimationFrame回调。这有一个好处,浏览器厂商可以自由地实现他们认为最好的解决方案,并随着时间的推移进行调整。
基本上,在 JavaScript 的中,浏览器有它自己的主循环,而你的代码存在于循环某些阶段。上面描述的主循环,试图避免脱离浏览器的控制。这种主循环附着于window.requestAnimationFrame()
方法,该方法将在浏览器的下一帧中执行,具体取决于浏览器如何与将其自己的主循环关联起来。W3C 规范并没有真正定义什么时候浏览器必须执行 requestAnimationFrame 回调。这有一个好处,浏览器厂商可以自由地实现他们认为最好的解决方案,并随着时间的推移进行调整。
现代版的Firefox和Google Chrome(可能还有其他版本)试图在框架的时间片的开始时将请求AnimationFrame回调与它们的主线程进行连接。因此,浏览器的主线程看起来就像下面这样:
+现代版的 Firefox 和 Google Chrome(可能还有其他版本)试图在框架的时间片的开始时将请求 AnimationFrame 回调与它们的主线程进行连接。因此,浏览器的主线程看起来就像下面这样:
您可以考虑开发实时应用程序,因为有时间做工作。所有上述步骤都必须在每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 的画布)放入复杂的层次结构中。每条路径都将导致不同的机会和约束。
如果你的游戏可以达到你所支持的任何硬件的最大刷新率,那么你的工作就变得相当容易了。 你可以简单地进行更新,渲染,然后在垂直同步之前什么都不用做。
+如果你的游戏可以达到你所支持的任何硬件的最大刷新率,那么你的工作就变得相当容易了。你可以简单地进行更新,渲染,然后在垂直同步之前什么都不用做。
/* * 以分号开始,以上例子中的代码行都是这样的 -* 依靠自动分号插入(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
并更新 {{ domxref("window.setInterval") }}或{{domxref("window.setTimeout")}}。
@@ -202,14 +202,14 @@ requestAnimationFrame
和更新一个setInterval
或setTimeout
一个Web工作者。
+ requestAnimationFrame
和更新一个setInterval
或setTimeout
一个Web 工作者。
requestAnimationFrame
并使用它来戳一个包含更新方法的Web Worker,其中包含要计算的刻度数(如果有的话)。
+ requestAnimationFrame
并使用它来戳一个包含更新方法的 Web Worker,其中包含要计算的刻度数(如果有的话)。
requestAnimationFrame
被调用并且不会污染主线程,加上你不依赖于老式的方法。再次,这比以前的两个选项更复杂一些,并且开始每个更新将被阻止,直到浏览器决定启动rAF回调。requestAnimationFrame
被调用并且不会污染主线程,加上你不依赖于老式的方法。再次,这比以前的两个选项更复杂一些,并且开始每个更新将被阻止,直到浏览器决定启动 rAF 回调。单独的更新和绘图方法可能如下面的示例。为了演示,该示例基于第三个项目符号,只是不使用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技术演示,你可以从中获得灵感和乐趣。这里证明了可以利用JavaScript,WebGL和相关的技术做些什么。前两个部分列出了可以玩的游戏,其中在第二个部分中列出的演示不一定是可交互的或是游戏。
+这个页面列出了许多令人印象深刻的 web 技术演示,你可以从中获得灵感和乐趣。这里证明了可以利用 JavaScript,WebGL 和相关的技术做些什么。前两个部分列出了可以玩的游戏,其中在第二个部分中列出的演示不一定是可交互的或是游戏。
欢迎来到MDN游戏开发中心! 在网站的这个模块我们为想要开发游戏的web开发者提供了资源。你可以在主菜单的左边找到很多有用的教程和技术文档,放轻松去探索吧。
+欢迎来到 MDN 游戏开发中心!在网站的这个模块我们为想要开发游戏的 web 开发者提供了资源。你可以在主菜单的左边找到很多有用的教程和技术文档,放轻松去探索吧。
-我们同样包含了参考书库,因此你可以轻易的找到有关游戏开发所有常用的API以及有用的引擎和工具清单和游戏案例.
+我们同样包含了参考书库,因此你可以轻易的找到有关游戏开发所有常用的 API 以及有用的引擎和工具清单和游戏案例.
注解: 在你开始尝试创建一个网页游戏之前你至少要掌握基础的核心web技术 —— 例如HTML、CSS和Javascript。如果你是一个完全的初学者, 这里 将会是一个很好的学习领域。
+注解: 在你开始尝试创建一个网页游戏之前你至少要掌握基础的核心 web 技术 —— 例如 HTML、CSS 和 Javascript。如果你是一个完全的初学者, 这里 将会是一个很好的学习领域。
如果你是一个本地游戏开发者(例如你用C++开发游戏),并且你对如何将本地游戏移植到Web感兴趣,你应该更多的学习关于我们的Emscripten 工具—— 这是一个LLVM JavaScript 编译器。它能获取LLVM字节码(例如用Clang编译C/C++或者其他语言生成的字节码)并且将它们编译成asm.js以在Web上运行。
+如果你是一个本地游戏开发者 (例如你用 C++开发游戏),并且你对如何将本地游戏移植到 Web 感兴趣,你应该更多的学习关于我们的Emscripten 工具—— 这是一个 LLVM JavaScript 编译器。它能获取 LLVM 字节码 (例如用 Clang 编译 C/C++或者其他语言生成的字节码)并且将它们编译成asm.js以在 Web 上运行。
-开始,查看以下:
+开始,查看以下:
现代的web已经高速发展成为一个可行可靠的平台,它不仅能够用来创建高质量的酷炫游戏,同时也能够用来发布和传播这些游戏。
+现代的 web 已经高速发展成为一个可行可靠的平台,它不仅能够用来创建高质量的酷炫游戏,同时也能够用来发布和传播这些游戏。
-采用现代网页技术和较新的浏览器,完全有可能做出令人印象深刻的顶级页面游戏。它能够制作的游戏种类可以和桌面端以及原生系统相当。我们这里所说的,并不是很久之前就采用Flash®制作出的简单卡牌游戏或者多人社交游戏。而是牛逼的3D 动作射击游戏,RPG 游戏等等。得益于 JavaScript 实时编译技术性能的大幅提升,以及新开放的 API。在制作运行在浏览器(或者是基于类似 Firefox OS 的 HTML5技术支持的设备)上的游戏时,我们不用妥协。
+采用现代网页技术和较新的浏览器,完全有可能做出令人印象深刻的顶级页面游戏。它能够制作的游戏种类可以和桌面端以及原生系统相当。我们这里所说的,并不是很久之前就采用 Flash®制作出的简单卡牌游戏或者多人社交游戏。而是牛逼的 3D 动作射击游戏,RPG 游戏等等。得益于 JavaScript 实时编译技术性能的大幅提升,以及新开放的 API。在制作运行在浏览器(或者是基于类似 Firefox OS 的 HTML5技术支持的设备)上的游戏时,我们不用妥协。
-你可以真正地为你的游戏考虑下 Web 来作为更好的目标平台。我们总是喜欢说,"the Web is the platform." 让我们浏览下 Web 平台的核心部分:
@@ -38,7 +38,7 @@作为一名游戏开发者,无论你是独立的个人还是大型游戏工作室,你想知道你的下一个游戏项目瞄准 Web 是有意义的 。让我们看看 Web 是如何帮到你的 。
+作为一名游戏开发者,无论你是独立的个人还是大型游戏工作室,你想知道你的下一个游戏项目瞄准 Web 是有意义的 。让我们看看 Web 是如何帮到你的。
技术同行们, 让我们发掘出所有关于Web的APIs,将它们呈现给所有的游戏开发者们。下面是一个比较完整的列表,可以一窥Web究竟能够做些什么:
+技术同行们,让我们发掘出所有关于 Web 的 APIs,将它们呈现给所有的游戏开发者们。下面是一个比较完整的列表,可以一窥 Web 究竟能够做些什么:
你已经跟着一两个教程做了一个HTML5游戏了——真棒 ! 这篇文章介绍了一些可以让你投放你的游戏的方式。 包括自己建立网站,在公开的应用市场上线,或是发布到Google Play或IOS的App Store。
+你已经跟着一两个教程做了一个 HTML5 游戏了——真棒 ! 这篇文章介绍了一些可以让你投放你的游戏的方式。 包括自己建立网站,在公开的应用市场上线,或是发布到 Google Play 或 IOS 的 App Store。
-用HTML5构筑游戏有许多好处,例如
+用 HTML5 构筑游戏有许多好处,例如
HTML5本身是多平台的,所以你只需要写一种代码就可以适配不同的平台。 从小型的智能手机和平板电脑,到笔记本电脑和台式电脑, 再到智能电视,智能手表甚至是智能冰箱(如果它内置现代化浏览器的话)。
+HTML5 本身是多平台的,所以你只需要写一种代码就可以适配不同的平台。 从小型的智能手机和平板电脑,到笔记本电脑和台式电脑,再到智能电视,智能手表甚至是智能冰箱(如果它内置现代化浏览器的话)。
你并不需要数个开发小组去编写不同平台的代码,你们只需要维护这一种基础代码。 你可以花更多时间去推广游戏和促进游戏收益化。
@@ -23,15 +23,15 @@若是HTML5游戏,你无需让大家去应用商店搜索,只需要给他们URL链接即可,他们点击链接就可以直接玩游戏,而不需要使用第三方平台或是下载一个很大的安装包来安装游戏。不过你仍需考虑你的游戏的大小是否可能会让用户花一点时间来加载资源,以及你的游戏对网速的需求。总之,如果你把你的游戏按照你的设想构建,并且在开玩之前没有那么多弯弯绕绕,推广它还是很容易的
+若是 HTML5 游戏,你无需让大家去应用商店搜索,只需要给他们 URL 链接即可,他们点击链接就可以直接玩游戏,而不需要使用第三方平台或是下载一个很大的安装包来安装游戏。不过你仍需考虑你的游戏的大小是否可能会让用户花一点时间来加载资源,以及你的游戏对网速的需求。总之,如果你把你的游戏按照你的设想构建,并且在开玩之前没有那么多弯弯绕绕,推广它还是很容易的
我们感兴趣的绝大部分流量——HTML5游戏玩家——都来自移动设备,所以如果你真的想要成功,你就必须专注于这一点。手机端是HTML5真正发光发热的地方,那里没有Flash,HTML5便是全部。
+我们感兴趣的绝大部分流量——HTML5 游戏玩家——都来自移动设备,所以如果你真的想要成功,你就必须专注于这一点。手机端是 HTML5 真正发光发热的地方,那里没有 Flash,HTML5 便是全部。
-要与PC端游直接竞争是很困难的,当然你也可以在PC端发布你的游戏(见下文的电脑平台)你也应该这么做,因为这可以让你的游戏支持的平台变得多样化,但谨记,电脑游戏的开发者拥有多年的经验,优秀的工具和稳定的发行渠道。许多HTML5游戏会与传统电脑游戏面向不同的受众市场。例如,简单的的小游戏比大型的沉浸式游戏更有人气,这类游戏通常设计成用两根手指,甚至一根手指玩,所以你可以拿着设备玩游戏,还可以用第二只手做你目前需要的任何事情。
+要与 PC 端游直接竞争是很困难的,当然你也可以在 PC 端发布你的游戏(见下文的电脑平台)你也应该这么做,因为这可以让你的游戏支持的平台变得多样化,但谨记,电脑游戏的开发者拥有多年的经验,优秀的工具和稳定的发行渠道。许多 HTML5 游戏会与传统电脑游戏面向不同的受众市场。例如,简单的的小游戏比大型的沉浸式游戏更有人气,这类游戏通常设计成用两根手指,甚至一根手指玩,所以你可以拿着设备玩游戏,还可以用第二只手做你目前需要的任何事情。
-话又说回来,电脑平台易于发行游戏,因为有许多好用的打包软件帮助你构造游戏的架构(见下文游戏打包),为你的游戏配置适应电脑端的控制器也是很不错的做法——即使你的游戏主要面向手机用户。用户可以在任何平台畅玩你的游戏,电脑端也应该是其中之一。此外,在电脑端先构建和测试游戏通常更为便捷,然后再到手机端测试BUG
+话又说回来,电脑平台易于发行游戏,因为有许多好用的打包软件帮助你构造游戏的架构(见下文游戏打包),为你的游戏配置适应电脑端的控制器也是很不错的做法——即使你的游戏主要面向手机用户。用户可以在任何平台畅玩你的游戏,电脑端也应该是其中之一。此外,在电脑端先构建和测试游戏通常更为便捷,然后再到手机端测试 BUG
如果你是前端开发者,你应该已经知道要做什么了. 一个HTML5游戏不过是又一个网站而已.。你可以将它上传到远程服务器,设置一个好记的域名,然后就可以自己开始运营游戏了。
+如果你是前端开发者,你应该已经知道要做什么了。一个 HTML5 游戏不过是又一个网站而已.。你可以将它上传到远程服务器,设置一个好记的域名,然后就可以自己开始运营游戏了。
-如果你想从游戏开发中赚钱,你应该用多种方法保护你的源码,这样其他人不会轻易地取得你的源码并且拿去当成自己的去出售. 你可以压缩和精简代码,让它变得更小,更难读,这样他人就不能轻易的复刻你的游戏。一个更好的方法是在网上发布测试版如果你打算打包你的项目并把它出售给Steam或者iTunes。
+如果你想从游戏开发中赚钱,你应该用多种方法保护你的源码,这样其他人不会轻易地取得你的源码并且拿去当成自己的去出售。你可以压缩和精简代码,让它变得更小,更难读,这样他人就不能轻易的复刻你的游戏。一个更好的方法是在网上发布测试版如果你打算打包你的项目并把它出售给 Steam 或者 iTunes。
-如果你只是为了娱乐性质的话, 开放源码可以让那些想要从你的作品中学习的人收益.你甚至不需要担心主机提供商,因为你可以在Github上托管游戏. 你可以有一个免费的主机,可控制的版本,以及可能的贡献者——如果这个项目足够有趣的话.
+如果你只是为了娱乐性质的话,开放源码可以让那些想要从你的作品中学习的人收益。你甚至不需要担心主机提供商,因为你可以在 Github 上托管游戏. 你可以有一个免费的主机,可控制的版本,以及可能的贡献者——如果这个项目足够有趣的话。
顾名思义,开发商可以帮助你发行游戏,是否交给开发商则取决于你的游戏开发计划:你想在全平台发行么?或你只向购买了游戏的用户开放游戏?这都取决于你,考虑各个选项,试验和结论。你可以在游戏收益化这篇文章中得到更详细的关于发行商的解释。
-这里还有许多独立的门户网站收集HTML5游戏,例如 HTML5Games.com, MarketJS.com, Clay.io, or Poki 你可以把你的游戏发布上去,它会得到一些自然的推广,因为这些网站吸引了大量的流量。一些网站会把你的文件放在他们的服务器上运营,而其他网站则只链接到你的网站或将你的游戏嵌入他们的网站,这样的曝光可能只是为你的游戏提供宣传,如果你的游戏旁边有广告(或其他赚钱的选项),它也可能为你的游戏提供收益化。
+这里还有许多独立的门户网站收集 HTML5 游戏,例如 HTML5Games.com, MarketJS.com, Clay.io, or Poki 你可以把你的游戏发布上去,它会得到一些自然的推广,因为这些网站吸引了大量的流量。一些网站会把你的文件放在他们的服务器上运营,而其他网站则只链接到你的网站或将你的游戏嵌入他们的网站,这样的曝光可能只是为你的游戏提供宣传,如果你的游戏旁边有广告 (或其他赚钱的选项),它也可能为你的游戏提供收益化。
你也可以直接把游戏发布到不同的应用商店里, 或者是应用市场,要做到这一点,你必须准备好并将其打包为针对您想要针对的每个应用程序生态系统的特定构建格式. 见下文应用市场—多样化平台来获取更多关于应用市场的细节
+你也可以直接把游戏发布到不同的应用商店里,或者是应用市场,要做到这一点,你必须准备好并将其打包为针对您想要针对的每个应用程序生态系统的特定构建格式。见下文应用市场—多样化平台来获取更多关于应用市场的细节
最适合HTML5的平台是基于web的商店. 为它们准备一款游戏很容易,因为这样的操作几乎不需要修改游戏本身——通常在包含所有资源的压缩包中添加包含必要信息的清单文件就足够了。
+最适合 HTML5 的平台是基于 web 的商店。为它们准备一款游戏很容易,因为这样的操作几乎不需要修改游戏本身——通常在包含所有资源的压缩包中添加包含必要信息的清单文件就足够了。
在移动市场上,iOS版的苹果应用商店(Apple App Store)、Android版的谷歌Play以及其他竞争对手。原生商店中已经充斥着销售优秀游戏的成熟开发者,所以你必须具备足够的天赋和幸运才能获得关注。
+在移动市场上,iOS 版的苹果应用商店 (Apple App Store)、Android 版的谷歌 Play 以及其他竞争对手。原生商店中已经充斥着销售优秀游戏的成熟开发者,所以你必须具备足够的天赋和幸运才能获得关注。
如果你想了解更多关于不同类型的应用程序商店的信息,你可以在维基百科上查看手机软件发布平台列表。
为了扩大你的受众,你也可以使用HTML5游戏去占据电脑游戏市场——只要记住那些已经占据了大部分市场份额的AAA级游戏,并仔细考虑这是否适合你的策略。要正确的在电脑端运行,您应该支持所有三种操作系统:Windows、Mac OS和Linux。最大的电脑游戏商店无疑是Steam — 独立开发者可以通过 Greenlight 接触steam. 请记住,您必须通过为不同的平台上传不同的版本来处理跨平台问题。
+为了扩大你的受众,你也可以使用 HTML5 游戏去占据电脑游戏市场——只要记住那些已经占据了大部分市场份额的 AAA 级游戏,并仔细考虑这是否适合你的策略。要正确的在电脑端运行,您应该支持所有三种操作系统:Windows、Mac OS 和 Linux。最大的电脑游戏商店无疑是Steam — 独立开发者可以通过 Greenlight 接触 steam. 请记住,您必须通过为不同的平台上传不同的版本来处理跨平台问题。
-在你入驻Steam之后,便会有许多类似于Humble Bundle等项目的讨论,这些项目可以把最受欢迎的独立游戏能够呈现给更多人。不过,这更像是一个绝佳的促销机会,而不是一种赚大钱的方式,因为捆绑游戏的价格通常相当低。
+在你入驻 Steam 之后,便会有许多类似于Humble Bundle等项目的讨论,这些项目可以把最受欢迎的独立游戏能够呈现给更多人。不过,这更像是一个绝佳的促销机会,而不是一种赚大钱的方式,因为捆绑游戏的价格通常相当低。
网页是HTML5游戏的首选也是最好的选择,但如果你想接触到更广泛的受众并在封闭的生态系统中发行你的游戏,你仍然可以通过打包它来做到这一点。好在你不需要几个独立的团队在不同的平台上致力于同一款游戏——你可以一次性构建它,并使用像 Phonegap 或 CocoonIO 这样的工具为本地商店打包游戏。生成的包通常非常可靠,但是您仍然应该测试它们,并注意要修复的小问题或bug。
+网页是 HTML5 游戏的首选也是最好的选择,但如果你想接触到更广泛的受众并在封闭的生态系统中发行你的游戏,你仍然可以通过打包它来做到这一点。好在你不需要几个独立的团队在不同的平台上致力于同一款游戏——你可以一次性构建它,并使用像 Phonegap 或 CocoonIO 这样的工具为本地商店打包游戏。生成的包通常非常可靠,但是您仍然应该测试它们,并注意要修复的小问题或 bug。
根据您的技能、首选框架或目标平台,可以选择多种工具。关键是为你的特定任务选择最好的工具。
其他替代工具包括:
+其他替代工具包括:
当你花时间创造一个游戏的时候, 从发布和促销中赚钱是你应该考虑的事. 如果你正做出大量努力去成为一个能够以此为生的独立游戏开发者, 接下去, 看看你有哪些选择. 技术手段已经足够成熟; 接下来只是选择正确的方法.
+当你花时间创造一个游戏的时候,从发布和促销中赚钱是你应该考虑的事。如果你正做出大量努力去成为一个能够以此为生的独立游戏开发者,接下去,看看你有哪些选择。技术手段已经足够成熟; 接下来只是选择正确的方法。
你可能想到的第一个,也是最明显的选择便是以面向AAA级游戏的方式销售游戏——即固定的预付款。即使数字市场是关键,你也不需要打印封面,也不需要将游戏放在实体店的盒子里,但要想以固定的价格销售游戏赚取可观的利润,你必须将时间和金钱投入到市场营销中去。只有最好的游戏才能做到收支平衡,或者赚得比制作成本还要多,你仍然需要很多的运气。
+你可能想到的第一个,也是最明显的选择便是以面向 AAA 级游戏的方式销售游戏——即固定的预付款。即使数字市场是关键,你也不需要打印封面,也不需要将游戏放在实体店的盒子里,但要想以固定的价格销售游戏赚取可观的利润,你必须将时间和金钱投入到市场营销中去。只有最好的游戏才能做到收支平衡,或者赚得比制作成本还要多,你仍然需要很多的运气。
-你为你的游戏收取多少费用取决于市场,游戏的质量和许多其他小因素。一款街机iOS游戏售价为0.99美元,但一款更长的rpg风格的Steam桌面游戏售价为20美元;两个价格都可以。你必须跟随市场,做自己的研究——迅速从错误中吸取教训是很重要的。
+你为你的游戏收取多少费用取决于市场,游戏的质量和许多其他小因素。一款街机 iOS 游戏售价为 0.99 美元,但一款更长的 rpg 风格的 Steam 桌面游戏售价为 20 美元;两个价格都可以。你必须跟随市场,做自己的研究——迅速从错误中吸取教训是很重要的。
你可以提供一款带有应用内购买功能(IAP)的免费游戏,而不是让人们预先为你的游戏付费。在这种情况下,玩家不需要花一分钱就可以获得游戏——将游戏交给玩家,但要提供游戏内的货币、奖金或福利。具体的例子可以包括奖金水平,更好的武器或咒语,或补充所需的能量发挥。设计一个好的IAP系统本身就是一门艺术。
+你可以提供一款带有应用内购买功能(IAP)的免费游戏,而不是让人们预先为你的游戏付费。在这种情况下,玩家不需要花一分钱就可以获得游戏——将游戏交给玩家,但要提供游戏内的货币、奖金或福利。具体的例子可以包括奖金水平,更好的武器或咒语,或补充所需的能量发挥。设计一个好的 IAP 系统本身就是一门艺术。
-记住,你需要下载数千次游戏才能使IAPs有效——只有一小部分玩家会真正为IAPs付费。多小?情况各不相同,但大约每千人中就有一个人处于平均水平。玩你的游戏的人越多,别人就越有可能付钱,所以你的收入很大程度取决于你的推广方式.
+记住,你需要下载数千次游戏才能使 IAPs 有效——只有一小部分玩家会真正为 IAPs 付费。多小?情况各不相同,但大约每千人中就有一个人处于平均水平。玩你的游戏的人越多,别人就越有可能付钱,所以你的收入很大程度取决于你的推广方式。
带有IAPs功能的游戏通常被称为免费增值游戏——免费增值游戏可以免费取得与游玩,但你可以为额外的(高级)功能、虚拟物品或其他好处付费。在大公司专注于创造游戏后,这个词本身就带有负面含义,其主要目的是为了从玩家那里获得尽可能多的钱,而不是提供一种有趣的体验。最糟糕的情况是,你可以用真金实银来获得相对于其他玩家的优势,或限制玩家进入游戏的下一阶段,除非玩家付费。“为赢付费”这个术语是被创造出来的,并且这种方法不受许多玩家和开发者的欢迎。如果你想要实现IAPs,那就试着用玩家喜欢的东西来为游戏增加价值,而不是把它拿出来然后收费。
+带有 IAPs 功能的游戏通常被称为免费增值游戏——免费增值游戏可以免费取得与游玩,但你可以为额外的 (高级) 功能、虚拟物品或其他好处付费。在大公司专注于创造游戏后,这个词本身就带有负面含义,其主要目的是为了从玩家那里获得尽可能多的钱,而不是提供一种有趣的体验。最糟糕的情况是,你可以用真金实银来获得相对于其他玩家的优势,或限制玩家进入游戏的下一阶段,除非玩家付费。“为赢付费”这个术语是被创造出来的,并且这种方法不受许多玩家和开发者的欢迎。如果你想要实现 IAPs,那就试着用玩家喜欢的东西来为游戏增加价值,而不是把它拿出来然后收费。
-扩展包和可下载内容是为已经发行的游戏提供额外价值的好方法,但请记住,您必须提供体面的、有趣的内容来吸引人们购买它。一套全新的带有新角色、武器和故事的关卡对于DLC来说是一个很好的素材,但要想获得足够的销量,游戏本身必须是受欢迎的,否则就不会有玩家愿意将他们辛苦赚来的钱花在这上面。
+扩展包和可下载内容是为已经发行的游戏提供额外价值的好方法,但请记住,您必须提供体面的、有趣的内容来吸引人们购买它。一套全新的带有新角色、武器和故事的关卡对于 DLC 来说是一个很好的素材,但要想获得足够的销量,游戏本身必须是受欢迎的,否则就不会有玩家愿意将他们辛苦赚来的钱花在这上面。
除了积极销售游戏以外,你也可以尝试被动销售 — 投放广告和开展相关活动或许有益于推广你的游戏,但你的游戏必须让人上瘾,这并不像听起来那么容易。你仍然需要计划好,在某种程度上,你也需要一些运气。如果你的游戏像病毒一样传播开来,人们开始分享它,你就能从广告中获得大量的下载和收益。
-有许多公司提供广告系统——你注册后,允许他们展示广告,以换取一定比例的利润。谷歌AdSense被认为是最有效的一个,但它不是为游戏而设计的,使用它来达到这个目的是一个非常糟糕的做法。不要冒着让你的账户被封禁,资产被冻结的风险,游戏开发者们更青睐门户网站,如LeadBolt。他们提供了易于实现的系统,以在您的游戏显示广告并与您分享收益。
+有许多公司提供广告系统——你注册后,允许他们展示广告,以换取一定比例的利润。谷歌 AdSense 被认为是最有效的一个,但它不是为游戏而设计的,使用它来达到这个目的是一个非常糟糕的做法。不要冒着让你的账户被封禁,资产被冻结的风险,游戏开发者们更青睐门户网站,如LeadBolt。他们提供了易于实现的系统,以在您的游戏显示广告并与您分享收益。
视频广告正变得越来越受欢迎,特别是以预播放的形式——它们会在游戏开始时显示,而此时游戏还在加载中。至于在游戏中放置广告的位置,这完全取决于你自己。它应该尽可能的微妙,以避免过多地惹恼玩家,但又足够的可见性让玩家点击它或至少注意到它。通过屏幕在游戏会话之间添加广告是一种流行的方法。
@@ -49,23 +49,23 @@独家性许可是针对一个发行商的一种许可类型——你创造了一款游戏,并将其所有权利出售给了一个实体,同时还拥有重新发行该游戏的权利 — Softgames就是这样一家发行商。 在出版商拥有版权的情况下,你不能再以任何形式出售它——这就是独家交易价值不菲的原因。到底是多少?这取决于游戏的质量,游戏类型,发行商,以及其他许多因素,但通常价格在2000到5000美元之间。一旦你卖出了独家授权,你就不用再参与推广这款游戏了,因为你赚不到更多钱,所以只有在你确信这款游戏足够盈利的情况下,你才会参与这样的交易。
+独家性许可是针对一个发行商的一种许可类型——你创造了一款游戏,并将其所有权利出售给了一个实体,同时还拥有重新发行该游戏的权利 — Softgames就是这样一家发行商。 在出版商拥有版权的情况下,你不能再以任何形式出售它——这就是独家交易价值不菲的原因。到底是多少?这取决于游戏的质量,游戏类型,发行商,以及其他许多因素,但通常价格在 2000 到 5000 美元之间。一旦你卖出了独家授权,你就不用再参与推广这款游戏了,因为你赚不到更多钱,所以只有在你确信这款游戏足够盈利的情况下,你才会参与这样的交易。
这种方法不那么严格——您可以将许可证出售给多个发布者。这是最受欢迎的方法,因为对于每一个新的发行商(总会有的),你都可以以非独家的条款出售你的游戏。请记住,有了这个许可,发行商就不能再对其进行重新发行了——这通常被称为站点锁定交易,因为他们购买了在自己的门户网站上发布游戏的权利。非独家许可的通常成本约为500美元。
+这种方法不那么严格——您可以将许可证出售给多个发布者。这是最受欢迎的方法,因为对于每一个新的发行商 (总会有的),你都可以以非独家的条款出售你的游戏。请记住,有了这个许可,发行商就不能再对其进行重新发行了——这通常被称为站点锁定交易,因为他们购买了在自己的门户网站上发布游戏的权利。非独家许可的通常成本约为 500 美元。
此外,用户还可以通过购买服务来月付你的游戏而不是一次性付款,每一款游戏每月都能为你提供一定的钱——大约20-50美元。你可以决定是一次性付清一段时间还是每月付一次。记住它可以被随时取消,所以它不是一个通解。
+此外,用户还可以通过购买服务来月付你的游戏而不是一次性付款,每一款游戏每月都能为你提供一定的钱——大约 20-50 美元。你可以决定是一次性付清一段时间还是每月付一次。记住它可以被随时取消,所以它不是一个通解。
你可以在自己的游戏中发布广告,并试图找到流量来赚取一些钱,但你也可以与发行商达成收益分成协议。他们将负责吸引流量,并将分享收益——通常是每月73开或者五五开的交易。
+你可以在自己的游戏中发布广告,并试图找到流量来赚取一些钱,但你也可以与发行商达成收益分成协议。他们将负责吸引流量,并将分享收益——通常是每月 73 开或者五五开的交易。
-请记住,许多新的、低质量的发行商会希望你的游戏获得广告收入而不是授权,因为这对他们来说更便宜,并且你可能只会在整个交易中获得每款游戏约2美元的收益。在与新出版商打交道时要小心——有时候,降低已知出版商的许可成本比冒着被未知出版商骗钱的风险要好。
+请记住,许多新的、低质量的发行商会希望你的游戏获得广告收入而不是授权,因为这对他们来说更便宜,并且你可能只会在整个交易中获得每款游戏约 2 美元的收益。在与新出版商打交道时要小心——有时候,降低已知出版商的许可成本比冒着被未知出版商骗钱的风险要好。
-发行商从你的游戏中获取收益分成,以及/或许可可能需要实现他们自己的API,这可能需要额外的工作,所以你也要考虑到这一点。
+发行商从你的游戏中获取收益分成,以及/或许可可能需要实现他们自己的 API,这可能需要额外的工作,所以你也要考虑到这一点。
在开发HTML5游戏时,你还可以通过其他方式赚钱,而这甚至不需要与游戏相关。
+在开发 HTML5 游戏时,你还可以通过其他方式赚钱,而这甚至不需要与游戏相关。
你可以写一些关于你的游戏的文章,甚至可以从中获得报酬。可以同时取得游戏推广和收益化的双赢,如果你不滥用它与太多的广告,读者将享受阅读他们以及学习一两个东西。如果你专注于先分享知识,并将游戏作为例子来使用,这应该是可以的。 浏览Tuts+ Game Development 或相似的网站来找寻协作机会
+你可以写一些关于你的游戏的文章,甚至可以从中获得报酬。可以同时取得游戏推广和收益化的双赢,如果你不滥用它与太多的广告,读者将享受阅读他们以及学习一两个东西。如果你专注于先分享知识,并将游戏作为例子来使用,这应该是可以的。浏览Tuts+ Game Development 或相似的网站来找寻协作机会
你可以售卖T恤,贴纸或其他周边 — 有些开发者从这些商品中赚的钱比从游戏本身中赚的钱还多,但它只适用于像愤怒的小鸟这样非常受欢迎且易于识别的游戏。不过,这也可能是另一种小的被动收入来源。你的收入越多样化,你的生意就越稳定。
+你可以售卖 T 恤,贴纸或其他周边 — 有些开发者从这些商品中赚的钱比从游戏本身中赚的钱还多,但它只适用于像愤怒的小鸟这样非常受欢迎且易于识别的游戏。不过,这也可能是另一种小的被动收入来源。你的收入越多样化,你的生意就越稳定。
当其他方法都失败时,你可以尝试在你的游戏页面上放置一个捐赠按钮并寻求社区的支持。有时候它是有效的,但前提是玩家了解你并觉得它能够帮助你。这就是为什么小心管理你的社区是如此重要。这在js13kGames比赛中很管用 — 每个参与者都得到了一件免费的t恤,有些人甚至还退了一些钱,以帮助它在未来几年继续运行下去。
+当其他方法都失败时,你可以尝试在你的游戏页面上放置一个捐赠按钮并寻求社区的支持。有时候它是有效的,但前提是玩家了解你并觉得它能够帮助你。这就是为什么小心管理你的社区是如此重要。这在js13kGames比赛中很管用 — 每个参与者都得到了一件免费的 t 恤,有些人甚至还退了一些钱,以帮助它在未来几年继续运行下去。
赚钱的方法有很多种——所有适用于“普通”AAA级游戏世界的东西,或多或少都可以应用于休闲HTML5游戏。然而,你也可以专注于销售许可证,做品牌,或者从广告中获得收入分成。你要走哪条路完全取决于你自己。
+赚钱的方法有很多种——所有适用于“普通”AAA 级游戏世界的东西,或多或少都可以应用于休闲 HTML5 游戏。然而,你也可以专注于销售许可证,做品牌,或者从广告中获得收入分成。你要走哪条路完全取决于你自己。
diff --git a/files/zh-cn/games/publishing_games/game_promotion/index.html b/files/zh-cn/games/publishing_games/game_promotion/index.html index a8c6bc145f11ac..4e5430345b0abd 100644 --- a/files/zh-cn/games/publishing_games/game_promotion/index.html +++ b/files/zh-cn/games/publishing_games/game_promotion/index.html @@ -5,52 +5,52 @@ ---开发与发行你的游戏并不是全部.。你应该让大家知道你有个大家会喜欢玩的游戏。这儿有很多方法去推广你的游戏——大部分方法是免费的, 所以即使即使你正努力以一名零预算的独立开发者的身份谋生,你也可以让人们知道你的新游戏.。推广游戏也对之后的游戏收益化大有裨益, 所以正确地推广游戏是很重要的。
+开发与发行你的游戏并不是全部.。你应该让大家知道你有个大家会喜欢玩的游戏。这儿有很多方法去推广你的游戏——大部分方法是免费的,所以即使即使你正努力以一名零预算的独立开发者的身份谋生,你也可以让人们知道你的新游戏.。推广游戏也对之后的游戏收益化大有裨益,所以正确地推广游戏是很重要的。
参加竞赛不仅将提升您的游戏开发技能,让你认识新朋友、学习开发,它还将让你参与到社区之中。如果你在比赛中做了一个好的游戏并赢得了一些奖品,你的游戏就会自然而然地被组织者和其他参与者推广开来。你会变得富有和出名,至少他们是这么说的。
- 许多优秀的游戏都是从一个游戏制作比赛上的demo开始的。如果你的想法和执行力都足够好,你就会成功。另外,比赛通常要求游戏有一个固定的主题,所以如果你一筹莫展,你也可以围绕这个主题进行创作。
你应该创建自己的网站,包含所有关于游戏的信息,这样人们就可以看到你在做什么。你能包含的信息越多越好 — 包括截图,简报,预告,宣传资料, 需求,可用的平台,赞助以及其他. 让你的用户在网上直接玩你的游戏——或者说测试版可以让你得到许多电子。同时,为了让你的用户能够更好的玩游戏,你应该做些网站优化(SEO)
+你应该创建自己的网站,包含所有关于游戏的信息,这样人们就可以看到你在做什么。你能包含的信息越多越好 — 包括截图,简报,预告,宣传资料,需求,可用的平台,赞助以及其他。让你的用户在网上直接玩你的游戏——或者说测试版可以让你得到许多电子。同时,为了让你的用户能够更好的玩游戏,你应该做些网站优化(SEO)
-你也应该在博客公布所有与你游戏开发有关的动作,写下你的开发历程,严重的bug,有趣的事情,经验教训,以及作为游戏开发者的起起伏伏。坚持发布信息有助于他人从中学习,提高你在社区中的声誉,改进你的网站优化。另一种选择是发布每月报告——总结你所有进展的报告——它能够帮助你看到你在整个月都完成了什么,还有什么需要去做,并不断提醒人们你的游戏即将发行——创造口碑总是好的。
+你也应该在博客公布所有与你游戏开发有关的动作,写下你的开发历程,严重的 bug,有趣的事情,经验教训,以及作为游戏开发者的起起伏伏。坚持发布信息有助于他人从中学习,提高你在社区中的声誉,改进你的网站优化。另一种选择是发布每月报告——总结你所有进展的报告——它能够帮助你看到你在整个月都完成了什么,还有什么需要去做,并不断提醒人们你的游戏即将发行——创造口碑总是好的。
你的社交媒体的风格很重要 — 选择正确的标签,交朋结友, 参与交流, 帮助其他开发者. 保持真诚,这是你与人结交的关键, 因为没有人喜欢无聊的新闻发布或者硬广告.。一旦游戏完成,你的社区会帮助你宣传你的小宝贝游戏的
+你的社交媒体的风格很重要 — 选择正确的标签,交朋结友,参与交流,帮助其他开发者。保持真诚,这是你与人结交的关键,因为没有人喜欢无聊的新闻发布或者硬广告.。一旦游戏完成,你的社区会帮助你宣传你的小宝贝游戏的
-你应该至少使用推特(Twitter)和脸书(Facebook)之中的一个,并且入驻一个合适的论坛,最出名的就是 HTML5GameDevs.com. 分享你的游戏开发信息,回答别人的问题, 这样人们会在心里衡量你所做的一切并且知道你做的很好.。记住也别逢人就说你的游戏——你可不是行走的广告
+你应该至少使用推特(Twitter)和脸书(Facebook)之中的一个,并且入驻一个合适的论坛,最出名的就是 HTML5GameDevs.com. 分享你的游戏开发信息,回答别人的问题,这样人们会在心里衡量你所做的一切并且知道你做的很好.。记住也别逢人就说你的游戏——你可不是行走的广告
-发展你的粉丝,你可以与他们交流,分享一些小贴士,提供一些福利, 在比赛中分发奖品,或者只是抱怨天气或者浏览器的问题,举止冷静,慷慨大方, 做你自己,去帮助别人,你就会得到尊重。
+发展你的粉丝,你可以与他们交流,分享一些小贴士,提供一些福利,在比赛中分发奖品,或者只是抱怨天气或者浏览器的问题,举止冷静,慷慨大方,做你自己,去帮助别人,你就会得到尊重。
设立门户网站主要与收益化挂钩, 但是如果你不打算售卖许可来让人们可以购买你的游戏而是打算发布广告 , 在免费的门户网站上推广游戏会更有效. 你可以在公共门户网站,比如HTML5Games.com发布游戏, 比起传统的游戏发行平台,它更像一个宣传平台.
+设立门户网站主要与收益化挂钩, 但是如果你不打算售卖许可来让人们可以购买你的游戏而是打算发布广告 , 在免费的门户网站上推广游戏会更有效。你可以在公共门户网站,比如HTML5Games.com发布游戏,比起传统的游戏发行平台,它更像一个宣传平台。
-免费的门户网站带来了流量, 但是,只有最好的广告才足够受欢迎,能够从发布的广告中获得一些业绩. 另一方面,如果你没有预算和有限的时间,门户网站也是一个完美的工具,它可以让更多人看到你的游戏
+免费的门户网站带来了流量,但是,只有最好的广告才足够受欢迎,能够从发布的广告中获得一些业绩。另一方面,如果你没有预算和有限的时间,门户网站也是一个完美的工具,它可以让更多人看到你的游戏
你可以试着联系媒体去宣传你的游戏,不过要记住,他们每天都在处理成吨的请求, 所以如果它们没有及时回复你,请保持耐心, 在于他们交流时保持礼貌. 一定要先检查他们是否只接纳特定类型的游戏或平台,这样你才不会发送与之无关的内容。如果你方式恰当并且你的游戏很好,那么你就有更多的成功机会
+你可以试着联系媒体去宣传你的游戏,不过要记住,他们每天都在处理成吨的请求,所以如果它们没有及时回复你,请保持耐心,在于他们交流时保持礼貌。一定要先检查他们是否只接纳特定类型的游戏或平台,这样你才不会发送与之无关的内容。如果你方式恰当并且你的游戏很好,那么你就有更多的成功机会
-如果你想了解更多关于联系媒体的礼仪,你可以阅读 How To Contact Press - 由 Pixel Prospector编写的一篇很棒的指南, 还有Video Game Journaliser,他们创建的一个记录媒体联络名单的网站.
+如果你想了解更多关于联系媒体的礼仪,你可以阅读 How To Contact Press - 由 Pixel Prospector 编写的一篇很棒的指南,还有Video Game Journaliser,他们创建的一个记录媒体联络名单的网站。
与其他开发者互通有无是很好的 — 毕竟你可能也曾在网上的一两篇文章上学到了些东西, 所以你要花时间把这些知识传递出去. 谈论或写一些你取得的成就或克服的问题是人们会感兴趣的事情. 你可以拿你自己的游戏做例子, 特别是当你展示你已经实现的事情. 这样每个人都会受益——人们学习新的技能,你的游戏会得到推广,如果你足够幸运,你甚至可以因为编写教程而获得报酬
+与其他开发者互通有无是很好的 — 毕竟你可能也曾在网上的一两篇文章上学到了些东西,所以你要花时间把这些知识传递出去。谈论或写一些你取得的成就或克服的问题是人们会感兴趣的事情。你可以拿你自己的游戏做例子,特别是当你展示你已经实现的事情. 这样每个人都会受益——人们学习新的技能,你的游戏会得到推广,如果你足够幸运,你甚至可以因为编写教程而获得报酬
-像是Tuts+ Game Development 这样的网站可能会更让人开心——他们为文章付稿费。 但并不是所有的主旨都会被接受。当你在写教程的时候,记住要把重点放在给读者提供一些有价值的东西上。他们想要学习一些东西——提供你的专业知识并将你的游戏作为案例研究。专注于一个方面,并试图解释它的全部和细节。如果人们有任何问题,请记得在评论中跟进讨论.
+像是Tuts+ Game Development 这样的网站可能会更让人开心——他们为文章付稿费。 但并不是所有的主旨都会被接受。当你在写教程的时候,记住要把重点放在给读者提供一些有价值的东西上。他们想要学习一些东西——提供你的专业知识并将你的游戏作为案例研究。专注于一个方面,并试图解释它的全部和细节。如果人们有任何问题,请记得在评论中跟进讨论。
-如果您联系的门户网站因你未写过教程而未采纳你的教程,可以在自己的博客先发布教程,这是锻炼你的写作技巧的最简单的方式.
+如果您联系的门户网站因你未写过教程而未采纳你的教程,可以在自己的博客先发布教程,这是锻炼你的写作技巧的最简单的方式。
-这是一种趋势 — 别低估了YouTuber视频主(YouTubers)们对游戏的影响力, 与他们交流,让他们做游戏实况会极大的宣传你的游戏. 不过,你也应该现实一点——不要认为仅仅这一点就会让你的下载量或访问量飙升,而且要准备好处理好不好的评论.
+这是一种趋势 — 别低估了 YouTuber 视频主(YouTubers)们对游戏的影响力,与他们交流,让他们做游戏实况会极大的宣传你的游戏。不过,你也应该现实一点——不要认为仅仅这一点就会让你的下载量或访问量飙升,而且要准备好处理好不好的评论。
-有两种方法可以让Youtubers选择你的游戏:第一种方法是你直接联系他们,并通过电子邮件或私人信息向他们发送游戏链接. 第二种方法更省时 - 如果你很有名,Youtubers可能会向你索要游戏链接或游戏文件. 这个YouTuber的名单是个很好的开始.
+有两种方法可以让 Youtubers 选择你的游戏:第一种方法是你直接联系他们,并通过电子邮件或私人信息向他们发送游戏链接。第二种方法更省时 - 如果你很有名,Youtubers 可能会向你索要游戏链接或游戏文件。这个YouTuber 的名单是个很好的开始。
在许多会议上,您可以发表演讲,解释您克服的一些技术困难,或者如何实现特定的API;其次,以你的游戏为例。专注于知识部分并降低市场营销是很重要的——开发者对这个问题很敏感,如果你只是想向他们推销一些东西,他们可能会对此不满。.
+在许多会议上,您可以发表演讲,解释您克服的一些技术困难,或者如何实现特定的 API;其次,以你的游戏为例。专注于知识部分并降低市场营销是很重要的——开发者对这个问题很敏感,如果你只是想向他们推销一些东西,他们可能会对此不满。.
另一个与活动相关的选项是展会(或博览会)——在这样的活动中,您可以在其他开发者中获得一个摊位,并向所有经过的参与者推广您的游戏。如果你这样做了,那就试着做得独特而有创意,这样你就很容易从人群中脱颖而出。以正确的方式去做,每个人都会谈论你和你的游戏。有一个展台可以让你与你的粉丝直接互动——除了推广部分,你还可以在普通人身上测试你的游戏的新版本,并修复他们发现的任何bug(或包含任何反馈)。你无法想象人们在玩你的游戏时可能会想到什么,以及你在花费数小时打磨游戏时错过了哪些明显的问题。
+另一个与活动相关的选项是展会 (或博览会)——在这样的活动中,您可以在其他开发者中获得一个摊位,并向所有经过的参与者推广您的游戏。如果你这样做了,那就试着做得独特而有创意,这样你就很容易从人群中脱颖而出。以正确的方式去做,每个人都会谈论你和你的游戏。有一个展台可以让你与你的粉丝直接互动——除了推广部分,你还可以在普通人身上测试你的游戏的新版本,并修复他们发现的任何 bug(或包含任何反馈)。你无法想象人们在玩你的游戏时可能会想到什么,以及你在花费数小时打磨游戏时错过了哪些明显的问题。
如果你是在销售游戏,那么你应该发行优惠码让人们免费游玩你的游戏(或至少是一个演示版或限时版), 并把它们发送到各地——给媒体,Youtuber,作为比赛奖品等等。如果游戏符合某些人的胃口,就相当于为成千上万人打了一次免费广告。如果你幸运的话,它比任何其他东西都能提高人们对你的游戏的兴趣
+如果你是在销售游戏,那么你应该发行优惠码让人们免费游玩你的游戏 (或至少是一个演示版或限时版),并把它们发送到各地——给媒体,Youtuber,作为比赛奖品等等。如果游戏符合某些人的胃口,就相当于为成千上万人打了一次免费广告。如果你幸运的话,它比任何其他东西都能提高人们对你的游戏的兴趣
HTML5游戏在发布和分发上具有极大的优势--你可以通过网络自由地发布,推广,获利,并且不受分发商的限制。你可以实现通过多种平台获利。这一系列的案例关注在当你想要发布,推广你的游戏,并当游戏变得有名时获取一些回报。
+HTML5 游戏在发布和分发上具有极大的优势--你可以通过网络自由地发布,推广,获利,并且不受分发商的限制。你可以实现通过多种平台获利。这一系列的案例关注在当你想要发布,推广你的游戏,并当游戏变得有名时获取一些回报。
你按照一个或两个教程(1,2)制作了一个HTML5游戏。Game distribution提供了你发布游戏时所需的一切知识。包括如何在线托管游戏,提交游戏到开放的游戏市场,或封闭的游戏市场,如Google Play,iOS App Store.
+你按照一个或两个教程(1,2)制作了一个 HTML5 游戏。Game distribution提供了你发布游戏时所需的一切知识。包括如何在线托管游戏,提交游戏到开放的游戏市场,或封闭的游戏市场,如 Google Play,iOS App Store.
开发完成游戏并不是结束。你必须让世界知道你制作了一些有趣的东西能使他们乐在其中。这些游戏推广技术— 有些是免费的 — 即使你作为一名0预算的独立开发者为生活奔波,你依旧可以让很多人知道你制作的这个新游戏。推广游戏或许能够使你获得收入。高效的推广非常重要。
+开发完成游戏并不是结束。你必须让世界知道你制作了一些有趣的东西能使他们乐在其中。这些游戏推广技术— 有些是免费的 — 即使你作为一名 0 预算的独立开发者为生活奔波,你依旧可以让很多人知道你制作的这个新游戏。推广游戏或许能够使你获得收入。高效的推广非常重要。
检测2D游戏中的碰撞算法,依赖于可碰撞物体的形状(例如:矩形与矩形,矩形与圆形,圆形与圆形)。通常情况下,你使用的的简单通用形状,会被称为“hitbox”的实体所覆盖,尽管发生的碰撞并不是像素完美契合的,它看起来也足够好,而且可跨多个实体执行碰撞。本文提供了一系列较为通用的2D游戏中碰撞侦测技术。
+检测 2D 游戏中的碰撞算法,依赖于可碰撞物体的形状(例如:矩形与矩形,矩形与圆形,圆形与圆形)。通常情况下,你使用的的简单通用形状,会被称为“hitbox”的实体所覆盖,尽管发生的碰撞并不是像素完美契合的,它看起来也足够好,而且可跨多个实体执行碰撞。本文提供了一系列较为通用的 2D 游戏中碰撞侦测技术。
碰撞侦测其中一种简单的形式是,在两个轴对齐的矩形之间碰撞 — 这意味着没有旋转。这个算法是确定两个矩形任意4边之间不再有间隔,存在间隔代表没有发生碰撞。
+碰撞侦测其中一种简单的形式是,在两个轴对齐的矩形之间碰撞 — 这意味着没有旋转。这个算法是确定两个矩形任意 4 边之间不再有间隔,存在间隔代表没有发生碰撞。
var rect1 = {x: 5, y: 5, width: 50, height: 50} var rect2 = {x: 20, y: 10, width: 10, height: 10} diff --git a/files/zh-cn/games/techniques/3d_collision_detection/index.html b/files/zh-cn/games/techniques/3d_collision_detection/index.html index 64a6e9b783d23a..3a548d217fa1fc 100644 --- a/files/zh-cn/games/techniques/3d_collision_detection/index.html +++ b/files/zh-cn/games/techniques/3d_collision_detection/index.html @@ -3,33 +3,33 @@ slug: Games/Techniques/3D_collision_detection translation_of: Games/Techniques/3D_collision_detection --- -{{GamesSidebar}}本文介绍了用于在3D环境中实现不同边界体积碰撞检测的技术。 后续文章将讨论特定3D库中的实现。
+{{GamesSidebar}}本文介绍了用于在 3D 环境中实现不同边界体积碰撞检测的技术。 后续文章将讨论特定 3D 库中的实现。
-Axis-aligned bounding boxes(AABB包围盒)
+Axis-aligned bounding boxes(AABB 包围盒)
在游戏中,为了简化物体之间的碰撞检测运算,通常会对物体创建一个规则的几何外形将其包围。其中,AABB(axis-aligned bounding box)包围盒被称为轴对齐包围盒。
-与2D碰撞检测一样,轴对齐包围盒是判断两个物体是否重叠的最快算法,物体被包裹在一个非旋转的(因此轴对齐的)盒中,并检查这些盒在三维坐标空间中的位置,以确定它们是否重叠。
+与 2D 碰撞检测一样,轴对齐包围盒是判断两个物体是否重叠的最快算法,物体被包裹在一个非旋转的(因此轴对齐的)盒中,并检查这些盒在三维坐标空间中的位置,以确定它们是否重叠。
-由于性能原因,轴对齐是有一些约束的。两个非旋转的盒子之间是否重叠可以通过逻辑比较进行检查,而旋转的盒子则需要三角运算,这会导致性能下降。如果你有旋转的物体,可以通过修改边框的尺寸,这样盒子仍可以包裹物体,或者选择使用另一种边界几何类型,比如球体(球体旋转,形状不会变)。下图是一个AABB物体旋转,动态调节盒大小适应物体的例子。
+由于性能原因,轴对齐是有一些约束的。两个非旋转的盒子之间是否重叠可以通过逻辑比较进行检查,而旋转的盒子则需要三角运算,这会导致性能下降。如果你有旋转的物体,可以通过修改边框的尺寸,这样盒子仍可以包裹物体,或者选择使用另一种边界几何类型,比如球体 (球体旋转,形状不会变)。下图是一个 AABB 物体旋转,动态调节盒大小适应物体的例子。
点与 AABB
-如果检测到一个点是否在AABB内部就非常简单了 — 我们只需要检查这个点的坐标是否在AABB内; 分别考虑到每种坐标轴. 如果假设 Px, Py 和 Pz 是点的坐标, BminX–BmaxX, BminY–BmaxY, 和 BminZ–BmaxZ 是AABB的每一个坐标轴的范围, 我们可以使用以下公式计算两者之间的碰撞是否发生:
+如果检测到一个点是否在 AABB 内部就非常简单了 — 我们只需要检查这个点的坐标是否在 AABB 内; 分别考虑到每种坐标轴。如果假设 Px, Py 和 Pz 是点的坐标, BminX–BmaxX, BminY–BmaxY, 和 BminZ–BmaxZ 是 AABB 的每一个坐标轴的范围,我们可以使用以下公式计算两者之间的碰撞是否发生:
-或者用JavaScript:
+或者用 JavaScript:
function isPointInsideAABB(point, box) { return (point.x >= box.minX && point.x <= box.maxX) && @@ -39,15 +39,15 @@点与 AABB
AABB 与 AABB
-检查一个AABB是否和另一个AABB相交类似于检测两个点一样. 我们只需要基于每一条坐标轴并利用盒子的边缘去检测. 下图显示了我们基于 X 轴的检测 — 当然, AminX–AmaxX 和 BminX–BmaxX 会不会重叠?
+检查一个 AABB 是否和另一个 AABB 相交类似于检测两个点一样。我们只需要基于每一条坐标轴并利用盒子的边缘去检测。下图显示了我们基于 X 轴的检测 — 当然, AminX–AmaxX 和 BminX–BmaxX 会不会重叠?
-在数学上的表示就像这样:
+在数学上的表示就像这样:
-在JavaScript我们可以这样:
+在 JavaScript 我们可以这样:
function intersect(a, b) { return (a.minX <= b.maxX && a.maxX >= b.minX) && @@ -58,20 +58,20 @@AABB 与 AABB
球体碰撞
-球体碰撞边缘检测比AABB盒子稍微复杂一点,但他的检测仍相当容易的。球体的主要优势是他们不变的旋转,如果包装实体旋转,边界领域仍将是相同的。他们的主要缺点是,除非他们包装的实体实际上是球形,包装的实体通常不是一个完美的球形(比如用这样的球形包装一个人将导致一些错误,而AABB盒子将更合适)。
+球体碰撞边缘检测比 AABB 盒子稍微复杂一点,但他的检测仍相当容易的。球体的主要优势是他们不变的旋转,如果包装实体旋转,边界领域仍将是相同的。他们的主要缺点是,除非他们包装的实体实际上是球形,包装的实体通常不是一个完美的球形 (比如用这样的球形包装一个人将导致一些错误,而 AABB 盒子将更合适)。
点与球
-检查是否一个球体包含一个点,我们需要计算点和球体的中心之间的距离。如果这个距离小于或等于球的半径,这个点就在里面。
+检查是否一个球体包含一个点,我们需要计算点和球体的中心之间的距离。如果这个距离小于或等于球的半径,这个点就在里面。
-两个点A和B之间的欧氏距离是
+
- ,我们的公式指出,球体碰撞检测是:两个点 A 和 B 之间的欧氏距离是
-
+ ,我们的公式指出,球体碰撞检测是:或者用JavaScript:
+或者用 JavaScript:
function isPointInsideSphere(point, sphere) { // we are using multiplications because is faster than calling Math.pow @@ -83,7 +83,7 @@点与球
-上面的代码有一个平方根,是一个开销昂贵的计算。一个简单的优化,以避免它由半径平方,所以优化方程不涉及
+distance < sphere.radius * sphere.radius
.上面的代码有一个平方根,是一个开销昂贵的计算。一个简单的优化,以避免它由半径平方,所以优化方程不涉及
distance < sphere.radius * sphere.radius
.球体与球体
@@ -92,11 +92,11 @@球体与球体
-在数学上,像这样:
+在数学上,像这样:
-或者JavaScript:
+或者 JavaScript:
function intersect(sphere, other) { // we are using multiplications because it's faster than calling Math.pow @@ -106,13 +106,13 @@-球体与球体
return distance < (sphere.radius + other.radius); } }球体与AABB
+球体与 AABB
-测试一个球和一个AABB的碰撞是稍微复杂,但过程仍然简单和快速。一个合乎逻辑的方法是,检查AABB每个顶点,计算每一个点与球的距离。然而这是大材小用了,测试所有的顶点都是不必要的,因为我们可以侥幸计算AABB最近的点(不一定是一个顶点)和球体的中心之间的距离,看看它是小于或等于球体的半径。我们可以通过逼近球体的中心和AABB的距离得到这个值。
+测试一个球和一个 AABB 的碰撞是稍微复杂,但过程仍然简单和快速。一个合乎逻辑的方法是,检查 AABB 每个顶点,计算每一个点与球的距离。然而这是大材小用了,测试所有的顶点都是不必要的,因为我们可以侥幸计算 AABB 最近的点 (不一定是一个顶点) 和球体的中心之间的距离,看看它是小于或等于球体的半径。我们可以通过逼近球体的中心和 AABB 的距离得到这个值。
-在 JavaScript, 我们可以像这样子做:
+在 JavaScript, 我们可以像这样子做:
function intersect(sphere, box) { // get box closest point to sphere center by clamping diff --git a/files/zh-cn/games/techniques/3d_on_the_web/basic_theory/index.html b/files/zh-cn/games/techniques/3d_on_the_web/basic_theory/index.html index 4e4041a8daeb76..4540ce81238c4f 100644 --- a/files/zh-cn/games/techniques/3d_on_the_web/basic_theory/index.html +++ b/files/zh-cn/games/techniques/3d_on_the_web/basic_theory/index.html @@ -1,5 +1,5 @@ --- -title: 解释基本的3D原理 +title: 解释基本的 3D 原理 slug: Games/Techniques/3D_on_the_web/Basic_theory tags: - 3D @@ -18,110 +18,110 @@坐标系统
-WebGL使用右手坐标系统 —
+x
轴向右,y
轴向上z
轴指向屏幕外, 在上图可以看到.WebGL 使用右手坐标系统 —
x
轴向右,y
轴向上z
轴指向屏幕外,在上图可以看到。物体
-使用顶点建立不同类型的物体. 一个顶点是在3D坐标系中拥有坐标位置的一个点以及一些额外可以定义它的信息。 每个点都包含这些属性:
+使用顶点建立不同类型的物体。 一个顶点是在 3D 坐标系中拥有坐标位置的一个点以及一些额外可以定义它的信息。 每个点都包含这些属性:
x
, y
, z
).0.0
到 1.0
).x
, y
, z
).0.0
到 1.0
).你可以使用这些信息建立几何体 — 这是一个立方体的例子:
+你可以使用这些信息建立几何体 — 这是一个立方体的例子:
-给定形状的一个面是顶点之间的一个平面. 例如, 一个立方体有8个不同的顶点和6个不同的面 每个面由4个顶点构成. 一条法线定义面的朝向. 同时, 连接这些点可以创建立方体的边. 这个几何体通过点和面构成, 材质使用的是一张纹理贴图, 这里使用一个纯蓝色或一张图片. 该物体的几何形状(geometry)由顶点和面构成,而材质(material)则是由纹理构成。如果我们将几何体和材质连接起来会得到一个网格(mesh).
+给定形状的一个面是顶点之间的一个平面。例如,一个立方体有 8 个不同的顶点和 6 个不同的面 每个面由 4 个顶点构成。一条法线定义面的朝向。同时,连接这些点可以创建立方体的边。这个几何体通过点和面构成,材质使用的是一张纹理贴图,这里使用一个纯蓝色或一张图片。该物体的几何形状 (geometry) 由顶点和面构成,而材质 (material) 则是由纹理构成。如果我们将几何体和材质连接起来会得到一个网格 (mesh).
渲染流程是个将之前准备好的模型输出到屏幕的过程. 3D渲染流程会接受使用顶点描述3D物体的原始数据作为输入用于处理, 并计算其片段(fragment), 然后渲染为像素(pixels)输出到屏幕.
+渲染流程是个将之前准备好的模型输出到屏幕的过程。3D 渲染流程会接受使用顶点描述 3D 物体的原始数据作为输入用于处理,并计算其片段 (fragment), 然后渲染为像素 (pixels) 输出到屏幕。
-上图中用到了如下术语:
+上图中用到了如下术语:
顶点和片段处理是可编程的 — 你可以编写自己的着色器 来控制输出.
+顶点和片段处理是可编程的 — 你可以编写自己的着色器 来控制输出。
顶点处理是将独立的顶点信息组合成原始数据并设置其在3D空间中的坐标, 方便显示器识别. 就像是对你准备的场景进行拍照 — 你必须先放置物品, 设置相机参数, 然后开拍.
+顶点处理是将独立的顶点信息组合成原始数据并设置其在 3D 空间中的坐标,方便显示器识别。就像是对你准备的场景进行拍照 — 你必须先放置物品,设置相机参数,然后开拍。
-这个过程分为四步: 第一步是筹备世界坐标中的物体, 也被称为模型转换(model transformation). 然后是视图转换(view transformation) , 这一步只关心位置和3D空间中摄像机的朝向设置. 摄像机有三个参数(位置, 方向和朝向), 在新创建的场景中必须定义这三个参数.
+这个过程分为四步:第一步是筹备世界坐标中的物体,也被称为模型转换 (model transformation). 然后是视图转换 (view transformation) , 这一步只关心位置和 3D 空间中摄像机的朝向设置。摄像机有三个参数 (位置,方向和朝向), 在新创建的场景中必须定义这三个参数。
-投射转换(projection transformation), 也被称作透视转换(perspective transformation), 这一步定义摄像机设置, 在此过程会设置哪些在摄像机中可见, 配置包含视野(field of view), 宽高比例(aspect ratio) 和可选的近裁剪和远裁剪参数. 阅读Three.js文章摄像机了解更多.
+投射转换(projection transformation), 也被称作透视转换 (perspective transformation), 这一步定义摄像机设置,在此过程会设置哪些在摄像机中可见,配置包含视野 (field of view), 宽高比例 (aspect ratio) 和可选的近裁剪和远裁剪参数。阅读 Three.js 文章摄像机了解更多。
-最后一步是视图窗口转换(viewport transformation), 这一步会将一切都输出给渲染流程中的下一步.
+最后一步是视图窗口转换(viewport transformation), 这一步会将一切都输出给渲染流程中的下一步。
栅格化将原始数据(从顶点信息转换过来的)转换为一系列的片段.
+栅格化将原始数据 (从顶点信息转换过来的) 转换为一系列的片段。
-那些片段(2D像素的3D投射)是对应到像素网格的, 所以在渲染合成阶段最后他们会被2D的屏幕直接打印到像素点上.
+那些片段 (2D 像素的 3D 投射) 是对应到像素网格的,所以在渲染合成阶段最后他们会被 2D 的屏幕直接打印到像素点上。
片段合成关注关注的是纹理和光照 — 它会基于给定参数计算最终的颜色.
+片段合成关注关注的是纹理和光照 — 它会基于给定参数计算最终的颜色。
纹理是在3D空间中用了是模型看起来更加真实的2D图片. 纹理是由称为纹素的单个纹理元素组合, 和像素组合的原理一样. 如果必要的话, 在渲染流程中的片段处理阶段添加纹理到模型上允许我们使用包装(wrapping)和过滤(filtering)进行适配.
+纹理是在 3D 空间中用了是模型看起来更加真实的 2D 图片。纹理是由称为纹素的单个纹理元素组合,和像素组合的原理一样。如果必要的话,在渲染流程中的片段处理阶段添加纹理到模型上允许我们使用包装 (wrapping) 和过滤 (filtering) 进行适配。
-纹理包装允许你在3D模型上重复使用2D图片. 纹理过滤是纹理贴图的原始分辨率和将要呈现的片段的分辨率不同的时候, 会根据情况对纹理进行缩放.
+纹理包装允许你在 3D 模型上重复使用 2D 图片。纹理过滤是纹理贴图的原始分辨率和将要呈现的片段的分辨率不同的时候,会根据情况对纹理进行缩放。
我们在屏幕上看到的颜色是光照和模型颜色, 材质进行交互之后的最终结果. 灯光会被吸收和反射, 在WebGL中实现的标准Phong光照模型 有一下四种光照参数:
+我们在屏幕上看到的颜色是光照和模型颜色,材质进行交互之后的最终结果。灯光会被吸收和反射,在 WebGL 中实现的标准Phong 光照模型 有一下四种光照参数:
在输出操作阶段所有来自3D空间的原始数据的片段会被转换到2D像素网格中, 然后打印到屏幕像素上.
+在输出操作阶段所有来自 3D 空间的原始数据的片段会被转换到 2D 像素网格中,然后打印到屏幕像素上。
-在输出合成阶段同样可以忽略不必要的信息, 例如在屏幕外的模型参数或者被其他模型遮挡的模型, 因为是不可见的所以不会被计算.
+在输出合成阶段同样可以忽略不必要的信息,例如在屏幕外的模型参数或者被其他模型遮挡的模型,因为是不可见的所以不会被计算。
现在你知道了3D操作背后的基本原理. 如果你想去练习或者看学习demo, 看看下面的教程:
+现在你知道了 3D 操作背后的基本原理。如果你想去练习或者看学习 demo, 看看下面的教程:
继续, 去创建一些炫酷3D实验吧!
+继续,去创建一些炫酷 3D 实验吧!
游戏中一个典型的3D场景(最简单的那种) 包含标准的物品比如在坐标轴中的形状, 一个实际可看到他们的摄像机, 灯光和材质让其看起来不错, 动画使其生动等等. Three.js, 和其他3D库一样, 提供内置的helper 函数来帮助你尽可能快地实现通用的3D功能 . 在这篇文章我们会带你了解使用Three的基本知识, 包含设置开发者环境, 必要的HTML结构, Three.js对象基础, 以及如何创建一个基本的demo.
+游戏中一个典型的 3D 场景 (最简单的那种) 包含标准的物品比如在坐标轴中的形状,一个实际可看到他们的摄像机,灯光和材质让其看起来不错,动画使其生动等等。 Three.js, 和其他 3D 库一样,提供内置的 helper 函数来帮助你尽可能快地实现通用的 3D 功能 . 在这篇文章我们会带你了解使用 Three 的基本知识,包含设置开发者环境,必要的 HTML 结构,Three.js 对象基础,以及如何创建一个基本的 demo.
注意: 我们选择Three.js因为它是最流行的WebGL 库之一, 并且很容易上手. 我们不会介绍任何其他更好的WebGL库, 你可以自由选择其他库做尝试, 比如 CopperLicht, GLGE, OSG.js, O3D, 或者其他你喜欢的库.
+注意: 我们选择 Three.js 因为它是最流行的WebGL 库之一,并且很容易上手。我们不会介绍任何其他更好的 WebGL 库,你可以自由选择其他库做尝试,比如 CopperLicht, GLGE, OSG.js, O3D, 或者其他你喜欢的库。
开始用 Three.js, 你不需要准备太多, 只需:
+开始用 Three.js, 你不需要准备太多,只需:
这是将用到的HTML结构.
+这是将用到的 HTML 结构。
<!DOCTYPE html> <html> @@ -74,7 +74,7 @@场景
摄像机
-我们有渲染场景,但是我们仍然需要一个摄像机来观察场景-想象没有摄像机的电影场景。下面的代码将摄像机放在三维坐标系中,并将其指向我们的场景,这样人们就能看到一些东西:
+我们有渲染场景,但是我们仍然需要一个摄像机来观察场景 - 想象没有摄像机的电影场景。下面的代码将摄像机放在三维坐标系中,并将其指向我们的场景,这样人们就能看到一些东西:
var camera = new THREE.PerspectiveCamera(70, WIDTH/HEIGHT); camera.position.z = 50; diff --git a/files/zh-cn/games/techniques/3d_on_the_web/glsl_shaders/index.html b/files/zh-cn/games/techniques/3d_on_the_web/glsl_shaders/index.html index dc10806eacd45b..a6366f01d7d150 100644 --- a/files/zh-cn/games/techniques/3d_on_the_web/glsl_shaders/index.html +++ b/files/zh-cn/games/techniques/3d_on_the_web/glsl_shaders/index.html @@ -1,5 +1,5 @@ --- -title: GLSL着色器 +title: GLSL 着色器 slug: Games/Techniques/3D_on_the_web/GLSL_Shaders tags: - GLSL @@ -8,59 +8,59 @@ - 顶点着色器 translation_of: Games/Techniques/3D_on_the_web/GLSL_Shaders --- -{{GamesSidebar}}使用GLSL的着色器(shader), GLSL是一门特殊的有着类似于C语言的语法, 在图形管道(graphic pipeline)中直接可执行的OpenGL着色语言. 着色器有两种类型 -- 顶点着色器(Vertex Shader)和片段着色器(Fragment Shader). 前者是将形状转换到真实的3D绘制坐标中, 后者是计算最终渲染的颜色和其他属性用的.
+{{GamesSidebar}}使用 GLSL 的着色器 (shader), GLSL 是一门特殊的有着类似于 C 语言的语法,在图形管道 (graphic pipeline) 中直接可执行的 OpenGL 着色语言。着色器有两种类型 -- 顶点着色器 (Vertex Shader) 和片段着色器 (Fragment Shader). 前者是将形状转换到真实的 3D 绘制坐标中,后者是计算最终渲染的颜色和其他属性用的。
-GLSL不同于JavaScript, 它是强类型语言, 并且内置很多数学公式用于计算向量和矩阵. 快速编写着色器非常复杂, 但创建一个简单的着色器并不难. 在这篇文章我们将介绍使用着色器的基础知识, 并且构建一个使用Three.js的例子来加速代码编写.
+GLSL 不同于 JavaScript, 它是强类型语言,并且内置很多数学公式用于计算向量和矩阵。快速编写着色器非常复杂,但创建一个简单的着色器并不难。在这篇文章我们将介绍使用着色器的基础知识,并且构建一个使用 Three.js 的例子来加速代码编写。
-你可能记得基本原理那篇文章, 一个顶点(vertex)是在空间中有自己3D坐标的点, 并且通常包含些被定义的其他信息. 空间本身会被坐标系统定义. 在那个3D空间中一切都是关于形状的呈现.
+你可能记得基本原理那篇文章,一个顶点 (vertex) 是在空间中有自己 3D 坐标的点,并且通常包含些被定义的其他信息。空间本身会被坐标系统定义。在那个 3D 空间中一切都是关于形状的呈现。
着色器类型
-一个着色器实际上就是一个绘制东西到屏幕上的函数. 着色器运行在GPU中, 它对这些操作进行了很多的优化, 这样你就可以卸载很多不必要的CPU, 然后集中处理能力去执行你自己的代码.
+一个着色器实际上就是一个绘制东西到屏幕上的函数。着色器运行在 GPU 中,它对这些操作进行了很多的优化,这样你就可以卸载很多不必要的 CPU, 然后集中处理能力去执行你自己的代码。
顶点着色器
-顶点着色器操作3D空间的坐标并且每个顶点都会调用一次这个函数. 其目的是设置
+gl_Position
变量 -- 这是一个特殊的全局内置变量, 它是用来存储当前顶点的位置:顶点着色器操作 3D 空间的坐标并且每个顶点都会调用一次这个函数。其目的是设置
gl_Position
变量 -- 这是一个特殊的全局内置变量,它是用来存储当前顶点的位置:void main() { gl_Position = makeCalculationsToHaveCoordinates; }-这个
+void main()
函数是定义全局gl_Position
变量的标准方式. 所有在这个函数里面的代码都会被着色器执行. 如果将3D空间中的位置投射到2D屏幕上这些信息都会保存在计算结果的变量中.这个
void main()
函数是定义全局gl_Position
变量的标准方式。所有在这个函数里面的代码都会被着色器执行。 如果将 3D 空间中的位置投射到 2D 屏幕上这些信息都会保存在计算结果的变量中。片段着色器
-片段 (或者纹理) 着色器 在计算时定义了每像素的 RGBA 颜色 — 每个像素只调用一次片段着色器. 这个着色器的作用是设置
+gl_FragColor
变量, 也是一个GLSL内置变量:片段 (或者纹理) 着色器 在计算时定义了每像素的 RGBA 颜色 — 每个像素只调用一次片段着色器。这个着色器的作用是设置
gl_FragColor
变量,也是一个 GLSL 内置变量:void main() { gl_FragColor = makeCalculationsToHaveColor; }-计算结果包含RGBA颜色信息.
+计算结果包含 RGBA 颜色信息。
例子
-让我们构建一个简单的例子来解释这些着色器的动作. 假设你已经看过Three.js 教程并掌握了场景, 物体和材质的基本概念.
+让我们构建一个简单的例子来解释这些着色器的动作。假设你已经看过Three.js 教程并掌握了场景,物体和材质的基本概念。
-注意: 记住你没必要使用Three.js或者其他库来编写着色器 -- 纯WebGL 完全够了. 我们这里使用Three.js来制作背景代码更简单和易理解. 所以你只需关注着色器代码. Three.js和其他3D库给你抽象了很多东西出来 -- 如果你想要用纯WebGL创建这个例子, 你得写很多其他的代码才能运行.
+注意: 记住你没必要使用 Three.js 或者其他库来编写着色器 -- 纯WebGL 完全够了。我们这里使用 Three.js 来制作背景代码更简单和易理解。所以你只需关注着色器代码。Three.js 和其他 3D 库给你抽象了很多东西出来 -- 如果你想要用纯 WebGL 创建这个例子,你得写很多其他的代码才能运行。
环境设置
-要开始编写WebGL着色器你不需要做太多, 只需:
+要开始编写 WebGL 着色器你不需要做太多,只需:
这是将用到的HTML结构.
+这是将用到的 HTML 结构。
<!DOCTYPE html> <html> @@ -87,53 +87,53 @@-HTML 结构
</html>
他包含了一些基本信息比如 文档的 {{htmlelement("title")}}, 并且设置了{{htmlelement("canvas")}}元素css样式的宽高, Three.js会插入到页面中占满整个可视区域. {{htmlelement("script")}}元素在包含Three.js库的{{htmlelement("head")}}中. 我们的代码将卸载{{htmlelement("body")}}标签中的script标签中:
+他包含了一些基本信息比如 文档的 {{htmlelement("title")}}, 并且设置了{{htmlelement("canvas")}}元素 css 样式的宽高,Three.js 会插入到页面中占满整个可视区域。 {{htmlelement("script")}}元素在包含 Three.js 库的{{htmlelement("head")}}中。我们的代码将卸载{{htmlelement("body")}}标签中的 script 标签中:
阅读之前, 复制这些代码到一个新的文本文件中, 保存到你的工作目录作为 index.html
. 我们将在这个文件中创建一个简单的立方体来解释着色器是如何工作的.
阅读之前,复制这些代码到一个新的文本文件中,保存到你的工作目录作为 index.html
. 我们将在这个文件中创建一个简单的立方体来解释着色器是如何工作的。
我们可以复用Building up a basic demo with Three.js 中立方体的源代码, 大多数元素例如渲染器, 摄像机和灯光都没有发生改变, 但是基本的材质会用到自己写的着色器.
+我们可以复用Building up a basic demo with Three.js 中立方体的源代码,大多数元素例如渲染器,摄像机和灯光都没有发生改变,但是基本的材质会用到自己写的着色器。
-去cube.html file on GitHub中, 复制第二个{{htmlelement("script")}}元素中所有的JavaScript代码, 粘贴到当前例子中的第三个<script>
标签中. 保存并运行 index.html
— 然后你会看到一个蓝色立方体
去cube.html file on GitHub中,复制第二个{{htmlelement("script")}}元素中所有的 JavaScript 代码,粘贴到当前例子中的第三个<script>
标签中。保存并运行 index.html
— 然后你会看到一个蓝色立方体
让我们继续编写顶点着色器 — 添加下面这段代码到你body的第一个 <script>
标签:
让我们继续编写顶点着色器 — 添加下面这段代码到你 body 的第一个 <script>
标签:
void main() { gl_Position = projectionMatrix * modelViewMatrix * vec4(position.x+10.0, position.y, position.z+5.0, 1.0); }-
每次的gl_Position
的结果是计算model-view矩阵和投射矩阵和投射矩阵相乘并得到最后的顶点位置.
每次的gl_Position
的结果是计算 model-view 矩阵和投射矩阵和投射矩阵相乘并得到最后的顶点位置。
注意: 你可以在 顶点处理中学到更多关于模型, 视图和投射变换, 并且你可以在文末看到更多学习链接.
+注意: 你可以在 顶点处理中学到更多关于模型,视图和投射变换,并且你可以在文末看到更多学习链接。
projectionMatrix
和 modelViewMatrix
两个函数都是Three.js提供的, 并且传入了一个新的3D位置向量, 转成着色器之后直接导致立方体向 x
轴移动10个单位, 向z
轴移动了5个单位. 我们可以忽略第四个参数并且保持为默认的1.0
; 这是用来控制3D空间中订单位置裁剪的, 这个例子中不需要.
projectionMatrix
和 modelViewMatrix
两个函数都是 Three.js 提供的,并且传入了一个新的 3D 位置向量,转成着色器之后直接导致立方体向 x
轴移动 10 个单位,向z
轴移动了 5 个单位。我们可以忽略第四个参数并且保持为默认的1.0
; 这是用来控制 3D 空间中订单位置裁剪的,这个例子中不需要。
现在我们将添加纹理着色器代码 — 将以下代码复制到第二个 <script>
标签中:
现在我们将添加纹理着色器代码 — 将以下代码复制到第二个 <script>
标签中:
void main() { gl_FragColor = vec4(0.0, 0.58, 0.86, 1.0); }-
这将设置一个RGBA颜色来重建当前的蓝色灯光 — 前三个浮点数(范围是0.0到1.0) 代表红, 绿, 蓝, 第四个值代表alpha通道, 控制透明度(0.0完全透明, 1.0是完全不透明).
+这将设置一个 RGBA 颜色来重建当前的蓝色灯光 — 前三个浮点数 (范围是 0.0 到 1.0) 代表红,绿,蓝,第四个值代表 alpha 通道,控制透明度 (0.0 完全透明,1.0 是完全不透明).
实际上是创建了一个新的着色器给立方体, 先用 basicMaterial
来定义:
实际上是创建了一个新的着色器给立方体,先用 basicMaterial
来定义:
// var basicMaterial = new THREE.MeshBasicMaterial({color: 0x0095DD});@@ -148,7 +148,7 @@
这个着色器材质使用脚本中的代码并将它们赋予给材质所赋予的物体
-然后, 在定义立方体材质那一行我们需要替换basicMaterial
:
然后,在定义立方体材质那一行我们需要替换basicMaterial
:
var cube = new THREE.Mesh(boxGeometry, basicMaterial);@@ -158,23 +158,23 @@
var cube = new THREE.Mesh(boxGeometry, shaderMaterial);-
Three.js编译和运行这两个这两个着色器到材质所在的网格(mesh)上. 在这个例子中, 为立方体添加了有顶点和纹理着色器. 好了, 你已经创建了最简单的着色器, 祝贺!
+Three.js 编译和运行这两个这两个着色器到材质所在的网格 (mesh) 上。在这个例子中,为立方体添加了有顶点和纹理着色器。好了,你已经创建了最简单的着色器,祝贺!
-下图是立方体最终效果:
+下图是立方体最终效果:
-它看起来好像和Three.js的立方体demo一样, 但不同的是, 位置有点轻微变化, 而且同样的蓝色使用的是着色器实现. 你可以看看实际操作, 这里有最终代码:{{JSFiddleEmbed("https://jsfiddle.net/end3r/LL55bhrz/","","350")}}
+它看起来好像和 Three.js 的立方体 demo 一样,但不同的是,位置有点轻微变化,而且同样的蓝色使用的是着色器实现。你可以看看实际操作,这里有最终代码:{{JSFiddleEmbed("https://jsfiddle.net/end3r/LL55bhrz/","","350")}}
-你也可以在 GitHub 看这个例子.
+你也可以在 GitHub 看这个例子。
本文教了你最基本的着色器实现. 我们虽然只能做这么多, 但你可以用着色器做很更多炫酷的事情 — 在 ShaderToy 上去看真正炫酷的例子找找灵感吧
+本文教了你最基本的着色器实现。我们虽然只能做这么多,但你可以用着色器做很更多炫酷的事情 — 在 ShaderToy 上去看真正炫酷的例子找找灵感吧
为了web上丰富的游戏体验,一个好武器是webGL, 并呈现在HTML的 {{htmlelement("canvas")}}元素上。WebGL基本上是Web的OpenGL ES 2.0版本 — 作为一个JavaScript API,它提供了能构建丰富的交互式动画和游戏的工具。你可以使用硬件加速的JavaScript 生成和呈现动态3D图像。
+为了 web 上丰富的游戏体验,一个好武器是 webGL,并呈现在 HTML 的 {{htmlelement("canvas")}}元素上。WebGL 基本上是 Web 的 OpenGL ES 2.0 版本 — 作为一个 JavaScript API,它提供了能构建丰富的交互式动画和游戏的工具。你可以使用硬件加速的 JavaScript 生成和呈现动态 3D 图像。
WebGL项目的文档和规范由Khronos Group维护,而非大部分Web APIs采用的W3C。它很好地支持了现代浏览器甚至是移动手机,由此你无需担心太多。主流浏览器均支持WebGL,你需要关注的仅仅是在你使用的设备上进行优化。
+WebGL项目的文档和规范由Khronos Group 维护,而非大部分 Web APIs 采用的 W3C。它很好地支持了现代浏览器甚至是移动手机,由此你无需担心太多。主流浏览器均支持 WebGL,你需要关注的仅仅是在你使用的设备上进行优化。
-目前进行的尝试是在不久的将来促成WebGL 2.0版本(基于OpenGL ES 3.0版本)的发布,WebGL 2.0版本将会带来许多改进,并且将会帮助开发者使用现在强大的硬件,为现代Web开发游戏。
+目前进行的尝试是在不久的将来促成 WebGL 2.0 版本(基于 OpenGL ES 3.0 版本)的发布,WebGL 2.0 版本将会带来许多改进,并且将会帮助开发者使用现在强大的硬件,为现代 Web 开发游戏。
-基本3D理论的核心围绕在3D空间的形状呈现上,通过使用坐标系计算出它们的位置。寻找你所要的信息,请参考我们的文章 Explaining basic 3D theory 。
+基本 3D 理论的核心围绕在 3D 空间的形状呈现上,通过使用坐标系计算出它们的位置。寻找你所要的信息,请参考我们的文章 Explaining basic 3D theory 。
你可以使用 WebGL 做很多事情。你需要深入了解和学习一些预先的理念——像着色器、碰撞检测或最新的热门话题——Web上的虚拟现实。
+你可以使用 WebGL 做很多事情。你需要深入了解和学习一些预先的理念——像着色器、碰撞检测或最新的热门话题——Web 上的虚拟现实。
值得提及的是着色器,着色器本身就是一个独立的故事。着色器使用GLSL,一个特殊的和C语言相似的 OpenGL 着色语言,但C语言直接通过图像管道执行。
+值得提及的是着色器,着色器本身就是一个独立的故事。着色器使用 GLSL,一个特殊的和 C 语言相似的 OpenGL 着色语言,但 C 语言直接通过图像管道执行。
虚拟现实这一概念并不新鲜,但由于硬件的进步,它大有席卷网络之势,如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-Frame、PlayCanvas和Babylon.js是最容易辨认的,拥有丰富的文档、在线编辑器和活跃的社区。
+最流行的 JavaScript 3D 库是Three.js,这是一个多用途工具,它使常见的 3D 技术更易于实现。还有其他流行的游戏开发库和框架值得检查。A-Frame、PlayCanvas和Babylon.js是最容易辨认的,拥有丰富的文档、在线编辑器和活跃的社区。
-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 是最受开发者欢迎的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是一个流行的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,与任何其他库一样,它给了您一个巨大的便利:不必编写数百行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 是一个基于 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 ---每个中型或大型游戏都应编译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 @@
(从脚本中创建的脚本默认为异步。) 默认的HTML shell Emscripten生成后者。
+(从脚本中创建的脚本默认为异步。) 默认的 HTML shell Emscripten 生成后者。
-两种常见的情况下是脚本是非异步的(由HTML规范定义)
+两种常见的情况下是脚本是非异步的(由HTML 规范定义)
<script async>code</script>@@ -37,7 +37,7 @@
两者都被视为“内联”脚本,阻塞其余所有任务,进行编译,编译完成后立即执行。
-如果你的代码是一个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")}} 将触发这些事件,因为我们就可以随意操控游戏(如:移动太空船)。 事件如下所示:
说明: 这篇 touch events 参考文章提供了更多的实例和介绍。
-这个实现了移动端触摸的little demo代码已经放到了GibHub上,我们下载这个示例就可以实现在移动端屏幕上移动飞船。
+这个实现了移动端触摸的little demo代码已经放到了 GibHub 上,我们下载这个示例就可以实现在移动端屏幕上移动飞船。
-我们将两种事件:touchstart
和touchmove
放到一个方法里处理. 为什么呢? touchHandler
方法定义的飞船位置变量适合下面两种情况下: 当玩家触摸时,但不移动它(touchstart
)和当手指在屏幕上开始移动 (touchmove
):
我们将两种事件:touchstart
和touchmove
放到一个方法里处理。为什么呢? touchHandler
方法定义的飞船位置变量适合下面两种情况下:当玩家触摸时,但不移动它(touchstart
)和当手指在屏幕上开始移动(touchmove
):
document.addEventListener("touchstart", touchHandler); document.addEventListener("touchmove", touchHandler);-
touchHandler
方法的代码如下:
touchHandler
方法的代码如下:
function touchHandler(e) { if(e.touches) { diff --git a/files/zh-cn/games/techniques/controls_gamepad_api/index.html b/files/zh-cn/games/techniques/controls_gamepad_api/index.html index b2e465c6b9ae36..1d99b3c630493b 100644 --- a/files/zh-cn/games/techniques/controls_gamepad_api/index.html +++ b/files/zh-cn/games/techniques/controls_gamepad_api/index.html @@ -7,7 +7,7 @@网页游戏的控制
-在历史上,在连接主机(console)的电视上玩游戏和在电脑(PC)上玩游戏是两种完全不一样的体验,最大的区别就是它们的控制方式。后来,额外的驱动程序和插件让我们能够使用主机控制器来游玩电脑端的游戏--不论是本地游戏,还是运行在浏览器中的游戏。 到现在的 HTML5 时代,我们终于有了 Gamepad API ,让我们能够在不安装任何插件的情况下,可以使用控制器来游玩基于浏览器的游戏。Gamepad API 通过提供一个接口公开按钮的按下和坐标的变化来实现这一点,在 JavaScript 中我们可以用这些变化来处理输入。这对于网页游戏来说是非常棒的特性。
+在历史上,在连接主机 (console) 的电视上玩游戏和在电脑 (PC) 上玩游戏是两种完全不一样的体验,最大的区别就是它们的控制方式。后来,额外的驱动程序和插件让我们能够使用主机控制器来游玩电脑端的游戏--不论是本地游戏,还是运行在浏览器中的游戏。 到现在的 HTML5 时代,我们终于有了 Gamepad API ,让我们能够在不安装任何插件的情况下,可以使用控制器来游玩基于浏览器的游戏。Gamepad API 通过提供一个接口公开按钮的按下和坐标的变化来实现这一点,在 JavaScript 中我们可以用这些变化来处理输入。这对于网页游戏来说是非常棒的特性。
@@ -25,7 +25,7 @@哪种控制器最好?
实例分析:Hungry Fridge
-GitHub Game Off II 比赛举行于2013年11月,Enclave Games 决定参加比赛。比赛的主题为“改变”(change),所以他们提交了这样一个游戏——你需要通过点击来喂食饥饿的冰箱健康的食物 (苹果、萝卜、莴苣) 并避开“坏”的食物 (啤酒、汉堡、披萨) 。其中会有倒计时会改变接下来几秒内冰箱想吃的东西,所以你又要小心动作又要块。你可以在这里尝试 Hungry Fridge。
+GitHub Game Off II 比赛举行于 2013 年 11 月,Enclave Games 决定参加比赛。比赛的主题为“改变”(change),所以他们提交了这样一个游戏——你需要通过点击来喂食饥饿的冰箱健康的食物 (苹果、萝卜、莴苣) 并避开“坏”的食物 (啤酒、汉堡、披萨) 。其中会有倒计时会改变接下来几秒内冰箱想吃的东西,所以你又要小心动作又要块。你可以在这里尝试 Hungry Fridge。
@@ -39,7 +39,7 @@实例分析:Hungry Fridge
示例
-Game API 的动作展示与JavaScript的源代码公布是在完整版的 Hungry Fridge 构建之后才开始的,然后据此创建了一个 简单的示例。部分 Gamepad API Content Kit 在Github 上供你分析代码并研究其如何工作。
+Game API 的动作展示与 JavaScript 的源代码公布是在完整版的 Hungry Fridge 构建之后才开始的,然后据此创建了一个 简单的示例。部分 Gamepad API Content Kit 在 Github 上供你分析代码并研究其如何工作。
@@ -51,7 +51,7 @@示例
实现方法
-使用Gamepad API时有两个重要的事件——
+gamepadconnected
和gamepaddisconnected
。 前者将于浏览器侦测到新控制器连接时触发;而后者则是断开连接 (不管是物理断开还是无响应了) 的时候触发。在示例中gamepadAPI
对象通常存储着所有关于 API 的东西:使用 Gamepad API 时有两个重要的事件——
gamepadconnected
和gamepaddisconnected
。前者将于浏览器侦测到新控制器连接时触发;而后者则是断开连接 (不管是物理断开还是无响应了) 的时候触发。在示例中gamepadAPI
对象通常存储着所有关于 API 的东西:-var gamepadAPI = { controller: {}, @@ -66,7 +66,7 @@
实现方法
axesStatus: [] };数组
+buttons
存储着 XBox 360 控制器的按键布局button layout:数组
buttons
存储着 XBox 360 控制器的按键布局 button layout:-buttons: [ 'DPad-Up','DPad-Down','DPad-Left','DPad-Right', @@ -193,7 +193,7 @@
监测按钮按下
} }如果
+gamepadAPI.turbo
为true
并有按钮被按下(或被按住),我们就会为其分配恰当的操作。在本例中,按下或按住A
开火,按下B
暂停游戏。如果
gamepadAPI.turbo
为true
并有按钮被按下 (或被按住),我们就会为其分配恰当的操作。在本例中,按下或按住A
开火,按下B
暂停游戏。坐标阈值
@@ -212,7 +212,7 @@坐标阈值
规范更新
-经过长达一年多的规范化,W3C Gamepaf API 于2015年4月更新了规范 (查看最新信息)。更新的改动并不是很大,但是我们最好了解一下到底更新了些什么—— 以下为更新。
+经过长达一年多的规范化,W3C Gamepaf API 于 2015 年 4 月更新了规范 (查看最新信息)。更新的改动并不是很大,但是我们最好了解一下到底更新了些什么—— 以下为更新。
获取控制器
diff --git a/files/zh-cn/games/techniques/index.html b/files/zh-cn/games/techniques/index.html index cd4899c2a27e18..e576d5499ba77c 100644 --- a/files/zh-cn/games/techniques/index.html +++ b/files/zh-cn/games/techniques/index.html @@ -15,8 +15,8 @@
{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Extra_lives", "Games/Workflows/2D_Breakout_game_Phaser/Buttons")}}
这是Gamedev Phaser教程 16 的第14步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson14.html完成本课程后找到源代码。
+这是Gamedev Phaser 教程 16 的第 14 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson14.html完成本课程后找到源代码。
为了使游戏看起来更加多汁和活泼,我们可以使用动画和补间。这将导致更好,更有趣的体验。让我们来探讨如何在游戏中实现Phaser动画和补间。
+为了使游戏看起来更加多汁和活泼,我们可以使用动画和补间。这将导致更好,更有趣的体验。让我们来探讨如何在游戏中实现 Phaser 动画和补间。
在Phaser,动画中,涉及从外部来源获取spritesheet并依次显示sprites。作为一个例子,当碰到一些东西时,我们会让球摇摆。
+在 Phaser,动画中,涉及从外部来源获取 spritesheet 并依次显示 sprites。作为一个例子,当碰到一些东西时,我们会让球摇摆。
-首先,从Github抓取spritesheet并将其保存在您的/img
目录中。
首先,从 Github 抓取 spritesheet并将其保存在您的/img
目录中。
接下来,我们将加载spritesheet - 将以下行放在preload()
函数的底部:
接下来,我们将加载 spritesheet - 将以下行放在preload()
函数的底部:
game.load.spritesheet('ball', 'img/wobble.png', 20, 20);-
而不是加载单个图像的球,我们可以加载整个spritesheet - 不同图像的集合。我们将按顺序显示精灵,创造动画的幻觉。该spritesheet()
方法的两个额外的表格确定给定spritesheet文件中每个单个框架的宽度和高度,指示程序如何切割以获取单个框架。
而不是加载单个图像的球,我们可以加载整个 spritesheet - 不同图像的集合。我们将按顺序显示精灵,创造动画的幻觉。该spritesheet()
方法的两个额外的表格确定给定 spritesheet 文件中每个单个框架的宽度和高度,指示程序如何切割以获取单个框架。
接下来,进入你的create()函数,找到加载球精灵的行,下面的调用animations.add()
如下所示:
接下来,进入你的 create() 函数,找到加载球精灵的行,下面的调用animations.add()
如下所示:
ball = game.add.sprite(50, 250, 'ball'); ball.animations.add('wobble', [0,1,0,2,0,1,0,2,0], 24); @@ -48,8 +48,8 @@加载动画
wobble.png
图像,您会看到有三个框架。Phaser提取它们并将它们存储在数组中 - 位置0,1和2.上面的数组表示我们显示帧0,然后是1,然后是0等。wobble.png
图像,您会看到有三个框架。Phaser 提取它们并将它们存储在数组中 - 位置 0,1 和 2.上面的数组表示我们显示帧 0,然后是 1,然后是 0 等。add.tween()
方法,指定brick.scale
为参数,因为这是我们想要补间。to()
方法定义补间结束时对象的状态。它需要一个包含所选参数的期望结束值的对象(比例取尺度值,1为大小的100%,0为大小的0%等),补间的时间(以毫秒为单位)以及使用的宽松类型补间。to()
方法定义补间结束时对象的状态。它需要一个包含所选参数的期望结束值的对象(比例取尺度值,1 为大小的 100%,0 为大小的 0%等),补间的时间(以毫秒为单位)以及使用的宽松类型补间。onComplete
事件处理程序,该处理程序定义了在补间程序完成时要执行的函数。start()
。game.add.tween(brick.scale).to({x:2,y:2}, 500, Phaser.Easing.Elastic.Out, true, 100);-
这个补间将使用弹性宽松在半秒内将砖的比例翻倍,将自动启动,延迟100毫秒。
+这个补间将使用弹性宽松在半秒内将砖的比例翻倍,将自动启动,延迟 100 毫秒。
动画和tweens看起来很不错,但我们可以添加更多的我们的游戏 - 在下一节我们将看看处理按钮输入。
+动画和 tweens 看起来很不错,但我们可以添加更多的我们的游戏 - 在下一节我们将看看处理按钮输入。
{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Extra_lives", "Games/Workflows/2D_Breakout_game_Phaser/Buttons")}}
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html index 745498bff635c7..dbf593850d649f 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/bounce_off_the_walls/index.html @@ -17,24 +17,24 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Physics", "Games/Workflows/2D_Breakout_game_Phaser/Player_paddle_and_controls")}}
这是Gamedev Phaser教程的第 6 步。在Gamedev-Phaser-Content-Kit / demos / lesson06.html完成本课后,您可以找到源代码。
+这是Gamedev Phaser 教程的第 6 步。在Gamedev-Phaser-Content-Kit / demos / lesson06.html完成本课后,您可以找到源代码。
现在已经介绍了物理引擎,我们可以开始在游戏中实现碰撞检测 - 首先我们来看看墙壁。
让我们的球从墙壁上弹起的最简单的方法是告诉框架,我们想要将<canvas>
元素的边界视为墙壁,而不是让球移过它们。在Phaser中,可以使用该collideWorldsBound
属性轻松实现。在现有game.physics.enable()
方法调用之后添加此行:
让我们的球从墙壁上弹起的最简单的方法是告诉框架,我们想要将<canvas>
元素的边界视为墙壁,而不是让球移过它们。在 Phaser 中,可以使用该collideWorldsBound
属性轻松实现。在现有game.physics.enable()
方法调用之后添加此行:
ball.body.collideWorldBounds = true;-
现在球将停在屏幕的边缘,而不是消失,但它不会弹起。为了使这种情况发生,我们必须设置它的bounciness。在上一行下面添加以下行:
+现在球将停在屏幕的边缘,而不是消失,但它不会弹起。为了使这种情况发生,我们必须设置它的 bounciness。在上一行下面添加以下行:
ball.body.bounce.set(1);-
再次尝试重新加载index.html - 现在您应该看到球从墙壁上弹起并在画布区域内移动。
+再次尝试重新加载 index.html - 现在您应该看到球从墙壁上弹起并在画布区域内移动。
{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Game_over", "Games/Workflows/2D_Breakout_game_Phaser/Collision_detection")}}
这是Gamedev Phaser教程 16 的第9步。在Gamedev-Phaser-Content-Kit / demos / lesson09.html完成本课后,您可以找到源代码。
+这是Gamedev Phaser 教程 16 的第 9 步。在Gamedev-Phaser-Content-Kit / demos / lesson09.html完成本课后,您可以找到源代码。
建立砖块比将单个对象添加到屏幕要复杂一点,尽管使用Phaser还是比纯JavaScript更容易。我们来探讨如何创建一组砖块,并使用循环在屏幕上打印。
+建立砖块比将单个对象添加到屏幕要复杂一点,尽管使用 Phaser 还是比纯 JavaScript 更容易。我们来探讨如何创建一组砖块,并使用循环在屏幕上打印。
您还需要从Github抓取砖图像并将其保存在您的/img
目录中。
您还需要从 Github 抓取砖图像并将其保存在您的/img
目录中。
在这里,我们循环遍历行和列,创建新的砖块并将其放在屏幕上。新创建的砖块为Arcade物理引擎启用,它的身体被设置为不可移动(所以当球被击中时它不会移动),我们还将锚点放在中间并添加砖到集团。
+在这里,我们循环遍历行和列,创建新的砖块并将其放在屏幕上。新创建的砖块为 Arcade 物理引擎启用,它的身体被设置为不可移动(所以当球被击中时它不会移动),我们还将锚点放在中间并添加砖到集团。
-目前的问题是,我们在一个地方绘制所有的砖,坐标(0,0)。我们需要做的是将每个砖块绘制在自己的x和y位置。更新brickX
和brickY
行如下:
目前的问题是,我们在一个地方绘制所有的砖,坐标(0,0)。我们需要做的是将每个砖块绘制在自己的 x 和 y 位置。更新brickX
和brickY
行如下:
var brickX = (r*(brickInfo.width+brickInfo.padding))+brickInfo.offset.left; var brickY = (c*(brickInfo.height+brickInfo.padding))+brickInfo.offset.top; @@ -114,7 +114,7 @@-画砖
每个
-brickX
位置都是brickInfo.width
加brickInfo.padding
号乘以行号r
,加上brickInfo.offset.left
; 用于所述逻辑brickY
是不同之处在于它使用的值列号相同c
,brickInfo.height
和brickInfo.offset.top
。现在每个砖都可以放置在正确的位置,每个砖块之间填充,并从左侧和顶部画布边缘偏移绘制。检查initBricks()代码
+检查 initBricks() 代码
这是功能的完整代码
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/buttons/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/buttons/index.html index e18a7fff13fc10..03040681742f70 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/buttons/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/buttons/index.html @@ -17,7 +17,7 @@initBricks()
:{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Animations_and_tweens", "Games/Workflows/2D_Breakout_game_Phaser/Randomizing_gameplay")}}
-这是Gamedev Phaser教程 16 的第15步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson15.html完成本课程后找到源代码
+这是Gamedev Phaser 教程 16 的第 15 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson15.html完成本课程后找到源代码
而不是立即开始游戏,我们可以通过添加他们可以按的开始按钮将该决定留给玩家。我们来调查如何做到这一点。
@@ -30,16 +30,16 @@新变量
var startButton;
我们可以加载按钮spritesheet与我们加载球的摆动动画相同的方式。将以下内容添加到preload()
函数底部:
我们可以加载按钮 spritesheet 与我们加载球的摆动动画相同的方式。将以下内容添加到preload()
函数底部:
game.load.spritesheet('button', 'img/button.png', 120, 40);-
单个按钮框架宽120像素,高40像素。
+单个按钮框架宽 120 像素,高 40 像素。
-您还需要从Github抓取按钮spritesheet,并将其保存在您的/img
目录中。
您还需要从 Github 抓取按钮 spritesheet,并将其保存在您的/img
目录中。
该button()
方法的参数如下:
this
指定执行上下文的引用{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_Phaser/The_score")}}
这是Gamedev Phaser教程 16 的第10步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson10.html完成本课程后找到源代码。
+这是Gamedev Phaser 教程 16 的第 10 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson10.html完成本课程后找到源代码。
现在接下来的挑战 - 球和砖块之间的碰撞检测。幸运的是,我们可以使用物理引擎来检查单个对象(如球和桨)之间的碰撞,也可以检测对象和组之间的碰撞。
@@ -42,9 +42,9 @@就是这样!重新加载你的代码,你应该看到新的碰撞检测工作正常。
-感谢Phaser,有两个参数传递给函数 - 第一个是球,我们在碰撞方法中明确定义,第二个是球碰撞的砖组中的单个砖。在功能内部,我们从屏幕上删除所讨论的砖块,只需运行其kill()
上的方法即可。
感谢 Phaser,有两个参数传递给函数 - 第一个是球,我们在碰撞方法中明确定义,第二个是球碰撞的砖组中的单个砖。在功能内部,我们从屏幕上删除所讨论的砖块,只需运行其kill()
上的方法即可。
您将期望在使用纯JavaScript时编写更多自己的计算机来实现碰撞检测。这是使用框架的好处 - 您可以为Phaser留下大量无聊的代码,并专注于制作游戏中最有趣和最有趣的部分。
+您将期望在使用纯 JavaScript时编写更多自己的计算机来实现碰撞检测。这是使用框架的好处 - 您可以为 Phaser 留下大量无聊的代码,并专注于制作游戏中最有趣和最有趣的部分。
{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Win_the_game", "Games/Workflows/2D_Breakout_game_Phaser/Animations_and_tweens")}}
这是Gamedev Phaser教程 16 的第13步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson13.html完成本课程后找到源代码。
+这是Gamedev Phaser 教程 16 的第 13 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson13.html完成本课程后找到源代码。
我们可以通过增加生活使游戏更愉快。在这篇文章中,我们将实施一个生活系统,以便玩家可以继续玩,直到他们失去了三个生命,而不仅仅是一个人。
@@ -44,7 +44,7 @@在livesText
与lifeLostText
物体看起来非常相似的scoreText
一个-它们定义在屏幕上的位置,显示实际文本和字体样式。前者被锚定在其右上边缘上,与屏幕正确对齐,后者位于中心位置,两者均使用anchor.set()
。
在livesText
与lifeLostText
物体看起来非常相似的scoreText
一个 - 它们定义在屏幕上的位置,显示实际文本和字体样式。前者被锚定在其右上边缘上,与屏幕正确对齐,后者位于中心位置,两者均使用anchor.set()
。
该lifeLostText
会表示,只有当生命消失,因此其知名度初始设置为false
。
{{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 游戏。
@@ -42,12 +42,12 @@学习路线的小提示 — 最好先熟悉使用原生JavaScript进行网页游戏开发,这样可以打下坚实的基础.如果你还不熟悉原生javascript开发,我们建议你先过一遍这个系列, 使用原生Javascript开发MDN消除游戏.
+学习路线的小提示 — 最好先熟悉使用原生 JavaScript 进行网页游戏开发,这样可以打下坚实的基础。如果你还不熟悉原生 javascript 开发,我们建议你先过一遍这个系列,使用原生 Javascript 开发 MDN 消除游戏.
-在那之后,你就能随意挑选框架并用在你的项目中;我们选择了Phaser这个稳定优越的框架,它有着好的支持和社区环境以及大量优秀的插件. 框架加速了开发并能帮你管理无趣的部分,让你专注于有意思的事务. 然而, 框架也有不好的地方, 所以当一些意想不到的事情发生了或者想实现一些框架没有提供的功能时,你就将需要原生的JavaScript知识了.
+在那之后,你就能随意挑选框架并用在你的项目中;我们选择了 Phaser 这个稳定优越的框架,它有着好的支持和社区环境以及大量优秀的插件。框架加速了开发并能帮你管理无趣的部分,让你专注于有意思的事务。然而,框架也有不好的地方,所以当一些意想不到的事情发生了或者想实现一些框架没有提供的功能时,你就将需要原生的 JavaScript 知识了。
注意: 本系列文章可用作实际游戏开发的材料。 如果您想要使用Phaser讨论游戏开发,您还可以使用基于本教程的 Gamedev Phaser内容套件.
+注意: 本系列文章可用作实际游戏开发的材料。如果您想要使用 Phaser 讨论游戏开发,您还可以使用基于本教程的 Gamedev Phaser 内容套件.
{{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文档结构非常的简单,这个游戏将整个被渲染在框架生成的{{htmlelement("canvas")}} 元素上. 拿起你最爱的编辑器,挑一个好目录,创建一个HTML文档,存成index.html,然后写下下面的代码:
+HTML 文档结构非常的简单,这个游戏将整个被渲染在框架生成的{{htmlelement("canvas")}} 元素上。拿起你最爱的编辑器,挑一个好目录,创建一个 HTML 文档,存成 index.html,然后写下下面的代码:
<!DOCTYPE html> <html> @@ -47,25 +47,25 @@-游戏的HTML
</html>
下面我们将下载Phaser的代码,并应用到我们的HTML文档中.
+下面我们将下载 Phaser 的代码,并应用到我们的 HTML 文档中。
这个时候我们在 {{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 变量来完成初始化的。参数的含义是:
AUTO,
CANVAS
和 WEBGL
。我们可以指定使用 Canvas 还是 WebGL 来渲染,如果使用了 Auto 则优先使用 WebGL,如果浏览器不支持则会选择 Canvas。{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Scaling", "Games/Workflows/2D_Breakout_game_Phaser/Move the ball")}}
这是Gamedev Phaser教程 16 的第三步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson03.html完成本课程后找到源代码
+这是Gamedev Phaser 教程 16 的第三步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson03.html完成本课程后找到源代码
我们的游戏将围绕屏幕滚动,弹出一个桨,摧毁砖块赚取积分 - 熟悉吗?在本文中,我们将介绍如何将sprite添加到我们的gameworld中。
+我们的游戏将围绕屏幕滚动,弹出一个桨,摧毁砖块赚取积分 - 熟悉吗?在本文中,我们将介绍如何将 sprite 添加到我们的 gameworld 中。
我们开始创建一个JavaScript变量来表示我们的球 - 在游戏初始化代码(我们的var game...
块)和preload()
函数之间添加以下行:
我们开始创建一个 JavaScript 变量来表示我们的球 - 在游戏初始化代码(我们的var game...
块)和preload()
函数之间添加以下行:
var ball;
注意:为了本教程,我们将使用全局变量。本教程的目的是教导Phaser特定的游戏开发方法,而不是主观的最佳方法。
+注意:为了本教程,我们将使用全局变量。本教程的目的是教导 Phaser 特定的游戏开发方法,而不是主观的最佳方法。
使用Phaser加载图像并将其打印在我们的画布上比使用纯JavaScript容易得多。要加载资产,我们将使用game
由Phaser创建的对象,执行其load.image()
方法。在preload()
函数的底部添加以下新行:
使用 Phaser 加载图像并将其打印在我们的画布上比使用纯 JavaScript 容易得多。要加载资产,我们将使用game
由 Phaser 创建的对象,执行其load.image()
方法。在preload()
函数的底部添加以下新行:
function preload() { // ... @@ -47,16 +47,16 @@-加载球精灵
第一个参数是我们要提供资产的名称 - 这将在我们的游戏代码中使用,例如我们的
-ball
变量名称,所以我们需要确保它是一样的。第二个参数是图形资源的相对路径。在我们的情况下,我们将加载我们的球的图像(请注意,文件名不一定是一致的,但我们建议,因为它使一切更容易遵循。)当然,要加载图像,它需要在我们的代码目录中可用。从Github抓住球图像,并将其保存
+/img
在与index.html
文件相同位置的目录中。当然,要加载图像,它需要在我们的代码目录中可用。从 Github 抓住球图像,并将其保存
-/img
在与index.html
文件相同位置的目录中。现在,要在屏幕上显示,我们将使用另一种Phaser方法
+add.sprite()
:在create()
函数内添加以下新的代码行,如图所示:现在,要在屏幕上显示,我们将使用另一种 Phaser 方法
add.sprite()
:在create()
函数内添加以下新的代码行,如图所示:function create() { ball = game.add.sprite(50, 50, 'ball'); }-这将添加球到游戏,并将其呈现在屏幕上。前两个参数是要添加的画布的x和y坐标,第三个是我们之前定义的资产的名称。就是这样 - 如果你加载你的
+index.html
文件,你会看到已经加载并在画布上渲染的图像!这将添加球到游戏,并将其呈现在屏幕上。前两个参数是要添加的画布的 x 和 y 坐标,第三个是我们之前定义的资产的名称。就是这样 - 如果你加载你的
index.html
文件,你会看到已经加载并在画布上渲染的图像!比较你的代码
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/move_the_ball/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/move_the_ball/index.html index a410bdb4934baf..dca75a25ddb06b 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/move_the_ball/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/move_the_ball/index.html @@ -17,7 +17,7 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Load_the_assets_and_print_them_on_screen", "Games/Workflows/2D_Breakout_game_Phaser/Physics")}}
-这是Gamedev Phaser教程 16 的第4步。在Gamedev-Phaser-Content-Kit / demos / lesson04.html完成本课后,您可以找到源代码。
+这是Gamedev Phaser 教程 16 的第 4 步。在Gamedev-Phaser-Content-Kit / demos / lesson04.html完成本课后,您可以找到源代码。
我们在屏幕上打印了我们的蓝色球,但它什么都不做,这样做会很酷。本文介绍如何做到这一点。
@@ -32,7 +32,7 @@在每个框架上更新球的位 }
上面的代码在每个框架上为表示画布上的球坐标的属性x
和y
属性添加了一个。重新加载index.html,你应该看到球在屏幕上滚动。
上面的代码在每个框架上为表示画布上的球坐标的属性x
和y
属性添加了一个。重新加载 index.html,你应该看到球在屏幕上滚动。
下一步是添加一些基本的碰撞检测,所以我们的球可以从墙壁反弹。这将需要几行代码 - 一个比我们迄今为止看到的更复杂的步骤,特别是如果我们也想添加桨和砖碰撞 - 但是幸运的是Phaser使我们比我们想要使用纯粹的方法更容易做到这一点JavaScript的。
+下一步是添加一些基本的碰撞检测,所以我们的球可以从墙壁反弹。这将需要几行代码 - 一个比我们迄今为止看到的更复杂的步骤,特别是如果我们也想添加桨和砖碰撞 - 但是幸运的是 Phaser 使我们比我们想要使用纯粹的方法更容易做到这一点 JavaScript 的。
-无论如何,在我们做所有的事情之前,我们将首先介绍Phaser的物理引擎,并做一些设置工作。
+无论如何,在我们做所有的事情之前,我们将首先介绍 Phaser 的物理引擎,并做一些设置工作。
{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Load_the_assets_and_print_them_on_screen", "Games/Workflows/2D_Breakout_game_Phaser/Physics")}}
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/physics/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/physics/index.html index 4d239f6ec9d35a..1b0b8a7da9d345 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/physics/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/physics/index.html @@ -17,21 +17,21 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Move_the_ball", "Games/Workflows/2D_Breakout_game_Phaser/Bounce_off_the_walls")}}
这是Gamedev Phaser教程 16 的第5步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson05.html完成本课程后找到源代码
+这是Gamedev Phaser 教程 16 的第 5 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson05.html完成本课程后找到源代码
为了在我们的游戏中的对象之间进行正确的碰撞检测,我们将需要物理学; 本文将向您介绍Phaser中的可用内容,以及演示典型的简单设置。
+为了在我们的游戏中的对象之间进行正确的碰撞检测,我们将需要物理学; 本文将向您介绍 Phaser 中的可用内容,以及演示典型的简单设置。
Phaser与三个不同的物理引擎(Arcade Physics,P2和Ninja Physics)捆绑在一起,第四个选项Box2D可作为商业插件使用。对于像我们这样的简单游戏,我们可以使用Arcade Physics引擎。我们不需要任何重的几何计算 - 毕竟只是一个球从墙壁和砖块弹起来。
+Phaser 与三个不同的物理引擎(Arcade Physics,P2 和 Ninja Physics)捆绑在一起,第四个选项 Box2D 可作为商业插件使用。对于像我们这样的简单游戏,我们可以使用 Arcade Physics 引擎。我们不需要任何重的几何计算 - 毕竟只是一个球从墙壁和砖块弹起来。
-首先,让我们在游戏中初始化Arcade Physics引擎。physics.startSystem()
在create
函数开头添加方法(使其成为函数内的第一行),如下所示:
首先,让我们在游戏中初始化 Arcade Physics 引擎。physics.startSystem()
在create
函数开头添加方法(使其成为函数内的第一行),如下所示:
game.physics.startSystem(Phaser.Physics.ARCADE);-
接下来,我们需要为物理系统启用我们的球 - 默认情况下,Phaser对象物理不启用。在create()
函数底部添加以下行:
接下来,我们需要为物理系统启用我们的球 - 默认情况下,Phaser 对象物理不启用。在create()
函数底部添加以下行:
game.physics.enable(ball, Phaser.Physics.ARCADE);diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/player_paddle_and_controls/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/player_paddle_and_controls/index.html index 24ba48ab112127..4e35eee0f7d3ae 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/player_paddle_and_controls/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/player_paddle_and_controls/index.html @@ -16,7 +16,7 @@
{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Bounce_off_the_walls", "Games/Workflows/2D_Breakout_game_Phaser/Game_over")}}
这是Gamedev Phaser教程 16 的第7步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson07.html完成本课程后找到源代码。
+这是Gamedev Phaser 教程 16 的第 7 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson07.html完成本课程后找到源代码。
我们有球从墙上移动并弹跳,但它很快变得无聊 - 没有互动!我们需要一种介绍游戏的方法,所以在这篇文章中,我们将创建一个桨来移动并击中球。
@@ -43,7 +43,7 @@所以我们不要忘记,在这一点上,你应该从Github 抓住这个图形,并保存在你的/img
文件夹中。
所以我们不要忘记,在这一点上,你应该从 Github 抓住这个图形,并保存在你的/img
文件夹中。
ball = game.add.sprite(game.world.width*0.5, game.world.height-25, 'ball'); ball.anchor.set(0.5);-
速度保持不变 - 我们只是将第二个参数的值从150改为-150,所以球将通过向上移动而不是下降来开始游戏。查找现有ball.body.velocity.set( ... )
行并将其更新为以下内容:
速度保持不变 - 我们只是将第二个参数的值从 150 改为 -150,所以球将通过向上移动而不是下降来开始游戏。查找现有ball.body.velocity.set( ... )
行并将其更新为以下内容:
ball.body.velocity.set(150, -150);diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/randomizing_gameplay/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/randomizing_gameplay/index.html index c5a9ef55d368c1..b1c788636b8fbd 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/randomizing_gameplay/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/randomizing_gameplay/index.html @@ -16,7 +16,7 @@
{{Previous("Games/Workflows/2D_Breakout_game_Phaser/Buttons")}}
这是Gamedev Phaser教程 16中的第16步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson16.html完成本课程后找到源代码。
+这是Gamedev Phaser 教程 16 中的第16 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson16.html完成本课程后找到源代码。
我们的游戏似乎已经完成了,但是如果你看起来足够近,你会发现球在整个游戏中都以相同的角度从桨上弹起。这意味着每个游戏都非常相似。为了解决这个问题,提高可玩性,我们应该使反弹角度更加随机,在本文中我们将介绍一下如何。
@@ -40,11 +40,11 @@你已经完成了所有的课程 - 恭喜你!在这一点上,您将了解到Phaser的基础知识和简单2D游戏背后的逻辑。
+你已经完成了所有的课程 - 恭喜你!在这一点上,您将了解到 Phaser 的基础知识和简单 2D 游戏背后的逻辑。
你可以在游戏中做更多的事情 - 添加任何你觉得最好的东西,使它更有趣和有趣。Phaser提供的无数有用的方法的基本介绍。以下是关于如何扩展我们的小游戏的一些建议,让您开始:
+你可以在游戏中做更多的事情 - 添加任何你觉得最好的东西,使它更有趣和有趣。Phaser 提供的无数有用的方法的基本介绍。以下是关于如何扩展我们的小游戏的一些建议,让您开始:
一定要检查越来越多的示例列表和官方文档,如果您需要任何帮助,请访问HTML5 Gamedevs论坛。
+一定要检查越来越多的示例列表和官方文档,如果您需要任何帮助,请访问HTML5 Gamedevs 论坛。
您也可以返回本教程系列的索引页。
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/scaling/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/scaling/index.html index dd5416e6662db2..d31f845dd66a1a 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/scaling/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/scaling/index.html @@ -16,14 +16,14 @@{{PreviousNext("Games/Tutorials/2D_Breakout_game_Phaser/Initialize_the_framework", "Games/Tutorials/2D_Breakout_game_Phaser/Load_the_assets_and_print_them_on_screen")}}
这是Gamedev Phaser教程系列的第二课. 在课程完成之后,你可以在Gamedev-Phaser-Content-Kit/demos/lesson02.html找到源码.
+这是Gamedev Phaser 教程系列的第二课。在课程完成之后,你可以在Gamedev-Phaser-Content-Kit/demos/lesson02.html找到源码。
缩放是指游戏画布如何在不同的屏幕尺寸上进行显示。我们可以在预加载阶段自动使游戏规模适合任何屏幕尺寸,之后就可以不用再担心屏幕尺寸的问题了。
-Phaser中有一个特殊的对象:scale
,它包含一些特别的方法和属性。让我们来更改一下上一节中创建的的preload()
函数:
Phaser 中有一个特殊的对象:scale
,它包含一些特别的方法和属性。让我们来更改一下上一节中创建的的preload()
函数:
function preload() { game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL; @@ -46,7 +46,7 @@Phaser中scale对象
设置背景颜色
-我们还可以给画布设置背景颜色来替代磨人的黑色背景。通过更改
+stage
对象的backgroundColor
属性来添加,我们可以使用CSS颜色定义语法进行设置。我们在刚才的代码下面添加以下代码:我们还可以给画布设置背景颜色来替代磨人的黑色背景。通过更改
stage
对象的backgroundColor
属性来添加,我们可以使用 CSS 颜色定义语法进行设置。我们在刚才的代码下面添加以下代码:game.stage.backgroundColor = '#eee';diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/the_score/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/the_score/index.html index 153c64819cc309..acbb674b60826d 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_phaser/the_score/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_phaser/the_score/index.html @@ -17,12 +17,12 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/Collision_detection", "Games/Workflows/2D_Breakout_game_Phaser/Win_the_game")}}
-这是Gamedev Phaser教程 16 的第11步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson11.html完成本课程后找到源代码。
+这是Gamedev Phaser 教程 16 的第 11 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson11.html完成本课程后找到源代码。
得分也可以使游戏更有趣 - 你可以尝试击败自己的高分,或者你的朋友。在这篇文章中,我们将为我们的游戏添加一个评分系统。
-我们将使用一个单独的变量来存储分数和Phaser的
+text()
方法将其打印到屏幕上。我们将使用一个单独的变量来存储分数和 Phaser 的
text()
方法将其打印到屏幕上。新变量
@@ -43,12 +43,12 @@将得分文字添加到游戏显
该
text()
方法可以采用四个参数:
最后一个参数与CSS样式非常相似。在我们的例子中,乐谱文字将为蓝色,大小为18像素,并使用Arial字体。
+最后一个参数与 CSS 样式非常相似。在我们的例子中,乐谱文字将为蓝色,大小为 18 像素,并使用 Arial 字体。
{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/The_score", "Games/Workflows/2D_Breakout_game_Phaser/Extra_lives")}}
这是Gamedev Phaser教程 16 的第12步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson12.html完成本课程后找到源代码。
+这是Gamedev Phaser 教程 16 的第 12 步。您可以在Gamedev-Phaser-Content-Kit / demos / lesson12.html完成本课程后找到源代码。
在我们的游戏中实现获胜是相当容易的:如果你碰巧摧毁所有的砖块,那么你赢了。
@@ -54,6 +54,6 @@失败和获胜都是实施的,所以我们的游戏的核心游戏就完成了。现在让我们添加一些额外的东西-我们会给玩家将3个生活的,而不是一个。
+失败和获胜都是实施的,所以我们的游戏的核心游戏就完成了。现在让我们添加一些额外的东西 - 我们会给玩家将 3 个生活的,而不是一个。
{{PreviousNext("Games/Workflows/2D_Breakout_game_Phaser/The_score", "Games/Workflows/2D_Breakout_game_Phaser/Extra_lives")}}
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html index 6654c88775ea7b..0eba8f91f78098 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/bounce_off_the_walls/index.html @@ -8,10 +8,10 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls")}}
本篇是 Gamedev Canvas tutorial 10节教程中的第三节。如果你完成了本篇教程之后,你可以从 Gamedev-Canvas-workshop/lesson3.html 看到源码。
+本篇是 Gamedev Canvas tutorial 10 节教程中的第三节。如果你完成了本篇教程之后,你可以从 Gamedev-Canvas-workshop/lesson3.html 看到源码。
看到我们的球动起来很惊讶吧,但是它很快就从屏幕上消失了,当然我们是可以控制它的。我们会实现一些非常简单的碰撞检测(详细后面解释),使球在画布的四周反弹回来。
+看到我们的球动起来很惊讶吧,但是它很快就从屏幕上消失了,当然我们是可以控制它的。我们会实现一些非常简单的碰撞检测 (详细后面解释),使球在画布的四周反弹回来。
有四面墙壁可以让它反弹回来,我们先来看上面的那面墙。我们需要判断球运动的每一帧,球体是否与画布的顶部边缘接触。如果有接触,我们将会改变球体的运动方向,使它向相反的方向移动,并保证它在画布的可见范围之内。记住坐标系统的左上角,让我们开始并加以下代码:
+有四面墙壁可以让它反弹回来,我们先来看上面的那面墙。我们需要判断球运动的每一帧,球体是否与画布的顶部边缘接触。如果有接触,我们将会改变球体的运动方向,使它向相反的方向移动,并保证它在画布的可见范围之内。记住坐标系统的左上角,让我们开始并加以下代码:
if(y + dy < 0) { dy = -dy; }-
如果球的纵坐标(y轴)值小于零,我们将在球体原有的运动方向上逆转。如果球体向上移动的速度是2像素/帧,现在就是向上移动速度是-2像素。这相当于此时向下移动的速度是2像素/帧。
+如果球的纵坐标(y 轴)值小于零,我们将在球体原有的运动方向上逆转。如果球体向上移动的速度是 2 像素/帧,现在就是向上移动速度是 -2 像素。这相当于此时向下移动的速度是 2 像素/帧。
上面的代码将处理球与画布顶部边缘的反射,现在让我们思考一下底部边缘如何处理:
@@ -41,7 +41,7 @@如果球的y位置大于canvas
的高度(记住,我们从左上角计算y值,所以顶部边缘从0开始,底部边缘在480像素),然后通过像以前那样反转y轴运动而离开底部边缘。
如果球的 y 位置大于canvas
的高度(记住,我们从左上角计算 y 值,所以顶部边缘从 0 开始,底部边缘在 480 像素),然后通过像以前那样反转 y 轴运动而离开底部边缘。
我们可以将这两句冗长的代码合二为一:
@@ -53,7 +53,7 @@我们有顶部和底部的边缘,所以我们来考虑一下左边和右边的边缘。 实际上非常相似,你所要做的就是颠倒x
而不是y
:
我们有顶部和底部的边缘,所以我们来考虑一下左边和右边的边缘。实际上非常相似,你所要做的就是颠倒x
而不是y
:
if(x + dx > canvas.width || x + dx < 0) { dx = -dx; @@ -63,15 +63,15 @@-从左边和右边反弹
dy = -dy; }
你应该把上面的代码块插入到draw()函数中,就在大括号之前。
+你应该把上面的代码块插入到 draw()函数中,就在大括号之前。
测试你的代码,你会看到我们的球碰到任一边缘都会反弹!然而,我们还发现了一个问题,当球碰撞到边缘,反弹之前:
+测试你的代码,你会看到我们的球碰到任一边缘都会反弹!然而,我们还发现了一个问题,当球碰撞到边缘,反弹之前:
-这是因为我们正在计算墙和球的中心碰撞点,而我们应该围绕它的周长来做。 如果碰到墙壁,球应该会弹起来,而不是陷入墙壁一半时,所以让我们来调整一下我们的判断条件。 更新你之前添加的代码:
+这是因为我们正在计算墙和球的中心碰撞点,而我们应该围绕它的周长来做。如果碰到墙壁,球应该会弹起来,而不是陷入墙壁一半时,所以让我们来调整一下我们的判断条件。更新你之前添加的代码:
if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { dx = -dx; @@ -84,7 +84,7 @@球部分消失在墙上!
比较你的代码
-让我们再次检查这个部分的代码与你之间有何差异:
+让我们再次检查这个部分的代码与你之间有何差异:
{{JSFiddleEmbed("https://jsfiddle.net/end3r/redj37dc/","","370")}}
@@ -94,6 +94,6 @@比较你的代码
下一步
-现在我们已经到了我们的球正在移动和留在游戏板上的阶段。 在第四章中,我们将看看如何实现一个可控制的paddle - 参见paddle和键盘控制。
+现在我们已经到了我们的球正在移动和留在游戏板上的阶段。在第四章中,我们将看看如何实现一个可控制的 paddle - 参见paddle 和键盘控制。
{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls")}}
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html index 00c88aee679d93..5ffe1310a65dc3 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/build_the_brick_field/index.html @@ -8,14 +8,14 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection")}}
-这是 Gamedev Canvas tutorial教程10节的第6节。您可以在完成本课程后在这里Gamedev-Canvas-workshop/lesson6.html找到源代码。
+这是 Gamedev Canvas tutorial教程 10 节的第 6 节。您可以在完成本课程后在这里Gamedev-Canvas-workshop/lesson6.html找到源代码。
在修改游戏机制后,我们可以输了 — 这样这游戏看起来终于像是一个游戏了,这真是太好了。但是,如果你总是让球与墙、板碰撞的话,很快就会感到无聊的。 好游戏需要的是让球消灭砖,这就是我们即将要做的!
设置砖变量
-本课题的总体目标是使用一个二维数组嵌套的循环,给出砖的几行代码。首先我们需要设置一些变量定义的砖,如宽度和高度信息, 行和列,等。在之前的变量声明处加入以下几行代码。
+本课题的总体目标是使用一个二维数组嵌套的循环,给出砖的几行代码。首先我们需要设置一些变量定义的砖,如宽度和高度信息,行和列,等。在之前的变量声明处加入以下几行代码。
var brickRowCount = 3; var brickColumnCount = 5; @@ -27,7 +27,7 @@设置砖变量
在这里,我们定义了砖的行数和列,宽度和高度,砖块之间的填充物,这样它们就不会互相接触;有一个上、左偏移量,所以它们不会从画布的边缘开始绘制。
-我们将在一个二维数组容纳我们所有的砖。它将包含砖列(c),砖行(R),每一个包含一个对象,其中包含x和y位置,让每个砖显示在屏幕上。在变量下面添加以下代码:
+我们将在一个二维数组容纳我们所有的砖。它将包含砖列(c),砖行(R),每一个包含一个对象,其中包含 x 和 y 位置,让每个砖显示在屏幕上。在变量下面添加以下代码:
var bricks = []; for(c=0; c<brickColumnCount; c++) { @@ -57,7 +57,7 @@-画砖的逻辑
} }再次,我们遍历的行和列,给每一块砖的位置设置
+X
和Y
,我们也画布上画砖,---brickwidth
Xbrickheight
。问题是我们都画在一个地方坐标(0,0)
处。我们需要做的是增加一些计算,计算每个循环迭代后的砖块的x和y位置:再次,我们遍历的行和列,给每一块砖的位置设置
X
和Y
,我们也画布上画砖,---brickwidth
Xbrickheight
。问题是我们都画在一个地方坐标(0,0)
处。我们需要做的是增加一些计算,计算每个循环迭代后的砖块的 x 和 y 位置:var brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft; var brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;@@ -84,7 +84,7 @@画砖的逻辑
到了展现真正画砖的时候了
-最后一件事就是在
+draw()
中调用drawBricks()
, 位置最好在函数开始处,在清除画布和画球之间。直接将下面代码加在drawBall()
处:最后一件事就是在
draw()
中调用drawBricks()
, 位置最好在函数开始处,在清除画布和画球之间。直接将下面代码加在drawBall()
处:drawBricks();@@ -101,6 +101,6 @@比较你的代码
下一节
-现在,我们有砖啦!但是球根本就没有和它们互动 —— 接下来的第七章我们将让球和砖产生碰撞: 碰撞检测。
+现在,我们有砖啦!但是球根本就没有和它们互动 —— 接下来的第七章我们将让球和砖产生碰撞:碰撞检测。
{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Collision_detection")}}
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html index e15235665bc331..26e30f957d12ec 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/collision_detection/index.html @@ -8,7 +8,7 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Build_the_brick_field", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Track_the_score_and_win")}}
-本篇为Gamedev Canvas tutorial10节教程中的第7节。在你完成这篇课程之后,你可以在Gamedev-Canvas-workshop/lesson7.html.找到我们的源代码。
+本篇为Gamedev Canvas tutorial10 节教程中的第 7 节。在你完成这篇课程之后,你可以在Gamedev-Canvas-workshop/lesson7.html.找到我们的源代码。
我们已经在屏幕上画出了砖块,但游戏仍然没有那么有趣,因为球通过它们。我们需要考虑增加碰撞检测,这样球就可以弹击砖块并打破它们。
@@ -17,7 +17,7 @@撞击侦测函数
-踢掉这一切,我们想创建一个碰撞检测功能,将循环通过所有砖块,并比较每一个砖的位置与球的坐标,因为每个帧绘制。为了更好地理解代码,我们将定义用于在碰撞检测的每个循环中存储砖块对象的B变量:
+踢掉这一切,我们想创建一个碰撞检测功能,将循环通过所有砖块,并比较每一个砖的位置与球的坐标,因为每个帧绘制。为了更好地理解代码,我们将定义用于在碰撞检测的每个循环中存储砖块对象的 B 变量:
function collisionDetection() { for(c=0; c<brickColumnCount; c++) { @@ -31,10 +31,10 @@撞击侦测函数
如果球的中心在我们的一块砖块的坐标内,我们将改变球的方向。对于球的中心在砖块内,以下四个陈述都必须是正确的:
让我们在代码中写下:
@@ -64,7 +64,7 @@接下来,我们将在绘制之前在 drawBricks()
中检查每个砖块的 status
属性的值-如果 status
是 1
,然后画它,但是如果它是 0
,那么它被球击中,我们不再希望它在屏幕上。更新您的 drawBricks()
函数如下:
接下来,我们将在绘制之前在 drawBricks()
中检查每个砖块的 status
属性的值 - 如果 status
是 1
,然后画它,但是如果它是 0
,那么它被球击中,我们不再希望它在屏幕上。更新您的 drawBricks()
函数如下:
function drawBricks() { for(c=0; c<brickColumnCount; c++) { diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html index ab5d87f3112646..fc7268f713358c 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/create_the_canvas_and_draw_on_it/index.html @@ -10,14 +10,14 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball")}}
--本篇是 Gamedev Canvas tutorial 10节教程中的第一节。如果你完成了本篇教程之后,你可以从 Gamedev-Canvas-workshop/lesson1.html 看到源码。
+本篇是 Gamedev Canvas tutorial 10 节教程中的第一节。如果你完成了本篇教程之后,你可以从 Gamedev-Canvas-workshop/lesson1.html 看到源码。
在我们开始编写游戏功能之前,我们可以通过HTML的canvas标签创建支撑游戏的基本结构。
+在我们开始编写游戏功能之前,我们可以通过 HTML 的 canvas 标签创建支撑游戏的基本结构。
页面部分
-HTML文档的结构是非常简单的,我们的游戏将完全呈现在这个HTML的canvas标签中。你可以选择一款你最喜欢的文本编辑器,创建一个HTML文件,保存到你理想的位置,名称为index.html。并添加以下代码:
+HTML 文档的结构是非常简单的,我们的游戏将完全呈现在这个 HTML 的 canvas 标签中。你可以选择一款你最喜欢的文本编辑器,创建一个 HTML 文件,保存到你理想的位置,名称为 index.html。并添加以下代码:
<!DOCTYPE html> <html> @@ -60,7 +60,7 @@-画布的基本属性
ctx.fill(); ctx.closePath();把全部指令放到 ctx.beginPath() 方法 和 ctx.closePath() 方法之间。我们使用 ctx.rect() 方法创建了一个矩形。这个方法的第一组参数(20,40)是确定这个矩形的左上角在画布上的坐标,第二组参数(50, 50)是指定矩形的宽度和高度。例子中矩形左上角的 x 坐标为20像素,y 坐标为40像素;宽和高各为50像素,这样画出一个完美的正方形。ctx.fillStyle 属性是用于填充绘画的颜色,这里填充的颜色为红色。ctx.fill() 方法是填充路径的内容区域生成实心的图形。
+把全部指令放到 ctx.beginPath() 方法 和 ctx.closePath() 方法之间。我们使用 ctx.rect() 方法创建了一个矩形。这个方法的第一组参数(20,40)是确定这个矩形的左上角在画布上的坐标,第二组参数(50, 50)是指定矩形的宽度和高度。例子中矩形左上角的 x 坐标为 20 像素,y 坐标为 40 像素;宽和高各为 50 像素,这样画出一个完美的正方形。ctx.fillStyle 属性是用于填充绘画的颜色,这里填充的颜色为红色。ctx.fill() 方法是填充路径的内容区域生成实心的图形。
我们不局限于绘制矩形 — 下面这段代码会绘制出一个绿色的圆;尝试添加到 JavaScript 代码的底部,保存并刷新:
@@ -81,7 +81,7 @@画布的基本属性
ctx.fillStyle 属性的值看起来和之前不大一样。这是因为它与 CSS 一样,颜色可以指定为十六进制值也可以指定为 rgba() 函数,或者任何其他可用的颜色值函数。
-当然我们也可以不使用 ctx.fill() 函数来填充图形和颜色,用 ctx.stroke() 函数来绘制定义图形的路径。试着将这段代码添加到您的JavaScript:
+当然我们也可以不使用 ctx.fill() 函数来填充图形和颜色,用 ctx.stroke() 函数来绘制定义图形的路径。试着将这段代码添加到您的 JavaScript:
ctx.beginPath(); ctx.rect(160, 10, 100, 40); @@ -93,7 +93,7 @@-画布的基本属性
比对你的代码
-以上是第一节的全部代码,可以运行在JSFiddle(在线JS代码调试工具)上:
+以上是第一节的全部代码,可以运行在 JSFiddle(在线 JS 代码调试工具)上:
{{JSFiddleEmbed("https://jsfiddle.net/end3r/x62h15e2/","","370")}}
@@ -103,7 +103,7 @@比对你的代码
下一节
-现在我们已经创建了基本的HTML和关于画布的基本知识。我们继续第二节,如何让球在游戏中动起来 — 让球动起来。
+现在我们已经创建了基本的 HTML 和关于画布的基本知识。我们继续第二节,如何让球在游戏中动起来 — 让球动起来。
{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball")}}
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 index 75ca5faa6abcb2..c546878ee17671 100644 --- 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 @@ -17,7 +17,7 @@{{Previous("Games/Workflows/2D_Breakout_game_pure_JavaScript/Mouse_controls")}}
-本篇为 Gamedev Canvas tutorial 10节教程中的第10节也是最后一节。完成这篇课程后,你可以在 Gamedev-Canvas-workshop/lesson10.html 找到我们的源代码。
+本篇为 Gamedev Canvas tutorial 10 节教程中的第 10 节也是最后一节。完成这篇课程后,你可以在 Gamedev-Canvas-workshop/lesson10.html 找到我们的源代码。
不管我们做什么游戏,它总是存在优化的空间。例如,我们可以为玩家多提供几条命,让他们能在发生一两次失误的情况下顺利完成游戏。或者,我们也可以在渲染代码上下工夫。
@@ -87,11 +87,11 @@用 requestAnimationFrame() 优
clearInterval(interval); // Needed for Chrome to end game-删除。然后,在
+draw()
函数的最下方(右花括号之前)加入下面这行代码。 它的作用是使draw()
函数递归调用自身:删除。然后,在
draw()
函数的最下方(右花括号之前)加入下面这行代码。它的作用是使draw()
函数递归调用自身:requestAnimationFrame(draw);-现在
+draw()
函数在requestAnimationFrame()
的循环中被反复调用,之先前做法最大的不同是,我们将帧率的控制权交给浏览器,而不是固定的 10 毫秒。浏览器会在适当的时机同步帧率,并且只在必要的时候才刷新渲染的图形。这使得我们的动画比之前的setInterval()
方法更加流畅且高效.现在
draw()
函数在requestAnimationFrame()
的循环中被反复调用,之先前做法最大的不同是,我们将帧率的控制权交给浏览器,而不是固定的 10 毫秒。浏览器会在适当的时机同步帧率,并且只在必要的时候才刷新渲染的图形。这使得我们的动画比之前的setInterval()
方法更加流畅且高效。比较你的代码
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html index eb4e11be856c27..09a6c32ac28269 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/game_over/index.html @@ -11,7 +11,7 @@这是 Gamedev Canvas tutorial教程的第五章。您可以在完成本课程后在这里Gamedev-Canvas-workshop/lesson5.html找到源代码。
-看球从墙上反弹,并能够移动球盘是很有趣的。但除此之外,游戏什么都不做,也没有任何进展或最终目标。 从游戏的角度来看,我们需要一个game over。 失败的逻辑很简单。 如果你的球拍错过了球,并且球到达屏幕的底部边缘,那么游戏就结束了。
+看球从墙上反弹,并能够移动球盘是很有趣的。但除此之外,游戏什么都不做,也没有任何进展或最终目标。从游戏的角度来看,我们需要一个 game over。失败的逻辑很简单。如果你的球拍错过了球,并且球到达屏幕的底部边缘,那么游戏就结束了。
实现游戏失败
@@ -25,17 +25,17 @@实现游戏失败
dy = -dy; }我们不需要让球从四面墙上反弹,应该只允许三个 - 左,上,右。 击中底部墙将结束游戏。 我们将编辑第二个if代码块,这是一个if else块,当球碰撞到画布的底部边缘时,它会触发我们的“游戏结束”状态。 现在我们将保持简单,显示一条警告消息,并通过重新加载页面重新开始游戏。
+我们不需要让球从四面墙上反弹,应该只允许三个 - 左,上,右。击中底部墙将结束游戏。我们将编辑第二个 if 代码块,这是一个 if else 块,当球碰撞到画布的底部边缘时,它会触发我们的“游戏结束”状态。现在我们将保持简单,显示一条警告消息,并通过重新加载页面重新开始游戏。
第一步,把您最开始使用的
setInterval()
函数setInterval(draw, 10);-替换成:
+替换成:
var interval = setInterval(draw, 10);-然后将第二个if块替换为以下内容:
+然后将第二个 if 块替换为以下内容:
if(y + dy < ballRadius) { dy = -dy; @@ -46,7 +46,7 @@实现游戏失败
让球拍接住球
-本课中最后要做的是在球和球拍之间创建一些碰撞检测,以便它可以反弹并返回到游戏区域。 最简单的方法是检查球的中心是否在球拍的左边和右边之间。 再次更新您修改的代码的最后一位(第二个if块),如下所示:
+本课中最后要做的是在球和球拍之间创建一些碰撞检测,以便它可以反弹并返回到游戏区域。最简单的方法是检查球的中心是否在球拍的左边和右边之间。再次更新您修改的代码的最后一位(第二个 if 块),如下所示:
if(y + dy < ballRadius) { dy = -dy; @@ -60,7 +60,7 @@-让球拍接住球
} }如果球击中画布的底部边缘,我们需要检查它是否碰到球拍。 如果是的话,就像你所期望的那样反弹。 如果没有,那么游戏就像以前一样结束。
+如果球击中画布的底部边缘,我们需要检查它是否碰到球拍。如果是的话,就像你所期望的那样反弹。如果没有,那么游戏就像以前一样结束。
代码对比
@@ -74,6 +74,6 @@代码对比
下一步
-到目前为止,我们的表现相当不错,游戏变得更有趣,并且现在你可以输了! 但它仍然缺少一些东西。 让我们继续前进到第六章 - 建造砖块 - 并创造一些砖块来消灭它们。
+到目前为止,我们的表现相当不错,游戏变得更有趣,并且现在你可以输了!但它仍然缺少一些东西。让我们继续前进到第六章 - 建造砖块 - 并创造一些砖块来消灭它们。
{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Paddle_and_keyboard_controls", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Build_the_brick_field")}}
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/index.html index 37f389106d31f6..9ff39476500011 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/index.html @@ -16,9 +16,9 @@{{Next("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it")}}
-在这里我们将完全使用JavaScript语言基于HTML5的canvas标签,一步一步的绘制一个简单的MDN消除游戏。
+在这里我们将完全使用 JavaScript 语言基于 HTML5 的 canvas 标签,一步一步的绘制一个简单的 MDN 消除游戏。
-过程中的每一步都会有例子可供体验,让你更清晰的了解他的制作过程。你将学习到如何使用canvas标签的基本语法去实现简单游戏的渲染、动画、碰撞、控制胜负。
+过程中的每一步都会有例子可供体验,让你更清晰的了解他的制作过程。你将学习到如何使用 canvas 标签的基本语法去实现简单游戏的渲染、动画、碰撞、控制胜负。
为了更快速高效的学习本系列教程,你需要掌握 JavaScript 的一些基础知识。学习完本教程之后你就可以创建自己的网页小游戏了。
@@ -28,7 +28,7 @@教程详情
-
全部教程 — MDN 消除小游戏 的各个版本我们正一起管理并托管到 GitHub 上:
+全部教程 — MDN 消除小游戏 的各个版本我们正一起管理并托管到 GitHub 上:
-对于实现一个网页游戏而言,最好的方式是从纯 JavaScirpt 着手,那样可以让我们建立更坚实的基础。之后你可以在你的项目中选择你喜欢的框架。框架也只是用JavaScript语言实现的工具;如果你想要在项目中使用框架,你必须先了解语言本身。框架可以帮你提高开发效率并生成一些基础的内容;但是如果没有达到你的预期,你只能慢慢调试或者使用原生JavaScript去实现解决方案。
+对于实现一个网页游戏而言,最好的方式是从纯 JavaScirpt 着手,那样可以让我们建立更坚实的基础。之后你可以在你的项目中选择你喜欢的框架。框架也只是用 JavaScript 语言实现的工具;如果你想要在项目中使用框架,你必须先了解语言本身。框架可以帮你提高开发效率并生成一些基础的内容;但是如果没有达到你的预期,你只能慢慢调试或者使用原生 JavaScript 去实现解决方案。
-说明: 如果你对使用第三方游戏资源库开发2d网页游戏感兴趣,可以参考本系列教程的 2D breakout game using Phaser.
+说明: 如果你对使用第三方游戏资源库开发 2d 网页游戏感兴趣,可以参考本系列教程的 2D breakout game using Phaser.
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 index 444a2257d6e659..4009ac91582565 100644 --- 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 @@ -17,7 +17,7 @@{{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 找到我们的源代码。
+本篇为 Gamedev Canvas tutorial 10 节教程中的第 9 节。在你完成这篇课程之后,你可以在 Gamedev-Canvas-workshop/lesson9.html 找到我们的源代码。
这个游戏实际已经完成,现在让我们着手去润色。我们已经添加过键盘控制,而加入鼠标控制也同样简单。
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html index 5c119602b43576..f62f2d18ddaa47 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/move_the_ball/index.html @@ -17,21 +17,21 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls")}}-本篇是 Gamedev Canvas tutorial 10节教程中的第二节。如果你完成了本篇教程之后,你可以从 Gamedev-Canvas-workshop/lesson2.html 看到源码。
+本篇是 Gamedev Canvas tutorial 10 节教程中的第二节。如果你完成了本篇教程之后,你可以从 Gamedev-Canvas-workshop/lesson2.html 看到源码。
从上一节中你已经知道如何去绘制一个球。现在让我们使它动起来。从技术上讲,我们将在画布上绘制一个球,之后让它消失,然后在一个稍微不用的位置上再绘制一个一样的球。就想电影里的每一帧动起来的感觉。
-我们需要定义一个绘图函数,每次使用一组不同的变量改变球体的位置;循环调用以保持画布上每一帧不断更新。你可以使用JavaScript时间函数 {{domxref("WindowTimers.setInterval()", "setInterval()")}} 或者 {{domxref("window.requestAnimationFrame()")}}。
+我们需要定义一个绘图函数,每次使用一组不同的变量改变球体的位置;循环调用以保持画布上每一帧不断更新。你可以使用 JavaScript 时间函数 {{domxref("WindowTimers.setInterval()", "setInterval()")}} 或者 {{domxref("window.requestAnimationFrame()")}}。
-在你的HTML文件只保留前两行,删除其他所有的JavaScript代码并在 draw() 函数中添加以下内容保证每10毫秒执行一次 draw() 函数:
+在你的 HTML 文件只保留前两行,删除其他所有的 JavaScript 代码并在 draw() 函数中添加以下内容保证每 10 毫秒执行一次 draw() 函数:
function draw() { // drawing code } setInterval(draw, 10);-得益于
+setInterval
的无限性,使得draw()
函数将每10毫秒就会被调用,除非我们停止它。现在,我们来绘制小球吧,在draw()
函数中添加以下内容:得益于
setInterval
的无限性,使得draw()
函数将每 10 毫秒就会被调用,除非我们停止它。现在,我们来绘制小球吧,在draw()
函数中添加以下内容:ctx.beginPath(); ctx.arc(50, 50, 10, 0, Math.PI*2); @@ -44,7 +44,7 @@-让球动起来
-你不会注意到球正在不停地被重新刷,因为它没有移动。让我们改变这种情况。首先,我们不再使用固定位置(50,50),而是用x和y的变量来定义画布底部的起始点,然后使用这些变量来定义圆被绘制的位置。
+你不会注意到球正在不停地被重新刷,因为它没有移动。让我们改变这种情况。首先,我们不再使用固定位置 (50,50),而是用 x 和 y 的变量来定义画布底部的起始点,然后使用这些变量来定义圆被绘制的位置。
首先,在
@@ -63,13 +63,13 @@draw()
函数上方添加以下两行,以定义x
和y
:让球动起来
}现在到了最重要的部分:我们想要在每一帧都被绘制出来之后,给
+x
和y
添加一个较小的值,让它看起来像是在移动。让我们将这些值定义为dx
和dy
,并将它们的值分别设为2
和-2
。在你的 x 和 y 变量声明下方添加以下内容:现在到了最重要的部分:我们想要在每一帧都被绘制出来之后,给
x
和y
添加一个较小的值,让它看起来像是在移动。让我们将这些值定义为dx
和dy
,并将它们的值分别设为2
和-2
。在你的 x 和 y 变量声明下方添加以下内容:var dx = 2; var dy = -2;-最后要做的是在每一帧上更新
+x
和y
,在每一次更新中,把球画在新的位置上。将下面的两条新线添加到你的draw()
函数:最后要做的是在每一帧上更新
x
和y
,在每一次更新中,把球画在新的位置上。将下面的两条新线添加到你的draw()
函数:function draw() { ctx.beginPath(); @@ -81,7 +81,7 @@-让球动起来
y += dy; }再次保存代码,并在浏览器中尝试。很好,尽管看起来球在后面留下了痕迹:
+再次保存代码,并在浏览器中尝试。很好,尽管看起来球在后面留下了痕迹:
@@ -89,7 +89,7 @@在每一帧更新之前清空画
球移动时留下了轨迹,因为我们在每一帧上都画了一个新的圆,而没有去掉之前的一个圆。不要担心,因为有一个方法来清空画布的内容:
-clearRect()
。该方法有四个参数:矩形左上角的x
和y
坐标,以及矩形的右下角的x
和y
坐标。这个矩形覆盖的整个区域里,之前所画的任何内容将被清除。将下列高亮显示行添加到
+draw()
函数:将下列高亮显示行添加到
draw()
函数:function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); @@ -103,7 +103,7 @@-在每一帧更新之前清空画 }
保存您的代码并再次尝试,这次你将看到球移动后没有留下轨迹。每隔10毫秒,画布就会被清除,蓝色的圆圈(我们的球)将被绘制在一个给定的位置上,而
+x
和y
的值将在下一个帧被更新。保存您的代码并再次尝试,这次你将看到球移动后没有留下轨迹。每隔 10 毫秒,画布就会被清除,蓝色的圆圈 (我们的球) 将被绘制在一个给定的位置上,而
x
和y
的值将在下一个帧被更新。保持代码整洁
diff --git a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html index 776815722eb2a8..07130ec9dc3ab7 100644 --- a/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html +++ b/files/zh-cn/games/tutorials/2d_breakout_game_pure_javascript/paddle_and_keyboard_controls/index.html @@ -8,7 +8,7 @@{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Game_over")}}
-这是Gamedev Canvas tutorial中的第四章。完成本课程后,你可以在Gamedev-Canvas-workshop/lesson4.html找到源码.
+这是Gamedev Canvas tutorial中的第四章。完成本课程后,你可以在Gamedev-Canvas-workshop/lesson4.html找到源码。
你可以看到球自由的、无限次的在墙壁上反弹,但是没有和我们发生任何交互。如果我们没有对它的控制操作,这仍然不是一个游戏。下面,我们新增一些用户操作:一个可以控制球的球板。
@@ -21,7 +21,7 @@定义一个球板去接球
var paddleWidth = 75; var paddleX = (canvas.width-paddleWidth)/2; -然后定义球拍的长和宽,以及为了之后的处理同时定义x轴上的初始位置。新建一个方法来在页面上描绘球板。把下列代码添加到你的
+drawBall()方法里去
:然后定义球拍的长和宽,以及为了之后的处理同时定义 x 轴上的初始位置。新建一个方法来在页面上描绘球板。把下列代码添加到你的
drawBall()方法里去
:function drawPaddle() { ctx.beginPath(); @@ -42,12 +42,12 @@允许用户控制球板
- 实现左右移动球拍
-按键可以使用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()")}} 来设置将放置在画布上的实际文本,和其放置位置。第一个参数是文本本身——上面的代码显示当前点的数量——最后两个参数是文本将放置在画布上的坐标。
若要在每次击中砖块时评分,则在
@@ -52,7 +52,7 @@collisionDetection()
中添加计分规则,以在每次检测到碰撞时增加得分变量的值。将下面突出显示的行添加到代码中:计算分数
当所有砖块被破坏时显示获胜消息
-收集这些点很有效,但是你不会永远添加它们-当所有的砖头都被破坏的时候呢?毕竟这是游戏的主要目的,所以如果收集到所有可用的点,你应该显示一个获胜的消息。将下面突出显示的部分添加到
+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 Orientation 和 Vibration APIs 来增强游戏玩法,并使用 Phaser 框架构建。 为了充分理解本教程建议您先学习基础的JavaScript 知识。
+在本教程中,我们将介绍构建 HTML5 移动游戏的过程。本游戏使用 Device Orientation 和 Vibration APIs 来增强游戏玩法,并使用 Phaser 框架构建。为了充分理解本教程建议您先学习基础的 JavaScript 知识。
Example game
-在本教程结束时,您将有一个功能齐全的游戏demo:Cyber Orb 。如下所示:
+在本教程结束时,您将有一个功能齐全的游戏 demo:Cyber Orb 。如下所示:
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")}} 以呈现游戏。您可以在您最喜爱的浏览器中打开index文件以启动并尝试游戏。目录中还有三个文件夹:
+您可以在您最喜爱的浏览器中打开 index 文件以启动并尝试游戏。目录中还有三个文件夹:
- -
img
: 我们将在游戏中使用的所有图片。- +
src
:定义了游戏中所有源代码的 JavaScript文件。src
:定义了游戏中所有源代码的 JavaScript 文件。audio:
在游戏中使用的声音文件。