Selaa lähdekoodia

Chinese Edition Updated (#115)

* 3rd edition

* catch up with
54bcb066 Björn Ritzl <[email protected]> on 2020/4/16 at 14:15

* catch up with
dc618151 Björn Ritzl <[email protected]> on 2020/6/17 at 15:32

* 7 files left
CocosGames 5 vuotta sitten
vanhempi
commit
a6ad9a6735
100 muutettua tiedostoa jossa 2152 lisäystä ja 3683 poistoa
  1. 117 118
      docs/zh/faq/faq.md
  2. 3 18
      docs/zh/manuals/addressing.md
  3. 27 27
      docs/zh/manuals/ads.md
  4. 12 3
      docs/zh/manuals/android.md
  5. 1 1
      docs/zh/manuals/bob.md
  6. 2 1
      docs/zh/manuals/components.md
  7. 32 32
      docs/zh/manuals/debugging-game-and-system-logs.md
  8. 47 47
      docs/zh/manuals/debugging-game-logic.md
  9. 27 28
      docs/zh/manuals/debugging-native-code-android.md
  10. 42 42
      docs/zh/manuals/debugging-native-code-ios.md
  11. 57 61
      docs/zh/manuals/debugging-native-code.md
  12. 4 172
      docs/zh/manuals/debugging.md
  13. 2 4
      docs/zh/manuals/extension-facebook.md
  14. 202 0
      docs/zh/manuals/extension-iap.md
  15. 295 0
      docs/zh/manuals/extension-push.md
  16. 7 0
      docs/zh/manuals/extension-websocket.md
  17. 259 0
      docs/zh/manuals/extension-webview.md
  18. 2 132
      docs/zh/manuals/extensions-debugging-ios.md
  19. 4 4
      docs/zh/manuals/extensions-debugging.md
  20. 5 1
      docs/zh/manuals/extensions-details.md
  21. 97 105
      docs/zh/manuals/extensions.md
  22. 1 1
      docs/zh/manuals/facebook.md
  23. 32 0
      docs/zh/manuals/factory.md
  24. 28 32
      docs/zh/manuals/file-access.md
  25. 16 20
      docs/zh/manuals/getting-help.md
  26. 45 45
      docs/zh/manuals/glossary.md
  27. 3 4
      docs/zh/manuals/gpgs.md
  28. 6 0
      docs/zh/manuals/gui-box.md
  29. 33 33
      docs/zh/manuals/gui-layouts.md
  30. 2 2
      docs/zh/manuals/gui.md
  31. 6 2
      docs/zh/manuals/html5.md
  32. 15 15
      docs/zh/manuals/http-requests.md
  33. 2 198
      docs/zh/manuals/iap.md
  34. 6 4
      docs/zh/manuals/input.md
  35. 1 1
      docs/zh/manuals/instant-games.md
  36. 45 7
      docs/zh/manuals/ios.md
  37. 4 0
      docs/zh/manuals/label.md
  38. 9 8
      docs/zh/manuals/linux.md
  39. 8 2
      docs/zh/manuals/live-update.md
  40. 10 2
      docs/zh/manuals/lua.md
  41. 32 32
      docs/zh/manuals/macos.md
  42. 38 32
      docs/zh/manuals/material.md
  43. 20 13
      docs/zh/manuals/mesh.md
  44. 6 0
      docs/zh/manuals/message-passing.md
  45. 3 3
      docs/zh/manuals/model.md
  46. 1 1
      docs/zh/manuals/models.md
  47. 7 57
      docs/zh/manuals/networking.md
  48. 20 20
      docs/zh/manuals/nintendo-switch.md
  49. 17 17
      docs/zh/manuals/online-services.md
  50. 3 0
      docs/zh/manuals/optimization.md
  51. 4 0
      docs/zh/manuals/particlefx.md
  52. 42 23
      docs/zh/manuals/physics.md
  53. 226 223
      docs/zh/manuals/project-settings.md
  54. 1 290
      docs/zh/manuals/push.md
  55. 106 107
      docs/zh/manuals/render.md
  56. 19 2
      docs/zh/manuals/script.md
  57. 1 1
      docs/zh/manuals/shader.md
  58. 7 7
      docs/zh/manuals/socket-connections.md
  59. 4 0
      docs/zh/manuals/sound.md
  60. 1 1
      docs/zh/manuals/spine.md
  61. 7 3
      docs/zh/manuals/spinemodel.md
  62. 7 3
      docs/zh/manuals/sprite.md
  63. 3 3
      docs/zh/manuals/texture-profiles.md
  64. 7 3
      docs/zh/manuals/tilemap.md
  65. 36 36
      docs/zh/manuals/web-monetization.md
  66. 3 5
      docs/zh/manuals/websocket-connections.md
  67. 2 305
      docs/zh/manuals/webview.md
  68. 2 2
      docs/zh/manuals/windows.md
  69. 1 1
      docs/zh/manuals/working-offline.md
  70. 3 6
      docs/zh/shared/blend-modes.md
  71. 1 1
      docs/zh/shared/install.md
  72. 6 0
      docs/zh/shared/material-constants.md
  73. 0 393
      docs/zh/tutorials/15-puzzle.md
  74. 0 27
      docs/zh/tutorials/astronaut.md
  75. 0 226
      docs/zh/tutorials/car.md
  76. 0 28
      docs/zh/tutorials/colorslide.md
  77. 0 35
      docs/zh/tutorials/getting-started.md
  78. 0 460
      docs/zh/tutorials/grading.md
  79. 0 145
      docs/zh/tutorials/hud.md
  80. BIN
      docs/zh/tutorials/images/15-puzzle/display_settings.png
  81. BIN
      docs/zh/tutorials/images/15-puzzle/input.png
  82. BIN
      docs/zh/tutorials/images/15-puzzle/main_collection.png
  83. BIN
      docs/zh/tutorials/images/15-puzzle/monalisa.png
  84. BIN
      docs/zh/tutorials/images/15-puzzle/slide.png
  85. BIN
      docs/zh/tutorials/images/15-puzzle/tilemap.png
  86. BIN
      docs/zh/tutorials/images/15-puzzle/tilesource.png
  87. BIN
      docs/zh/tutorials/images/car/start_add_car_component.png
  88. BIN
      docs/zh/tutorials/images/car/start_add_car_gameobject.png
  89. BIN
      docs/zh/tutorials/images/car/start_adding_car_collection.png
  90. BIN
      docs/zh/tutorials/images/car/start_build_and_launch.png
  91. BIN
      docs/zh/tutorials/images/car/start_car.png
  92. BIN
      docs/zh/tutorials/images/car/start_car_collection_complete.png
  93. BIN
      docs/zh/tutorials/images/car/start_delete_go.png
  94. BIN
      docs/zh/tutorials/images/car/start_input_bindings.png
  95. BIN
      docs/zh/tutorials/images/car/start_new_collection.png
  96. BIN
      docs/zh/tutorials/images/car/start_sprite_properties.png
  97. BIN
      docs/zh/tutorials/images/car/start_sprites_atlas.png
  98. BIN
      docs/zh/tutorials/images/car/start_tire.png
  99. BIN
      docs/zh/tutorials/images/getting-started/new-project.png
  100. BIN
      docs/zh/tutorials/images/getting-started/[email protected]

+ 117 - 118
docs/zh/faq/faq.md

@@ -1,189 +1,188 @@
 ---
-title: Defold engine and editor FAQ
-brief: Frequently asked questions about the Defold game engine, editor and platform.
+title: Defold 引擎与编辑器常见问题和解答
+brief:有关 Defold 游戏引擎和编辑器及平台的常见问题和解答.
 ---
 
-# Frequently asked questions
+# 常见问题
 
-## General questions
+## 一般常见
 
-#### Q: Is Defold really free?
+#### 问: Defold 真的免费吗?
 
-A: Yes, the Defold engine and editor with full functionality is completely free of charge. No hidden costs, fees or royalties. Just free.
+答: 对, Defold 引擎与编辑器和所有功能完全免费. 没有暗扣费, 手续费和使用权费用. 完全免费.
 
 
-#### Q: Why on earth would the Defold Foundation give Defold away?
+#### 问: Defold 基金会为什么开发并免费提供 Defold?
 
-A: One of the objectives of the [Defold Foundation](/foundation) is to make sure that the Defold software is available to developers world-wide and that the source code is available free of charge.
+答: [Defold 基金会](/foundation) 的一大目标就是让 Defold 软件能够被世界上所有开发者免费使用并且源码也是公开免费的.
 
 
-#### Q: How long will you support Defold?
+#### 问: Defold 能持续维护多久?
 
-A: We are deeply committed to Defold. The [Defold Foundation](/foundation) has been set up in such a way that it is guaranteed to exist as a responsible owner for Defold for many years to come. It is not going away.
+答: 我们承诺维护 Defold. [Defold 基金会](/foundation) 的成立就是为了保证 Defold 能够被持续维护. 我们不会放弃.
 
 
-#### Q: Can I trust Defold for professional development?
+#### 问: 专业开发的话 Defold 值得信赖吗?
 
-A: Absolutely. Defold is used by a growing number of professional game developers and game studios. Check out the [games showcase](/showcase) for examples of games created using Defold.
+答: 必须值得信赖. Defold 已被越来越多的职业开发者和工作室所采用. 可以参考位于 [游戏展示页](/showcase) 上的用 Defold 开发的各种样例.
 
 
-#### Q: What kind of user tracking are you doing?
+#### 问: 你们做了什么样的用户跟踪?
 
-A: We log anonymous usage data from our websites and the Defold editor in order to improve our services and product. There is no user tracking in the games you create (unless you add an analytics service yourself). Read more about this in our [Privacy Policy](/privacy-policy).
+答: 我们的网站和 Defold 编辑器会使用匿名回报一些数据用以提升我们的服务和产品质量. 你编译出版的游戏里不带任何用户跟踪 (除非你自己加入分析服务功能). 详情请见我们的 [隐私政策](/privacy-policy).
 
 
-#### Q: Who made Defold?
+#### 问: 谁制作了 Defold?
 
-A: Defold was created by Ragnar Svensson and Christian Murray. They started working on the engine, editor and servers in 2009. King and Defold started a partnership in 2013 and King acquired Defold in 2014. Read the full story [here](/about).
+答: Defold 由 Ragnar Svensson 和 Christian Murray 开发. 他们从2009年就开始了游戏引擎, 编辑器和配套服务的开发. King 和 Defold 在2013年建立了合作关系然后并于2014年获得 Defold. 详情请见 [这里](/about).
 
 
-## Platform questions
+## 平台相关
 
-#### Q: What platforms does Defold run on?
+#### 问: Defold 可以运行在哪些平台上?
 
-A: The following platforms are supported for the editor/tools and the engine runtime:
+答: 下表列出了编辑器工具与游戏引擎运行环境的支持情况:
 
-  | System                     | Supported            |
+  | 系统                        | 支持                  |
   | -------------------------- | -------------------- |
-  | macOS 10.7 Lion            | Editor and runtime   |
-  | Windows Vista              | Editor and runtime   |
-  | Ubuntu 18.04 (64 bit)(1)   | Editor               |
-  | Linux (64 bit)(2)          | Runtime              |
-  | iOS 8.0                    | Runtime              |
-  | Android 4.1 (API level 16) | Runtime              |
-  | HTML5                      | Runtime              |
+  | macOS 10.7 Lion            | 编辑器与游戏引擎        |
+  | Windows Vista              | 编辑器与游戏引擎        |
+  | Ubuntu 18.04 (64 bit)(1)   | 编辑器                |
+  | Linux (64 bit)(2)          | 游戏引擎              |
+  | iOS 8.0                    | 游戏引擎              |
+  | Android 4.1 (API level 16) | 游戏引擎              |
+  | HTML5                      | 游戏引擎              |
 
-  (1 The editor is built and tested for 64-bit Ubuntu 18.04. It should work on other distributions as well but we give no guarantees.)
+  (1 编辑器在 64-bit Ubuntu 18.04 平台上通过编译和测试. 其他版本应该同样可以运行但是未经过测试.)
 
-  (2 The engine runtime should run on most 64-bit Linux distributions as long as graphics drivers are up to date and supporting OpenGL ES 2.0.)
+  (2 游戏引擎在大多数 64-bit Linux 版本上只要更新显卡驱动支持 OpenGL ES 2.0 的基本都能运行.)
 
 
-#### Q: What are the system requirements for the editor
+#### 问: 运行编辑器需要什么硬件系统?
 
-A: The editor will use up to 75% of the available memory of the system. On a computer with 4 GB of RAM this should be enough for smaller Defold projects. For mid-sized or large projects it is recommended to use 6 GB or more of RAM.
+答: 编辑器最多占用 75% 的空闲系统内存. 一般 4 GB 内存的电脑就可以运行 Defold 小项目了. 中大型项目建议配备 6 GB 或更多内存.
 
 
-#### Q: What target platforms can I develop games for with Defold?
+#### 问: Defold 能输出哪些平台的游戏?
 
-A: With one click you can publish to Nintendo Switch, iOS, Android and HTML5 as well as macOS/OS X, Windows and Linux. It’s truly one codebase with multiple supported platforms.
+答: 可以一键发布 任天堂 Switch, iOS, Android 和 HTML5 游戏, 外加 macOS/OS X, Windows 和 Linux 游戏. 真正的一套代码平台通用.
 
 
-#### Q: What rendering API does Defold rely on?
+#### 问: Defold 基于何种渲染引擎?
 
-A: Defold uses OpenGL ES 2.0 for graphics rendering, which is available on all our supported platforms.
+A: Defold 使用 OpenGL ES 2.0 进行图像渲染, 全平台有效. (如果平台渲染引擎更新, Defold引擎也会随之更新)
 
 
-#### Q: Can I do 3D games in Defold?
+#### 问: Defold 能做 3D 游戏吗?
 
-A: Absolutely! The engine is a full blown 3D engine. However, the toolset is made for 2D so you will have to do a lot of heavy lifting yourself. Better 3D support is planned.
+答: 可以! 游戏引擎纯 3D. 然而, 工具都是针对 2D 游戏设计的, 所以 3D 游戏工具你得自己开发. 提升 3D 支持的计划进行中.
 
 
-#### Q: What programming language do I work with in Defold?
+#### 问: Defold 游戏开发用什么语言?
 
-A: Game logic in your Defold project is primarily written using the Lua language (specifically Lua 5.1/LuaJIT, refer to the [Lua manual](/manuals/lua) for details). Lua is a lightweight dynamic language that is fast and very powerful. You can also use native code (C/C++, Objective-C, Java and JavaScript depending on the platform) to extend the Defold engine with new functionality. When building custom materials, OpenGL ES SL shader language is used to write vertex and fragment
-shaders.
+答: Defold 项目游戏逻辑基本使用 Lua 语言 (特指 Lua 5.1/LuaJIT, 详情请见 [Lua 教程](/manuals/lua)). Lua 是一种强大快速的动态语言. 同时也支持使用原生 (C/C++, Objective-C, Java 和 JavaScript等) 语言来扩展 Defold 引擎功能. 自定义材质, 使用 OpenGL ES SL 语言编写的顶点和片元着色程序.
 
 
-#### Q: Is there a way to know what version I'm running?
+#### 问: 如何获取 Defold 版本信息?
 
-A: Yes, select the "About" option in the Help menu. The popup clearly shows Defold beta version and, more importantly, the specific release SHA1. For runtime version lookup, use [`sys.get_engine_info()`](/ref/sys/#sys.get_engine_info).
+答: 点击菜单栏 "About" 项. 弹出窗口详细列出了 Defold 版本号, 和文件哈希 SHA1. 对于游戏引擎版本, 调用 [`sys.get_engine_info()`](/ref/sys/#sys.get_engine_info) 获取.
 
-The latest beta version available for download from http://d.defold.com/beta can be checked by opening http://d.defold.com/beta/info.json (the same file exists for stable versions as well: http://d.defold.com/stable/info.json)
+最新测试版位于 http://d.defold.com/beta 可以查看 http://d.defold.com/beta/info.json (正式版同样也有: http://d.defold.com/stable/info.json) 文件获取最新版本信息.
 
 
-#### Q: Is there a way to know what platform the game is running on at runtime?
+#### 问: 运行时如何获取系统信息?
 
-A: Yes, check out [`sys.get_sys_info()`](/ref/sys#sys.get_sys_info).
+答: 调用 [`sys.get_sys_info()`](/ref/sys#sys.get_sys_info) 获取.
 
 
-#### Q: Are Defold beta versions auto-updating?
+#### 问: Defold 测试版会自动更新吗?
 
-A: Yes. The Defold beta editor checks for an update at startup, just like the Defold stable version does.
+答: Defold 测试版编辑器会在启动时检查并自动更新, 正式版也是.
 
 
-## Publishing games
+## 发布相关
 
-#### Q: I'm trying to publish my game to AppStore. How should I respond to IDFA?
+#### 问: 我想把游戏发布到 AppStore. 如何设置 IDFA?
 
-A: When submitting, Apple has three checkboxes for their three valid use cases for the IDFA:
+答: 提交游戏时, Apple 为广告商提供了3种 IDFA 用例:
 
-  1. Serve ads within the app
-  2. Install attribution from ads
-  3. User action attribution from ads
+  1. 应用内展示广告
+  2. 用广告提升安装量
+  3. 用广告提升点击量
 
-  If you check option 1, the app reviewer will look for ads to show up in the app. If your game does not show ads, the game might get rejected. Defold itself doesn't use AD id.
+  如果选择第一个, 编辑会在你的游戏里找广告. 如果没找到, 游戏很可能会被拒. Defold 本身不使用广告商id.
 
 
-#### Q: How do I monetize my game?
+#### 问: 怎么用游戏获利?
 
-A: Defold has support for in-app purchases and various advertising solutions. Check the [Monetization category in the Asset Portal](https://defold.com/tags/stars/monetization/) for an up to date list of available monetization options.
+答: Defold 支持游戏内付费和多种广告服务. 最新相关信息详见 [资源中心的盈利类目](https://defold.com/tags/stars/monetization/).
 
 
-## Errors using Defold
+## Defold 报错
 
-#### Q: Why doesn't the editor start or open my project?
+#### 问: 编辑器不启动, 项目不加载?
 
-A: Check if there are spaces in the path leading up to the Defold application. For instance, if you put the folder *Defold-macosx* containing the OSX version of the editor in your *Applications* folder, then you should be ok.  If you rename the folder *Defold macosx* the editor might not start anymore. On Windows, putting Defold under *C:\\Program Files\\* can trigger this problem. This is due to a known bug in the underlying Eclipse framework.
+答: 检查 Defold 安装路径里是否有空格. 比如, 把编辑器放在mac系统 *Applications* 中的 *Defold-macosx* 文件夹里, 就能运行.  改成 *Defold macosx* 就无法运行. 在 Windows 上, 像 *C:\\Program Files\\* 这样的路径都不行. 这归因于系统架构的一个bug.
 
 
-#### Q: I can't start the game and there is no build error. What's wrong?
+#### 问: 游戏无法启动也没有报错. 怎么办?
 
-A: The build process can fail to rebuild files in rare cases where it have previously encountered build errors that you have fixed. Force a full rebuild by selecting *Project > Rebuild And Launch* from the menu.
+答: 如果二次编译不通过很肯能由你最后做的改动导致. 从菜单栏选择 *Project > Rebuild And Launch* 试试.
 
 
-#### Q: Why am I getting a java exception when I try to start Defold?
+#### 问: 启动 Defold 时报了 Java 相关的错?
 
-A: `javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target`
+: `javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target`
 
-This exception occurs when the editor tries to make an https connection but the certificate chain provided by the server cannot be verified.
+这个错是由于编辑器尝试建立 https 连接而服务器证书无法验证导致.
 
-See [this link](https://github.com/defold/editor2-issues/blob/master/faq/pkixpathbuilding.md) for details on this error.
+详情请见 [这里](https://github.com/defold/editor2-issues/blob/master/faq/pkixpathbuilding.md).
 
 
 ## Linux
-:[Linux FAQ](../shared/linux-faq.md)
+:[Linux 问答](../shared/linux-faq.md)
 
 
 ## Android
-:[Android FAQ](../shared/android-faq.md)
+:[Android 问答](../shared/android-faq.md)
 
 
 ## HTML5
-:[HTML5 FAQ](../shared/html5-faq.md)
+:[HTML5 问答](../shared/html5-faq.md)
 
 
 ## Windows
-:[Windows FAQ](../shared/windows-faq.md)
+:[Windows 问答](../shared/windows-faq.md)
 
 ## Nintendo Switch
-:[Nintendo Switch FAQ](../shared/nintendo-switch-faq.md)
+:[Nintendo Switch 问答](../shared/nintendo-switch-faq.md)
 
 
-## Game content
+## 游戏内容相关
 
-#### Q: Does Defold support prefabs?
+#### 问: Defold 里有 prefab 吗?
 
-A: Yes, it does. They are called [collections](/manuals/building-blocks/#collections). They allow you to create complex game object hierarchies and store those as a separate building blocks that you can instance in the editor or at runtime (through collection spawning). For GUI nodes there is support for GUI templates.
+答: 有. Defold 里叫 [集合](/manuals/building-blocks/#collections). 它能帮助建立储存游戏内容为树形结构以便在编辑器或者游戏运行时创建实例. 对于 GUI 节点类似结构称为 GUI 模板.
 
 
-#### Q: I can't add a game object as a child to another game object, why?
+#### 问: 为什么我不能在游戏对象下建立子游戏对象?
 
-A: Chances are that you try to add a child in the game object file and that is not possible. To understand why, you have to remember that parent-child hierarchies are strictly a _scene-graph_ transform hierarchy. A game object that has not been placed (or spawned) into a scene (collection) is not part of a scene-graph and can't therefore be part of a scene-graph hierarchy.
+答: 有一种可能是因为父级游戏对象是一个文件引用. 对于父子结构的游戏对象来说它们的位移关系通过 _场景结构_ 表达. 没有被加入到场景里的游戏对象无法于其他对象建立父子关系.
 
 
-#### Q: Why can't I broadcast messages to all children of a game object?
+#### 问: 为什么我不能在所有子游戏对象间广播消息?
 
-A: Parent-child relations express nothing else than the scene-graph transform relations and should not be mistaken for object orientation aggregates. If you try to focus on your game data and how to best transform it as your game alter its state you will likely find less need to send messages with state data to many objects all the time. In the cases where you will need data hierarchies, these are easily constructed and handled in Lua.
+答: 父子关系除了场景结构中表现相对位移以外别无其他特别之处. 如果需要跟踪子对象状态无需时刻向所有子对象发送消息. 这种情况下你需要使用 Lua 编写数据结构.
 
 
-#### Q: Why am I experiencing visual artifacts around the edges of my sprites?
+#### 问: 精灵对象周围出现黑白边?
 
-A: That is a visual artifact called "edge bleeding" where the edge pixels of neighboring pixels in an atlas bleed into the image assigned to your sprite. The solution is to pad the edge of your atlas images with extra row(s) and column(s) of identical pixels. Luckily this can be done automatically by the atlas editor in Defold. Open your atlas and set the *Extrude Borders* value to 1.
+答: 这被称作 "边缘出血" 现象, 渲染精灵对象的时候把纹理旁边的一些像素也加入进来了. 解决办法是用纹理边缘的像素再扩充一圈. 好在 Defold 编辑器有工具能自动做这件事. 尝试打开图集并且设置 *Extrude Borders* 的值为 1.
 
 
-#### Q: Can I tint my sprites or make them transparent, or do I have to write my own shader for it?
+#### 问: 精灵变色, 透明效果如何制作?
 
-A: The built-in sprite shader that is used by default for all sprites has a constant "tint" defined:
+A: 精灵默认着色程序包含 "tint" 属性:
 
   ```lua
   local red = 1
@@ -194,93 +193,93 @@ A: The built-in sprite shader that is used by default for all sprites has a cons
   ```
 
 
-#### Q: If I set the z coordinate of a sprite to 100 then it's not rendered. Why?
+#### 问: 为什么游戏对象的z值设为100就看不见了?
 
-A: The Z-position of a game object controls rendering order. Low values are drawn before higher values. In the default render script game objects with a depth ranging between -1 and 1 are drawn, anything lower or higher will not be drawn. You can read more about the rendering script in the official [Render documentation](/manuals/render). On GUI nodes the Z value is ignored and does not affect rendering order at all. Instead nodes are rendered in the order they are listed and according to child hierarchies (and layering). Read more about gui rendering and draw call optimization using layers in the official [GUI documentation](/manuals/gui).
+答: z值表示深度方向的遮挡关系. z值小的位于z值大的游戏对象前面. 默认渲染程序的z值范围是 -1 到 1, 此范围之外的不被渲染. 关于渲染脚本详情请见 [渲染教程](/manuals/render). 对于 GUI 节点来说z值毫无作用. 节点的遮挡顺序取决于树形结构 (以及层次设置). 关于用户界面节点的渲染详情请见 [GUI 教程](/manuals/gui).
 
 
-#### Q: Would changing the view projection Z-range to -100 to 100 impact performance?
+#### 问: 要是把视口深度范围设为 -100 到 100 会影响性能吗?
 
-A: No. The only effect is precision. The z-buffer is logarithmic and have very fine resolution of z values close to 0 and less resolution far away from 0. For instance, with a 24 bit buffer the values 10.0 and 10.000005 can be differentiated whereas 10000 and 10005 cannot.
+答: 不影响性能但是影响精度. z缓存是一种对数结构靠近 0 差别明显, 远离 0 差别不明显. 比如说, 用 24 位缓存 10.0 对比 10.000005 区别明显但是 10000 对比 10005 区别不明显.
 
 
-#### Q: There is no consistency to how angles are represented, why?
+#### 问: 角度的单位为什么不一致?
 
-A: Actually there is consistency. Angles are expressed as degrees everywhere in the editor and the game APIs. The math libs use radians. Currently the convention breaks for the `angular_velocity` physics property that is currently expressed as radians/s. That is expected to change.
+答: 实际上一致. 编辑器和游戏API使用角度制. 数学计算库使用弧度制. 目前对于物理 `angular_velocity` 是个例外使用了弧度制. 以后可能会矫正.
 
 
-#### Q: When creating a GUI box-node with only color (no texture), how will it be rendered?
+#### 问: 只有颜色没有纹理的GUI节点如何渲染?
 
-A: It is just a vertex colored shape. Bear in mind that it will still cost fill-rate.
+答: 作为顶点着色形状渲染, 注意其性能消耗.
 
 
-#### Q: If I change assets on the fly, will the engine automatically unload them?
+#### 问: 如何释放资源所占用的内存?
 
-A: All resources are ref-counted internally. As soon as the ref-count is zero the resource is released.
+答: 引擎对所有资源都有引用计数. 一旦引用为0则资源自动被释放.
 
 
-#### Q: Is it possible to play audio without the use of an audio component attached to a game object?
+#### 问: 不用游戏对象能播放声音吗?
 
-A: Everything is component-based. It's possible to create a headless game object with multiple sounds and play sounds by sending messages to the sound-controller object.
+答: 游戏引擎设计模式基于组件. 可以建立一个不可见游戏对象把声音组件放入然后需要播放时给它发消息即可.
 
 
-#### Q: Is it possible to change the audio file associated with an audio component at run time?
+#### 问: 运行时声音组件播放的声音文件能更改吗?
 
-A: In general all resources are statically declared with the benefit that you get resource management for free. You can use [resource properties](/manuals/script-properties/#resource-properties) to change which resource that is assigned to a component.
+答: 一般资源都是静态声明随意管理的. 可以使用 [资源属性](/manuals/script-properties/#resource-properties) 来修改与组件关联的资源.
 
 
-#### Q: Is there a way to access the physics collision shape properties?
+#### 问: 存取物理碰撞形状属性的方法?
 
-A: No, it is currently not possible.
+答: 目前尚未支持.
 
 
-#### Q: Is there any quick way to render the collision objects in my scene? (like Box2D's debugdraw)
+#### 问: 有办法快速渲染物理碰撞对象吗? (就像 Box2D 的 debugdraw 那样)
 
-A: Yes, set *physics.debug* flag in *game.project*. (Refer to the official [Project settings documentation](/manuals/project-settings/#debug))
+答: 有, 要在 *game.project* 里设置 *physics.debug* 项. (参见 [项目设置教程](/manuals/project-settings/#debug))
 
 
-#### Q: What are the performance costs of having many contacts/collisions?
+#### 问: 许多物理碰撞的主要性能消耗在哪里?
 
-A: Defold runs a modified version of Box2D in the background and the performance cost should be quite similar. You can always see how much time the engine spends on physics by bringing up the [profiler](/manuals/debugging). You should also consider what kind of collisions objects you use. Static objects are cheaper performance wise for instance. Refer to the official [Physics documentation](/manuals/physics) in Defold for more details.
+答: Defold 包含的是 Box2D 略微修改版本, 所以性能应该和原版差不多. 可以使用 [调试器](/manuals/debugging) 跟踪物理碰撞数量. 确保用对碰撞对象. 比如静态碰撞对象性能高些. 详情请见 Defold 的 [物理教程](/manuals/physics).
 
 
-#### Q: What's the performance impact of having many particle effect components?
+#### 问: 如果有许多粒子效果, 对性能影响大不大?
 
-A: It depends on if they are playing or not. A ParticleFx that isn't playing have zero performance cost. The performance implication of a playing ParticleFx must be evaluated using the profiler since its impact depends on how it is configured. As with most other things the memory is allocated up front for the number of ParticleFx defined as max_count in game.project.
+答: 这取决于粒子效果是否正在播放. 没有播放的粒子效果不消耗性能. 播放中的粒子效果性能消耗取决于其配置情况, 可以用调试器来观察. 粒子效果的内存消耗基本上取决于项目设置的 max_count 数.
 
 
-#### Q: How do I receive input to a game object inside a collection loaded via a collection proxy?
+#### 问: 如何得到集合代理加载的集合里的游戏对象的输入信息?
 
-A: Each proxy loaded collection has their own input stack. Input is routed from the main collection input stack via the proxy component to the objects in the collection. This means that it's not enough for the game object in the loaded collection to acquire input focus, the game object that _holds_ the proxy component need to acquire input focus as well. See the [Input documentation](/manuals/input) for details.
+答: 每个集合都有自己的输入栈. 输入从主集合通过代理组件传递到被载入集合里的游戏对象. 换句话说仅游戏对象获得输入焦点是不够的, 那个代理组件 _所在的_ 游戏对象同样需要获得输入焦点. 详情请见 [输入教程](/manuals/input).
 
 
-#### Q: Can I use string type script properties?
+#### 问: 脚本属性有字符串类型的吗?
 
-A: No. Defold supports properties of [hash](/ref/builtins#hash) types. These can be used to indicate types, state identifiers or keys of any kind. Hashes can also be used to store game object id's (paths) although [url](/ref/msg#msg.url) properties are often preferable since the editor automatically populate a drop-down with relevant URLs for you. See the [Script properties documentation](/manuals/script-properties) for details.
+答: 没有. Defold 只有 [哈希](/ref/builtins#hash) 类型的脚本属性. 用来表示枚举, 表示状态, 表示各种类型都没问题. 而且游戏对象的 id (路径) 也是用其 [url](/ref/msg#msg.url) 属性的哈希来保存, 遇到这样的属性时编辑器会自动建立相关路径弹框供你选择. 详情请见 [脚本属性教程](/manuals/script-properties).
 
 
-#### Q: How do I access the individual cells of a matrix (created using [vmath.matrix4()](/ref/vmath/#vmath.matrix4:m1) or similar)?
+#### 问: 如何存取矩阵 (使用 [vmath.matrix4()](/ref/vmath/#vmath.matrix4:m1) 之类的函数生成的) 内部数据?
 
-A: You access the cells using `mymatrix.m11`, `mymatrix.m12`, `mymatrix.m21` etc
+答: 使用 `mymatrix.m11`, `mymatrix.m12`, `mymatrix.m21` 之类的属性可以访问内部数据.
 
 
-#### Q: I am getting `Not enough resources to clone the node` when using [gui.clone()](/ref/gui/#gui.clone:node) or [gui.clone_tree()](/ref/gui/#gui.clone_tree:node)
+#### 问: 使用 [gui.clone()](/ref/gui/#gui.clone:node) 或 [gui.clone_tree()](/ref/gui/#gui.clone_tree:node) 时报 `Not enough resources to clone the node` 的错误信息?
 
-A: Increase the `Max Nodes` value of the gui component. You find this value in the Properties panel when selecting the root of the component in the Outline.
+答: 增加gui组件的 `Max Nodes` 值. 在大纲视图gui根节点的属性面板上就能看到.
 
 
-## The forum
+## 论坛相关
 
-#### Q: Can I post a thread where I advertise my work?
+#### 问: 我能在论坛上打广告吗?
 
-A: Of course! We have a special ["Work for hire" category](https://forum.defold.com/c/work-for-hire) for that. We will always encourage everything which benefits the community, and offering your services to the community---for remuneration or not---is a good example of that.
+答: 可以! 论坛有一个 ["Work for hire" 类目](https://forum.defold.com/c/work-for-hire). 能充实社区论坛的所有信息都欢迎, 这里可以发布求职广告.
 
 
-#### Q: I made a thread and added my work—can I add more?
+#### 问: 可以无限打广告?
 
-A: In order to reduce bumping of "Work for hire" threads, you may not post more than once per 14 days in your own thread (unless it’s a direct reply to a comment in the thread, in which case you may reply). If you want to add additional work to your thread within the 14-day period, you must edit your existing posts with your added content.
+答: 为避免 "Work for hire" 类目论坛被爆, 至少14天内不许再加广告 (除非有人回复找你, 此时你可以立即回复这个人). 14天内, 只能通过更新帖子的方式加入新内容.
 
 
-#### Q: Can I use the Work for Hire category to post job offerings?
+#### 问: 我能发布招聘广告吗?
 
-A: Sure, knock yourselves out! It can be used for offerings as well as requests, e.g. “Programmer looking for 2D pixel artist; I’m rich and I’ll pay you well”.
+答: 可以, 自己找! 招聘也行求职也行, 比如 “程序员找美工; 高价求不差钱”.

+ 3 - 18
docs/zh/manuals/addressing.md

@@ -109,26 +109,11 @@ id可以随意设置. 当前我们对游戏对象设置了一个id "bean", sprit
 
 实际上相对地址在后台已经把上下文考虑在内. 这同样很方便因为你可以用同样的代码创建很多个集合的实例.
 
-简化符
-: Defold 支持如下相对地址简化符:
+### 简化符
 
-  `.`
-  : 代表本游戏对象.
+Defold 提供两种简化写法用来简化消息传递时需要输入的完整地址:
 
-  `#`
-  : 代表本组件.
-
-  举例:
-
-  ```lua
-   -- Let this game object acquire input focus
-   msg.post(".", "acquire_input_focus")
-  ```
-
-  ```lua
-   -- Post "reset" to the current script
-   msg.post("#", "reset")
-  ```
+:[Shorthands](../shared/url-shorthands.md)
 
 ## 游戏对象路径
 

+ 27 - 27
docs/zh/manuals/ads.md

@@ -5,57 +5,57 @@ brief: 广告是网页游戏和手机游戏的基本盈利方式. 本教程介
 
 # 广告
 
-Ads has become a very common way of monetizing web and mobile games and it has turned into a billion dollar industry. As a developer you get paid based on the number of people watching the ads you show in your game. It is usually as simple as more viewers equals more money, but other factors also have an impact on how much you get paid:
+广告作为网页游戏和手机游戏的一种普遍盈利方式日趋壮大. 玩家观看游戏里的广告, 开发者有机会获利. 一般看的越多获利越多, 但是最终受益还要取决于下面几项:
 
-* The ad quality - relevant ads are more likely to get interaction and attention from your players.
-* The ad format - banner ads usually pay less while full screen ads viewed from start to to finish pays more.
-* The ad network - the amount you get paid varies from ad networks to ad network.
+* 广告质量 - 游戏内容相关的广告容易获得玩家点击与关注.
+* 广告类型 - 广告条的利润低而从头看到尾的全屏广告利润高.
+* 广告商 - 不同广告供应商的广告利润有高有低.
 
-::: sidenote
-CPM = Cost per mille. The amount an advertiser pays per one thousand views. The CPM varies between ad networks and ad formats.
+::: 注意
+CPM = 千人成本. 广告商为一千个浏览量支付的报酬. 不同广告商不同广告类型费用也不同.
 :::
 
-## Formats
+## 类型
 
-There are many different kinds of ad formats that can be used in games. Some of the more common ones are banner, interstitial and reward ads:
+游戏中可以放各种广告. 常见的有广告条, 插播广告和奖励广告:
 
-### Banner ads
+### 广告条
 
-Banner ads are text, image or video based and cover a relatively small part of the screen, usually at the top or bottom of the screen. Banner ads are very easy to implement and they fit very well with casual single screen games where it is easy to reserve an area of the screen for advertisements. Banner ads maximize exposure as users play your game without interruption.
+广告条可以是文字的, 图片的或者视频的并且占据一部分屏幕, 一般不是屏幕上边就是底边. 广告条很容易植入, 休闲小游戏也容易空出广告条的位置来. 曝光率高, 玩家反感较少.
 
-### Interstitial ads
+### 插播广告
 
-Interstitial ads are large full screen experiences with animations and sometimes also interactive rich media content. Interstitial ads are typically shown in between levels or game sessions as it is a natural break in the game experience. Interstitial ads typically generate less views than banner ads, but the cost (CPM) is much higher than for banner ads, resulting in significant overall ad revenue.
+插播广告是一种带动画有的还有多媒体交互的全屏广告. 插播广告通常出现在游戏关与关之间或者游戏暂停等时候. 插播广告曝光不高, 但是付费较高, 可以带来不菲收入.
 
-### Rewarded ads
+### 奖励广告
 
-Rewarded ads (also know as Incentivized ads) are optional and therefore less obtrusive than many other forms of ads. Rewarded ads are usually full screen experiences like interstitial ads. The user can choose a reward in exchange for viewing the ad - for instance loot, coins, lives, time or some other in-game currency or benefit. Rewarded ads usually has the highest cost (CPM), but the number of views is directly related to user opt-in rates. Rewarded ads will only generate great performance if the rewards are valuable enough and offered at the right time.
+奖励广告 (也叫激励广告) 是一种玩家最不反感的广告. 样子通常跟插播广告类似. 玩家可以通过观看广告获得游戏虚拟奖励 - 比如财产, 金币, 命, 游戏延时等等. 奖励广告通常付费最高, 但是观看率取决于玩家. 在关键时刻给予玩家渴望的奖励才能取得激励的效果.
 
 
-## Ad networks
+## 广告商
 
-The [Defold Asset Portal](/tags/stars/ads/) contains several assets which integrate with ad providers:
+在 [Defold 资源中心](/tags/stars/ads/) 提供了一些广告商的支持程序:
 
-* [AdMob](https://defold.com/assets/admob/) - Show ads using the Google ad network.
-* [Enhance](https://defold.com/assets/enhance/) - Supports a number of different ad networks. Requires an additional post-build step.
-* [Facebook Instant Games](https://defold.com/assets/facebookinstantgames/) - Show ads in your Facebook Instant Game.
-* [IronSource](https://defold.com/assets/ironsource/) - Show ads using the IronSource Ad network.
-* [Unity Ads](https://defold.com/assets/defvideoads/) - Show ads using the Unity Ads network.
+* [AdMob](https://defold.com/assets/admob/) - 谷歌广告.
+* [Enhance](https://defold.com/assets/enhance/) - 广告商大集合. 编译后需要额外的安装步骤.
+* [Facebook Instant Games](https://defold.com/assets/facebookinstantgames/) - 脸书广告.
+* [IronSource](https://defold.com/assets/ironsource/) - IronSource 广告.
+* [Unity Ads](https://defold.com/assets/defvideoads/) - Unity 广告.
 
 
-# How to integrate ads in your game
+# 广告游戏整合
 
-When you have decided on an ad network to integrate in your game you need to follow the installation and usage instructions for that particular asset. What you typically do is to first add the extension as a [project dependency](/manuals/libraries/#setting-up-library-dependencies). Once you have the asset added to your project you can proceed with the integration and call the functions specific to the asset to load and show ads.
+决定好合作广告商就可以按步骤地植入广告资源了. 一般都要首先加入 [项目依赖](/manuals/libraries/#setting-up-library-dependencies). 之后载入广告资源, 展示广告内容.
 
 
-# Combining ads and in-app purchases
+# 广告与内支付
 
-It is quite common in mobile games to offer an [In-app purchase](/manuals/iap) to get rid of ads permanently.
+手机游戏通常含有 [应用内支付](/manuals/iap) 功能以便获得更大收益.
 
 
-## Learn more
+## 更多资源
 
-There are many online resources to learn from when it comes to optimizing ad revenue:
+网上也有很多关于优化广告的教程:
 
 * Google AdMob [Monetize mobile games with ads](https://admob.google.com/home/resources/monetize-mobile-game-with-ads/)
 * Game Analytics [Popular ad formats and how to use them](https://gameanalytics.com/blog/popular-mobile-game-ad-formats.html)

+ 12 - 3
docs/zh/manuals/android.md

@@ -32,11 +32,11 @@ keytool -genkey -v -noprompt -dname "CN=John Smith, OU=Area 51, O=US Air Force,
 这个命令会生成一个叫做 `mykeystore.keystore` 的签名, 其中包含了证书和密码. 密匙 `5Up3r_53cR3t` 保护其不备破解. 这个签名有效期为 25 年 (9125 天). 这个签名的id叫做 `myAlias`.
 
 ::: 注意
-要把签名和密匙保存好. 如果要手动上传 Google Play 但是签名密码丢失的话就没办法使用 Google Play 来更新你的应用了. 图省事的话就用 Google Play App Signing 搞定签名.
+要把签名和密匙保存好. 如果要手动上传 Google Play 但是签名密码丢失的话就没办法使用 Google Play 来更新你的应用了. 图省事的话就用 Google Play App Signing 搞定签名.
 :::
 
 
-## 证书和安卓包
+## 安卓应用打
 
 编辑器打包安卓包十分方便. 打包之前可以为应用指定图标, 设置版本号等等, 都在 "game.project" [项目配置文件](/manuals/project-settings/#android) 里设置.
 
@@ -50,12 +50,16 @@ keytool -genkey -v -noprompt -dname "CN=John Smith, OU=Area 51, O=US Air Force,
 
 ![Signing Android bundle](images/android/sign_bundle2.png)
 
+Defold 支持创建 APK 和 AAB 文件. 从打包格式下拉菜单中选择.
+
 点击 <kbd>Create Bundle</kbd> 会提示选择打包文件存放位置.
 
 ![Android Application Package file](images/android/apk_file.png)
 
 ### 安装 Android 应用包
 
+#### 安装 APK
+
 编辑器生成 Android 应用包 *.apk* 文件. 应用包可以通过 `adb` 工具 (见下文), 或者通过 Google Play 的 [Google Play 开发者控制台](https://play.google.com/apps/publish/) 安装到设备上.
 
 ```
@@ -65,6 +69,10 @@ $ adb install Defold\ examples.apk
 Success
 ```
 
+#### Installing an AAB
+
+对于 *.aab* 文件可以通过 [Google Play 开发者控制台](https://play.google.com/apps/publish/) 上传给 Google Play. 也可以使用 *.aab* 文件制作 *.apk* 以便使用 [Android 打包工具](https://developer.android.com/studio/command-line/bundletool) 在本地安装.
+
 ## 权限
 
 Defold 引擎需要一些权限来运行各种功能. 权限在 `AndroidManifest.xml` 文件中定义, 并在 "game.project" [项目配置文件](/manuals/project-settings/#android) 中配置. 关于 Android 权限详见 [官方文档](https://developer.android.com/guide/topics/permissions/overview). 默认配置需要如下权限:
@@ -131,5 +139,6 @@ I/defold  ( 6210):
 D/defold  ( 6210): DEBUG:SCRIPT: Hello there, log!
 ...
 ```
+
 ## 常见问题
-:[Android FAQ](../shared/android-faq.md)
+:[Android 问答](../shared/android-faq.md)

+ 1 - 1
docs/zh/manuals/bob.md

@@ -9,7 +9,7 @@ Bob 是一个用于Defold项目编辑器之外的命令行编译工具.
 
 Bob 用来编译操作 (对应编辑器里的 <kbd>Project ▸ Build</kbd>), 来创建数据档或者创建可独立发布的应用 (对应编辑器里的 <kbd>Project ▸ Bundle ▸ ...</kbd> 选项)
 
-Bob 集合了编译所需的一切, 作为Java包 _JAR_ 发布. 你可以在其发布地址 http://d.defold.com 里下载到 *bob.jar* . 先选择版本, 再下载 *bob/bob.jar*. 要运行 Bob 工具, 你需要 [安装OpenJDK 11](https://openjdk.java.net/projects/jdk/11/).
+Bob 集合了编译所需的一切, 作为Java包 _JAR_ 发布. 最新的 *bob.jar* 发布在 [Defold 下载页](http://d.defold.com) 和 [GitHub 发布页](https://github.com/defold/defold/releases) 上. 选择一个版本, 下载 *bob/bob.jar*. 运行这个工具, 需要 [OpenJDK 11](https://openjdk.java.net/projects/jdk/11/) 支持.
 
 ## 用法
 

+ 2 - 1
docs/zh/manuals/components.md

@@ -3,7 +3,7 @@ title: 游戏对象组件
 brief: 本教程提供了游戏对象组件概览及其使用方法.
 ---
 
-#  组件
+# 组件
 
 :[组件](../shared/components.md)
 
@@ -18,6 +18,7 @@ Defold 提供以下组件类型:
 * [Factory](/manuals/factory) - 创建游戏对象实例
 * [GUI](/manuals/gui) - 渲染图形用户界面
 * [Label](/manuals/label) - 渲染文本
+* [Mesh](/manuals/mesh) - 显示3D网格 (同时具有实时创建和维护功能)
 * [Model](/manuals/model) 显示3D模型 (可以带动画)
 * [Particle FX](/manuals/particlefx) -  创建粒子
 * [Script](/manuals/script) - 添加游戏逻辑

+ 32 - 32
docs/zh/manuals/debugging-game-and-system-logs.md

@@ -1,57 +1,57 @@
 ---
-title: Debugging - game and system logs
-brief: This manual explains how to read game and system logs.
+title: 调试 - 游戏和系统日志
+brief: 本教程介绍了获取游戏和系统日志的方法.
 ---
 
-# Game and system log
+# 游戏和系统日志
 
-The game log shows all of the output from the engine, native extensions and your game logic. The [print()](/ref/stable/base/#print:...) and [pprint()](/ref/stable/builtins/?q=pprint#pprint:v) commands can be used from your scripts and Lua modules to show information in the game log. You can use the functions in the [dmLog namespace](/ref/stable/dmLog/) to write to the game log from native extensions. The game log can be read from the editor, from a terminal window, using platform specific tools or from a log file.
+游戏日志保存了引擎的所有输出, 包括原生扩展和脚本代码上的输出. 用 [print()](/ref/stable/base/#print:...) 和 [pprint()](/ref/stable/builtins/?q=pprint#pprint:v) 函数就能在日志里留下游戏输出. 可以使用原生扩展 [dmLog](/ref/stable/dmLog/) 下的函数读写日志文件. 各种文本阅读编辑器都能打开日志文件.
 
-System logs are generated by the operating system and it can provide additional information that can help you pintpoint a problem. The system logs can contain stack traces for crashes and low memory warnings.
+系统日志是由操作系统提供的, 也许会对调试游戏有所帮助. 系统日志可以记录应用崩溃时的调用堆栈和内存不足等信息.
 
-::: important
-The game log will only show information in debug builds. The log will be completely empty in release builds.
+::: 注意
+游戏日志只会在 debug 模式的编译版本中出现. 发布版本会去掉所有日志输出.
 :::
 
-## Reading the game log from the editor
+## 用编辑器查看游戏日志
 
-When you run your game locally from the editor or connected to the [mobile dev app](/manuals/dev-app) all of the output will be shown in the console pane of the editor:
+当在编辑器本地或者连接了 [mobile 开发版应用](/manuals/dev-app) 运行游戏时, 所有日志输出都能做编辑器控制台看到:
 
 ![Editor 2](images/editor/editor2_overview.png)
 
-## Reading the game log from the terminal
+## 用控制台查看游戏日志
 
-When you run a Defold game from the terminal the log will show in the terminal window itself. On Windows and Linux you type the name of the executable in the terminal to start the game. On macOS you need to launch the engine from within the .app file:
+当使用控制台启动游戏时, 日志文件也会打印在当前控制台上. 在 Windows 和 Linux 控制台上直接打游戏可执行文件名即可. 在 macOS 控制台上要打 .app 文件里面的游戏引擎名:
 
 ```
 $ > ./mygame.app/Contenst/MacOS/mygame
 ```
 
-## Reading game and system logs using platform specific tools
+## 不同平台的日志读取
 
 ### HTML5
 
-Logs can be read using the developer tools provided by most browsers.
+绝大多数浏览器都提供了显示日志输出的控制台.
 
-* [Chrome](https://developers.google.com/web/tools/chrome-devtools/console) - Menu > More Tools > Developer Tools
-* [Firefox](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console) - Tools > Web Developer > Web Console
+* [Chrome](https://developers.google.com/web/tools/chrome-devtools/console) - 菜单 > 更多工具 > 开发者工具
+* [Firefox](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console) - 工具 > 网络开发者 > 网络控制台
 * [Edge](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/console)
-* [Safari](https://support.apple.com/guide/safari-developer/log-messages-with-the-console-dev4e7dedc90/mac) - Develop > Show JavaScript Console
+* [Safari](https://support.apple.com/guide/safari-developer/log-messages-with-the-console-dev4e7dedc90/mac) - 开发 > 显示JavaScript控制台
 
 ### Android
 
-You can use the [Android Debug Bridge (ADB) tool](https://developer.android.com/studio/command-line/adb.html) to view the game and system log.
+可以使用 [Android Debug Bridge (ADB) 工具](https://developer.android.com/studio/command-line/adb.html) 查看游戏和系统日志.
 
-  Once installed and setup, connect your device with USB, open a terminal and run:
+  工具安装好之后, 通过 USB 连接你的设备, 启动控制台, 输入:
 
   ```txt
   cd <path_to_android_sdk>/platform-tools/
   adb logcat
   ```
 
-  The device will then dump all the output to the current terminal, along with any prints from the game.
+  设备会把所有日志信息打印在当前控制台上, 包含游戏输出信息.
 
-  If you want to see only Defold application outputs use this command:
+  要只查看 Defold 输出的日志信息, 可以这么输入:
 
   ```txt
   cd <path_to_android_sdk>/platform-tools/
@@ -60,33 +60,33 @@ You can use the [Android Debug Bridge (ADB) tool](https://developer.android.com/
 
 ### iOS
 
-You can use the [Console tool](https://support.apple.com/guide/console/welcome/mac) to read game and system log. You can use the LLDB debugger to attach to a game running on device. To debug a game it needs to be signed with a “Apple Developer Provisioning Profile” that include the device you want to debug on. Bundle the game from the editor and supply the provisioning profile in the bundle dialog (bundling for iOS is only available on macOS).
+可以使用 [控制台工具](https://support.apple.com/guide/console/welcome/mac) 读取游戏和系统日志. 可以使用 LLDB 调试器连接设备上运行的游戏. 调试前确保设备上存有该应用的 “Apple Developer Provisioning Profile”. 从编辑器的打包对话框那里提供档案文件 (只能在 macOS 平台上打包 iOS 应用).
 
-  To launch the game and attach the debugger you will need a tool called [ios-deploy](https://github.com/phonegap/ios-deploy). Install and debug your game by running the following in a terminal:
+  需要一个叫做 [ios-deploy](https://github.com/phonegap/ios-deploy) 的工具才能进行调试. 命令如下:
 
   ```txt
-  ios-deploy --debug --bundle <path_to_game.app> # NOTE: not the .ipa file
+  ios-deploy --debug --bundle <path_to_game.app> # 注意: 不是 .ipa 文件
   ```
 
-  This will install the app on your device, start it and automatically attach a LLDB debugger to it. If you are new to LLDB, read [Getting Started with LLDB](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-basics.html).
+  它会把应用安装到设备上, 启动应用并且把 LLDB 调试器连接到应用上. 如果不熟悉 LLDB, 参考 [LLDB 基础教程](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-basics.html).
 
 
-## Reading the game log from the log file
+## 从日志文件中读取日志信息
 
-If you enable the *Write Log* setting in "game.project", any game output will be written to disk, to a file called "log.txt". Here is how you extract the file if you run the game on device:
+如果你在 "game.project" 文件里打开了 *Write Log* 项, 所有游戏输出都会被记录到硬盘上, 保存为 "log.txt" 文件. 下面介绍了从设备上获取日志文件的方法:
 
 iOS
-: Connect your device to a computer with macOS and Xcode installed.
+: 把设备连接到安装有 macOS 和 Xcode 的电脑上.
 
-  Open Xcode and go to <kbd>Window ▸ Devices and Simulators</kbd>.
+  启动 Xcode 选择 <kbd>Window ▸ Devices and Simulators</kbd>.
 
-  Select your device in the list, then select the relevant app in the *Installed Apps* list.
+  在列表中选择你的设备, 然后在 *Installed Apps* 列表中选择你的游戏应用.
 
-  Click the cog icon below the list and select <kbd>Download Container...</kbd>.
+  点击列表下方的齿轮图标选择 <kbd>Download Container...</kbd>.
 
   ![download container](images/debugging/download_container.png){srcset="images/debugging/[email protected] 2x"}
 
-  Once the container has been extracted it will be shown in *Finder*. Right click the container and select <kbd>Show Package Content</kbd>. Locate the file "log.txt", which should be located in "AppData/Documents/".
+  容器被下载解压之后就可以在 *Finder* 中看到了. 右键单击容器选择 <kbd>Show Package Content</kbd>. 找到 "log.txt", 一般位于 "AppData/Documents/".
 
 Android
-: The ability to extract the "log.txt" depends on OS version and manufacturer. Here is a short and simple step by step guide: https://stackoverflow.com/a/48077004/129360
+: "log.txt" 的获取取决于操作系统版本和制造商. 在这里有一个简单的获取步骤: https://stackoverflow.com/a/48077004/129360

+ 47 - 47
docs/zh/manuals/debugging-game-logic.md

@@ -5,128 +5,128 @@ brief: 本教程介绍了 Defold 中自带的调试功能.
 
 # 调试游戏逻辑
 
-Defold contains an integrated Lua debugger with an inspection facility. Together with the built-in [profiling tools](/manuals/profiling) it is a powerful tool that can help finding the cause of bugs in your game logic or help analyze performance issues.
+Defold 内置集成式 Lua 调试器及检视工具. 加上内置的 [分析工具](/manuals/profiling) 构成强大工具集帮你快速找到逻辑错误和性能问题.
 
-## Print and visual debugging
+## 打印输出与可视调试
 
-The simplest way to debug your game in Defold is to use [print debugging](http://en.wikipedia.org/wiki/Debugging#Techniques). Use `print()` or [`pprint()`](/ref/builtins#pprint) statements to watch variables or indicate the flow of execution. If a game object without a script acts weird, you can just attach a script to it with the sole purpose of debugging. Using any of the printing functions will print to the *Console* view in the editor and to the [game log](/manuals/debugging-game-and-system-logs).
+Defold 最基础的调试功能是 [控制台打印输出](http://en.wikipedia.org/wiki/Debugging#Techniques). 使用 `print()` 或 [`pprint()`](/ref/builtins#pprint) 来检查变量值或者逻辑流程. 如果有个游戏对象不正常, 只需要将包含调试代码的脚本组件拖上去就行了. 打印输出函数会把信息发送到编辑器的 *控制台* 与 [游戏日志](/manuals/debugging-game-and-system-logs) 中.
 
-In addition to printing, the engine can also draw debug text and straight lines on the screen. This is done by posting messages to the `@render` socket:
+更进一步来说, 引擎有绘制调试信息的功能, 可以显示文字和画线. 用此功能需要向 `@render` 接口发送消息:
 
 ```lua
--- Draw value of "my_val" with debug text on the screen
+-- 把变量 "my_val" 画在屏幕上
 msg.post("@render:", "draw_text", { text = "My value: " .. my_val, position = vmath.vector3(200, 200, 0) })
 
--- Draw colored text on the screen
+-- 画出带颜色的文字
 local color_green = vmath.vector4(0, 1, 0, 1)
 msg.post("@render:", "draw_debug_text", { text = "Custom color", position = vmath.vector3(200, 180, 0), color = color_green })
 
--- Draw debug line between player and enemy on the screen
+-- 在主角和敌人之间画一条线
 local start_p = go.get_position("player")
 local end_p = go.get_position("enemy")
 local color_red = vmath.vector4(1, 0, 0, 1)
 msg.post("@render:", "draw_line", { start_point = start_p, end_point = end_p, color = color_red })
 ```
 
-The visual debug messages adds data to the rendering pipeline and is drawn as part of the regular render pipeline.
+调试绘制与普通的渲染处于同一个渲染管线之上.
 
-* `"draw_line"` adds data that is rendered with the `render.draw_debug3d()` function in the render script.
-* `"draw_text"` is rendered with the "/builtins/fonts/system_font.font" that uses the "/builtins/fonts/system_font.material" material.
-* `"draw_debug_text"` is the same as `"draw_text"`, but it's rendered in a custom color.
+* `"draw_line"` 实际是是使用渲染脚本的 `render.draw_debug3d()` 函数进行绘制的.
+* `"draw_text"` 使用的是 "/builtins/fonts/system_font.font" 字体和 "/builtins/fonts/system_font.material" 材质.
+* `"draw_debug_text"` 与 `"draw_text"` 类似, 只是可以自定义文字颜色.
 
-Note that you probably want to update this data every frame so posting the messages in the `update()` function is a good idea.
+注意一般调试信息都需要实时更新所以把它们放在 `update()` 函数中是个好主意.
 
-## Running the debugger
+## 运行调试器
 
-To run the debugger, either <kbd>Debug ▸ Run with Debugger</kbd> which starts up the game with the debugger attached, or select <kbd>Debug ▸ Attach Debugger</kbd> to attach the debugger to an already running game.
+一种办法是通过 <kbd>Debug ▸ Run with Debugger</kbd> 运行游戏并且自动接入调试器, 另一种是通过 <kbd>Debug ▸ Attach Debugger</kbd> 把调试器接入正在运行中的游戏上.
 
 ![overview](images/debugging/overview.png){srcset="images/debugging/[email protected] 2x"}
 
-As soon as the debugger is attached, you have control of the execution of the game through the debugger control buttons in the console, or through the <kbd>Debug</kbd> menu:
+调试器接入后, 就可以使用控制台上的调试控制按钮, 或者使用 <kbd>Debug</kbd> 菜单了:
 
 Break
 : ![pause](images/debugging/pause.svg){width=60px .left}
-  Break execution of the game immediately. The game will break at its current point. You are now able to inspect the state of the game, advance the game step by step, or continue running it until the next breakpoint. The current point of execution is marked in the code editor:
+  立即断下游戏. 游戏于此点暂停. 此时可以观察游戏状态, 逐步运行, 或者运行到下一个断点. 断点会在代码编辑器上标识出来:
 
   ![script](images/debugging/script.png){srcset="images/debugging/[email protected] 2x"}
 
 Continue
 : ![play](images/debugging/play.svg){width=60px .left}
-  Continue running the game. The game code will continue to run until you either press pause or the execution hits a breakpoint that you have set. If execution breaks at a set breakpoint, the the execution point is marked in the code editor on top of the breakpoint marker:
+  继续运行游戏. 直到按下暂停键或者遇到断点. 如果遇到断点停下, 运行点会在代码编辑器的断点标识之上标识出来:
 
   ![break](images/debugging/break.png){srcset="images/debugging/[email protected] 2x"}
 
 Stop
 : ![stop](images/debugging/stop.svg){width=60px .left}
-  Stop the debugger. Pressing this button will immediately stop the debugger, detach it from the game and terminate the running game.
+  停止调试. 立即停止调试, 断开调试器, 关闭游戏.
 
 Step Over
 : ![step over](images/debugging/step_over.svg){width=60px .left}
-  Advance execution of the program one step. If the execution involves running another Lua function, the execution _will not step into the function_ but continue running and stop on the next line below the function call. In this example, if the user presses "step over", the debugger will execute code and stop at the `end` statement below the line with the call to the function `nextspawn()`:
+  步越. 步进时如果运行到某个 Lua 函数, 步越 _不会进入这个函数_ 而是执行它然后停在函数下一行上. 图中, 如果用户按下 "step over", 调试器会执行代码直至调用 `nextspawn()` 函数下面的 `end` 位置处:
 
   ![step](images/debugging/step.png){srcset="images/debugging/[email protected] 2x"}
 
-::: sidenote
-A line of Lua code does not correspond to a single expression. Stepping in the debugger moves ahead one expression at a time, meaning that currently you may have to hit the step button more than once to advance to the next line.
+::: 注意
+一行Lua代码不一定就是一句Lua表达式. 调试器按表达式步进, 也就是说有可能出现一行多个表达式的情况就要多按几下步进才会运行到下一行.
 :::
 
 Step Into
 : ![step in](images/debugging/step_in.svg){width=60px .left}
-  Advance execution of the program one step. If the execution involves running another Lua function, the execution _will step into the function_. Calling the function adds an entry to the call stack. You can click each entry in the call stack list to view the entry point and the content of all variables in that closure. Here, the user has stepped into the function `nextspawn()`:
+  步入. 步进时如果运行到某个 Lua 函数, 步入 _会进入这个函数_. 一个函数调用会在调用堆栈上增加一项. 可以在堆栈列表上点选来查看各函数入口及其所有变量信息. 图中, 用户步入了 `nextspawn()` 函数:
 
   ![step into](images/debugging/step_into.png){srcset="images/debugging/[email protected] 2x"}
 
 Step Out
 : ![step out](images/debugging/step_out.svg){width=60px .left}
-  Continue execution until it returns from the current function. If you have stepped execution into a function, pressing the button "step out" will continue execution until the function returns.
+  步出. 运行游戏直到函数出口. 如果步入了一个函数, 按 "step out" 按钮能运行代码到函数返回位置.
 
-Setting and clearing breakpoints
-: You can set an arbitrary number of breakpoints in your Lua code. When the game runs with the debugger attached, it will stop execution at the next breakpoint it encounters and wait for further interaction from you.
+设置/清除断点
+: 可以在代码中随意设置断点. 接入调试器的游戏运行时, 会在断点处暂停, 等待你的下一步交互.
 
   ![add breakpoint](images/debugging/add_breakpoint.png){srcset="images/debugging/[email protected] 2x"}
 
-  To set or clear a breakpoint, click in the column just right of the line numbers in the code editor. You can also select <kbd>Edit ▸ Toggle Breakpoint</kbd> from the menu.
+  设置/清除断点, 可以在代码编辑器里行号右边右键点击. 还可以从菜单中选择 <kbd>Edit ▸ Toggle Breakpoint</kbd>.
 
-Evaluating Lua expressions
-: With the debugger attached and the game stopped at a breakpoint, a Lua runtime is available with the current context. Type Lua expressions in the bottom of the console and press <kbd>Enter</kbd> to evaluate them:
+执行Lua表达式
+: 调试器停在断点上时, 可以直接使用包含有当前上下文的 Lua 运行时. 在控制台底部输入表达式后按 <kbd>回车键</kbd> 来运行:
 
   ![console](images/debugging/console.png){srcset="images/debugging/[email protected] 2x"}
 
-  It is currently not possible to modify variables through the evaluator.
+  目前不支持用表达式来修改变量.
 
-Detaching the debugger
-: Select <kbd>Debug ▸ Detach Debugger</kbd> to detach the debugger from the game. It will continue running immediately.
+断开调试器
+: 通过选择 <kbd>Debug ▸ Detach Debugger</kbd> 可以把调试器从游戏上断开. 游戏会继续运行.
 
-## Lua debug library
+## Lua 调试库
 
-Lua comes with a debug library that is useful in some situations, particularly if you need to inspect the innards of your Lua environment. You can find more information about it here: http://www.lua.org/pil/contents.html#23.
+Lua 包含一个有用的调试库, 帮你查看 Lua 环境的底层. 详情请见: http://www.lua.org/pil/contents.html#23.
 
-## Debugging checklist
+## 调试步骤
 
-If you encounter an error or if your game does not behave like expected, here is a debugging checklist:
+如果发现错误或者bug, 建议进行如下调试:
 
-1. Check the console output and verify that there are no runtime errors.
+1. 检查控制台看看输出什么报错没有.
 
-2. Add `print` statements to your code to verify that the code is actually running.
+2. 在适当地方加入 `print` 语句证明这段代码运行到了没有.
 
-3. If it's not running, check that you have done the proper setup in the editor required for the code to run. Is the script added to the right game object? Have your script acquired input focus? Are the input-triggers correct? Is the shader code added to the material? Etc.
+3. 看看编辑器各种设置是否配置正确. 代码加到游戏对象上了吗? 输入得到焦点了吗? 输入消息监听对了吗? 材质上有着色程序吗? 等等.
 
-4. If your code is depending on the values of variables (in an if-statement, for example), either `print` those values where they are used or checked, or inspect them with the debugger.
+4. 如果某些代码取决于变量的值 (比如if语句), 使用 `print` 或者调试器看看那些变量值对不对.
 
-Sometimes finding a bug can be a hard and time consuming process, requiring you to go through your code bit by bit, checking everything and narrowing down the faulty code and eliminating sources of error. This is best done by a method called "divide and conquer":
+有的 bug 藏得很深, 调试起来很费时, 需要一丝一丝地捋, 逐步缩小可能出错的范围最终消灭错误源头. 这种情况下建议使用 "二分法":
 
-1. Figure out which half (or less) of the code that must contain the bug.
-2. Again, figure out which half, of that half, must contain the bug.
-3. Continue narrowing down the code that must cause the bug until you find it.
+1. 线确定哪一半代码一定包含着错误.
+2. 继续二分二分, 缩小范围.
+3. 最终找到并消灭错误.
 
-Happy hunting!
+祝你调试愉快!
 
-## Debugging problems with physics
+## 物理引擎调试
 
-If you have problems with physics and collisions aren't working as expected it is recommended to enable physics debugging. Check the *Debug* checkbox in the *Physics* section of the *game.project* file:
+如果使用物理系统过程中发现错误请开启物理调试. 在 *game.project* 文件的 *Physics* 部分, 勾选 *Debug* 项:
 
 ![physics debug setting](images/debugging/physics_debug_setting.png)
 
-When this checkbox is enabled Defold will draw all collision shapes and contact points of collisions:
+这样 Defold 就会把所有物理形状和碰撞接触点绘制到屏幕上:
 
 ![physics debug visualisation](images/debugging/physics_debug_visualisation.png)

+ 27 - 28
docs/zh/manuals/debugging-native-code-android.md

@@ -1,83 +1,82 @@
 ---
-title: Debugging on Android
-brief: This manual describes how to debug a build running on an Android device.
+title: Android 平台调试
+brief: 本教程介绍了在安卓设备上调试游戏的方法.
 ---
 
-# Debugging on Android
+# Android 平台调试
 
-Here we list some ways to debug your executable running on an Android device
+下面列出了一些在 Android 设备上调试游戏的方法
 
 ## Android Studio
 
-* Prepare the bundle by setting the `android.debuggable` option in `game.project`
+* 在 `game.project` 中设置 `android.debuggable`
 
 	![android.debuggable](images/extensions/debugging/android/game_project_debuggable.png)
 
-* Bundle the app in debug mode into a folder of choice.
+* 在 debug 模式下打包游戏
 
 	![bundle_android](images/extensions/debugging/android/bundle_android.png)
 
-* Launch [Android Studio](https://developer.android.com/studio/)
+* 启动 [Android Studio](https://developer.android.com/studio/)
 
-* Choose `Profile or debug APK`
+* 选择 `Profile or debug APK`
 
 	![debug_apk](images/extensions/debugging/android/android_profile_or_debug.png)
 
-* Choose the apk bundle you just created
+* 选择刚刚输出的apk文件
 
 	![select_apk](images/extensions/debugging/android/android_select_apk.png)
 
-* Select the main `.so` file, and make sure it has debug symbols
+* 选择主 `.so` 文件, 确保里面含有调试信息
 
 	![select_so](images/extensions/debugging/android/android_missing_symbols.png)
 
-* If it doesn't, upload an unstripped `.so` file. (size is around 20mb)
+* 没有的话可以上传完整 `.so` 文件. (文件大约 20mb)
 
-* Path mappings help you remap where the individual paths from where the executable was built (in the cloud) to an actual folder on your local drive.
+* 路径映射帮助建立从编译 (在云端) 到本地文件夹的文件对应关系.
 
-* Select the .so file, then add a mapping your local drive
+* 选择 .so 文件, 添加路径映射
 
 	![path_mapping1](images/extensions/debugging/android/path_mappings_android.png)
 
 	![path_mapping2](images/extensions/debugging/android/path_mappings_android2.png)
 
-* If you have access to the engine source, add a path mapping to that too
+* 要是动过引擎源码, 也要对引擎代码添加路径映射
 
-		* make sure to checkout the version you are currently debugging
+		* 注意一定要获取与你所用版本完全一致的引擎版本
 
 			defold$ git checkout 1.2.148
 
-* Press `Apply changes`
+* 点击 `Apply changes`
 
-* You should now see the source mapped in your project
+* 这时路径映射已经生效
 
 	![source](images/extensions/debugging/android/source_mappings_android.png)
 
-* Add a breakpoint
+* 加断点
 
 	![breakpoint](images/extensions/debugging/android/breakpoint_android.png)
 
-* Press `Run` -> `Debug "Appname"` and invoke the code you meant to break into
+* 点击 `Run` -> `Debug "Appname"` 然后运行断点处的程序
 
 	![breakpoint](images/extensions/debugging/android/callstack_variables_android.png)
 
-* You can now step in the callstack as well as inspect the variables
+* 步进可用, 变量和调用堆栈一目了然
 
 
-## Notes
+## 注意
 
-### Native Extension job folder
+### 原生扩展 job 文件夹
 
-Currently, the workflow is a bit troublesome for development. This is because the job folder name
-is random for each build, making the path mapping invalid for each build.
+目前, 开发流程有点麻烦. 因为job文件夹名是随机的, 每次编译都不一样.
 
-However, it works fine for a debugging session.
+但是还是有办法使用的.
 
-The path mappings are stored in the <project>.iml file in the Android Studio project.
+路径映射保存于 Android Studio 项目的 <project>.iml 文件中.
 
-It's possible to get the job folder from the executable
+运行下列命令就能得到job文件夹名
 
 	$ arm-linux-androideabi-readelf --string-dump=.debug_str build/armv7-android/libdmengine.so | grep /job
 
-The jobfolder is named like so `job1298751322870374150`, each time with a random number.
+类似 `job1298751322870374150` 这样的名字, 后面的数字每次编译都不相同.
 

+ 42 - 42
docs/zh/manuals/debugging-native-code-ios.md

@@ -1,29 +1,29 @@
 ---
-title: Debugging on iOS/macOS
-brief: This manual describes how to debug a build using Xcode.
+title: 在 iOS/macOS 中调试
+brief: 本教程介绍了如何使用 Xcode 进行调试.
 ---
 
-# Debugging on iOS/macOS
+# 在 iOS/macOS 中调试
 
-Here we describe how to debug a build using [Xcode](https://developer.apple.com/xcode/), Apple's preferred IDE for developing for macOS and iOS.
+这里我们介绍如何使用 [Xcode](https://developer.apple.com/Xcode/), Apple的 macOS 和 iOS 首选开发环境来调试应用.
 
 ## Xcode
 
-* Bundle the app by using bob, with the `--with-symbols` option
+* 使用 bob, 加上 `--with-symbols` 选项打包应用
 
 		$ cd myproject
 		$ wget http://d.defold.com/archive/<sha1>/bob/bob.jar
 		$ java -jar bob.jar --platform armv7-darwin build --with-symbols debug --archive bundle -bo build/ios -mp <app>.mobileprovision --identity "iPhone Developer: Your Name (ID)"
 
-* Install the app, either with `Xcode`, `iTunes` or [ios-deploy](https://github.com/ios-control/ios-deploy)
+* 安装应用, 可以通过 `Xcode`, `iTunes` 或者 [ios-deploy](https://github.com/ios-control/ios-deploy)
 
 		$ ios-deploy -b <AppName>.ipa
 
-* Get the `.dSYM` folder (i.e the debug symbols)
+* 得到 `.dSYM` 文件夹 (即调试 symbols)
 
-	* If it's not using Native Extensions, you can download the `.dSYM` file from [d.defold.com](http://d.defold.com)
+	* 如果没使用原生扩展, 可以从 [d.defold.com](http://d.defold.com) 下载 `.dSYM` 文件
 
-	* If you are using a native extension, then the `.dSYM` folder is generated when you build with [bob.jar](https://www.defold.com/manuals/bob/). Only building is required (no archive or bundling):
+	* 如果使用了原生扩展, 可以使用 [bob.jar](https://www.defold.com/manuals/bob/) 生成 `.dSYM` 文件夹. 只需要 building (不需要 archive 和 bundling):
 
 			$ cd myproject
 			$ unzip .internal/cache/arm64-ios/build.zip
@@ -31,106 +31,106 @@ Here we describe how to debug a build using [Xcode](https://developer.apple.com/
 			$ mv <AppName>.dSYM/Contents/Resources/DWARF/dmengine <AppName>.dSYM/Contents/Resources/DWARF/<AppName>
 
 
-### Create Project
+### 创建项目
 
-To properly debug, we need to have a project, and the source code mapped.
-We're not using this project to build things, only debug.
+要正确的调试, 我们需要一个项目, 以及一个代码映射(source map).
+这次项目不是用来编译的, 只是调试举例.
 
-* Create new Xcode project, choose the `Game` template
+*新建 Xcode 项目, 选择 `Game` 模板
 
 	![project_template](images/extensions/debugging/ios/project_template.png)
 
-* Choose a name (e.g. `debug`) and the default settings
+* 指定一个名字 (例如 `debug`) 并且使用默认设置
 
-* Choose a folder to save the project into
+* 选择一个存放项目的目录
 
-* Add your code to the app
+* 为应用加入代码文件
 
 	![add_files](images/extensions/debugging/ios/add_files.png)
 
-* Make sure the "Copy items if needed" is unchecked.
+* 确保 "Copy items if needed" 未选中.
 
 	![add_source](images/extensions/debugging/ios/add_source.png)
 
-* This is the end result
+* 结果是这样
 
 	![added_source](images/extensions/debugging/ios/added_source.png)
 
 
-* Disable the `Build` step
+* 关闭 `Build` 步骤
 
 	![edit_scheme](images/extensions/debugging/ios/edit_scheme.png)
 
 	![disable_build](images/extensions/debugging/ios/disable_build.png)
 
-* Set the `Deployment target` version so it's now larger than your device iOS version
+* 设置 `Deployment target` 版本
 
 	![deployment_version](images/extensions/debugging/ios/deployment_version.png)
 
-* Select the target device
+* 设置目标设备
 
 	![select_device](images/extensions/debugging/ios/select_device.png)
 
 
-### Launch the debugger
+### 启动调试器
 
-You have a few options to debug an app
+调试应用有如下方法
 
-1. Either choose `Debug` -> `Attach to process...` and select the app from there
+* 可以使用 `Debug` -> `Attach to process...` 然后选择要调试应用
 
-1. Or choose the `Attach to process by PID or Process name`
+* 也可以选择 `Attach to process by PID or Process name`
 
 	![select_device](images/extensions/debugging/ios/attach_to_process_name.png)
 
-	1. Start the app on the device
+	然后在设备上启动应用
 
-1. In `Edit Scheme` add the <AppName>.app folder as the executable
+* 在 `Edit Scheme` 中加入 <AppName>.app 作为可运行文件夹
 
-### Debug symbols
+### 调试 symbols
 
-**To use lldb, the execution must be paused**
+**要使用 lldb, 运行必须先暂停**
 
-* Add the `.dSYM` path to lldb
+* 把 `.dSYM` 目录加入到 lldb 中
 
 		(lldb) add-dsym <PathTo.dSYM>
 
 	![add_dsym](images/extensions/debugging/ios/add_dsym.png)
 
-* Verify that `lldb` read the symbols successfully
+* 确认 `lldb` 成功读取 symbols
 
 		(lldb) image list <AppName>
 
-### Path mappings
+### 路径映射
 
-* Add the engine source (change accordingly for your need)
+* 加入引擎路径 (根据你的安装目录自行调整)
 
 		(lldb) settings set target.source-map /Users/builder/ci/builds/engine-ios-64-master/build /Users/mathiaswesterdahl/work/defold
 		(lldb) settings append target.source-map /private/var/folders/m5/bcw7ykhd6vq9lwjzq1mkp8j00000gn/T/job4836347589046353012/upload/videoplayer/src /Users/mathiaswesterdahl/work/projects/extension-videoplayer-native/videoplayer/src
 
-	* It's possible to get the job folder from the executable.
-	The jobfolder is named like so `job1298751322870374150`, each time with a random number.
+	* 从可运行文件夹里可以得到 job 文件夹.
+	job 文件夹命名类似这样 `job1298751322870374150`, 每次都是随机数字.
 
 			$ dsymutil -dump-debug-map <executable> 2>&1 >/dev/null | grep /job
 
-* Verify the source mappings
+* 验证路径映射
 
 		(lldb) settings show target.source-map
 
-You can check what source file a symbol was originating from using
+可以使用如下命令确定 symbol 的源代码文件
 
 	(lldb) image lookup -va <SymbolName>
 
 
-### Breakpoints
+### 断点
 
-* Open a file in the project view, and set a breakpoint
+* 从 project 视图打开一个文件, 然后设置断点
 
 	![breakpoint](images/extensions/debugging/ios/breakpoint.png)
 
-## Notes
+## 注意
 
-### Check UUID of binary
+### 检查二进制文件 UUID
 
-In order for the debugger to accept the `.dSYM` folder, the UUID need to match the UUID of the executable being debugged. You can check the UUID like so:
+为了让调试器接受 `.dSYM` 文件夹, UUID 需要与可运行文件的 UUID 相匹配. 你可以这样检查 UUID:
 
 	$ dwarfdump -u <PathToBinary>

+ 57 - 61
docs/zh/manuals/debugging-native-code.md

@@ -1,23 +1,23 @@
 ---
-title: Debugging native code in Defold
-brief: This manual explains how to debug native code in Defold.
+title: Defold 中的原生代码调试
+brief: 本教程介绍了在 Defold 中调试原生代码的方法.
 ---
 
-# Debugging native code
+# 原生代码调试
 
-Defold is well tested and should very rarely crash under normal circumstances. It is however impossible to guarantee that it will never crash, especially if your game uses native extensions. If you run into problems with crashes or native code that doesn't behave as expected there are a number of different ways forward:
+Defold 几经测试鲜有崩溃情况出现. 但是崩溃这种事谁能保证永远避免, 尤其是游戏中还使用了原生扩展代码的情况下. 要是游戏崩溃或者原生代码出错请从下面几方面入手检查:
 
-* Use a debugger to step through the code
-* Use print debugging
-* Analyze a crash log
-* Symbolicate a callstack
+* 使用调试器调试代码
+* 使用 print 函数检查代码
+* 分析崩溃日志
+* 调用堆栈代码文件映射
 
 
-## Use a debugger
+## 使用调试器
 
-The most common way is to run the code via a `debugger`. It let's you step through the code, set `breakpoints` and it will stop the execution if you get a crash.
+首先推荐使用 `调试器`. 使用它步进代码, 设置 `断点` 最重要的是游戏崩溃时会自动暂停.
 
-There are several debuggers for each platform.
+不同平台调试器有很多.
 
 * Visual studio - Windows
 * VSCode - Windows, macOS, Linux
@@ -27,39 +27,35 @@ There are several debuggers for each platform.
 * lldb / gdb - macOS, Linux, (Windows)
 * ios-deploy - macOS
 
-Each tool can debug certain platforms:
+每个工具可以调试的应用如下:
 
-* Visual studio - Windows + platforms supporting gdbserver (E.g. Linux/Android)
+* Visual studio - Windows + platforms supporting gdbserver (比如 Linux/Android)
 * VSCode - Windows, macOS (lldb), Linux (lldb/gdb) + platforms supporting gdbserver
-* Xcode -  macOS, iOS ([learn more](/manuals/debugging-native-code-ios))
-* Android Studio - Android ([learn more](/manuals/debugging-native-code-android))
+* Xcode -  macOS, iOS ([详见](/manuals/debugging-native-code-ios))
+* Android Studio - Android ([详见](/manuals/debugging-native-code-android))
 * WinDBG - Windows
 * lldb/gdb - macOS, Linux, (iOS)
 * ios-deploy - iOS (via lldb)
 
 
-## Use print debugging
+## 使用 print 函数
 
-The simplest way to debug your native code is to use [print debugging](http://en.wikipedia.org/wiki/Debugging#Techniques). Use the functions in the [dmLog namespace](/ref/stable/dmLog/) to watch variables or indicate the flow of execution. Using any of the log functions will print to the *Console* view in the editor and to the [game log](/manuals/debugging-game-and-system-logs).
+调试最简单的方法就是使用 [print 函数](http://en.wikipedia.org/wiki/Debugging#Techniques). 位于 [dmLog 命名空间](/ref/stable/dmLog/) 下的 print 函数可以用来检查变量值或者用来检查程序执行流程. 它可以在 *控制台* 视图和 [游戏日志](/manuals/debugging-game-and-system-logs) 中输出数据.
 
 
-## Analyze a crash log
+## 崩溃日志分析
 
-The Defold engine saves a `_crash` file if it does a hard crash. The crash file will contain information about the system as well as the crash. The [game log output](/manuals/debugging-game-and-system-logs) will write where the crash file is located (it varies depending on operating system, device and application).
+崩溃时, Defold 引擎保存了一个 `_crash` 日志文件. 其中包含了系统信息与崩溃信息. 其存放位置参考 [游戏日志输出](/manuals/debugging-game-and-system-logs) (不同设备, 系统, 位置不同).
 
-You can use the [crash module](https://www.defold.com/ref/crash/) to read this file in the subsequent session. It is recommended that you read the file, gather the information, print it to the console and send it to an [analytics services](/tags/stars/analytics/) that supports collection of crash logs.
+可以使用 [崩溃模块](https://www.defold.com/ref/crash/) 帮助分析这个文件. 推荐你阅读, 收集信息, 打印信息到控制台, 然后把信息发送到 [第三方分析服务](/tags/stars/analytics/) 上去.
 
-::: important
-On Windows a `_crash.dmp` file is also generated. This file is useful when debugging a crash.
-:::
-
-### Getting the crash log from a device
+### 从设备上获取崩溃日志
 
-If a crash happens on a mobile device you can chose to download the crash file to your own computer and parse it locally.
+手机上的崩溃日志可以下载到本地以便查看.
 
 #### Android
 
-If the app is [debuggable](/manuals/project-settings/#android), you can get the crash log using the [Android Debug Bridge (ADB) tool](https://developer.android.com/studio/command-line/adb.html) and the `adb shell` command:
+如果应用是 [可调式的](/manuals/project-settings/#android), 就可以使用 [Android Debug Bridge (ADB) 工具](https://developer.android.com/studio/command-line/adb.html) 和 `adb shell` 命令得到崩溃日志:
 
 ```
 	$ adb shell "run-as com.defold.example sh -c 'cat /data/data/com.defold.example/files/_crash'" > ./_crash
@@ -67,81 +63,81 @@ If the app is [debuggable](/manuals/project-settings/#android), you can get the
 
 #### iOS
 
-In iTunes, you can view/download an apps container.
+在 iTunes 里, 可以下载 app 容器.
 
-In the `Xcode -> Devices` window, you can also select the crash logs
+在 `Xcode -> Devices` 窗口中也能获取到崩溃日志.
 
 
-## Symbolicate a callstack
+## 调用堆栈代码文件映射
 
-If you get a callstack from either a `_crash` file or a [log file](/manuals/debugging-game-and-system-logs), you can symbolicate. This means translating each address in the callstack into a filename and line number, which in turn helps when finding out the root cause.
+从 `_crash` 文件或者 [日志文件](/manuals/debugging-game-and-system-logs), 都可以进行代码文件映射. 即把调用堆栈里的每个地址映射到文件名和代码行, 利于寻找代码的问题.
 
-It is important that you match the correct engine with the callstack. Otherwise it's very likely to send you debugging the incorrect things. If you are building with native extensions, be sure to add the flag [--with-symbols](https://www.defold.com/manuals/bob/) so that you get all the needed data from the build server:
+注意引擎版本要选择正确. 不然映射会错乱. 需要编译原生扩展, 命令行要加入 [--with-symbols](https://www.defold.com/manuals/bob/) 参数才能下载到所需的全部数据:
 
-* iOS and macOS - the `dmengine.dSYM` folder in the `build.zip` contains the debug symbols for iOS/macOS builds.
-* Android and Linux - the executables themselves contain the debug symbols.
-* Windows - the `dmengine.pdb` file in the `build.zip` contains the debug symbols for Windows builds.
-* HTML5 - the `dmengine.js.symbols` file in the `build.zip` contains the debug symbols for HTML5 builds.
+* iOS 与 macOS - `build.zip` 里的 `dmengine.dSYM` 文件夹下包含了调试映射数据.
+* Android 与 Linux - 可执行文件中就包含全部调试映射数据.
+* Windows - `build.zip` 里的 `dmengine.pdb` 文件中包含了调试和映射数据.
+* HTML5 - `build.zip` 里的 `dmengine.js.symbols` 文件中包含了调试和映射数据.
 
-If you are building without native extensions the debug symbols are available from the [Defold download website](http://d.defold.com):
+如果无需编译原生扩展, 那么调试用信息可以从 [Defold 下载站](http://d.defold.com) 下载到:
 
-* iOS - The `engine/armv7-darwin/dmengine_release.dSYM.zip` and `engine/arm64-darwin/dmengine_release.dSYM.zip` files contain the debug symbols for 32 and 64-bit engine versions.
-* macOS - The `engine/x86_64-darwin/dmengine_release.dSYM.zip` file contains the debug symbols.
-* Android - The `engine/armv7-android/dmengine.apk` and `engine/arm64-android/dmengine.apk` engines include the debug symbols for 32 and 64-bit engine versions.
-* Linux - The `engine/x86_64-linux/dmengine_release` engine includes the debug symbols.
-* Windows -  The `engine/x86_64-win32/dmengine_release.pdb` file contains the debug symbols.
-* HTML5 - The `engine/js-web/dmengine_release.js.symbols` file contaons the debug symbols.
+* iOS - `engine/armv7-darwin/dmengine_release.dSYM.zip` 和 `engine/arm64-darwin/dmengine_release.dSYM.zip` 文件分别包含32位和64位调试映射数据.
+* macOS - `engine/x86_64-darwin/dmengine_release.dSYM.zip` 文件包含调试映射数据.
+* Android - `engine/armv7-android/dmengine.apk` 和 `engine/arm64-android/dmengine.apk` 游戏引擎文件分别包含32位和64位调试映射数据.
+* Linux - `engine/x86_64-linux/dmengine_release` 游戏引擎文件包含调试映射数据.
+* Windows -  `engine/x86_64-win32/dmengine_release.pdb` 文件包含调试映射数据.
+* HTML5 - `engine/js-web/dmengine_release.js.symbols` 文件包含调试映射数据.
 
-::: important
-It is very important that your save the debug symbols somewhere for each public release you make of your game and that you know which release the debug symbols belong to. You will not be able to debug any native crashes if you do not have the debug symbols! Also, you should keep an unstripped version of the engine. This allows for the best symbolication of the callstack.
+::: 注意
+对于游戏的每个发布版本一定要保留一套对应的调试数据. 不然的话原生扩展上线以后出错误就没法调试! 为了方便查看调用堆栈, 也要保存好对应的游戏引擎.
 :::
 
-### Symbolicate an Android callstack
+### Android调用堆栈映射
 
-1. Get it from your build folder
+1. 找到编译文件夹
 
 	$ ls <project>/build/<platform>/[lib]dmengine[.exe|.so]
 
-1. Unzip to a folder:
+1. 解压引擎:
 
 	$ unzip dmengine.apk -d dmengine_1_2_105
 
-1. Find the callstack address
+1. 找到地址
 
-	E.g. in the non symbolicated callstack it could look like this
+	例如下面这个文件
 
 	#00 pc 00257224 libmy_game_name.so
 
-	Where *00257224* is the address
+	其中 *00257224* 就是地址
 
-1. Resolve the address
+1. 映射地址
 
     $ arm-linux-androideabi-addr2line -C -f -e dmengine_1_2_105/lib/armeabi-v7a/libdmengine.so _address_
 
-Note: If you get hold of a stack trace from the [Android logs](/manuals/debugging-game-and-system-logs), you might be able to symbolicate it using [ndk-stack](https://developer.android.com/ndk/guides/ndk-stack.html)
+注意: 要是从 [Android 日志](/manuals/debugging-game-and-system-logs) 获取的调用堆栈数据, 可能需要使用 [ndk-stack](https://developer.android.com/ndk/guides/ndk-stack.html) 进行地址解析
 
-### Symbolicate an iOS callstack
+### iOS 调用堆栈映射
 
-1. If you are using Native Extensions, the server can provide the symbols (.dSYM) for you (pass `--with-symbols` to bob.jar)
+1. 如果使用了原生扩展, 服务器会为你提供映射数据 (.dSYM) 文件 (使用 bob.jar 连同 `--with-symbols` 参数)
 
 	$ unzip <project>/build/arm64-darwin/build.zip
-	# it will produce a Contents/Resources/DWARF/dmengine
+	# 文件会被解压到 Contents/Resources/DWARF/dmengine
 
-1. If you're not using Native Extensions, download the vanilla symbols:
+1. 如果没用原生扩展, 直接下载映射文件:
 
 	$ wget http://d.defold.com/archive/<sha1>/engine/arm64-darwin/dmengine.dSYM
 
-1. Symbolicate using load address
+1. 地址映射
 
-	For some reason, simply putting the address from the callstack doesn't work (i.e. load address 0x0)
+	不能直接使用堆栈里的地址 (比如载入地址 0x0)
 
 		$ atos -arch arm64 -o Contents/Resources/DWARF/dmengine 0x1492c4
 
-	# Neither does specifying the load address directly
+	# 也不能作为参数加入载入地址
 
 		$ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp -l0x100000000 0x1492c4
 
-	Adding the load address to the address works:
+	二者相加才可以:
 
 		$ atos -arch arm64 -o MyApp.dSYM/Contents/Resources/DWARF/MyApp 0x1001492c4
 		dmCrash::OnCrash(int) (in MyApp) (backtrace_execinfo.cpp:27)

+ 4 - 172
docs/zh/manuals/debugging.md

@@ -1,179 +1,11 @@
 ---
 title: Defold 调试
-brief: 本教程介绍了 Defold 预置的调试功能.
+brief: 本教程介绍了 Defold 的内置调试工具.
 ---
 
 # 调试
 
-Defold 包含了一个集成 Lua 调试和检视的功能. 连同内置 [性能分析工具](/manuals/profiling) 能够帮助你找到问题根源和性能瓶颈.
+Defold 内置集成式 Lua 调试器与检视工具. 加上内置的 [分析工具](/manuals/profiling) 一起提供了强大的游戏调试除错性能分析功能. 万一游戏崩溃了 Defold 还能提供游戏引擎崩溃日志.
 
-## 输出和可视调试
-
-Defold 里最简单的调试方法是用 [print 调试](http://en.wikipedia.org/wiki/Debugging#Techniques). 使用 `print()` 或者 [`pprint()`](/ref/builtins#pprint) 语句观察变量或者定位执行流程. 如果有个游戏对象行为与预料不符, 就可以在它上面加个脚本以便进行调试. 使用打印函数能把内容输出到编辑器内的 *控制台* 上.  除了打印函数, 引擎还提供了在屏幕上画调试文字和直线的功能. 发送消息到 `@render` 接口即可:
-
-```lua
--- 在屏幕上画 "my_val" 的值以及一些调试文字
-msg.post("@render:", "draw_text", { text = "My value: " .. my_val, position = vmath.vector3(200, 200, 0) })
-
--- 在屏幕上玩家和敌人之间画调试直线
-local start_p = go.get_position("player")
-local end_p = go.get_position("enemy")
-local color_red = vmath.vector4(1, 0, 0, 1)
-msg.post("@render:", "draw_line", { start_point = start_p, end_point = end_p, color = color_red })
-```
-
-可视调试信息把数据加入渲染流程以便进行常规渲染.
-
-* `"draw_line"` 加入的数据在渲染脚本 `render.draw_debug3d()` 函数里渲染.
-* `"draw_text"` 使用 "/builtins/fonts/system_font.font" 以及 "/builtins/fonts/system_font.material" 材质进行渲染.
-
-注意如果需要每帧都进行渲染, 把消息发送放在 `update()` 函数里是个好主意.
-
-## 运行调试器
-
-要运行调试器, 或者选择 <kbd>Debug ▸ Run with Debugger</kbd> 即可打开带调试器的游戏, 或者选择 <kbd>Debug ▸ Attach Debugger</kbd> 把调试器附加的已经运行着的游戏上.
-
-![overview](images/debugging/overview.png){srcset="images/debugging/[email protected] 2x"}
-
-调试器一旦附加到游戏上, 你就可以通过控制台调试器面板按钮或者从 <kbd>Debug</kbd> 菜单来控制游戏运行了:
-
-Break
-: ![pause](images/debugging/pause.svg){width=60px .left}
-  立即停止游戏执行. 游戏会在断点处停止运行. 此时可以查看游戏状态, 步进游戏, 或者继续运行直到下一个断点. 编辑器上表明了当前运行的点:
-
-  ![script](images/debugging/script.png){srcset="images/debugging/[email protected] 2x"}
-
-Continue
-: ![play](images/debugging/play.svg){width=60px .left}
-  Continue running the game. The game code will continue to run until you either press pause or the execution hits a breakpoint that you have set. If execution breaks at a set breakpoint, the the execution point is marked in the code editor on top of the breakpoint marker:
-
-  ![break](images/debugging/break.png){srcset="images/debugging/[email protected] 2x"}
-
-Stop
-: ![stop](images/debugging/stop.svg){width=60px .left}
-  Stop the debugger. Pressing this button will immediately stop the debugger, detach it from the game and terminate the running game.
-
-Step Over
-: ![step over](images/debugging/step_over.svg){width=60px .left}
-  Advance execution of the program one step. If the execution involves running another Lua function, the execution _will not step into the function_ but continue running and stop on the next line below the function call. In this example, if the user presses "step over", the debugger will execute code and stop at the `end` statement below the line with the call to the function `nextspawn()`:
-
-  ![step](images/debugging/step.png){srcset="images/debugging/[email protected] 2x"}
-
-::: sidenote
-A line of Lua code does not correspond to a single expression. Stepping in the debugger moves ahead one expression at a time, meaning that currently you may have to hit the step button more than once to advance to the next line.
-:::
-
-Step Into
-: ![step in](images/debugging/step_in.svg){width=60px .left}
-  Advance execution of the program one step. If the execution involves running another Lua function, the execution _will step into the function_. Calling the function adds an entry to the call stack. You can click each entry in the call stack list to view the entry point and the content of all variables in that closure. Here, the user has stepped into the function `nextspawn()`:
-
-  ![step into](images/debugging/step_into.png){srcset="images/debugging/[email protected] 2x"}
-
-Step Out
-: ![step out](images/debugging/step_out.svg){width=60px .left}
-  Continue execution until it returns from the current function. If you have stepped execution into a function, pressing the button "step out" will continue execution until the function returns.
-
-Setting and clearing breakpoints
-: You can set an arbitrary number of breakpoints in your Lua code. When the game runs with the debugger attached, it will stop execution at the next breakpoint it encounters and wait for further interaction from you.
-
-  ![add breakpoint](images/debugging/add_breakpoint.png){srcset="images/debugging/[email protected] 2x"}
-
-  To set or clear a breakpoint, click in the column just right of the line numbers in the code editor. You can also select <kbd>Edit ▸ Toggle Breakpoint</kbd> from the menu.
-
-Evaluating Lua expressions
-: With the debugger attached and the game stopped at a breakpoint, a Lua runtime is available with the current context. Type Lua expressions in the bottom of the console and press <kbd>Enter</kbd> to evaluate them:
-
-  ![console](images/debugging/console.png){srcset="images/debugging/[email protected] 2x"}
-
-  It is currently not possible to modify variables through the evaluator.
-
-Detaching the debugger
-: Select <kbd>Debug ▸ Detach Debugger</kbd> to detach the debugger from the game. It will continue running immediately.
-
-## Debugging on mobile devices
-
-Some issues can be hard to debug with the editor debugger. Diagnosing problems such as native crashes and out of memory issues may need you to connect to the devices with USB cable and make use of a terminal.
-
-Android
-: Once your game is launched on your Android device, you can view all program output and crash stacktraces using the "adb" tool, which is part of the Android SDK. Documentation for "adb" and installation links can be found here: https://developer.android.com/studio/command-line/adb.html
-
-  Once installed and setup, connect your device with USB, open a terminal and run:
-
-  ```txt
-  cd <path_to_android_sdk>/platform-tools/
-  adb logcat
-  ```
-
-  The device will then dump all the output to the current terminal, along with any prints from the game.
-
-  If you want to see only Defold application outputs use next command:
-  ```txt
-  cd <path_to_android_sdk>/platform-tools/
-  adb logcat -s defold
-  ```
-
-iOS
-: On iOS you can attach the LLDB debugger to a game running on device. To debug a game it needs to be signed with a “Apple Developer Provisioning Profile” that include the device you want to debug on. Bundle the game from the editor and supply the provisioning profile in the bundle dialog (bundling for iOS is only available on macOS).
-
-  To launch the game and attach the debugger you will need a tool called [ios-deploy](https://github.com/phonegap/ios-deploy). Install and debug your game by running the following in a terminal:
-
-  ```txt
-  ios-deploy --debug --bundle <path_to_game.app> # NOTE: not the .ipa file
-  ```
-
-  This will install the app on your device, start it and automatically attach a LLDB debugger to it. If you are new to LLDB, read [Getting Started with LLDB](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-basics.html).
-
-
-## Extracting the log.txt file
-
-If you enable the *Write Log* setting in "game.project", any game output will be written to disk, to a file called "log.txt". Here is how you extract the file if you run the game on device:
-
-iOS
-: Connect your device to a computer with macOS and Xcode installed.
-
-  Open Xcode and go to <kbd>Window ▸ Devices and Simulators</kbd>.
-
-  Select your device in the list, then select the relevant app in the *Installed Apps* list.
-
-  Click the cog icon below the list and select <kbd>Download Container...</kbd>.
-
-  ![download container](images/debugging/download_container.png){srcset="images/debugging/[email protected] 2x"}
-
-  Once the container has been extracted it will be shown in *Finder*. Right click the container and select <kbd>Show Package Content</kbd>. Locate the file "log.txt", which should be located in "AppData/Documents/".
-
-Android
-: The ability to extract the "log.txt" depends on OS version and manufacturer. Here is a short and simple step by step guide: https://stackoverflow.com/a/48077004/129360
-
-## Lua debug library
-
-Lua comes with a debug library that is useful in some situations, particularly if you need to inspect the innards of your Lua environment. You can find more information about it here: http://www.lua.org/pil/contents.html#23.
-
-## Debugging checklist
-
-If you encounter an error or if your game does not behave like expected, here is a debugging checklist:
-
-1. Check the console output and verify that there are no runtime errors.
-
-2. Add `print` statements to your code to verify that the code is actually running.
-
-3. If it's not running, check that you have done the proper setup in the editor required for the code to run. Is the script added to the right game object? Have your script acquired input focus? Are the input-triggers correct? Is the shader code added to the material? Etc.
-
-4. If your code is depending on the values of variables (in an if-statement, for example), either `print` those values where they are used or checked, or inspect them with the debugger.
-
-Sometimes finding a bug can be a hard and time consuming process, requiring you to go through your code bit by bit, checking everything and narrowing down the faulty code and eliminating sources of error. This is best done by a method called "divide and conquer":
-
-1. Figure out which half (or less) of the code that must contain the bug.
-2. Again, figure out which half, of that half, must contain the bug.
-3. Continue narrowing down the code that must cause the bug until you find it.
-
-Happy hunting!
-
-## Debugging problems with physics
-
-If you have problems with physics and collisions aren't working as expected it is recommended to enable physics debugging. Check the *Debug* checkbox in the *Physics* section of the *game.project* file:
-
-![physics debug setting](images/debugging/physics_debug_setting.png)
-
-When this checkbox is enabled Defold will draw all collision shapes and contact points of collisions:
-
-![physics debug visualisation](images/debugging/physics_debug_visualisation.png)
+* 参考 [调试游戏逻辑](/manuals/debugging-game-logic).
+* 参考 [调试原生代码](/manuals/debugging-native-code).

+ 2 - 4
docs/zh/manuals/extension-facebook.md

@@ -19,11 +19,9 @@ https://github.com/defold/extension-facebook/archive/master.zip
 
 推荐使用 [指定版本](https://github.com/defold/extension-facebook/releases) 的zip包链接作为依赖.
 
-从 Defold 1.2.162 开始, 此扩展需要其他依赖:
-```
-https://github.com/defold/extension-gps/archive/master.zip
-```
+Facebook API 文档位于 [fb扩展主页](https://defold.github.io/extension-facebook/).
 
+## 注册为 Facebook 开发者
 
 开发 Facebook 应用首先要注册成为 Facebook 开发者. 这样你的 Defold 游戏就能与 Facebook 应用交互了.
 

+ 202 - 0
docs/zh/manuals/extension-iap.md

@@ -0,0 +1,202 @@
+---
+title: Defold 中的内支付
+brief: 应用内支付 (也称内购买) 允许用户付费以获得额外的内容或功能. 本教程介绍了相关功能的 Defold API.
+---
+
+# 应用内支付
+
+Defold 提供了方便的 iOS Appstore "in-app purchases" 和 Google Play 及 Amazon "in-app billing" 系统接口. Facebook Canvas 的 "game payments" 用于 Facebook Canvas 游戏. 这些服务能让你销售:
+
+* 标准应用内支付 (一次性购买) 的消耗品和非消耗品
+* 订阅 (自动循环购买)
+
+::: 注意
+目前 Defold 接口可以与 Apple 的 Storekit 完整交互. 对于 Google Play 和 Facebook Canvas, 接口是一致的, 这有助于代码跨平台. 但是不同平台需要的流程有所不同. 而且注意目前没有针对 OS X 系统上 Mac Appstore 的支付接口.
+:::
+
+关于 Apple, Google, Amazon 和 Facebook 的详细文档参考:
+
+* [In-App Purchase Programming Guide](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html).
+* [Google Play In-app Billing documentation](http://developer.android.com/google/play/billing/index.html).
+* [Amazon In-app Purchase documentation](https://developer.amazon.com/public/apis/earn/in-app-purchasing).
+* [Facebook game payments documentation](https://developers.facebook.com/docs/payments).
+
+## 安装扩展
+
+首先要在 `game.project` 文件中加入内支付扩展依赖. 最新稳定版本地址如下:
+```
+https://github.com/defold/extension-iap/archive/master.zip
+```
+
+推荐使用 [正式发布版](https://github.com/defold/extension-iap/releases) 的zip连接作为依赖引用.
+
+其 API 文档详见 [扩展项目首页](https://defold.github.io/extension-iap/).
+
+
+## 使用静态报告测试 Google Play Billing
+
+Android 建议使用 Google Play 的静态报告来实现 IAP. 这样在正式发布之前就可以确保内支付工作正常. 测试用静态报告包括4个ID:
+
+`android.test.purchased`
+: Google Play 报告模拟支付完成. 此报告包含一个 JSON 字符串, 内含模拟支付信息 (比如模拟用户ID等).
+
+`android.test.canceled`
+: Google Play 报告模拟支付取消. 这种情况可能因为付款时出现错误, 比如信用卡无效, 或者用户付款前订单被取消.
+
+`android.test.refunded`
+: Google Play 报告模拟退款完成.
+
+`android.test.item_unavailable`
+: Google Play 报告app可购买物品列表里找不到用户购买的项目.
+
+## 内支付准备流程
+
+iOS 和 Android 内支付的准备流程差不多:
+
+1. 注册为 Apple 或 Google Play 开发者.
+2. 为目标平台进行项目配置. 参考 [iOS 开发教程](/manuals/ios) 与 [Android 开发教程](/manuals/android).
+3. 为应用商店进行测试配置:
+
+    - Android 上, 使用 [Google Play Developer Console](https://play.google.com/apps/publish/).
+    - iOS 上, 使用 [iTunes Connect](https://itunesconnect.apple.com/). 注意你的 App ID (于 https://developer.apple.com 上的 "成员中心" 配置) 要开启 "In-App Purchase" 选项.
+
+    ![iTunes Connect and Google Play Dev Console](images/iap/itunes_connect_google_play.png)
+
+4. 对于 Google Play, 你需要 _上传并发布_ 测试版 *.apk* 文件. 对于 iTunes Connect, 直到应用审批之前你 _不用上传_ 应用文件给 iTunes Connect. 加入上传了未完成的应用文件给 iTunes Connect, Apple 会拒绝该应用.
+
+5. 设置应用内消费品.
+
+    ![iTunes 消费品](images/iap/itunes_products.png)
+
+    ![Google Play 消费品](images/iap/google_play_products.png)
+
+6. 设置测试用账户.
+    - 在 iTunes Connect 页面 *用户与规则* 中可以设置专门用于 _沙盒环境_ 的模拟支付用户. 要给应用做开发者证书签名然后在测试设备上登录 Appstore 沙盒账户进行测试.
+    - 在 Google Play Developer Console 上, 选择 *设置 > 账户详情* 的 License Testing 部分设置测试用户 email. 多个 email 用逗号分隔. 然后测试者可以登录并购买消费品而不会真的扣款.
+    - 在 Google Play 上, 还需要为测试者们建立 Google Group. Google 使用组来管理应用测试组成员. 在 *Alpha Testing* 页面的 *Manage list of testers* 设置测试者 Google Group. 应用上线前必须通过 Alpha 测试.
+
+![Alpha testers](images/iap/alpha_testers.png)
+
+Facebook 内支付准备流程:
+
+1. 注册为 Facebook 开发者. 登录 [Facebook for developers](https://developers.facebook.com/), 在 "My Apps" 下 "Register as a developer", 完成注册步骤.
+2. Facebook 要求支持同步和异步两种支付方式. 详情请见 [Payment overview](https://developers.facebook.com/docs/payments/overview)
+3. 建立应用托管和回调服务器:
+    * 建立托管应用的加密 canvas 地址. 详情请见 [Games on Facebook](https://developers.facebook.com/docs/games/gamesonfacebook/hosting).
+    * 建立回调服务器. 详情请见 [Setting up your callback server](https://developers.facebook.com/docs/payments/realtimeupdates#yourcallbackserver).
+4. 配置应用. 详情请见 [Facebook Developer Dashboard](https://developers.facebook.com/quickstarts/?platform=canvas).
+5. 加入测试用户. 在应用面板的 "Canvas Payments" 部分进行设置.
+6. 建立应用消费品. 详情请见 [Defining products](https://developers.facebook.com/docs/payments/implementation-guide/defining-products/).
+
+## 异步的内支付 API
+
+内支付 API 是异步的, 也就是说应用发送信息给服务器, 然后能继续运行. 等到从服务器传回的信息时, 一个 _回调_ 函数会被调用, 从中可以根据回调数据进行各种处理工作.
+
+获得消费品列表:
+
+```lua
+local COINS_ID = "com.defold.examples.coins"
+local LOGO_ID = "com.defold.examples.logo"
+
+local function product_list(self, products, error)
+    if error == nil then
+        for i,p in pairs(products) do
+            print(p.ident)
+            print(p.title)
+            print(p.description)
+            print(p.currency_code)
+            print(p.price_string)
+        end
+    else
+        print(error.error)
+    end
+end
+
+function init(self)
+    -- 初始化消费品列表 (对于 Google Play 来说一次能获取 20 个)
+    iap.list({ COINS_ID, LOGO_ID }, product_list)
+end
+```
+
+对于正式交易, 首先要注册交易结果监听器, 然后在玩家购买时调用内支付函数:
+
+```lua
+local function iap_listener(self, transaction, error)
+    if error == nil then
+        if transaction.state == iap.TRANS_STATE_PURCHASING then
+            print("Purchasing...")
+        elseif transaction.state == iap.TRANS_STATE_PURCHASED then
+            print("Purchased!")
+        elseif transaction.state == iap.TRANS_STATE_UNVERIFIED then
+            print("Unverified!")
+        elseif transaction.state == iap.TRANS_STATE_FAILED then
+            print("Failed!")
+        elseif transaction.state == iap.TRANS_STATE_RESTORED then
+            print("Restored")
+        end
+    else
+        print(error.error)
+    end
+end
+
+function on_message(self, message_id, message, sender)
+    ...
+    -- 注册内支付结果监听器.
+    iap.set_listener(iap_listener)
+    -- 买一个金币...
+    iap.buy(COINS_ID)
+    ...
+end
+```
+
+操作系统会自动弹出支付界面. 要是处于测试/沙盒环境下, 界面中会明确标明.
+
+![Confirm purchase](images/iap/ios_confirm_purchase.png)
+
+![Android purchase](images/iap/android_purchase.png)
+
+![Confirm purchase](images/iap/ios_purchase_done.png)
+
+## 实时付款
+
+大多数付款系统都是实时的. 支付完成时应用会收到一个消息, TRANS_STATE_PURCHASED. 这是交易的最终状态, 表明对于这笔交易不会再有其他消息了.
+
+## 非实时付款
+
+有的付款系统需要非实时的支持. 也就是说你的应用只在付款开始时收到一个消息. 为了验证付款完成与否, 需要你的服务器 (或者客户端) 与付款系统进行更多的交流.
+这种情况下支付完成时应用会收到一个 TRANS_STATE_UNVERIFIED 消息 (而不是 TRANS_STATE_PURCHASED). 这也是交易的最终状态, 表明对于这笔交易不会再有其他消息了.
+
+## 购买交付
+
+玩家购买消费品之后, 应用有义务告知玩家支付已完成 (比如服务器验证支付成功之后).
+内支付支持 auto-completion, 也就是自动产生支付完成的消息 (默认设置). 也可以在项目配置里关闭 auto-completion. 支付完成时手动调用 `iap.finish()`, 来产生完成消息.
+
+### 消耗品与非消耗品
+Google Play 应用商店只支持消耗品. 必须使用非消耗品的话就关闭 auto-completion 并且不要调用完成函数. 这样在 `iap.set_listener()` 被调用时, 消费品购买总是保持着购买中的状态.
+
+Apple App Store 支持非消耗品, 也就是说购买完成时才向玩家提供消费品交付. 这种情况下 auto-completion 可以开启也可以关闭 (比如你需要自己验证支付成功) 之后调用 `iap.finish()`.
+
+## 支付收据
+
+收据是一堆加密数据, 可以把它发送给 App Store 来验证付款是否真正完成. 这是用开发者服务器验证付款必须使用的东西.
+
+## 除错
+
+Android `iap.list()` 返回 "failed to fetch product"
+: 你需要上传 *.apk* 文件到 Google Play Developer Console 的 alpha 或者 beta 频道. 还要注意确保你的设配上 _日期和时间_ 是正确的.
+
+Android (Google Play) `iap.list()` 只返回 20 个消费品
+: Google 有 [每次请求返回最多 20 个消费品的限制](https://github.com/googlesamples/android-play-billing/blob/master/TrivialDrive/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl#L62). 可以多次调用 `iap.list()` 然后合并返回结果以实现20个以上的消费品列表.
+
+iOS `iap.list()` 返回空值
+: 确保你的账户是 iOS 付款应用账户, 并且签署好一切所需文件. 没有经过认证的话, 你的 iOS 应用内支付 (甚至测试支付) 操作不会正确执行.
+
+  检查 "Member Center" 上的应用ID是否开启了 in-app purchases  (检查 "Member Center" 里 "Certificates, Identifiers & Profiles" 的 "Enabled Services:" 项) 并且该应用 (或者调试版应用) 已用供应商档案进行了签名而且签名没过期.
+
+  内支付消费品信息传到沙盒环境需要几小时时间, 请耐心等待.
+
+iOS `iap.list()` 产生错误日志 "Unexpected callback set"
+: `iap.list()` 调用不可以嵌套. 从 `iap.list()` 调用 `iap.list()` 就会产生这个错误日志.
+
+在 iOS 上, "price_string" 里有个 '~' 字符
+: '~' 是未找到字体的字符占位符. 调用 `iap.list()` 返回的数据使用 _不间断空白_ (`\u00a0`) 分割价格和货币符号并填充 "price_string" 变量. 使用 GUI 组件渲染的话, 需要在字体 *extra_characters* 属性里设置所需字符. 在 Mac OS X 上按 <kbd>Option + SPACE</kbd> 就是不间断空白. 详情请见 http://en.wikipedia.org/wiki/Non-breaking_space.

+ 295 - 0
docs/zh/manuals/extension-push.md

@@ -0,0 +1,295 @@
+---
+title: Defold 的 iOS 和 Android 推送通知
+brief: 本教程介绍了如何配置和实现游戏中的本地和远程 iOS 与 Android 平台的推送通知.
+---
+
+# 推送通知
+
+推送通知作为 [原生扩展](/manuals/extensions/) 在 iOS 和 Android 设备上用来给玩家提示修改和更新之类的信息. iOS 和 Android 实现方法基本一样但是也有一些平台相关的东西需要注意.
+
+推送通知为了找到从服务器到目标设备的通路, 需要得到应用的一些信息. 最复杂的部分包括用于校验客户端接收通知的合法性的应用安全信息. 还需要用于 Apple 或者 Google 校验你发送通知合法性的服务器安全信息. 最后, 推送通知的时候, 你需要知道到用户设备的唯一路径. 为此你需要指定设备的唯一 token (用来分辨用户).
+
+## 安装扩展
+
+使用之前要在 `game.project` 文件里配置扩展依赖. 最新稳定版依赖的 URL 是:
+
+```
+https://github.com/defold/extension-push/archive/master.zip
+```
+
+推荐使用 [指定版本](https://github.com/defold/extension-push/releases) 的zip包链接作为依赖.
+
+```
+https://github.com/defold/extension-firebase-core/archive/master.zip
+```
+
+API 文档在 [推送通知扩展项目](https://defold.github.io/extension-push/) 页上.
+
+## iOS 配置
+
+::: 注意
+为了更好地使用 Apple Push Notification 服务, 最好先熟读 [Apple 的官方文档](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html).
+:::
+
+iOS 上, 推送通知需要做以下准备:
+
+* 要为 App ID 开启推送通知.
+* 需要包含此 App ID 的应用提供商档案.
+* 还需要一个 SSL 证书用来把数据从消息服务应用发送到 Apple 服务器.
+
+准备就绪后登录到 [Apple 开发者中心](https://developer.apple.com/membercenter). 找到 AppID 打开通知推送服务.
+
+![AppID push notifications](images/push/push_ios_app_id.png)
+
+记得创建推送服务 SSL 证书:
+
+![APN SSL certificate](images/push/push_ios_certificate.png)
+
+从你的服务器往通知推送服务器发送数据时需要这个证书. 开发调试时, 可以先在本地安装这个证书然后运行 [APNS-Pusher](https://github.com/KnuffApp/APNS-Pusher) 或者 [NWPusher](https://github.com/noodlewerk/NWPusher) 之类的测试工具.
+
+记得创建包含要推送通知 AppID 的供应商档案, 并且在档案中设置好开发设备. 可以在 "Member Center" 页面或者 Xcode 中进行这些操作.
+
+![Provisioning profile](images/push/push_ios_provisioning_profile.png)
+
+注意 Apple 的沙盒服务器可能需要一段时间更新信息, 通知推送功能也许不能马上使用. 要有耐心.
+
+推送通知测试代码如下:
+
+<a name="above-code"></a>
+```lua
+local function push_listener(self, payload, origin)
+    -- 通知到达这里.
+    pprint(payload)
+end
+
+function init(self)
+    local sysinfo = sys.get_sys_info()
+    if sysinfo.system_name == "Android" then
+        msg.post("#", "push_android")
+    elseif sysinfo.system_name == "iPhone OS" then
+        msg.post("#", "push_ios")
+    end
+end
+
+function on_message(self, message_id, message)
+    if message_id == hash("push_ios") then
+        local alerts = {push.NOTIFICATION_BADGE, push.NOTIFICATION_SOUND, push.NOTIFICATION_ALERT}
+        push.register(alerts, function (self, token, error)
+            if token then
+                local t = ""
+                for i = 1,#token do
+                    t = t .. string.format("%02x", string.byte(token, i))
+                end
+                -- 打印设备token
+                print(t)
+            else
+                -- 错误
+                print(error.error)
+            end
+        end)
+        push.set_listener(push_listener)
+    elseif message_id == hash("push_android") then
+        push.register(nil, function (self, token, error)
+            if token then
+                -- 打印设备token
+                print(token)
+            else
+                -- 错误
+                print(error.error)
+            end
+        end)
+        push.set_listener(push_listener)
+    end
+end
+```
+
+如果一切顺利通知监听器会被注册然后打印出设备的 token:
+
+```txt
+DEBUG:SCRIPT: 1f8ba7869b84b10df69a07aa623cd7f55f62bca22cef61b51fedac643ec61ad8
+```
+
+如果运行的是测试应用, 你现在就可以尝试使用设备token和通知服务SSL证书向你的设备推送通知了.
+
+![Pusher test](images/push/push_ios_pusher.png)
+
+通知发送之后会被测试应用接收, 进入 `push_listener()` 函数:
+
+```txt
+DEBUG:SCRIPT:
+{
+  aps = {
+    badge = 42,
+    alert = Testing.. (1),
+    sound = default,
+  }
+}
+```
+
+同时 iOS 桌面会提示通知:
+
+![iOS notification](images/push/push_ios_notification.png)
+
+如果要在图标上显示计数角标, 可以使用 `push.set_badge_count()` 函数.
+
+## Android 配置
+
+::: 注意
+建议首先阅读 Firebase Cloud Messaging 服务文档. 文档在这里 https://firebase.google.com/docs/cloud-messaging/
+:::
+
+Android 上, 推送通知需要做以下准备:
+
+* Firebase CM Sender ID 和应用 ID. 这些id会打包到应用中去.
+* 用于使用 Firebase 服务的服务器 API Key.
+
+::: 注意
+如果你的应用使用了 Google Cloud Messaging 平台, 现在需要导入 Firebase Cloud Messaging 平台中. 把应用从 Google dashboard 导入到 Firebase 即可. 导入后 *sender id* 保持不变, 你的 `game.project` 文件需要更新使用 `Firebase Application ID` (见下文).
+:::
+
+基本配置很简单. 登录 [https://console.firebase.google.com](https://console.firebase.google.com), 选择或者新建应用. 然后进入 *Grow* 的 *Cloud Messaging* 页面.
+
+![Adding Cloud Messaging to a Firebase project](images/push/push_fcm_add_cm.png)
+
+点击 Android 图标开始配置通知推送.
+
+
+![Configure Cloud Messaging for Android](images/push/push_fcm_configure_android.png)
+
+根据提示, 输入 Defold 游戏项目使用的包名.
+
+![Android cloud services info](images/push/push_fcm_register.png)
+
+下载 `google-services.json`, 我们需要这个文件里面的一些信息.
+
+![Google Cloud Messaging sender ID](images/push/push_fcm_download_json.png)
+
+下面两步可以跳过, *Add Firebase SDK* 和 *Run your app to verify installation*. SDK 已打包进 Defold, 无需手动添加.
+
+用文本编辑器打开 `google-services.json` 文件, 找到 *`project_number`* 和 *`mobilesdk_app_id`*. 把这俩id考入 `game.project` 文件, 对应 *android* 部分, `Gcm Sender Id` (`project_number`) 和 `Fcm Application Id` (`mobilesdk_app_id`).
+
+```
+{
+  "project_info": {
+    "project_number": "123456789123",
+    "firebase_url": "https://project-name-ki7h7.firebaseio.com",
+    "project_id": "project-name-ki7h7",
+    "storage_bucket": "project-name-ki7h7.appspot.com"
+  },
+  "client": [
+    {
+      "client_info": {
+        "mobilesdk_app_id": "1:123456789123:android:c1de85bbda9bc512",
+        "android_client_info": {
+          "package_name": "my.package.name"
+        }
+      },
+
+```
+
+![Settings applied to game.project](images/push/push_fcm_game_project.png)
+
+至此客户端准备就绪. [上面测试ios时用的代码](#above-code) 对 Android 同样有效. 运行并记录设备 token.
+
+```txt
+DEBUG:SCRIPT: APA91bHkcKm0QHAMUCEQ_Dlpq2gzset6vh0cz46kDDV6230C5rFivyWZMCxGXcjxRDKg1PK4z1kWg3xnUVqSDiO_4_RiG8b8HeYJfaoW1ho4ukWYXjq5RE0Sy-JTyrhqRusUP_BxRTcE
+```
+
+发送通知之前需要一个 Firebase 服务认证 key. 这个 key 位于 Firebase dashboard 的 *Settings* 的 *Cloud Messaging* 页面中.
+
+![Server Key location](images/push/push_fcm_server_key.png)
+
+一切准备就绪. 可以通过使用 Web API 的 *curl* 命令测试推送功能:
+
+```sh
+$ curl  -X POST  -H "Content-type: application/json"  -H 'Authorization: key=SERVER_KEY' -d '{"registration_ids" : ["TOKEN_ID"], "data": {"alert": "Hello"}}' https://fcm.googleapis.com/fcm/send
+```
+
+注意把 `SERVER_KEY` 和 `TOKEN_ID` 替换成你记录下的key和token.
+
+## 本地通知
+
+除了远程推送还可以使用本地通知推送. 下面是本地通知的示例:
+
+```lua
+-- 3秒后推送本地通知
+local payload = '{"data" : {"field" : "Some value", "field2" : "Other value"}}'
+id, err = push.schedule(3, "A notification!", "Hello there", payload, { action = "get going" })
+```
+
+通知安排调用返回唯一id以便后续使用. `push.schedule()` 函数的最后一个参数不同平台有不同内容:
+
+action
+: (iOS 有效). 这个值用来设置通知右键标题或者用来替换解锁提示  "slide to unlock" 中的 "unlock" 字样.
+
+badge_count
+: (iOS 有效). 图标计数角标. 设置为0清除角标.
+
+priority
+: (Android 有效). 优先级决定了UI如何展示通知. 有以下5个等级:
+
+  - push.PRIORITY_MIN
+  - push.PRIORITY_LOW
+  - push.PRIORITY_DEFAULT
+  - push.PRIORITY_HIGH
+  - push.PRIORITY_MAX
+
+  如果不指定, 默认使用最大优先级.
+
+## 本地通知查看
+
+API 提供了两个函数用来查看当前安排下的本地通知.
+
+```lua
+n = push.get_scheduled(id)
+pprint(n)
+```
+
+这个表里记录了通知相关的详细信息:
+
+```txt
+DEBUG:SCRIPT:
+{
+  payload = {"data":{"field":"Some value","field2":"Other value"}},
+  title = A notification!,
+  priority = 2,
+  seconds = 19.991938,
+  message = Hello there,
+}
+```
+
+注意 `seconds` 是指离通知推送还差多少秒. 还有一个函数可以查看当前安排下的 _所有_ 通知:
+
+```lua
+all_n = push.get_all_scheduled()
+pprint(all_n)
+```
+
+结果是通知id与其内容对应的表:
+
+```txt
+DEBUG:SCRIPT:
+{
+  0 = {
+    payload = {"data":{"field":"Some value","field2":"Other value"}},
+    title = A notification!,
+    priority = 2,
+    seconds = 6.009774,
+    message = Hey hey,
+  }
+  1 = {
+    payload = {"data":{"field":"Some value","field2":"Other value"}},
+    title = Another notification!,
+    priority = 2,
+    seconds = 12.652521,
+    message = Hello there,
+  }
+  2 = {
+    payload = {"data":{"field":"Some value","field2":"Other value"}},
+    title = Hey, much notification!,
+    priority = 2,
+    seconds = 15.553719,
+    message = Please answer!,
+  }
+}
+```

+ 7 - 0
docs/zh/manuals/extension-websocket.md

@@ -0,0 +1,7 @@
+---
+title: WebSocket 连接
+brief: 本教程介绍了 websocket 连接的使用方法.
+---
+## WebSocket 连接
+
+Defold 没有内置 WebSocket 连接功能. 建议使用 [Defold-WebSocket 扩展程序](https://github.com/britzl/defold-websocket) 实现该功能.

+ 259 - 0
docs/zh/manuals/extension-webview.md

@@ -0,0 +1,259 @@
+---
+title: Defold 的 WebViews
+brief: WebViews 可以在你的手机上显示一个网页层. 同时支持在后台运行用户定义的js代码. 本教程介绍了 Defold 的官方 WebView 扩展, API 和功能.
+---
+
+# WebViews
+WebView 提供了一套特殊的 API 用来在手机上显示一个网页层. 首先让我们来实现一个简单的 webview.
+然后我们会讨论如何使用一套简单的控制按钮控制这个 webview.
+
+## 安装扩展
+
+在你的 `game.project` 文件中设置 webview 依赖.
+最新版本位于如下 URL:
+```
+https://github.com/defold/extension-webview/archive/master.zip
+```
+
+API文档位于 [扩展首页](https://defold.github.io/extension-webview/).
+
+## 打开 webview
+使用 `webview.create` 就能创建一个网页层, 并且返回一个唯一id. 下文中我们把这个 ID 称为 `webview_id`,
+多个 `webview` 之间进行交互时会用到这个id. 也就是说创建和维护多个 webview 是可行的.
+
+`webview.create` 带着一个函数参数, 待会儿我们再来仔细看看这个回调, 现在先给它留空.
+```lua
+local webview_id = webview.create(function()
+        -- 目前无代码
+    end)
+```
+默认状况下新建的 webview 都是不可见的, 因为它还没有加载任何内容. 其主要功能就是显示网页, 现在就来加载个超酷的网页吧!
+
+调用 `webview.open` 函数, 第一个参数就是上文的那个 `webview_id`, 第二个参数是要打开的URL.
+
+```lua
+local request_id = webview.open(webview_id, "http://www.defold.com") --广告无处不在
+```
+
+这个函数返回网页请求的id, 这个id我们稍后也会用到.
+
+如果一切顺利你将看到神奇的网页占满了屏幕, 就是 Defold 官方首页.
+
+::: 注意
+要在 iOS 里访问的网页必须遵循在 `Info.plist` 文件中的 `NSAppTransportSecurity` 里面设置好的键值对.
+```
+<key>NSAllowsArbitraryLoads</key>
+<true/>
+```
+
+开发的时候可以随便设置, 但是发布到 App Store 之后就只能通过使用 `NSExceptionDomains` 键代替. 这有点超出本教程讨论范围,
+详情可以参考 [Apple 开发者文档](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35).
+:::
+
+## 回调函数
+顺利打开网页固然是好, 但要是 URL 无效或者出现其他不可预知的问题时要给用户显示错误信息怎么办? 或者要在用户离开网页时做些什么该怎么办?
+幸运的是 webview 扩展程序具备了报错, 导航, 载入成功等等事件回调功能. 只需在调用 `webview.create` 时传入回调函数作为参数即可.
+
+回调函数特征如下:
+```lua
+function callback(self, webview_id, request_id, type, data)
+```
+
+* **`self`** - 回调函数所处的脚本引用.
+* **`webview_id`** - 回调函数可以做到多个webview共用, 这个参数引用的是回调事件发生的那个webview的id.
+* **`request_id`** - 同样 `webview.open` 也可以共用一个回调回调函数, 这个参数引用的是回调事件发生的那个载入请求的id.
+* **`type`** - 事件的类型, 枚举类型, 下文 *回调类型* 章节会详细探讨.
+* **`data`** - 不同时间连带的各种数据信息.
+
+#### 回调类型
+回调的 `type` 参数可以被设置为以下枚举之一:
+
+* **`webview.CALLBACK_RESULT_URL_LOADING`** - 在 webview 内导航时, 载入事件被触发. 调用 `webview.open` 或者
+用户点击页面上的超级链接都会造成事件触发. 事件的处理结果决定了载入请求是否被允许. 如果返回 `false` 则载入终止, 其他值则是允许载入.
+被允许的链接也会记录在回调函数 `data` 表的 `url` 项里.
+* **`webview.CALLBACK_RESULT_URL_ERROR`** 和 **`webview.CALLBACK_RESULT_EVAL_ERROR`** -一旦载入出错, 或者
+执行JavaScript脚本出错 (下文 *运行JavaScript脚本* 章节会详细探讨), 错误事件就会被触发. `data` 表的 `result` 项用一个字符串记录了错误的详细内容.
+* **`webview.CALLBACK_RESULT_URL_OK`** 和 **`webview.CALLBACK_RESULT_EVAL_OK`** - 一旦载入成功, 或者执行JavaScript脚本成功,
+OK事件就会被触发. 对于成功执行的JavaScript程序, 其执行结果会被保存在 `data` 表的 `result` 项之中.
+
+事件触发介绍完了, 现在我们来看一个复杂点的例子.
+
+比如我们要向玩家展示一个反馈页面, 玩家通过一个 HTML 表格发送反馈意见. 我们要在载入不成功的时候要提示友好的错误信息并关闭webview而不是把白屏留给玩家.
+接下来我们尽量不让玩家离开这个反馈页面.
+
+升级版的 `webview.create` 调用和回调被设计成下面这样:
+```lua
+local player_feedback_url = "https://example.com/my_game_name/customer_feedback"
+
+local function webview_callback(self, webview_id, request_id, type, data)
+    if type == webview.CALLBACK_RESULT_URL_ERROR then
+        -- 遇到错误!
+        -- 关闭 webview 然后显示提示文本!
+        webview.destroy(webview_id)
+        label.set_text("#label", "Player feedback not available at this moment.")
+
+    elseif type == webview.CALLBACK_RESULT_URL_LOADING then
+        -- 不让玩家离开这个页面.
+        if data.url ~= player_feedback_url then
+            return false
+        end
+    end
+end
+
+local feedback_webview = webview.create(webview_callback)
+webview.open(feedback_webview, player_feedback_url)
+```
+
+一个反馈页面展示就完成了. 网页自己做, 打开后大概像这个样子:
+
+![Player feedback web page](images/webview/webview_player_feedback1.png)
+
+注意: 我们的例子里有一个指向 google.com 的超级链接, 目的是试试玩家点别的链接出不出的去. --牛虻
+
+强制反馈功能完成! 但是怎么提交反馈呢? 也许玩家不想提交反馈呢, 怎么返回游戏? 再说, 全屏的网页真的合适吗? 后面的游戏界面全都被挡住了啊!
+我们会在下文的 *运行 JavaScript 脚本* 和 *可视定位控制面板* 章节继续探讨.
+
+## 载入展示自己的 HTML 网页
+继续深入探讨之前, 我们来动手做一个可以用来交互的 HTML 简单网页.
+
+通过调用 `webview.open_raw` 函数我们可以让webview直接解析加载 HTML 文件源码. 这样即使没有服务器, 网络环境恶劣的情况下, 都可以载入我们的网页.
+
+`webview.open_raw` 的第一个参数和 `webview.open` 一样是 `webview_id`. 第二个参数换成网页源代码引用.
+
+下面来看一个把网页代码直接写在脚本里的例子:
+```lua
+local feedback_html = [[
+<html>
+<script type="text/javascript">
+    function closeWebview() {
+        // 暂时留空
+    }
+    function submitFeedback() {
+        // 暂时留空
+    }
+</script>
+<body>
+    <center>
+    <h4>Hello Player!</h4>
+    <p>Please provide some feedback for my awesome game!</p>
+    <form>
+        <label>Game feedback:<br><textarea placeholder="Is it fun? What can be improved?" style="width: 300px; height: 80px"></textarea></label><br>
+        <input type="button" onclick="submitFeedback()" value="Submit feedback">
+        <br>
+        <input type="button" onclick="closeWebview()" value="Cancel">
+    </form>
+</center>
+</body>
+</html>
+]]
+
+local function webview_callback(self, webview_id, request_id, type, data)
+    -- ...
+end
+
+local webview_id = webview.create(webview_callback)
+webview.open_raw(webview_id, feedback_html)
+```
+
+效果与前面的示例类似, 不同的是这次我们可以随时任意修改网页代码.
+**注意:** 本例中 `webview_callback` 函数与前例类似故忽略.
+
+众所周知一个 HTML 源码包含所有代码和资源是不明智的, 最好把 JavaScript 和 CSS 等资源分门别类保存为文件, 这种情况下
+可以使用 [`sys.load_resource`](https://www.defold.com/ref/sys/#sys.load_resource:filename) 进行资源文件的预加载.
+而且这样做还有一个好处就是可以随时打开网页浏览器查看网页效果.
+
+新建一个文件夹 (`custom_resources`) 和一个 HTML 文件 (`feedback.html`). 然后用 `feedback_html` 变量引用这些资源.
+
+```lua
+local feedback_html = sys.load_resource("/custom_resources/feedback.html")
+-- ...
+webview.open_raw(webview_id, feedback_html)
+```
+
+## 可视性和位置控制
+现在来解决网页占据全屏问题.
+
+为了更方便的互动, 我们要把网页放在游戏屏幕上半部分. 可以使用 `webview.set_position` 函数设置webview的位置和宽高.
+设置 `-1` 代表在这个轴向上占据全部屏幕.
+
+```lua
+local webview_id = webview.create(webview_callback)
+-- 位置: 屏幕左上角 (0, 0)
+-- 尺寸: 全屏款, 500像素高
+webview.set_position(webview_id, 0, 0, -1, 500)
+```
+
+![Resized feedback page](images/webview/webview_player_feedback2.png)
+
+遇到性能不理想的设备, 网页从加载到显示可能会白屏很长时间. 这个体验很不好, 所以加载完成之前我们先把webview隐藏起来. 同时我们还要提示玩家资源正在加载.
+
+这里用到 `webview.open_raw` (`webview.open` 同样) 的第三个参数, 传入一个表, 然后设置 `hidden` 键为 `true`.
+默认是 `false`, 代表像前面示例那样一调用加载就可见.
+
+```lua
+webview.open_raw(webview_id, feedback_html, {hidden = true})
+```
+
+等到 `webview.CALLBACK_RESULT_URL_OK` 事件触发说明资源加载完毕. 这时就可以显示webview了, 调用 `webview.set_visible` 函数即可.
+
+升级版的回调函数如下:
+```lua
+local function webview_callback(self, webview_id, request_id, type, data)
+    if type == webview.CALLBACK_RESULT_URL_OK then
+        -- 顺利完成加载, 显示webview!
+        webview.set_visible(webview_id, 1)
+    elseif type == webview.CALLBACK_RESULT_URL_ERROR then
+        -- ...
+```
+
+## 运行 JavaScript 脚本
+现在来解决关闭webview的事.
+
+前例中已经出现过, 遇到错误事件触发时, 调用了 `webview.destroy` 函数. 但是没有错误就没法把握关闭webview的时机.
+幸好引擎提供了从 Lua 到webview里运行的 JavaScript 程序的交互功能. 这样我们就能关注webview里js变量的变化.
+
+当玩家按下网页上的一个按钮时, 运行一段程序, 改变一个变量.
+```js
+var shouldClose = false;
+function closeWebview() {
+    shouldClose = true;
+}
+function submitFeedback() {
+    // 自定义反馈处理代码
+    // ...
+    closeWebview();
+}
+
+```
+
+不论玩家按了 "提交反馈" 还是 "取消反馈" 按钮, 程序都会把 `shouldClose` 变量设置为 true.
+
+在 Lua 脚本里我们只要发现 `shouldClose` 变为 true 了, 就知道该调用 `webview.destroy` 了.
+正好有个好地方来关注这个变量, 就是在每帧都会被调用的 `update` 函数里.
+
+```lua
+function update(self, dt)
+    if not self.closeCheckRequest then
+        self.closeCheckRequest = webview.eval(webview_id, "shouldClose")
+    end
+end
+```
+
+注意这里 `webview.eval` 返回的并不是 JavaScript 的运行结果, 而是 *运行请求id*. 我们首先要确定回调函数的请求id, 这个函数里传入的 `data.result` 才是真正的 JavaScript 运行结果.
+
+```lua
+local function webview_callback(self, webview_id, request_id, type, data)
+    if type == webview.CALLBACK_RESULT_EVAL_OK and
+        request_id == self.closeCheckRequest then
+
+        -- 比较JavaScript执行结果, 如果是 "true" (iOS 上为 "1" )
+        -- 就应该关闭 webview!
+        if data.result == "true" or data.result == "1" then
+            webview.destroy(webview_id)
+        end
+
+    elseif type == webview.CALLBACK_RESULT_URL_OK then
+        -- ...
+```
+
+这样一来玩家在点击按钮之后就能返回继续游戏了!

+ 2 - 132
docs/zh/manuals/extensions-debugging-ios.md

@@ -1,136 +1,6 @@
 ---
 title: 在 iOS/macOS 中调试
-brief: 本教程介绍了如何使用 XCode 进行调试.
+brief: 本教程介绍了如何使用 Xcode 进行调试.
 ---
 
-# 在 iOS/macOS 中调试
-
-这里我们介绍如何使用 [XCode](https://developer.apple.com/xcode/), Apple的 macOS 和 iOS 首选开发环境来调试应用.
-
-## Xcode
-
-* 使用 bob, 加上 `--with-symbols` 选项打包应用
-
-		$ cd myproject
-		$ wget http://d.defold.com/archive/<sha1>/bob/bob.jar
-		$ java -jar bob.jar --platform armv7-darwin build --with-symbols debug --archive bundle -bo build/ios -mp <app>.mobileprovision --identity "iPhone Developer: Your Name (ID)"
-
-* 安装应用, 可以通过 `XCode`, `iTunes` 或者 [ios-deploy](https://github.com/ios-control/ios-deploy)
-
-		$ ios-deploy -b <AppName>.ipa
-
-* 得到 `.dSYM` 文件夹 (即调试 symbols)
-
-	* 如果没使用原生扩展, 可以从 [d.defold.com](http://d.defold.com) 下载 `.dSYM` 文件
-
-	* 如果使用了原生扩展, 可以使用 [bob.jar](https://www.defold.com/manuals/bob/) 生成 `.dSYM` 文件夹. 只需要 building (不需要 archive 和 bundling):
-
-			$ cd myproject
-			$ unzip .internal/cache/arm64-ios/build.zip
-			$ mv dmengine.dSYM <AppName>.dSYM
-			$ mv <AppName>.dSYM/Contents/Resources/DWARF/dmengine <AppName>.dSYM/Contents/Resources/DWARF/<AppName>
-
-
-### 创建项目
-
-要正确的调试, 我们需要一个项目, 以及一个代码映射(source map).
-这次项目不是用来编译的, 只是调试举例.
-
-*新建 XCode 项目, 选择 `Game` 模板
-
-	![project_template](images/extensions/debugging/ios/project_template.png)
-
-* 指定一个名字 (例如 `debug`) 并且使用默认设置
-
-* 选择一个存放项目的目录
-
-* 为应用加入代码文件
-
-	![add_files](images/extensions/debugging/ios/add_files.png)
-
-* 确保 "Copy items if needed" 未选中.
-
-	![add_source](images/extensions/debugging/ios/add_source.png)
-
-* 结果是这样
-
-	![added_source](images/extensions/debugging/ios/added_source.png)
-
-
-* 关闭 `Build` 步骤
-
-	![edit_scheme](images/extensions/debugging/ios/edit_scheme.png)
-
-	![disable_build](images/extensions/debugging/ios/disable_build.png)
-
-* 设置 `Deployment target` 版本
-
-	![deployment_version](images/extensions/debugging/ios/deployment_version.png)
-
-* 设置目标设备
-
-	![select_device](images/extensions/debugging/ios/select_device.png)
-
-
-### 启动调试器
-
-调试应用有如下方法
-
-* 可以使用 `Debug` -> `Attach to process...` 然后选择要调试应用
-
-* 也可以选择 `Attach to process by PID or Process name`
-
-	![select_device](images/extensions/debugging/ios/attach_to_process_name.png)
-
-	然后在设备上启动应用
-
-* 在 `Edit Scheme` 中加入 <AppName>.app 作为可运行文件夹
-
-### 调试 symbols
-
-**要使用 lldb, 运行必须先暂停**
-
-* 把 `.dSYM` 目录加入到 lldb 中
-
-		(lldb) add-dsym <PathTo.dSYM>
-
-	![add_dsym](images/extensions/debugging/ios/add_dsym.png)
-
-* 确认 `lldb` 成功读取 symbols
-
-		(lldb) image list <AppName>
-
-### 路径映射
-
-* 加入引擎路径 (根据你的安装目录自行调整)
-
-		(lldb) settings set target.source-map /Users/builder/ci/builds/engine-ios-64-master/build /Users/mathiaswesterdahl/work/defold
-		(lldb) settings append target.source-map /private/var/folders/m5/bcw7ykhd6vq9lwjzq1mkp8j00000gn/T/job4836347589046353012/upload/videoplayer/src /Users/mathiaswesterdahl/work/projects/extension-videoplayer-native/videoplayer/src
-
-	* 从可运行文件夹里可以得到 job 文件夹.
-	job 文件夹命名类似这样 `job1298751322870374150`, 每次都是随机数字.
-
-			$ dsymutil -dump-debug-map <executable> 2>&1 >/dev/null | grep /job
-
-* 验证路径映射
-
-		(lldb) settings show target.source-map
-
-可以使用如下命令确定 symbol 的源代码文件
-
-	(lldb) image lookup -va <SymbolName>
-
-
-### 断点
-
-* 从 project 视图打开一个文件, 然后设置断点
-
-	![breakpoint](images/extensions/debugging/ios/breakpoint.png)
-
-## 注意
-
-### 检查二进制文件 UUID
-
-为了让调试器接受 `.dSYM` 文件夹, UUID 需要与可运行文件的 UUID 相匹配. 你可以这样检查 UUID:
-
-	$ dwarfdump -u <PathToBinary>
+本教程已被移至 [调试 iOS 原生代码](/manuals/debugging-native-code-ios).

+ 4 - 4
docs/zh/manuals/extensions-debugging.md

@@ -32,7 +32,7 @@ brief: 本教程介绍了一些调试包含原生扩展程序应用的方法.
 * Visual studio - Windows
 * VSCode - Windows, macOS, Linux
 * Android Studio - Windows, macOS, Linux
-* XCode - macOS
+* Xcode - macOS
 * WinDBG - Windows
 * lldb / gdb - macOS, Linux, (Windows)
 * ios-deploy - macOS
@@ -41,7 +41,7 @@ brief: 本教程介绍了一些调试包含原生扩展程序应用的方法.
 
 * Visual studio - Windows + platforms supporting gdbserver (E.g. Linux/Android)
 * VSCode - Windows, macOS (lldb), Linux (lldb/gdb) + platforms supporting gdbserver
-* XCode -  macOS, iOS
+* Xcode -  macOS, iOS
 * Android Studio - Android
 * WinDBG - Windows
 * lldb/gdb - macOS, Linux, (iOS)
@@ -64,7 +64,7 @@ brief: 本教程介绍了一些调试包含原生扩展程序应用的方法.
 
 #### [iOS](/manuals/extensions-debugging-ios)
 
-在 iOS 中, 你要使用 iTunes 或者 XCode 来观察设备日志.
+在 iOS 中, 你要使用 iTunes 或者 Xcode 来观察设备日志.
 
 ### Defold 崩溃日志
 
@@ -90,7 +90,7 @@ adb 可以显示此文件在哪 (不同设备保存位置不同)
 
 在 iTunes 中, 你可以 view/download 应用容器.
 
-在 `XCode -> Devices` 窗口中, 也可以选择崩溃日志
+在 `Xcode -> Devices` 窗口中, 也可以选择崩溃日志
 
 
 ### Symbolication

+ 5 - 1
docs/zh/manuals/extensions-details.md

@@ -18,6 +18,10 @@ brief: 本教程介绍了有关编译系统用来编译原生扩展的一些细
 
 ## 工具链
 
+
+
+
+
 ### SDK 版本
 
 * Android: NDK 20r, Build Tools 23.0.2, Api Level 16 for armv7 and Api level 21 for arm64
@@ -35,7 +39,7 @@ brief: 本教程介绍了有关编译系统用来编译原生扩展的一些细
 * Win32: `Microsoft Visual Studio 2019` (`clang 9` on build server)
 * iOS/MacOS: `apple-clang` (`clang 9` on build server)
 
-对于 iOS/MacOS, 我们分别使用了 `-miphoneos-version-min=8.0` 和 `-mmacosx-version-min=10.7`.
+对于 iOS/MacOS, 我们分别使用了 `-miphoneos-version-min=8.0` 和 `-mmacosx-version-min=10.7` 参数.
 
 由于我们不指定 C++ 版本, 所以各个编译器都使用了默认设置.
 

+ 97 - 105
docs/zh/manuals/extensions.md

@@ -1,25 +1,25 @@
 ---
-title: Writing native extensions for Defold
-brief: This manual explains how to write a native extension for the Defold game engine and how to compile it through the zero setup cloud builders.
+title: 为 Defold 编写原生扩展
+brief: 本教程介绍了给 Defold 游戏引擎编写原生扩展的方法以及云端编译器的用法.
 ---
 
-# Native extensions
+# 原生扩展
 
-If you need custom interaction with external software or hardware on a low level where Lua won't suffice, the Defold SDK allows you to write extensions to the engine in C, C++, Objective C, Java or Javascript, depending on target platform. Typical use cases for native extensions are:
+如果需要使用 Lua 本身不提供的功能, 比如第三方软件交互或者底层硬件控制, Defold SDK 接受使用 C, C++, Objective C, Java 以及 Javascript 编写的扩展程序, 语言选取取决于目标发布平台. 原生扩展的常见用法有:
 
-- Interaction with specific hardware, for instance the camera on mobile phones.
-- Interaction with external low level APIs, for instance advertising network APIs that do not allow interaction through network APIs where Luasocket could be used.
-- High performance calculations and data processing.
+- 与特定硬件交互, 例如手机摄像头.
+- 与底层软件交互, 例如未提供的底层网络交互要使用 Luasocket 扩展包实现.
+- 高性能计算, 数据处理等.
 
-## The build platform
+## 编译平台
 
-Defold provides a zero setup entry point to native extensions with a cloud based build solution. Any native extension that is developed and added to a game project, either directly or through a [Library Project](/manuals/libraries/), becomes part of the ordinary project content. There is no need to build special versions of the engine and distribute them to team members, that is handled automatically---any team member that builds and runs the project will get a project specific engine executable with all native extensions baked in.
+Defold 提供了一个云端服务器编译方案. 游戏项目的各种依赖, 或者直接引用或者通过 [库项目](/manuals/libraries/) 加入, 都会变成项目内容的一部分. 没有必要重新编译特别版引擎然后分发给开发组成员, 任何成员对项目的编译运行使所有成员都能得到嵌入全部所需库的引擎程序.
 
 ![Cloud build](images/extensions/cloud_build.png)
 
-## Project layout
+## 项目结构
 
-To create a new extension, create a folder in the project root. This folder will contain all settings, source code, libraries and resources associated with the extension. The extension builder recognizes the folder structure and collects any source files and libraries.
+在项目根目录下为扩展程序建立一个文件夹. 这个文件夹将包含扩展程序所需要的一切, 源代码, 外部库和资源文件. 云编译服务器解析这个结构以便分别获取所需要的各种文件.
 
 ```
  myextension/
@@ -41,42 +41,43 @@ To create a new extension, create a folder in the project root. This folder will
 
 ```
 *ext.manifest*
-: The extension folder _must_ contain an *ext.manifest* file. This file is a YAML format file that is picked up by the extension builder. A minimal manifest file should contain the name of the extension.
+: 原生扩展程序文件夹下 _必须_ 包含一个 *ext.manifest* 文件. 这是一个 YAML 格式的文件, 编译服务器通过此文件了解扩展项目结构. 这个文件里至少要包含一项就是原生扩展的名字.
 
 *src*
-: This folder should contain all source code files.
+: 包含所有源代码.
 
 *include*
-: This optional folder contains any include files.
+: 包含所有外部引用文件(可选).
 
 *lib*
-: This optional folder contains any compiled libraries that the extension depends on. Library files should be placed in subfolders named by `platform`, or `architecure-platform`, depending on what architectures are supported by your libraries.
+: 包含要用到的所有外部编译好的库. 库文件要根据称为 `platform` 或 `architecure-platform` 的子文件夹分类放置, 也就是说什么平台用什么库.
 
   :[platforms](../shared/platforms.md)
-  
+
 *manifests*
-: This optional folder contains additional files used in the build or bundling process. See below for details.
+: 包含编译过程所需配置文件(可选). 详见下文.
 
 *res*
-: This optional folder contains any extra resources that the extension depends on. Resource files should be placed in subfolders named by `platform`, or `architecure-platform` just as the "lib" subfolders. A subfolder `common` is also allowed, containing resource files common for all platforms.
+: 包含原生扩展所需的一切资源文件(可选). 资源文件要根据称为 `platform` 或 `architecure-platform` 的子文件夹分类放置, 也就是说什么平台用什么资源. 其中 `common` 文件夹包含各种平台的通用资源文件.
 
 ### Manifest files
 
-The optional *manifests* folder of an extension contains additional files used in the build and bundling process. Files should be placed in subfolders named by `platform`:
+*manifests* 包含编译时不同平台所需的配置文件. 配置文件要根据称为 `platform` 的子文件夹分类放置:
+
+* `android` - 这里存放片段配置文件用以与主配置文件混合 ([就像这里介绍的那样](extension-manifest-merge-tool)). 还可以存放 `build.gradle` 文件及其依赖以便 Gradle 可以解析 ([示例](https://github.com/defold/extension-facebook/blob/master/facebook/manifests/android/build.gradle)). 还能存放0个或多个 ProGuard 代码混淆文件 (试验功能).
+* `ios` - 这里存放片段配置文件用以与主配置文件混合 ([就像这里介绍的那样](extension-manifest-merge-tool)).
+* `osx` - 这里存放片段配置文件用以与主配置文件混合 ([就像这里介绍的那样](extension-manifest-merge-tool)).
+* `web` - 这里存放片段配置文件用以与主配置文件混合 ([就像这里介绍的那样](extension-manifest-merge-tool)).
 
-* `android` - This folder accepts a manifest stub file to be merged into the main application ([as described here](extension-manifest-merge-tool)). The folder can also contain a `build.gradle` file with dependencies to be resolved by Gradle ([example](https://github.com/defold/extension-facebook/blob/master/facebook/manifests/android/build.gradle)). Finally the folder can also contain zero or more ProGuard files (experimental).
-* `ios` - This folder accepts a manifest stub file to be merged into the main application ([as described here](extension-manifest-merge-tool)).
-* `osx` - This folder accepts a manifest stub file to be merged into the main application ([as described here](extension-manifest-merge-tool)).
-* `web` - This folder accepts a manifest stub file to be merged into the main application ([as described here](extension-manifest-merge-tool)).
 
+## 共享原生扩展
 
-## Sharing an extension
+原生扩展如同其他资源文件一样也可以共享. 如果库项目包含原生扩展文件夹的话, 它就能作为项目依赖库共享给其他人. 详情请见 [库项目教程](/manuals/libraries/).
 
-Extensions are treated just like any other assets in your project and they can be shared in the same way. If a native extension folder is added as a Library folder it can be shared and used by others as a project dependency. Refer to the [Library project manual](/manuals/libraries/) for more information.
 
-## A simple example extension
+## 简单示例
 
-Let's build a very simple extension. First, we create a new root folder *myextension* and add a file *ext.manifest* containing the name of the extension "MyExtension". Note that the name is a C++ symbol and must match the first argument to `DM_DECLARE_EXTENSION` (see below).
+从头开始做一个简单的原生扩展. 第一步, 创建 *myextension* 文件夹并加入 *ext.manifest* 文件, 文件中包含扩展名 "MyExtension". 注意这个扩展名会作为一个 C++ 变量名填充在 `DM_DECLARE_EXTENSION` 宏的第一个参数位置上 (见下文).
 
 ![Manifest](images/extensions/manifest.png)
 
@@ -85,11 +86,11 @@ Let's build a very simple extension. First, we create a new root folder *myexten
 name: "MyExtension"
 ```
 
-The extension consists of a single C++ file, *myextension.cpp* that is created in the "src" folder.
+这个扩展就一个 C++ 文件, *myextension.cpp*, 位于 "src" 文件夹里.
 
 ![C++ file](images/extensions/cppfile.png)
 
-The extension source file contains the following code:
+源代码如下:
 
 ```cpp
 // myextension.cpp
@@ -99,42 +100,27 @@ The extension source file contains the following code:
 
 // include the Defold SDK
 #include <dmsdk/sdk.h>
-#include <stdlib.h>
 
-static int Rot13(lua_State* L)
+static int Reverse(lua_State* L)
 {
-    int top = lua_gettop(L);
+    // The number of expected items to be on the Lua stack
+    // once this struct goes out of scope
+    DM_LUA_STACK_CHECK(L, 1);
 
     // Check and get parameter string from stack
-    const char* str = luaL_checkstring(L, 1);
+    char* str = (char*)luaL_checkstring(L, 1);
 
-    // Allocate new string
+    // Reverse the string
     int len = strlen(str);
-    char *rot = (char *) malloc(len + 1);
-
-    // Iterate over the parameter string and create rot13 string
-    for(int i = 0; i <= len; i++) {
-        const char c = str[i];
-        if((c >= 'A' && c <= 'M') || (c >= 'a' && c <= 'm')) {
-            // Between A-M just add 13 to the char.
-            rot[i] = c + 13;
-        } else if((c >= 'N' && c <= 'Z') || (c >= 'n' && c <= 'z')) {
-            // If rolling past 'Z' which happens below 'M', wrap back (subtract 13)
-            rot[i] = c - 13;
-        } else {
-            // Leave character intact
-            rot[i] = c;
-        }
+    for(int i = 0; i < len / 2; i++) {
+        const char a = str[i];
+        const char b = str[len - i - 1];
+        str[i] = b;
+        str[len - i - 1] = a;
     }
 
-    // Put the rotated string on the stack
-    lua_pushstring(L, rot);
-
-    // Free string memory. Lua has a copy by now.
-    free(rot);
-
-    // Assert that there is one item on the stack.
-    assert(top + 1 == lua_gettop(L));
+    // Put the reverse string on the stack
+    lua_pushstring(L, str);
 
     // Return 1 item
     return 1;
@@ -143,7 +129,7 @@ static int Rot13(lua_State* L)
 // Functions exposed to Lua
 static const luaL_reg Module_methods[] =
 {
-    {"rot13", Rot13},
+    {"reverse", Reverse},
     {0, 0}
 };
 
@@ -191,47 +177,48 @@ dmExtension::Result FinalizeMyExtension(dmExtension::Params* params)
 DM_DECLARE_EXTENSION(MyExtension, LIB_NAME, AppInitializeMyExtension, AppFinalizeMyExtension, InitializeMyExtension, 0, 0, FinalizeMyExtension)
 ```
 
-Note the macro `DM_DECLARE_EXTENSION` that is used to declare the various entry points into the extension code. The first argument `symbol` must match the name specified in *ext.manifest*. For this simple example, there is no need for any "update" or "on_event" entry points, so `0` is provided in those locations to the macro.
+注意 `DM_DECLARE_EXTENSION` 宏用来声明扩展程序执行入口. 第一个参数 `symbol` 要与 *ext.manifest* 上的扩展名一致. 本例中没有用到 "update" 或 "on_event" 执行入口, 所以用 `0` 填充了宏的相应参数.
 
-Now it is just a matter of building the project (<kbd>Project ▸ Build and Launch</kbd>). This will upload the extension to the extension builder which will produce a custom engine with the new extension included. If the builder encounters any errors, a dialog with the build errors will show.
+现在就差编译运行了 (<kbd>Project ▸ Build and Launch</kbd>). 带原生扩展的项目会被上传到云编译服务器编译. 如果编译出错, 将会弹出一个包含错误信息的窗口.
 
-To test the extension, create a game object and add a script component with some test code:
+测试扩展运行, 新建一个游戏对象和一个脚本组件, 再写一些测试代码:
 
 ```lua
 local s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
-local rot_s = myextension.rot13(s)
-print(rot_s) --> nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM
+local reverse_s = myextension.reverse(s)
+print(reverse_s) --> ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba
 ```
 
-And that's it! We have created a fully working native extension.
+成功了! 我们从零开始完整地制作了一个扩展程序.
 
-## Extension Lifecycle
 
-As we saw above the `DM_DECLARE_EXTENSION` macro is used to declare the various entry points into the extension code:
+## 扩展程序生命周期
+
+上面提到了 `DM_DECLARE_EXTENSION` 宏用来声明程序执行入口:
 
 `DM_DECLARE_EXTENSION(symbol, name, app_init, app_final, init, update, on_event, final)`
 
-The entry points will allow you to run code at various points in the lifecycle of an extension:
+入口对应扩展程序的各种生命周期函数, 运行顺序如下:
 
-* Engine start
-  * Engine systems are starting
-  * Extension `app_init`
-  * Extension `init` - All Defold APIs have been initialized. This is the recommended point in the extension lifecycle where Lua bindings to extension code is created.
-  * Script init - The `init()` function of script files are called.
-* Engine loop
-  * Engine update
-    * Extension `update`
-    * Script update - The `update()` function of script files are called.
-  * Engine events (window minimize/maximize etc)
-    * Extension `on_event`
-* Engine shutdown (or reboot)
-  * Script final - The `final()` function of script files are called.
-  * Extension `final`
-  * Extension `app_final`
+* 引擎启动
+  * 引擎代码运行
+  * 扩展 `app_init`
+  * 扩展 `init` - Defold API 初始化. 建议扩展程序从这里开始运行并且暴露给Lua脚本.
+  * 脚本 `init()` 函数调用.
+* 引擎循环
+  * 引擎刷新
+    * 扩展 `update`
+    * 脚本 `update()` 函数调用.
+  * 引擎事件 (窗口最大/最小化之类的)
+    * 扩展 `on_event`
+* 引擎关闭 (或重启)
+  * 脚本 `final()` 函数调用.
+  * 扩展 `final`
+  * 扩展 `app_final`
 
-## Defined platform identifiers
+## 预定义的平台标识
 
-The following identifiers are defined by the builder on each respective platform:
+编译器中预定义了如下平台标识:
 
 * DM_PLATFORM_WINDOWS
 * DM_PLATFORM_OSX
@@ -240,9 +227,14 @@ The following identifiers are defined by the builder on each respective platform
 * DM_PLATFORM_LINUX
 * DM_PLATFORM_HTML5
 
-## The ext.manifest file
+## 编译服务器日志
+
+当项目使用了原生扩展, 编译时就会生成编译服务器日志. 编译服务器日志文件 (`log.txt`) 与被编译的项目一起下载到本地, 并保存在项目 build 文件夹的 `.internal/%platform%/build.zip` 文件中.
+
+
+## ext.manifest 文件
 
-Apart from the name of the extension, the manifest file can contain platform specific compile flags, link flags, libs and frameworks. If the *ext.manifest* file does not contain a "platforms" segment, or a platform is missing from the list, the platform you bundle for will still build, but without any extra flags set.
+除了扩展名称, ext.manifest 文件还可以包含指定平台的编译参数, 链接参数, 外部程序和链接库. 如果 *ext.manifest* 文件不包含 "platforms" 项, 或者找不到对应的平台配置参数, 编译仍会继续, 只是不加各种编译参数.
 
 Here is an example:
 
@@ -267,27 +259,27 @@ platforms:
             defines:    ["MY_DEFINE"]
 ```
 
-### Allowed keys
+### 可用参数项
 
-Allowed keys are for platform specific compile flags are:
+各个平台可用参数项如下:
 
-* `frameworks` - Apple frameworks to include when building (iOS and OSX)
-* `flags` - Flags that should be passed to the compiler
-* `linkFlags` - Flags that should be passed to the linker
-* `libs` - Libraries to include when linking
-* `defines` - Defines to set when building
-* `aaptExtraPackages` - Extra package name that should be generated (Android)
-* `aaptExcludePackages` - Regexp (or exact names) of packages to exclude (Android)
-* `aaptExcludeResourceDirs` - Regexp (or exact names) of resource dirs to exclude (Android)
+* `frameworks` - 加入苹果库 (iOS 和 OSX)
+* `flags` - 编译参数
+* `linkFlags` - 链接参数
+* `libs` - 链接库
+* `defines` - 编译预定义
+* `aaptExtraPackages` - 导入外部包 (Android)
+* `aaptExcludePackages` - 排除内部包 (Android)
+* `aaptExcludeResourceDirs` - 排除资源文件夹 (Android)
 
-## Example extensions
+## 原生扩展举例
 
-* [Basic extension example](https://github.com/defold/template-native-extension) (the extension from this manual)
-* [Android extension example](https://github.com/defold/extension-android)
-* [HTML5 extension example](https://github.com/defold/extension-html5)
-* [MacOS, iOS and Android videoplayer extension](https://github.com/defold/extension-videoplayer)
-* [MacOS and iOS camera extension](https://github.com/defold/extension-camera)
-* [iOS and Android In-app Purchase extension](https://github.com/defold/extension-iap)
-* [iOS and Android Firebase Analytics extension](https://github.com/defold/extension-firebase-analytics)
+* [基础示例](https://github.com/defold/template-native-extension) (本教程所使用的简单示例)
+* [Android 扩展示例](https://github.com/defold/extension-android)
+* [HTML5 扩展示例](https://github.com/defold/extension-html5)
+* [MacOS, iOS 和 Android 的 videoplayer 扩展程序](https://github.com/defold/extension-videoplayer)
+* [MacOS 和 iOS 的摄像头扩展程序](https://github.com/defold/extension-camera)
+* [iOS 和 Android 的内支付扩展程序](https://github.com/defold/extension-iap)
+* [iOS 和 Android 的 Firebase Analytics 扩展程序](https://github.com/defold/extension-firebase-analytics)
 
-The [Defold asset portal](https://www.defold.com/assets/) also contain several native extensions.
+[Defold 资源中心](https://www.defold.com/assets/) 也包含有许多原生扩展项目资源.

+ 1 - 1
docs/zh/manuals/facebook.md

@@ -3,4 +3,4 @@ title: Defold Facebook 教程
 brief: 本教程介绍了如何在 Defold 游戏中设置和整合 Facebook 功能.
 ---
 
-[本教程已被移除](/extension-facebook)
+本教程已移至 [这里](/extension-facebook)

+ 32 - 0
docs/zh/manuals/factory.md

@@ -86,6 +86,38 @@ end
 Defold 目前不支持碰撞形状的非等比缩放. 如果赋了非等比值, 比如 `vmath.vector3(1.0, 2.0, 1.0)` 则 sprite 会正确缩放但是碰撞形状不会正确缩放.
 :::
 
+
+## 定位新对象
+
+Defold 的地址定位机制可以在运行时定位任何对象和组件. 关于定位详情请见 [地址定位教程](/manuals/addressing/). 对于工厂新建对象及其组件同样如此. 新建的对象id经常被使用, 比如发送消息时:
+
+```lua
+local function create_hunter(target_id)
+    local id = factory.create("#hunterfactory")
+    msg.post(id, "hunt", { target = target_id })
+    return id
+end
+```
+
+::: 注意
+发给游戏对象而非组件的消息会传遍对象上的所有组件. 一般不会造成问题, 但是处理消息时要明白这一点.
+:::
+
+要获取对象上的组件, 比如关闭碰撞或改变Sprite图片该怎么办呢? 使用游戏对象id再加上组件名生成的地址即可.
+
+```lua
+local function create_guard(unarmed)
+    local id = factory.create("#guardfactory")
+    if unarmed then
+        local weapon_sprite_url = msg.url(nil, id, "weapon")
+        msg.post(weapon_sprite_url, "disable")
+
+        local body_sprite_url = msg.url(nil, id, "body")
+        sprite.play_flipbook(body_sprite_url, hash("red_guard"))
+    end
+end
+```
+
 ## 新对象引用和对象父级
 
 调用 `factory.create()` 会返回新游戏对象的id, 以便保存其引用. 通常把 id:s 保存到一个表里以便需要时统一删除, 比如重启关卡时:

+ 28 - 32
docs/zh/manuals/file-access.md

@@ -1,50 +1,46 @@
 ---
-title: Working with files
-brief: This manual explains how to save and load files and perform other kinds of file operations.
+title: 处理文件
+brief: 本教程介绍了保存和加载文件等处理文件的方法.
 ---
 
-# Working with files
-There are many different ways to create and/or access files. The file paths and the ways your access these files varies depending on the type of file and the location of the file.
+# 处理文件
+存取文件有很多种方式. 文件的路径和文件类型决定了采取何种方式.
 
-## Functions for file and folder access
-Defold provides several different functions to work with files:
+## 文件/文件夹存取函数
+Defold 提供如下函数用以存取文件/文件夹:
 
-* You can use the standard [`io.*` functions](https://defold.com/ref/stable/io/) to read and write files. These functions give you very fine-grained control over the entire I/O process.
-* You can use [`os.rename()`](https://defold.com/ref/stable/os/#os.rename:oldname-newname) and [`os.remove()`](https://defold.com/ref/stable/os/#os.remove:filename) to rename and remove files.
-* You can use [`sys.save()`](https://defold.com/ref/stable/sys/#sys.save:filename-table) and [`sys.load()`](https://defold.com/ref/stable/sys/#sys.load:filename) to read and write Lua tables. Additional [`sys.*`](https://defold.com/ref/stable/sys/) functions exist to help with platform independent file path resolution.
+* 标准输入输出库 [`io.*` functions](https://defold.com/ref/stable/io/). 用于文件/文件夹存取, 底层高效细致灵活.
+* 操作系统库 [`os.rename()`](https://defold.com/ref/stable/os/#os.rename:oldname-newname) 和 [`os.remove()`](https://defold.com/ref/stable/os/#os.remove:filename) 用于文件改名和删除.
+* 游戏引擎系统库 [`sys.save()`](https://defold.com/ref/stable/sys/#sys.save:filename-table) 和 [`sys.load()`](https://defold.com/ref/stable/sys/#sys.load:filename) 用于存取 Lua 表. 其他 [`sys.*`](https://defold.com/ref/stable/sys/) 下的函数用于不同操作系统文件路径的解析.
 
-## File and folder locations
-File and folder locations can be divided into three categories:
+## 文件/文件夹位置
+有三个文件/文件夹位置可供游戏应用存取使用:
 
-* Application specific files created by your application
-* Files and folders bundled with your application
-* System specific files accessed by your application
+* 游戏应用所在位置下的文件
+* 游戏应用打包进去的文件
+* 操作系统所管理的文件
 
-### How to save and load application specific files
-When saving and loading application specific files such as high scores, user settings and game state it is recommended to do so in a location provided by the operating system and intended specifically for this purpose. You can use [`sys.get_save_file()`](https://defold.com/ref/stable/sys/#sys.get_save_file:application_id-file_name) to get the OS specific absolute path to a file. Once you have the absolute path you can use the `sys.*`, `io.*` and `os.*` functions (see above).
+### 游戏指定位置的文件处理
+像最高分数, 用户设置和游戏状态等信息建议如此处理. 用 [`sys.get_save_file()`](https://defold.com/ref/stable/sys/#sys.get_save_file:application_id-file_name) 函数得到操作系统指定的文件绝对路径. 然后用 `sys.*`, `io.*` 和 `os.*` 函数处理文件/文件夹 (见上文).
 
 [Check the example showing how to use sys.save() and sys.load()](/examples/file/sys_save_load/).
 
-### How to access files bundled with the application
-You can bundle files with your application in two ways:
+### 游戏应用打包进去的文件处理
+游戏打包有两种方法:
 
-1. As part of the game archive using the [*Custom Resources* field](https://defold.com/manuals/project-settings/#project) in *game.project*. You can read these files using [`sys.load_resource()`](https://defold.com/ref/sys/#sys.load_resource). Note that these aren't actual files on the file system. Files included this way becomes part of the binary game archive and the only way to access them is through `sys.load_resource()`.
+1. 在 *game.project* 配置文件中的 [*Custom Resources* 项](https://defold.com/manuals/project-settings/#project) 设置自定义资源. 然后就可以使用 [`sys.load_resource()`](https://defold.com/ref/sys/#sys.load_resource) 函数进行加载. 其实这不是在加载磁盘上的文件. 打包进游戏的资源文件作为游戏的一部分保存为二进制数据, 只能使用 `sys.load_resource()` 载入.
 
-2. As additional files and folders located as a part of your application bundle using the [*Bundle Resources* field](https://defold.com/manuals/project-settings/#project) in *game.project*. You can use [`sys.get_application_path()`](https://defold.com/ref/stable/sys/#sys.get_application_path:) to get the path to where the application is stored. Use this application base path to create the final absolute path to the files you need access to. Once you have the absolute path of these files you can use the `io.*` and `os.*` functions to access the files (see above).
+2. 在 *game.project* 配置文件中的 [*Bundle Resources* 项](https://defold.com/manuals/project-settings/#project) 设置额外打包文件. 然后就可以使用 [`sys.get_application_path()`](https://defold.com/ref/stable/sys/#sys.get_application_path:) 取得游戏所在位置. 进而取得文件的绝对路径. 然后用 `sys.*`, `io.*` 和 `os.*` 函数处理文件/文件夹 (见上文).
 
-::: sidenote
-For security reasons browsers (and by extension any JavaScript running in a browser) is prevented from accessing system files. File operations in HTML5 builds in Defold still work, but only on a "virtual file system" using the IndexedDB API in the browser. What this means is that there is no way to access bundle resources using `io.*` or `os.*` functions. You can however access bundle resources using `http.request()`.
-:::
-
-### System file access
-Access to system files may be restricted by the operating system for security reasons. You can use the [`extension-directiories`](https://defold.com/assets/extensiondirectories/) native extension to get the absolute path to some common system directories (ie documents, resource, temp). Once you have the absolute path of these files you can use the `io.*` and `os.*` functions to access the files (see above).
+### 操作系统文件处理
+基于安全考虑操作系统所管理的文件存取被严格限制. 可以使用 [`extension-directiories`](https://defold.com/assets/extensiondirectories/) 原生扩展来存取某些地方的绝对路径 (例如 documents, resource, temp). 然后用 `sys.*`, `io.*` 和 `os.*` 函数处理文件/文件夹 (见上文).
 
-::: sidenote
-For security reasons browsers (and by extension any JavaScript running in a browser) is prevented from accessing system files. File operations in HTML5 builds in Defold still work, but only on a "virtual file system" using the IndexedDB API in the browser. What this means is that there is no way to access system files in HTML5 builds.
+::: 注意
+基于安全考虑浏览器 (及浏览器里运行的 JavaScript 插件) 不允许访问本地文件. 虽然 HTML5 游戏也能运行, 但是只能用浏览器提供的 IndexedDB API 在 "虚拟文件系统" 中存取数据. 也就是说不允许使用 `io.*` 和 `os.*` 下的函数. 但是可以用 `http.request()` 请求在线资源文件.
 :::
 
-## Extensions
-The [Asset Portal](https://defold.com/assets/) contains several assets to simplify file and folder access. Some examples:
+## 相关原生扩展
+在 [资源中心](https://defold.com/assets/) 里有些原生扩展能简化文件存取的工作. 例如:
 
-* [Lua File System (LFS)](https://defold.com/assets/luafilesystemlfs/) - Functions to work with directories, file permissions etc
-* [DefSave](https://defold.com/assets/defsave/) - A module to help you save / load config and player data between session.
+* [Lua File System (LFS)](https://defold.com/assets/luafilesystemlfs/) - 提供操作文件夹, 文件权限之类的功能.
+* [DefSave](https://defold.com/assets/defsave/) - 一个用于保存/加载游戏设置和玩家数据档的模块.

+ 16 - 20
docs/zh/manuals/getting-help.md

@@ -9,7 +9,15 @@ brief: 本教程介绍了使用 Defold 遇到麻烦时该如何寻求帮助.
 
 ## 在论坛里提交问题
 
-在我们的 [论坛](https://forum.defold.com) 上提交问题是一个好方法. 依据你的问题的类型可以在 [Questions](https://forum.defold.com/c/questions) 或者 [Bugs](https://forum.defold.com/c/bugs) 类目下发帖. 提交问题的时候请尽附加可能多的信息. 记得发问之前在论坛 [搜索](https://forum.defold.com/search) 一下相关内容, 也许论坛上已经存在你的问题的解决方案了. 提问时请填写以下信息:
+在我们的 [论坛](https://forum.defold.com) 上提交问题是一个好方法. 依据你的问题的类型可以在 [Questions](https://forum.defold.com/c/questions) 或者 [Bugs](https://forum.defold.com/c/bugs) 类目下发帖. 提交问题的时候请尽附加可能多的信息. 记得发问之前在论坛 [搜索](https://forum.defold.com/search) 一下相关内容, 也许论坛上已经存在你的问题的解决方案了.
+
+有多个问题, 就发多张帖子. 不要在一个帖子说发布不相干的问题.
+
+### 提供信息
+提问时请提供以下信息:
+
+**题目**
+简明扼要的标题. 像 "如何让游戏对象延面对方向前进?" 或者 "如何实现 Sprite 渐隐效果?" 就比较好. 像 "我需要 Defold 的帮助!" 或者 "我的游戏不动了!" 就不怎么好.
 
 * **问题的描述 (必须)** - 问题的简短描述.
 
@@ -48,7 +56,7 @@ brief: 本教程介绍了使用 Defold 遇到麻烦时该如何寻求帮助.
 
 ![](images/getting_help/report_issue.png)
 
-这样就会在 GitHub 上生成一个错误报告. 请尽量详述错误的相关信息. 参考 [下面关于日志文件获取的章节](#log-files).
+这样就会在 GitHub 上生成一个错误报告. 请提供 [日志文件](#log-files), 操作系统, 重现方法, 临时绕过错误的方法等信息.
 
 ::: 注意
 报告之前确保你已经拥有 GitHub 账户.
@@ -64,21 +72,9 @@ brief: 本教程介绍了使用 Defold 遇到麻烦时该如何寻求帮助.
 
 游戏引擎, 编辑器和云编译服务器都有日志系统, 这对于定位调试错误十分有利. 报告错误时请务必带上日志文件.
 
-## 引擎日志
-- Android: 可以使用 `adb` (Android Debug Bridge) 命令获取. 有关 `adb` 命令详情请见 [Android 教程](/manuals/android/#android-debug-bridge).
-- iOS: 可以使用 XCode 的设备和模拟器菜单项获取.
-- HTML5: 浏览器控制台会输出日志:
-  - Chrome: 菜单 > 更多工具 > 开发者工具
-  - Firefox: 工具 > 网络开发者 > 网络控制台
-  - Safari: 开发 > 显示 JavaScript 控制台
-- Desktop: 如果从终端/命令控制台启动 Defold 程序的话, 就可以在上面看到输出的日志了.
-
-有个功能就是程序崩溃时把相关信息写入一个日志文件中去. 详情请见 [调试教程](/manuals/debugging/#extracting-the-logtxt-file).
-
-## 编辑器日志
-- Windows: `C:\Users\ **Your Username** \AppData\Local\Defold`
-- macOS: `/Users/ **Your Username** /Library/Application Support/` 或者 `~/Library/Application Support/Defold`
-- Linux: `~/.Defold`
-
-## 云编译服务器日志
-使用原生扩展时才会有编译服务器日志. 编译时其日志文件 (`log.txt`) 与自定义引擎一起下载并保存在 `.internal/%platform%/build.zip` 文件中.
+* [引擎日志](/manuals/debugging-game-and-system-logs)
+* 编辑器日志
+  * Windows: `C:\Users\ **Your Username** \AppData\Local\Defold`
+  * macOS: `/Users/ **Your Username** /Library/Application Support/` 或 `~/Library/Application Support/Defold`
+  * Linux: `~/.Defold`
+* [编译服务器日志](/manuals/extensions#build-server-logs)

+ 45 - 45
docs/zh/manuals/glossary.md

@@ -3,178 +3,178 @@ title: Defold 术语
 brief: 本教程列举了使用 Defold 工作中会遇到的各种专用词汇及其简短的解释.
 ---
 
-# Defold glossary
+# Defold 术语
 
-该名词表简要介绍了您在 Defold 中遇到的所有东西。在大多数情况下,您会找到更多相关详细文档的链接。
+该名词表简要介绍了您在 Defold 中遇到的各种术语。在大多数情况下,您会找到更多相关详细文档的链接。
 
 ## Animation set
 
-![Animation set](images/icons/animationset.png){.left} An animation set resource contains a list of .dae files or other .animationset files from where to read animations. Adding one .animationset files to another is handy if you share partial sets of animations between several models. See the [3D graphics manual](/manuals/graphics/) for details.
+![Animation set](images/icons/animationset.png){.left} 包含一组动画的 .dae 文件或其他用以读取动画的 .animationset 文件的动画集资源. 如果多个模型文件共享一组动画的话, 可以方便地把 .animationset 文件设置给其他模型. 详情请见 [3D 图像教程](/manuals/graphics/).
 
 ## Atlas
 
-![Atlas](images/icons/atlas.png){.left} An atlas is a set of separate images that are compiled into a larger sheet for performance and memory reasons. They can contain still images or flip-book animated series of images. Atlases are used by GUI, Sprite, Spine model and ParticleFX components to share graphics resources. See the [Atlas documentation](/manuals/atlas) for more information.
+![Atlas](images/icons/atlas.png){.left} 图集是为了增加性能减少显存消耗而把许多单张图片合并而成的一张大图. 其中可以包括静态图和逐帧动画序列图. 图集可被 GUI, Sprite, Spine model 和 ParticleFX 组件所共享. 详情请见 [图集教程](/manuals/atlas).
 
 ## Builtins
 
-![Builtins](images/icons/builtins.png){.left} The builtins project folder is a read-only folder containing useful default resources. Here you find the default renderer, render script, materials and more. If you need custom modifications on any of these resources, simply copy them into your project and edit as you see fit.
+![Builtins](images/icons/builtins.png){.left} 项目内置文件夹是一个包含必要默认资源的只读文件夹. 里面由默认着色器, 默认渲染脚本, 默认材质等等. 如果需要自定义这些默认资源, 只要把它们拷贝到你的项目目录中去, 然后自由修改即可.
 
 ## Camera
 
-![Camera](images/icons/camera.png){.left} The camera component helps to decide what part of the game world should be visible and how it should be projected. A common use case is to attach a camera to the player game object, or to have a separate game object with a camera that follows the player around with some smoothing algorithm. See the [Camera documentation](/manuals/camera) for more information.
+![Camera](images/icons/camera.png){.left} 摄像机组件决定了游戏世界哪些可见哪些不可见以及视口的投射类型. 一个常见用法是把摄像机放到主角游戏对象上, 或者放到一个跟随主角的包含一些平滑移动算法的游戏对象上. 详情请见 [摄像机教程](/manuals/camera).
 
 ## Collision object
 
-![Collision object](images/icons/collision-object.png){.left} Collision objects are components that extend game objects with physical properties (like spatial shape, weight, friction and restitution). These properties govern how the collision object should collide with other collision objects. The most common types of collision objects are kinematic objects, dynamic objects and triggers. A kinematic object gives detailed collision information that you have to manually respond to, a dynamic object is automatically simulated by the physics engine to obey Newtonian laws of physics. Triggers are simple shapes that detect if other shapes have entered or exited the trigger. See the [Physics documentation](/manuals/physics) for details on how this works.
+![Collision object](images/icons/collision-object.png){.left} 碰撞对象组件为游戏对象增添了物理属性 (比如形状, 重量, 摩擦力和弹性). 这些属性决定了碰撞对象之间的碰撞效果. 常见碰撞对象有运动学, 动态和触发器三种类型. 运动学碰撞对象必须手动设置它的物理属性值, 动态碰撞对象由物理引擎基于牛顿物理定律计算它的物理属性. 触发器是一个形状, 能够检测其他物体进入或者离开. 详情请见 [物理教程](/manuals/physics).
 
 ## Component
 
-Components are used to give specific expression and/or functionality to game objects, like graphics, animation, coded behavior and sound. They don’t live a life of their own but have to be contained inside game objects. There are many kinds of components available in Defold. See [the Building blocks manual](/manuals/building-blocks) for a description of components.
+组件赋予游戏对象以独特的功能和表现, 如图像, 动画, 逻辑和声音等等. 组件依附于游戏对象之上. Defold 中预置了许多组件. 详情请见 [游戏组成教程](/manuals/building-blocks).
 
 ## Collection
 
-![Collection](images/icons/collection.png){.left} Collections are Defold’s mechanism for creating templates, or what in other engines are called "prefabs" in where hierarchies of game objects can be reused. Collections are tree structures that hold game objects and other collections. A collection is always stored on file and brought into the game either statically by placing it manually in the editor, or dynamically by spawning. See [the Building blocks manual](/manuals/building-blocks) for a description of collections.
+![Collection](images/icons/collection.png){.left} 集合是 Defold 的模板机制, 相当于其他引擎的 "prefabs" 即可重用游戏对象的树形结构. 集合可以包含游戏对象和其他集合. 集合结构作为文件资源储存, 既可以在编辑器里手动创建实例, 又可以在运行时动态创建实例. 详情请见 [游戏组成教程](/manuals/building-blocks).
 
 ## Collection factory
 
-![Collection factory](images/icons/collection-factory.png){.left} A Collection factory component is used to spawn hierarchies of game objects dynamically into a running game. See the [Collection factory manual](/manuals/collection-factory) manual for details.
+![Collection factory](images/icons/collection-factory.png){.left} 集合工厂是集合实例制造者, 可以在运行时动态创建集合实例. 详情请见 [集合工程教程](/manuals/collection-factory).
 
 ## Collection proxy
 
-![Collection](images/icons/collection.png){.left} A Collection proxy is used to load and enable collections on the fly while an app or game is running. The most common use case for Collection proxies is to load levels as they are to be played. See the [Collection proxy documentation](/manuals/collection-proxy) for details.
+![Collection proxy](images/icons/collection-proxy.png){.left} 集合代理可以在游戏进行时加载并激活集合. 常常被用来切换游戏关卡. 详情请见 [集合代理教程](/manuals/collection-proxy).
 
 ## Cubemap
 
-![Cubemap](images/icons/cubemap.png){.left} A cubemap is a special type of texture that consists of 6 different textures that are mapped on the sides of a cube. This is useful for rendering skyboxes and different kinds of reflection and illumination maps.
+![Cubemap](images/icons/cubemap.png){.left} Cubemap 是由 6 张纹理组成的一种特殊纹理, 可以完整覆盖在立方体上. 常常被用于天空盒, 也被用作各种反射纹理和光照纹理等.
 
 ## Debugging
 
-At some point your game will behave in an unexpected way and you need to figure out what is wrong. Learning how to debug is an art and fortunately Defold ships with a built in debugger to help you out. See the [Debugging manual](/manuals/debugging) for more information.
+调试是程序除错的方法. Defold 给用户提供了方便的内置调试器. 详情请见 [调试教程](/manuals/debugging).
 
 ## Display profiles
 
-![Display profiles](images/icons/display-profiles.png){.left} The display profiles resource file is used for specifying GUI layouts depends on the orientation, aspect ratio or device model. It helps to adapt your UI for any kind of devices. Read more in the [Layouts manual](/manuals/gui-layouts).
+![Display profiles](images/icons/display-profiles.png){.left} 显示档案是一种文件资源用来确定在指定屏幕方向, 宽高比, 或设备型号匹配到显示设备时使用哪种用户界面布局方案. 它能帮助用户适配各种设备屏幕. 详情请见 [界面布局教程](/manuals/gui-layouts).
 
 ## Factory
 
-![Factory](images/icons/factory.png){.left} In some situations you cannot manually place all needed game objects in a collection, you have to create the game objects dynamically, on the fly. For instance, a player might fire bullets and each shot should be dynamically spawned and sent off whenever the player presses the trigger. To create game objects dynamically (from a pre-allocated pool of objects), you use a factory component. See the [Factory manual](/manuals/factory) for details.
+![Factory](images/icons/factory.png){.left} 工厂是游戏对象实例制造者, 用来在运行时创建游戏对象实例. 例如, 发射子弹游戏对象, 就可以可以使用工厂 (其内部含有对象池功能). 详情请见 [工厂教程](/manuals/factory).
 
 ## Font
 
-![Font file](images/icons/font.png){.left} A Font resource is built from a TrueType or OpenType font file. The Font specifies which size to render the font in and what type of decoration (outline and shadow) the rendered font should have. Fonts are used by GUI and Label components. See the [Font manual](/manuals/font/) for details.
+![Font file](images/icons/font.png){.left} 字体资源源自 TrueType 或 OpenType 字体文件. 可以设置渲染文字的大小和外观 (描边和阴影). GUI 和 Label 组件要用到字体资源. 详情请见 [字体教程](/manuals/font/).
 
 ## Fragment shader
 
-![Fragment shader](images/icons/fragment-shader.png){.left} This is a program that is run on the graphics processor for each pixel (fragment) in a polygon when it is drawn to the screen. The purpose of the fragment shader is to decide the color of each resulting fragment. This is done by calculation, texture lookups (one or several) or a combination of lookups and computations. See the [Shader manual](/manuals/shader) for more information.
+![Fragment shader](images/icons/fragment-shader.png){.left} 一种运行于显卡上的用于处理多边形上每个像素 (片元) 的渲染程序. 由此程序决定每个像素的颜色. 最终像素颜色值通过计算和纹理查找 (一个或多个) 的方法得出. 详情请见 [着色器教程](/manuals/shader).
 
 ## Gamepads
 
-![Gamepads](images/icons/gamepad.png){.left} A gamepads resource file defines how specific gamepad device input is mapped to gamepad input triggers on a certain platform. See the [Input manual](/manuals/input) for details.
+![Gamepads](images/icons/gamepad.png){.left} 手柄资源文件用来定义游戏手柄设备在指定平台上的输入对游戏的意义. 详情请见 [输入教程](/manuals/input).
 
 ## Game object
 
-![Game object](images/icons/game-object.png){.left} Game objects are simple objects that have a separate lifespan during the execution of your game. Game objects are containers and are usually equipped with visual or audible components, like a sound or a sprite. They can also be equipped with behavior through script components. You create game objects and place them in collections in the editor, or spawn them dynamically at run-time with factories. See [the Building blocks manual](/manuals/building-blocks) for a description of game objects.
+![Game object](images/icons/game-object.png){.left} 游戏对象在游戏过程中有各自的生命周期. 游戏对象是组件的容器, 比如可以包含声音和图像组件等. 游戏对象还是游戏逻辑脚本代码的载体. 游戏对象既可以使用编辑器创建并放置于集合志宏, 也可以使用工厂在运行时进行实例化. 详情请见 [游戏组成教程](/manuals/building-blocks).
 
 ## GUI
 
-![GUI component](images/icons/gui.png){.left} A GUI component contains elements used to construct user interfaces: text and colored and/or textured blocks. Elements can be organized into hierarchical structures, scripted and animated. GUI components are typically used to create heads-up displays, menu systems and on-screen notifications. GUI components are controlled with GUI scripts that define the behavior of the GUI and control the user interaction with it. Read more in the [GUI documentation](/manuals/gui).
+![GUI component](images/icons/gui.png){.left} GUI 组件用来组成用户界面: 包含文字, 图像等等. 这些组件组成树形结构, 可以被脚本和动画控制. GUI 组件常用于组成屏幕操作界面, 菜单系统和提示框等等. GUI 组件使用 GUI 脚本控制以实现交互行为. 详情请见 [GUI 教程](/manuals/gui).
 
 ## GUI script
 
-![GUI script](images/icons/script.png){.left} GUI scripts are used to control the behaviour of GUI components. They control GUI animations and how the user interacts with the GUI. See the [Lua in Defold manual](/manuals/lua) for details on how Lua scripts are used in Defold.
+![GUI script](images/icons/script.png){.left} GUI 脚本用于控制界面组件的行为. 它决定了界面元素如何移动, 用户如何与界面元素交互. 详情请见 [Defold 的 Lua 教程](/manuals/lua).
 
 ## Hot reload
 
-The Defold editor allows you to update content in an already running game, on desktop and device. This feature is extremely powerful and can improve the development workflow a lot. See the [Hot reload manual](/manuals/hot-reload) for more information.
+Defold 允许在游戏运行时进行内容更新, 支持桌面和移动设备. 这项功能能为游戏开发者大大节省开发和调试时间. 详情请见 [热重载教程](/manuals/hot-reload).
 
 ## Input binding
 
-![Input binding](images/icons/input-binding.png){.left} Input binding files define how the game should interpret hardware input (mouse, keyboard, touchscreen and gamepad). The file binds hardware input to high level input _actions_ like "jump" and "move_forward". In script components that listen to input you are able to script the actions the game or app should take given certain input. See the [Input documentation](/manuals/input) for details.
+![Input binding](images/icons/input-binding.png){.left} 输入绑定定义了输入设备 (鼠标, 键盘, 触摸屏和手柄等) 输入信息的含义. 它把硬件输入与游戏行为进行绑定, 比如 "跳跃" 和 "前进" _行为_. 这样监听输入的脚本就能根据这些行为控制与之相配的动作. 详情请见 [输入教程](/manuals/input).
 
 ## Label
 
-![Label](images/icons/label.png){.left} The label component allows you to attach text content to any game object. It renders a piece of text with a particular font, on screen, in game space. See the [Label manual](/manuals/label) for more information.
+![Label](images/icons/label.png){.left} 标签组件用来给游戏对象加上文字内容. 它使用指定字体在游戏空间中被渲染出来. 详情请见 [标签教程](/manuals/label).
 
 ## Library
 
-![Game object](images/icons/builtins.png){.left} Defold allows you to share data between projects through a powerful library mechanism. You can use it to set up shared libraries that are accessible from all your projects, either for yourself or across the whole team. Read more about the library mechanism in the [Libraries documentation](/manuals/libraries).
+![Game object](images/icons/builtins.png){.left} Defold 使用库机制进行资源共享. 资源共享可以是项目间的, 也可以是团队成员间的. 详情请见 [库教程](/manuals/libraries).
 
 ## Lua language
 
-The Lua programming language is used in Defold to create game logic. Lua is a powerful, efficient, very small scripting language. It supports procedural programming, object-oriented programming, functional programming, data-driven programming, and data description. You can read more about the language on the official Lua homepage at https://www.lua.org/ and in the [Lua in Defold manual](/manuals/lua).
+Lua 语言在 Defold 中用来创建游戏逻辑. Lua 是一种强大高效而又轻量级的脚本语言. 它支持多种设计模式和数据描述. 详情请见官网 https://www.lua.org/ 和 [Defold 脚本手册](/manuals/lua).
 
 ## Lua module
 
-![Lua module](images/icons/lua-module.png){.left} Lua modules allow you to structure your project and create reusable library code. Read more about it in the [Lua modules manual](/manuals/modules/)
+![Lua module](images/icons/lua-module.png){.left} Lua 模块可以用来构建项目编写可重用代码. 详情请见 [Lua 模块教程](/manuals/modules/)
 
 ## Material
 
-![Material](images/icons/material.png){.left} Materials define how different objects should be rendered by specifying shaders and their properties. See the [Material manual](/manuals/material) for more information.
+![Material](images/icons/material.png){.left} 材质使用指定的着色器及其属性来实现特定的视觉效果. 详情请见 [材质教程](/manuals/material).
 
 ## Message
 
-Components communicate with each other and other systems through message passing. Components also respond to a set of predefined messages that alter them or trigger specific actions. You send messages to hide graphics or nudge physics objects. The engine also uses messages to notify components of events, for instance when physics shapes collide. The message passing mechanism needs a recipient for each sent message. Therefore, everything in the game is uniquely addressed. To allow communication between objects, Defold extends Lua with message passing. Defold also provides a library of useful functions.
+组件使用消息与系统或者与其他游戏对象进行信息交流. 有许多预定义的消息提供给组件使用以便实现某些功能. 比如隐藏图像或者推动物理物体. 游戏引擎通过消息传递事件, 比如物理物体碰撞事件. 要发送消息必须有接收者. 所以每个游戏对象每个组件的路径都是唯一的. Defold 给 Lua 增添了消息传递功能以及包含各种功能的库.
 
-For instance, the Lua-code required to hide a sprite component on a game object looks like this:
+举个例子, 要隐藏一个 sprite 可以这么写:
 
 ```lua
 msg.post("#weapon", "disable")
 ```
 
-Here, `"#weapon"` is the address of the current object's sprite component. `"disable"` is a message that sprite components respond to. See the [Message passing documentation](/manuals/message-passing) for an in depth explanation of how message passing works.
+此处, `"#weapon"` 就是游戏对象 sprite 组件的路径. `"disable"` 是发给 sprite 组件的消息内容. 详情请见 [消息传递教程](/manuals/message-passing).
 
 ## Model
 
-![Model](images/icons/model.png){.left} With the 3D model component can import Collada mesh, skeleton and animation assets into your game. See the [Model manual](/manuals/model/) for more information.
+![Model](images/icons/model.png){.left} 3D 模型组件支持在游戏中使用 Collada 网格模型, 骨骼和动画. 详情请见 [模型教程](/manuals/model/).
 
 ## ParticleFX
 
-![ParticleFX](images/icons/particlefx.png){.left} Particles are very useful for creating nice visual effects, particularly in games. you can use them to create fog, smoke, fire, rain or falling leaves. Defold contains a powerful particle effects editor that allows you to build and tweak effects while you run them real time in your game. The [ParticleFX documentation](/manuals/particlefx) gives you the details on how that works.
+![ParticleFX](images/icons/particlefx.png){.left} 粒子特效用来实现游戏里的某些视觉效果. 包括雾, 烟, 火, 雨或者落叶等等. Defold 自带了一个功能强大的例子编辑器用来创建和实时调整粒子效果. 详情请见 [粒子教程](/manuals/particlefx).
 
 ## Profiling
 
-Good performance is key in games and it is vital that you are able to do performance and memory profiling to measure your game and identify performance bottlenecks and memory problems that needs to be fixed. See the [Profiling manual](/manuals/profiling) for more information on the profiling tools available for Defold.
+性能对于游戏至关重要, 通过数据分析你可以发现游戏性能上的瓶颈以及内存泄漏等问题. 详情请见 [性能分析教程](/manuals/profiling).
 
 ## Render
 
-![Render](images/icons/render.png){.left} Render files contain settings used when rendering the game to the screen. Render files define which Render script to use for rendering and which materials to use. See the [Render manual](/manuals/render/) for more details.
+![Render](images/icons/render.png){.left} 渲染文件包含把游戏渲染到屏幕所需的设置和参数. 渲染文件决定了使用哪个渲染脚本和哪个材质资源. 详情请见 [Render manual](/manuals/render/).
 
 ## Render script
 
-![Render script](images/icons/script.png){.left} A Render script is a Lua script that controls how the game or app should be rendered to the screen. There is a default Render script that covers most common cases, but you can write your own if you need custom lighting models and other effects. See the [Render manual](/manuals/render/) for more details on how the render pipeline works, and the [Lua in Defold manual](/manuals/lua) for details on how Lua scripts are used in Defold.
+![Render script](images/icons/script.png){.left} 渲染脚本是由 Lua 语言编写的用于渲染游戏内容的脚本. 自带的默认渲染脚本大多数情况下可用, 但是如果需求自定义效果就需要自己写渲染脚本了. 详情请见 [渲染教程](/manuals/render/) for more details on how the render pipeline works, and the [Lua in Defold manual](/manuals/lua).
 
 ## Script
 
-![Script](images/icons/script.png){.left}  A script is a component that contains a program that defines game object behaviors. With scripts you can specify the rules of your game, how objects should respond to various interactions (with the player as well as other objects). All scripts are written in the Lua programming language. To be able to work with Defold, you or someone on your team needs to learn how to program in Lua. See the [Lua in Defold manual](/manuals/lua) for an overview on Lua and details on how Lua scripts are used in Defold.
+![Script](images/icons/script.png){.left}  脚本是包含代码的组件, 它控制着游戏对象的行为. 使用脚本可以编写游戏逻辑, 对象交互 (人机交互或者游戏内游戏对象交互). 脚本用 Lua 语言写成. 使用 Defold, 必须要会写 Lua 脚本. 详情请见 [Defold 脚本教程](/manuals/lua).
 
 ## Sound
 
-![Sound](images/icons/sound.png){.left} The sound component is responsible for playing a specific sound. Currently, Defold supports sound files in the WAV and Ogg Vorbis formats. See the [Sound manual](/manuals/sound) for more information.
+![Sound](images/icons/sound.png){.left} 声音组件用于播放声音. 目前 Defold 支持 WAV 和 Ogg Vorbis 格式的声音文件. 详情请见 [声音教程](/manuals/sound).
 
 ## Spine model
 
-![Spine model](images/icons/spine-model.png){.left} The Spine model component is used to bring Spine skeletal animations to life in Defold. Read more about how to use it in the [Spine model manual](/manuals/spinemodel).
+![Spine model](images/icons/spine-model.png){.left} Spine model 组件用于在 Defold 中使用 Spine 骨骼动画. 详情请见 [Spine 模型教程](/manuals/spinemodel).
 
 ## Spine scene
 
-![Spine scene](images/icons/spine-scene.png){.left} The Spine scene resource ties together the Spine JSON data file and the Defold image atlas file that is used to fill bone slots with graphics. The [Spine animation manual](/manuals/spine) contains more information.
+![Spine scene](images/icons/spine-scene.png){.left} Spine scene 资源把 Spine JSON 数据文件与 Defold 图集资源文件结合起来填充 Spine 骨架. 详情请见 [Spine 动画教程](/manuals/spine).
 
 ## Sprite
 
-![Sprite](images/icons/sprite.png){.left} A sprite is a component that extends game objects with graphics. It displays an image either from a Tile source or from an Atlas. Sprites have built-in support for flip-book and bone animation. Sprites are usually used for characters and items.
+![Sprite](images/icons/sprite.png){.left} Sprite 可以使游戏对象显示出图像. 它使用瓷砖图源或者图集资源的数据显示图像. Sprite 也支持逐帧动画. 它常常被用于显示人物, 物品等.
 
 ## Texture profiles
 
-![Texture profiles](images/icons/texture-profiles.png){.left} The texture profiles resource file is used in the bundling process to automatically process and compress image data (in Atlas, Tile sources, Cubemaps and stand-alone textures used for models, GUI etc). Read more in the [Texture profiles manual](/manuals/texture-profiles).
+![Texture profiles](images/icons/texture-profiles.png){.left} 纹理档案资源文件用于编译时自动处理和压缩图片数据 (Atlas, Tile sources, 3D Cubemaps 和 textures , GUI 等等). 详情请见 [Texture profiles manual](/manuals/texture-profiles).
 
 ## Tile map
 
-![Tile map](images/icons/tilemap.png){.left} Tile map components display images from a tile source in one or more overlaid grids. They are most commonly used to build game environments: ground, walls, buildings and obstacles. A tile map can display several layers aligned on top of each other with a specified blend mode. This is useful to, for example, put foliage on top of grass background tiles. It is also possible to dynamically change the displayed image in a tile. That allows you to, for instance, destroy a bridge and make it impassable by simply replacing the tiles with ones depicting the broken down bridge and containing the corresponding physics shape. See the [Tile map documentation](/manuals/tilemap) for more information.
+![Tile map](images/icons/tilemap.png){.left} 瓷砖地图使用瓷砖图源数据建立一层或多层结构的平铺图像. 通常用来作为游戏场景: 背景, 墙, 建筑物和遮挡物等等. 可以指定混合模式显示多层关系. 比如叶子落在地上. 瓷砖也可以动态更换. 比如可以用来制作桥梁被炸毁的效果. 详情请见 [瓷砖地图教程](/manuals/tilemap).
 
 ## Tile source
 
-![Tile source](images/icons/tilesource.png){.left} A tile source describes a texture that is composed of multiple smaller images, each with the same size. You can define flip-book animations from a sequence of images in a tile source. Tile sources can also automatically calculate collision shapes from image data. This is very useful for creating tiled levels that object can collide and interact with. Tile sources are used by Tile map components (and Sprite and ParticleFX) to share graphics resources. Note that Atlases are often a better fit than tile sources. See the [Tile map documentation](/manuals/tilemap) for more information.
+![Tile source](images/icons/tilesource.png){.left} 瓷砖图源由许多相同大小码放整齐的小图组成. 可以使用瓷砖图源创建逐帧动画. 瓷砖图源可以通过图片数据自动生成碰撞形状. 做关卡时碰撞形状可以当作障碍或者与角色产生交互. 瓷砖地图 (以及 Sprite 和 ParticleFX) 之间可以共享图像资源. 注意能用图集别用瓷砖图源. 详情请见 [瓷砖地图教程](/manuals/tilemap).
 
 ## Vertex shader
 
-![Vertex shader](images/icons/vertex-shader.png){.left} The vertex shader computes the screen geometry of a component's primitive polygon shapes. For any type of visual component, be it a sprite, spine model or model, the shape is represented by a set of polygon vertex positions. The vertex shader program processes each vertex (in world space) and computes the resulting coordinate that each vertex of a primitive should have. See the [Shader manual](/manuals/shader) for more information.
+![Vertex shader](images/icons/vertex-shader.png){.left} 顶点着色器用于计算多边形在屏幕上投射的位置. 对于各种可视组件, 比如 sprite, spine 模型 或者 3D 模型, 它们的形状由多边形顶点构成. 顶点着色程序负责处理顶点 (在全局游戏空间) 的位置并且负责计算出每个多边形顶点的在屏幕上的映射位置. 详情请见 [Shader manual](/manuals/shader).

+ 3 - 4
docs/zh/manuals/gpgs.md

@@ -1,6 +1,5 @@
 ---
-title: Google Play Game Services in Defold
-brief: This document describes how to set up and use Google Play Game Services
+title: Defold 中的 Google Play Game 服务
+brief: 本教程介绍了配置和使用 Google Play Game 服务的方法
 ---
-
-[本教程已被移除](/extension-gpgs)
+[本教程已被移至这里](/extension-gpgs)

+ 6 - 0
docs/zh/manuals/gui-box.md

@@ -41,6 +41,12 @@ GUIs 对于其元素的大小改变是积极的: 面板和对话框总是应该
 - 边缘部分延单轴缩放. 左右边缘竖直缩放. 上下边缘水平缩放.
 - 中央部分正常延两个轴缩放.
 
+上述关于 *九宫格* 纹理缩放的描述仅在节点 size 改变时生效:
+
+![GUI box node size](images/gui-box/slice9_size.png){srcset="images/gui-box/[email protected] 2x"}
+
+如果更改方块节点的缩放属性 - 节点和纹理的缩放都不会带九宫格效果.
+
 因为渲染器里 mipmapping 的工作方式, 部分缩放纹理可能会造成小问题. 当你把纹理一部分 _缩小_ 到比本身小的时候. 渲染器会自动选择一个低分辨率的 mipmap 来渲染这部分, 导致了这个小问题.
 
 ![九宫格 mipmapping](images/gui-box/mipmap.png){srcset="images/gui-box/[email protected] 2x"}

+ 33 - 33
docs/zh/manuals/gui-layouts.md

@@ -3,98 +3,98 @@ title: Defold 里的 GUI 布局
 brief: Defold 支持让 GUIs 自动适配手机屏幕方向的改变. 本教程介绍这部分功能.
 ---
 
-# Layouts
+# 布局
 
 Defold支持可自动适应移动设备上屏幕方向变化的GUI。通过使用此功能,您可以设计适合各种屏幕尺寸的方向和纵横比的GUI。也可以创建与特定设备型号匹配的布局。
 
-## Creating display profiles
+## 新建显示档案
 
-By default, the "game.project" settings specify that a built in display profiles settings file ("builtins/render/default.display_profiles") is used. The default profiles are "Landscape" (1280 pixels wide and 720 pixels high) and "Portrait" (720 pixels wide and 1280 pixels high). No device models are set on the profiles so they will match on any device.
+"game.project" 默认使用内置显示档案文件 ("builtins/render/default.display_profiles"). 默认 "横屏" (1280 像素宽 720 像素高) 和 "竖屏" (720 像素宽 1280 像素高). 未指定显示器型号以便适应各种设备.
 
-To create a new profiles settings file, either copy the one from the "builtins" folder or <kbd>right click</kbd> a suitable location in the *Assets* view and select <kbd>New... ▸ Display Profiles</kbd>. Give the new file a suitable name and click <kbd>Ok</kbd>.
+要新建显示档案文件, 要么把 "builtins" 文件夹拷贝出来, 要么在  *Assets* 视图中 <kbd>右键点击</kbd> 然后选择 <kbd>New... ▸ Display Profiles</kbd>. 输入文件名然后点击 <kbd>Ok</kbd>.
 
-The editor now opens the new file for editing. Add new profiles by clicking the <kbd>+</kbd> in the *Profiles* list. For each profile, add a set of *qualifiers* for the profile:
+编辑器会自动打开新建的文件. 在 *Profiles* 列表里点击 <kbd>+</kbd>. 给每个档案加入不同的 *限定*:
 
 Width
-: The pixel width of the qualifier.
+: 限定宽度像素数.
 
 Height
-: The pixel height of the qualifier.
+: 限定高度像素数.
 
 Device Models
-: A comma separated list of device models. The device model matches the start of the device model name, e.g. `iPhone10` will match "iPhone10,\*" models. Model names with commas should be enclosed in quotes, i.e. `"iPhone10,3", "iPhone10,6"` matches iPhone X models (see https://www.theiphonewiki.com/wiki/Models). Note that the only platforms reporting a device model when calling `sys.get_sys_info()` is Android and iOS. Other platforms return an empty string and will therefore never pick a display profile that has a device model qualifier.
+: 以逗号分隔的设备型号名称表. 型号名只要匹配设备型号的开头就算匹配成功, 例如 `iPhone10` 匹配 "iPhone10,\*" 的所有设备. 型号名带逗号的要使用双引号包裹, 例如 `"iPhone10,3", "iPhone10,6"` 匹配 iPhone X 那两种设备 (参考 https://www.theiphonewiki.com/wiki/Models). 注意调用 `sys.get_sys_info()` 函数在 Android 和 iOS 会返回设备名. 其他平台返回空字符, 也就是说这样的设备对于限定了设备型号的档案都无法匹配.
 
 ![New display profiles](images/gui-layouts/new_profiles.png){srcset="images/gui-layouts/[email protected] 2x"}
 
-You also need to specify that the engine should use your new profiles. Open "game.project" and select the display profiles file in the *Display Profiles* setting under *display*:
+别忘了指定引擎使用你自己的档案文件. 打开 "game.project" 在 *display* 部分 *Display Profiles* 项里进行设置:
 
 ![Settings](images/gui-layouts/settings.png){srcset="images/gui-layouts/[email protected] 2x"}
 
-::: sidenote
-The current development app for iOS does not respect the *Dynamic Orientation* setting but will always change orientation dynamically.
+::: 注意
+目前 iOS 版开发用app的 *Dynamic Orientation* 设置不起作用, 不论设置为什么值, 应用屏幕都会自动旋转.
 :::
 
-If you want the engine to automatically switch between portrait and landscape layouts on device rotation, check the *Dynamic Orientation* box. The engine will dynamically select a matching layout and also change the selection if the device changes orientation.
+勾选 *Dynamic Orientation* 选项可以使引用在屏幕上自动旋转以适应横屏竖屏. 游戏引擎也会根据横屏竖屏选取合适的界面布局.
 
-## GUI layouts
+## GUI 布局
 
-The current set of display profiled can be used to create layout variants of your GUI node setup. To add a new layout to a GUI scene, right-click the *Layouts* icon in the *Outline* view and select <kbd>Add ▸ Layout ▸ ...</kbd>:
+显示档案里可以为用户界面设置各种布局. 为 GUI 常见添加布局, 在 *Outline* 视图的 *Layouts* 图标上右键点击然后选择 <kbd>Add ▸ Layout ▸ ...</kbd>:
 
 ![Add layout to scene](images/gui-layouts/add_layout.png){srcset="images/gui-layouts/[email protected] 2x"}
 
-When editing a GUI scene, all nodes are edited on a particular layout. The currently selected layout is indicated in the GUI scene layout dropdown in the toolbar. If no layout is chosen, the nodes are edited in the *Default* layout.
+编辑用户界面时, 每个操作都是针对一种布局而进行. 即针对在 GUI 场景的工具栏的下拉框中选中的布局进行编辑操作. 如果未选择任何布局, 默认操作的是 *Default* 布局.
 
 ![Layouts toolbar](images/gui-layouts/toolbar.png){srcset="images/gui-layouts/[email protected] 2x"}
 
 ![portrait edit](images/gui-layouts/portrait.png){srcset="images/gui-layouts/[email protected] 2x"}
 
-Each change to a node property that you do with a layout selected _overrides_ the property in respect to the *Default* layout. Properties that are overridden are marked in blue. Nodes with overridden properties are also marked in blue. You can click on the reset button next to any overridden property to reset it to the original value.
+选择指定布局之后每个节点的属性编辑都会 _覆盖_ *Default* 布局里的属性. 被覆盖的属性以蓝色高亮显示. 其节点同样以蓝色高亮显示. 属性旁边的重置按钮用来恢复默认属性值.
 
 ![landscape edit](images/gui-layouts/landscape.png){srcset="images/gui-layouts/[email protected] 2x"}
 
-A layout cannot delete or create new nodes, only override properties. If you need to remove a node from a layout you can either move the node off-screen or delete it with script logic. You should also pay attention to the currently selected layout. If you add a layout to your project, the new layout will be set up according to the currently selected layout. Also, copying and pasting nodes considers the currently selected layout, when copying *and* when pasting.
+布局不会增加或减少节点, 只会覆盖节点属性. 如果某个布局需要减少节点可以把它移到屏幕之外或者使用脚本删除掉. 注意不要忘记当前选择的布局. 新建布局之后编辑器会自动把它设置为当前布局. 而且复制粘贴节点的时候尤其要考虑当前选择的布局, 包括复制节点的时候 *和* 粘贴节点的时候.
 
-## Dynamic profile selection
+## 动态布局选择
 
-The dynamic layout matcher scores each display profile qualifier according to the following rules:
+动态布局匹配度根据以下规则为每个显示档案文件限制匹配评分:
 
-1. If there is no device model set, or the device model matches, a score (S) is calculated for the qualifier.
+1. 无设备型号限制或者匹配到了设备, 分数 (S) 加一.
 
-2. The score (S) is calculated with the area of the display (A), the area from the qualifier (A_Q), the aspect ratio of the display (R) and the aspect ratio of the qualifier (R_Q):
+2. 分数 (S) 的计算公式用到了显示器面积 (A), 面积限制 (A_Q), 显示器宽高比 (R) 和宽高比限制 (R_Q):
 
 <img src="https://latex.codecogs.com/svg.latex?\inline&space;S=\left|1&space;-&space;\frac{A}{A_Q}\right|&space;&plus;&space;\left|1&space;-&space;\frac{R}{R_Q}\right|" title="S=\left|1 - \frac{A}{A_Q}\right| + \left|1 - \frac{R}{R_Q}\right|" />
 
-3. The profile with the lowest scoring qualifier is selected, if the orientation (landscape or portrait) of the qualifier matches the display.
+3. 如果屏幕方向 (横屏或者竖屏) 与限制匹配, 则分数最低的显示档案被采用.
 
-4. If no profile with a qualifier of the same orientation is found, the profile with the best scoring qualifier of the other orientation is selected.
+4. 如果屏幕方向无匹配, 则另一方向分数最高的显示档案被采用.
 
-5. If no profile can be selected, the *Default* fallback profile is used.
+5. 如果没有显示档案被采用, 则 *Default* 显示档案被采用.
 
-Since the *Default* layout is used as fallback in runtime if there are no better matching layout it means that if you add a "Landscape" layout, it will be the best match for *all* orientations until you also add a "Portrait" layout.
+*Default* 布局只在没有自定义布局时产生作用, 也就是说如果你只制作了 "横屏" 布局, *任何* 方向的设备屏幕都会匹配到这个布局, 直到你又制作了 "竖屏" 布局.
 
-## Layout change messages
+## 布局变换消息
 
-When the engine switches layout as a result of device rotation, a `layout_changed` message is posted to the GUI components' scripts that are affected by the change. The message contains the hashed id of the layout so the script can perform logic depending on which layout is selected:
+当引擎发现屏幕方向被旋转, 就会向受影响的用户界面组件脚本发送一个 `layout_changed` 消息. 消息包含布局id的哈希值以便代码做针对性处理:
 
 ```lua
 function on_message(self, message_id, message, sender)
   if message_id == hash("layout_changed") and message.id == hash("My Landscape") then
-    -- switching layout to landscape
+    -- 转换为横屏布局
   elseif message_id == hash("layout_changed") and message.id == hash("My Portrait") then
-    -- switching layout to portrait
+    -- 转换为竖屏布局
   end
 end
 ```
 
-In addition, the current render script receives a message whenever the window (game view) changes and this includes orientation changes.
+而且当应用窗体 (游戏视口) 发生改变时, 包括屏幕方向改变时, 渲染脚本也会收到相应的消息.
 
 ```lua
 function on_message(self, message_id, message)
   if message_id == hash("window_resized") then
-    -- The window was resized. message.width and message.height contain the
-    -- new dimensions of the window.
+    -- 窗体尺寸变化. message.width 与 message.height 对应
+    -- 改变后窗口的宽和高.
   end
 end
 ```
 
-When orientation is switched, the GUI layout manager will automatically rescale and reposition GUI nodes according to your layout and node properties. In-game content, however, is rendered in a separate pass (by default) with a stretch-fit projection into the current window. To change this behavior, either supply your own modified render script, or use a camera [library](/assets/).
+屏幕方向改变时, 用户界面布局管理器会根据定义好的布局和节点属性缩放节点. 但是非用户界面节点的游戏内容, 默认用另一个渲染管线进行渲染, 所以会在改变的窗体里进行拉伸. 不想要这种效果的话, 要么自己写渲染脚本, 要么使用 [摄像机](/assets/).

+ 2 - 2
docs/zh/manuals/gui.md

@@ -5,9 +5,9 @@ brief: 本教程介绍了 Defold GUI 编辑器, 各种各样的 GUI 节点以及
 
 # GUI
 
-Defold provides you with a custom GUI editor and powerful scripting possibilities that are tailor made for the construction and implementation of user interfaces.
+Defold 提供了 GUI 编辑器以及与之配套的脚本用以实现用户界面.
 
-A graphical user interface in Defold is a component that you build and attach to a game object and place in a collection. This component has the following properties:
+Defold 的图形用户界面是被放在集合里的, 依附于游戏对象的 GUI 组件. 这种组件有如下特点:
 
 * It has simple, but powerful, layout features that allow resolution and aspect ratio independent rendering of your user interface.
 * It can have logic behavior attached to it through a *GUI script*.

+ 6 - 2
docs/zh/manuals/html5.md

@@ -38,6 +38,10 @@ Python 3:
 不能直接用浏览器打开 HTML5 游戏的 `index.html` 文件. 要通过服务器访问打开.
 :::
 
+::: 注意
+如果在控制台见到 "wasm streaming compile failed: TypeError: Failed to execute ‘compile’ on ‘WebAssembly’: Incorrect response MIME type. Expected ‘application/wasm’." 错误, 请确保你的服务器设置了 `application/wasm` MIME 类型对应 .wasm 文件.
+:::
+
 ## 打包 HTML5 游戏
 
 Defold 打包 HTML5 游戏很简单, 跟其他平台一样: 从菜单栏选择 <kbd>Project ▸ Bundle...​ ▸ HTML5 Application...</kbd>:
@@ -213,5 +217,5 @@ DEFOLD_ENGINE_ARGUMENTS
 
 HTML5 支持 `sys.save()`, `sys.load()` 和 `io.open()` 之类的文件操作, 但是与其他平台实现方法不同. 基于安全考虑浏览器里运行的 Javascript 无权直接读写本地文件. Emscripten (即 Defold) 使用 [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB) 代替, 它是基于浏览器的持久化存储方案, 基于浏览器的虚拟文件系统. 与其他平台的区别主要是比直接读写文件要慢而且实质上读写的是一个数据库. 浏览器开发者工具通常都提供了 IndexedDB 的读写功能.
 
-## FAQ
-:[HTML5 FAQ](../shared/html5-faq.md)
+## 问答
+:[HTML5 问答](../shared/html5-faq.md)

+ 15 - 15
docs/zh/manuals/http-requests.md

@@ -1,15 +1,15 @@
 ---
-title: HTTP Requests
-brief: This manual explains how to make HTTP requests.
+title: HTTP 请求
+brief: 本教程介绍了发布 HTTP 请求的方法.
 ---
 
-## HTTP requests
+## HTTP 请求
 
-Defold can make normal HTTP requests using the `http.request()` function.
+Defold 可以使用 `http.request()` 函数发布普通 HTTP 请求.
 
 ### HTTP GET
 
-This is the most basic request to get some data from the server. Example:
+这是最常见的获得信息的请求类型. 举个例子:
 
 ```Lua
 local function handle_response(self, id, response)
@@ -19,15 +19,15 @@ end
 http.request("https://www.defold.com", "GET", handle_response)
 ```
 
-This will make an HTTP GET request to https://www.defold.com. The function is asynchronous and will not block while making the request. Once the request has been made and a server has sent a response it will invoke/call the provided callback function. The callback function will receive the full server response, including status code and response headers.
+这段代码向 https://www.defold.com 发送了一个 HTTP GET 请求. 函数是异步的所以不会把游戏卡住. 一接到服务器回复便会调用回调函数. 回调函数里可以获取服务器返回的所有信息, 包括状态码和回复头信息.
 
-::: sidenote
-HTTP requests are automatically cached in the client to improve network performance. The cached files are stored in an OS specific application support path in a folder named `defold/http-cache`. You usually don't have to care about the HTTP cache but if you need to clear the cache during development you can manually delete the folder containing the cached files. On macOS this folder is located in `%HOME%/Library/Application Support/Defold/http-cache/` and on Windows in `%APP_DATA%/defold/http-cache`.
+::: 注意
+为了提高效率, HTTP 请求会自动缓存在客户端. 缓存文件保存在一个叫 `defold/http-cache` 的文件夹里, 其路径根据操作系统不同而不同. 一般来说不必关心缓存的存在, 除非你需要手动清除缓存文件. macOS 系统路径是 `%HOME%/Library/Application Support/Defold/http-cache/` , Windows 系统路径是 `%APP_DATA%/defold/http-cache`.
 :::
 
 ### HTTP POST
 
-When sending data, like a score or some authentication data, to a server it is typically done using a POST requests:
+当需要传输数据, 比如上传分数或者认证信息到服务器时, 通常需要发布 POST 请求:
 
 ```Lua
 local function handle_response(self, id, response)
@@ -41,14 +41,14 @@ local body = "foo=bar"
 http.request("https://httpbin.org/post", "POST", handle_response, headers, body)
 ```
 
-### Other HTTP methods
+### 其他 HTTP 请求类型
 
-Defold HTTP requests also support the HEAD, DELETE and PUT methods.
+Defold HTTP 请求支持 HEAD, DELETE 和 PUT 类型.
 
-### API Reference
+### API 文档
 
-Refer to the [API reference](/ref/http/) to learn more.
+请参考 [API 文档](/ref/http/).
 
-### Extensions
+### 扩展
 
-An alternative HTTP request implementation can be found in the [TinyHTTP extension](https://defold.com/assets/tinyhttp/).
+有一个第三方实现的 HTTP 请求扩展库叫做 [TinyHTTP extension](https://defold.com/assets/tinyhttp/).

+ 2 - 198
docs/zh/manuals/iap.md

@@ -1,202 +1,6 @@
 ---
 title: Defold 中的内支付
-brief: In-app purchases (or in-app billing) allows you to charge your players or app users for extra content or functionality. This manual explains Defold's API available for this functionality.
+brief: 应用内支付 (也称内购买) 允许用户付费以获得额外的内容或功能. 本教程介绍了相关功能的 Defold API.
 ---
 
-# In-app purchases
-
-Defold provides a unified, simple to use interface to Apple's iOS Appstore "in-app purchases" and Google Play's or Amazon's "in-app billing" on Android devices. Facebook Canvas "game payments" are supported for Facebook Canvas. These services gives you the opportunity to sell products as:
-
-* Standard in-app products (one time billing) of consumables or non-consumables and
-* Subscriptions (recurring, automated billing)
-
-::: important
-The current Defold interface allows full interaction with Apple's Storekit functionality. For Google Play and Facebook Canvas, the interface is identical, meaning that you can run the same code on either platform. However, some process flow might differ from platform to platform. Also note that there is currently no support for OS X purchases through the Mac Appstore.
-:::
-
-Detailed documentation from Apple, Google, Amazon and Facebook can be found here:
-
-* [In-App Purchase Programming Guide](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Introduction.html).
-* [Google Play In-app Billing documentation](http://developer.android.com/google/play/billing/index.html).
-* [Amazon In-app Purchase documentation](https://developer.amazon.com/public/apis/earn/in-app-purchasing).
-* [Facebook game payments documentation](https://developers.facebook.com/docs/payments).
-
-## Installing the extension
-
-To start using the In-app purchases extension you need to add it as a dependency to your `game.project` file. The latest stable version is available with the dependency URL:
-```
-https://github.com/defold/extension-iap/archive/master.zip
-```
-
-We recommend using a link to a zip file of a [specific release](https://github.com/defold/extension-iap/releases).
-
-Documentation of the API is available on the [extension GitHub page](https://defold.github.io/extension-iap/).
-
-
-## Testing Google Play Billing with static responses
-
-On Android it is recommended that you start implementing IAP in your app by using static responses from Google Play. This enables you to verify that everything in your app works correctly before you publish the app. Four reserved product IDs exist for testing static In-app Billing responses:
-
-`android.test.purchased`
-: Google Play responds as though you successfully purchased an item. The response includes a JSON string, which contains fake purchase information (for example, a fake order ID).
-
-`android.test.canceled`
-: Google Play responds as though the purchase was canceled. This can occur when an error is encountered in the order process, such as an invalid credit card, or when you cancel a user's order before it is charged.
-
-`android.test.refunded`
-: Google Play responds as though the purchase was refunded.
-
-`android.test.item_unavailable`
-: Google Play responds as though the item being purchased was not listed in your application's product list.
-
-## Setting up your app for purchases/billing
-
-The procedure on iOS and Android is similar:
-
-1. Make sure you are a registered Apple or Google Play developer.
-2. Set up your project so it works on your target device. See the [iOS development](/manuals/ios) and [Android development](/manuals/android) guides.
-3. Set up the app for testing:
-
-    - For Android, this is done on the [Google Play Developer Console](https://play.google.com/apps/publish/).
-    - For iOS, this is done on [iTunes Connect](https://itunesconnect.apple.com/). Make sure that your App ID (created in the "Member Center" on https://developer.apple.com) has "In-App Purchase" enabled.
-
-    ![iTunes Connect and Google Play Dev Console](images/iap/itunes_connect_google_play.png)
-
-4. For Google Play, you need to _upload and publish_ an alpha *.apk* file. For iTunes Connect, you should _not upload_ the development binary to iTunes Connect until the application is ready for App Review approval. If you upload a binary to iTunes Connect and it is not fully functional, Apple will likely reject it.
-
-5. Create products for your app.
-
-    ![iTunes Products](images/iap/itunes_products.png)
-
-    ![Google Play Products](images/iap/google_play_products.png)
-
-6. Add test users.
-    - The iTunes Connect page *Users and Roles* allow you to add users that can do test purchases in the _sandbox environment_. You should sign your app with a Developer certificate and use the sandbox account in Appstore on the test device.
-    - From the Google Play Developer Console, choose *Settings > Account Details* where you can add user emails to the License Testing section. Separate the emails by commas. This allows your testers to use test purchases that don’t actually cost real money.
-    - On Google Play, you also need to set up a Google Group for your testers. Google uses Groups to manage testers that can download your app from the Alpha and Beta stores. Click on the *Alpha Testing* tab and then *Manage list of testers* to add your Google Group as Alpha testers. The app must have passed through alpha publishing before you can see the opt-in link.
-
-![Alpha testers](images/iap/alpha_testers.png)
-
-The procedure on Facebook:
-
-1. Make sure you are a registered Facebook developer. Go to [Facebook for developers](https://developers.facebook.com/), "My Apps" and "Register as a developer", follow the steps.
-2. Facebook has extensive payment functionality and requires support of both synchronous and asynchronous payments. More info here [Payment overview](https://developers.facebook.com/docs/payments/overview)
-3. Set up app hosting and callback server:
-    * You will need to set up a secure canvas URL hosting your project. How this works is explained here [Games on Facebook](https://developers.facebook.com/docs/games/gamesonfacebook/hosting).
-    * The next step is to set up your callback server. Follow the steps here [Setting up your callback server](https://developers.facebook.com/docs/payments/realtimeupdates#yourcallbackserver).
-4. Set up you canvas app. Follow the steps on [Facebook Developer Dashboard](https://developers.facebook.com/quickstarts/?platform=canvas).
-5. Add test users. This is done in the "Canvas Payments" section of the app dashboard.
-6. Create products for your app [Defining products](https://developers.facebook.com/docs/payments/implementation-guide/defining-products/).
-
-## Asynchronous transactions
-
-The IAP API is asynchronous, meaning that after each request that your program sends to the server, the program will not halt and wait for a response. Instead, the program continues as ordinary and when the response arrives, a _callback_ function is invoked where you can react to the response data.
-
-To fetch all product information available:
-
-```lua
-local COINS_ID = "com.defold.examples.coins"
-local LOGO_ID = "com.defold.examples.logo"
-
-local function product_list(self, products, error)
-    if error == nil then
-        for i,p in pairs(products) do
-            print(p.ident)
-            print(p.title)
-            print(p.description)
-            print(p.currency_code)
-            print(p.price_string)
-        end
-    else
-        print(error.error)
-    end
-end
-
-function init(self)
-    -- Initiate a fetch of products (max 20 at a time for Google Play)
-    iap.list({ COINS_ID, LOGO_ID }, product_list)
-end
-```
-
-To perform actual transactions, first register a function that will listen to transaction results, then call the store function at the appropriate time:
-
-```lua
-local function iap_listener(self, transaction, error)
-    if error == nil then
-        if transaction.state == iap.TRANS_STATE_PURCHASING then
-            print("Purchasing...")
-        elseif transaction.state == iap.TRANS_STATE_PURCHASED then
-            print("Purchased!")
-        elseif transaction.state == iap.TRANS_STATE_UNVERIFIED then
-            print("Unverified!")
-        elseif transaction.state == iap.TRANS_STATE_FAILED then
-            print("Failed!")
-        elseif transaction.state == iap.TRANS_STATE_RESTORED then
-            print("Restored")
-        end
-    else
-        print(error.error)
-    end
-end
-
-function on_message(self, message_id, message, sender)
-    ...
-    -- Register the function that will listen to IAP transactions.
-    iap.set_listener(iap_listener)
-    -- Initiate a purchase of a coin...
-    iap.buy(COINS_ID)
-    ...
-end
-```
-
-The device operating system will automatically show a pop-up window allowing the user to go through with the purchase. The interface clearly indicates when you are running in the test/sandbox environment.
-
-![Confirm purchase](images/iap/ios_confirm_purchase.png)
-
-![Android purchase](images/iap/android_purchase.png)
-
-![Confirm purchase](images/iap/ios_purchase_done.png)
-
-## Synchronous payments
-
-Most payment providers only supports synchronous payments. This means that the client (your application) will receive a notification when the payment is complete, TRANS_STATE_PURCHASED. This is the final state of the payment, meaning no more callbacks will be done on this transaction.
-
-## Asynchronous payments
-
-Some payment providers require supporting asynchronous payments. This means that the client (your application) will only receive a notification when the payment is initiated. In order to verify completion of payment, further communication needs to be done between the developer server (or client) and the payment provider in order to verify.
-In the case of an initiated asynchronous payment the IAP listener will receive the state TRANS_STATE_UNVERIFIED to indicate this (as opposed to TRANS_STATE_PURCHASED). This is the final state of the payment, meaning no more callbacks will be done on this transaction.
-
-## Purchase fulfillment
-
-In order to complete a purchase from a payment provider, the application needs to signal a purchase fulfillment to the provider telling the provider the purchase has gone through (for example by developer server-side verification).
-IAP supports auto-completion, where fulfillment is automatically signaled to the provider when a purchase is complete (this is the default behavior). You can also disable auto-completion in the game project settings. You are then required to call `iap.finish()` when the transaction is complete, which will signal purchase fulfillment to the provider.
-
-### Consumable vs non-consumable products
-The Google Play store does only support consumable products. If you need non-consumable products it is recommended to use manual fulfillment of purchases and never finish purchases for products that should be non-consumable. As long as a purchase isn't finished it will be returned as an active purchase when `iap.set_listener()` is called.
-
-The Apple App Store supports non-consumable products which means that you need to finish all purchases when you provide products to your users. You can do it automatically by keeping the default behavior in the game project settings or manually (if you want to do that after server validation, for example) using `iap.finish()`.
-
-## Transaction receipt
-
-The receipt is a signed chunk of data that can be sent to the App Store to verify that the payment was successfully processed. This is most useful when designing a store that uses a separate server to verify that payment was processed.
-
-## Troubleshooting
-
-Android `iap.list()` returns "failed to fetch product"
-: You need to upload and publish an *.apk* on the alpha or beta channels on the Google Play Developer Console. Also make sure that the _time and date_ on your device is correct.
-
-Android (Google Play) `iap.list()` never returns more than 20 products
-: Google has an [limit of 20 products per request](https://github.com/googlesamples/android-play-billing/blob/master/TrivialDrive/app/src/main/aidl/com/android/vending/billing/IInAppBillingService.aidl#L62). The solution is to make multiple calls to `iap.list()` and combine the results if the number of products exceeds 20.
-
-iOS `iap.list()` returns nothing
-: Make sure that you’ve requested an iOS Paid Applications account, and all proper documentation has been filed. Without proper authorization, your iOS app purchasing (even test purchases) will not work.
-
-  Check that the AppId you have on the "Member Center" has in-app purchases activated and that you are signing your app (or the dev-app) with a provisioning profile that is up to date with the AppId (check the "Enabled Services:" field in the provisioning profile details in the "Certificates, Identifiers & Profiles" area of "Member Center")
-
-  Wait. It can take a few hours for the In-App product IDs to propagate to the Sandbox environment.
-
-iOS `iap.list()` fails logging error "Unexpected callback set"
-: `iap.list()` does not support nested calls. Calling `iap.list()` from an `iap.list()` callback function will be ignored, with the engine logging this error.
-
-On iOS, the "price_string" field contains '~' characters
-: The '~' characters are placeholders where no matching character could be found in the font file. The "price_string" field returned in the product list when using `iap.list()` is formatted with a _non breaking space_ (`\u00a0`) between the value and the currency denominator. If you render this string in the GUI, you need to add the character to the font's *extra_characters* field. On Mac OS X you can type non breaking spaces by pressing <kbd>Option + SPACE</kbd>. See http://en.wikipedia.org/wiki/Non-breaking_space for more information.
+[本教程已被移至](/extension-iap)

+ 6 - 4
docs/zh/manuals/input.md

@@ -1,11 +1,11 @@
 ---
 title: Defold 的设备输入操作
-brief: This manual explains how input works, how to capture input actions and create interactive script reactions.
+brief: 本教程介绍了输入系统如何工作, 如何捕获输入行为和相关脚本代码.
 ---
 
-# Input
+# 输入
 
-All user input is captured by the engine and dispatched as actions to script- and GUI script components in game objects that have acquired input focus and that implement the `on_input()` function. This manual explains how you set up bindings to capture input and how you create code that responds to it.
+输入由引擎捕获并转化为输入行为传送到获取了输入焦点并且实现了 `on_input()` 函数的游戏对象脚本组件中去. This manual explains how you set up bindings to capture input and how you create code that responds to it.
 
 The input system uses a set of simple and powerful concepts, allowing you to manage input as you see fit for your game.
 
@@ -36,7 +36,7 @@ Consuming input
 
 ## Setting up input bindings
 
-The input bindings is a project wide table that allows you to specify how device input should translate into named *actions* before they are dispatched to your script components and GUI scripts. You can create a new input binding file, <kbd>right click</kbd> a location in the *Assets* view and select <kbd>New... ▸ Input Binding</kbd>. To make the enginen use the new file, change the *Game Binding* entry in "game.project".
+The input bindings is a project wide table that allows you to specify how device input should translate into named *actions* before they are dispatched to your script components and GUI scripts. You can create a new input binding file, <kbd>right click</kbd> a location in the *Assets* view and select <kbd>New... ▸ Input Binding</kbd>. To make the engine use the new file, change the *Game Binding* entry in "game.project".
 
 ![Input binding setting](images/input/setting.png){srcset="images/input/[email protected] 2x"}
 
@@ -92,6 +92,8 @@ Gamepad Triggers
   On Windows, only XBox 360 controllers are currently supported. To hook up your 360 controller to your Windows machine, make sure it is setup correctly. See http://www.wikihow.com/Use-Your-Xbox-360-Controller-for-Windows
 
   Gamepad input setup uses a separate mapping file for each hardware gamepad type. See below for more information.
+  
+  Gamepad input bindings also provides two separate bindings named `Connected` and `Disconnected` to detect when a gamepad is connected (even those connected from the start) or disconnected.
 
 Touch Triggers
 : Single-touch type triggers are available on iOS and Android devices. Single-touch type triggers are not set up from the Touch Triggers section of the input bindings. Instead **single-touch triggers are automatically set up when you have mouse button input set up for `MOUSE_BUTTON_LEFT` or `MOUSE_BUTTON_1`**.

+ 1 - 1
docs/zh/manuals/instant-games.md

@@ -3,4 +3,4 @@ title: Facebook Instant Games
 brief: 本教程介绍了如何使用 Defold 创建 Facebook Instant Games.
 ---
 
-[此教程已被移除](/extension-fbinstant)
+本教程已被移至 [这里](/extension-fbinstant)

+ 45 - 7
docs/zh/manuals/ios.md

@@ -30,13 +30,13 @@ Provisioning Profiles
 在 Defold 中给应用做签名时, 需要提供加密证书和提供商档案文件.
 
 ::: 注意
-Member Center 页面的一些功能在 XCode 里也可以进行---前提是先安装好XCode.
+Member Center 页面的一些功能在 Xcode 里也可以进行---前提是先安装好Xcode.
 :::
 
 Device identifier (UDID)
 : iOS 设备的 UDID 可以通过wifi或者线路连接计算机查找. 打开 Xcode 选择 <kbd>Window ▸ Devices and Simulators</kbd>. 选中设备就会显示出序列号和UDID.
 
-  ![xcode devices](images/ios/xcode_devices.png)
+  ![Xcode devices](images/ios/Xcode_devices.png)
 
   如果没安装 Xcode也可以从 iTunes 里查看. 首先选中要查看的设备.
 
@@ -57,7 +57,7 @@ Device identifier (UDID)
 5. 选择 "Team" (自动生成) 并为app设置 bundle identifier.
 6. 确保 Xcode 为app生成了 *Provisioning Profile* 和 *Signing Certificate*.
 
-   ![](images/ios/xcode_certificates.png)
+   ![](images/ios/Xcode_certificates.png)
 
 7. 编译并且在设备上运行. 首次运行, Xcode 会提示打开开发者模式并为调试做好准备. 可能要等待一会儿.
 8. 确定应用正常运行后, 在硬盘上找到编译好的app. 可以在 "Report Navigator" 的编译报告里找到app位置.
@@ -72,7 +72,7 @@ Device identifier (UDID)
 
    ![](images/ios/free_provisioning.png)
 
-这个供应商档案文件连同加密证书可以在 Defold 为应用签名, 有效期一周, _限一个设备_. 这样生成的供应商档案无法向其增加更多的 UDID.
+这个供应商档案文件连同加密证书可以在 Defold 为应用签名, 有效期一周.
 
 档案过期后, 可以在 Xcode 里如法炮制再次生成临时档案文件.
 
@@ -90,13 +90,51 @@ Device identifier (UDID)
 
 点击 *Create Bundle* 并选择打包应用存放位置.
 
-可以在 *game.project* 项目配置文件中设置app图标, 启动图片等等.
+![ipa iOS application bundle](images/ios/ipa_file.png){.left}
+
+可以在 *game.project* 项目配置文件的 [iOS 部分](/manuals/project-settings/#ios) 设置应用的图标, 启动屏幕 storyboard 等等.
+
+### 创建 storyboard
+
+使用 Xcode 创建 storyboard. 启动 Xcode 新建一个项目. 选择 iOS 和单视图应用:
+
+![Create project](images/ios/storyboard_create_project.png)
+
+点击 Next 继续配置项目并输入名称:
+
+![Project settings](images/ios/storyboard_create_project_settings.png)
+
+点击 Create 完成项目创建. 接下来就可以创建 storyboard 了:
+
+![The project view](images/ios/storyboard_project_view.png)
+
+把需要的图片拖入项目. 然后打开 `Assets.xcassets`, 再把图片拖放到 `Assets.xcassets` 中去:
+
+![Add image](images/ios/storyboard_add_image.png)
+
+打开 `LaunchScreen.storyboard` 点击加号 (<kbd>+</kbd>) 按钮. 输入 "imageview" 找到 ImageView 控件.
+
+![Add image view](images/ios/storyboard_add_imageview.png)
+
+把控件拖放到 storyboard 上:
+
+![Add to storyboard](images/ios/storyboard_add_imageview_to_storyboard.png)
+
+从下拉列表中选择刚才放入 `Assets.xcassets` 的图片:
+
+![](images/ios/storyboard_select_image.png)
+
+进行摆放位置等操作, 还可能加入些文字标签或者其他界面组件. 制作好之后选择 <kbd>Product</kbd> -> <kbd>Build</kbd>. 等编译处理完成.
+
+最后一步, 拷贝编译生成的 `LaunchScreen.storyboardc` 文件. 打开仿达, 把 `LaunchScreen.storyboardc` 文件粘贴到你的 Defold 项目目录:
+
+
+    /Library/Developer/Xcode/DerivedData/YOUR-PRODUCT-NAME-cbqnwzfisotwygbybxohrhambkjy/Build/Intermediates.noindex/YOUR-PRODUCT-NAME.build/Debug-iphonesimulator/YOUR-PRODUCT-NAME.build/Base.lproj/LaunchScreen.storyboardc
 
 ::: 注意
-iOS 上的应用, 启动图片决定了应用分辨率. 如果图片分辨率错误, 应用可能也会分辨率错误带黑边.
+社区牛人 Sergey Lerg 已把上述步骤 [录成了视频](https://www.youtube.com/watch?v=6jU8wGp3OwA&feature=emb_logo) 供大家参考.
 :::
 
-![ipa iOS application bundle](images/ios/ipa_file.png){.left}
 
 ## 安装 iOS 打包应用
 

+ 4 - 0
docs/zh/manuals/label.md

@@ -125,3 +125,7 @@ function init(self)
     go.set("#my_label", "scale.x", scale_x * 2)
 end
 ```
+
+## 相关项目配置
+
+在 *game.project* 文件里有些关于标签的 [设置项目](/manuals/project-settings#label).

+ 9 - 8
docs/zh/manuals/linux.md

@@ -1,15 +1,16 @@
+
 ---
-title: Defold development for the Linux platform
-brief: This manual describes how to build and run Defold applications on Linux
+title: Defold 开发 Linux 游戏
+brief: 本教程介绍了如何在 Linux 上编译运行 Defold 游戏
 ---
 
-# Linux development
+# Linux 开发
 
-Developing Defold applications for the Linux platform is a straight forward process with very few considerations to make.
+在 Linux 上编译运行 Defold 游戏十分简单.
 
-## Project settings
+## 项目配置
 
-Linux specific application configuration is done from the [Linux section](/manuals/project-settings/#linux) of the *game.project* settings file.
+Linux 相关设置位于 *game.project* 文件的 [Linux 部分](/manuals/project-settings/#linux).
 
-## FAQ
-:[Linux FAQ](../shared/linux-faq.md)
+## 问答
+:[Linux 问答](../shared/linux-faq.md)

+ 8 - 2
docs/zh/manuals/live-update.md

@@ -1,8 +1,10 @@
 ---
 title: Defold 的热更新
-brief: The Live update functionality provides a mechanism allowing the runtime to fetch and store resources to the application bundle that were intentionally left out of the bundle at build time. This manual explains how it works.
+brief: 热更新允许游戏运行时获取和存储编译时并不存在的资源. 本教程介绍了热更新的用法.
 ---
 
+# 目前热更新机制正在升级, 本教程可能随时变化
+
 # Live update
 
 When bundling a game, Defold packs all the game resources into the resulting platform specific package. In most cases this is preferred since the running engine has instant access to all resources and can load them swiftly from storage. However, there are instances where you might want to postpone the loading of resources to a later stage. For instance:
@@ -152,6 +154,10 @@ When storing a new manifest the manifest data will be verified before it is actu
 
 From the user's perspective the verification process is completely opaque but it is important to note the steps involved to avoid the most common pitfalls.
 
+::: important
+If you see a "ERROR:RESOURCE: Byte mismatch in decrypted manifest signature. Different keys used for signing?" error in the console on HTML5 builds it is likely that your webserver doesn't serve the excluded content or updated manifest file using the correct MIME type. Make sure the MIME type is `application/octet-stream`. You can add a `.htaccess` file with a single `AddType application/octet-stream .` line to the folder where the live update resources are downloaded from.
+:::
+
 ### Supported engine versions
 A manifest will always support the Defold version used when generating it. If you want to support any additional engine versions, add them to the list in the Live update settings. This can be useful if your live game uses a different Defold version than the one you are using to generate the manifest with.
 
@@ -354,4 +360,4 @@ Forcing re-download of resources
 
   ![Local storage](images/live-update/local-storage.png)
 
-  The location of the application support folder depends on the operating system. It can be found with `print(sys.get_save_file("", ""))`.
+  The location of the application support folder depends on the operating system. It can be found with `print(sys.get_save_file("", ""))`.

+ 10 - 2
docs/zh/manuals/lua.md

@@ -34,10 +34,18 @@ Defold 包含所有 [Lua 5.1 标准库](http://www.lua.org/manual/5.1/manual.htm
 
 ## Lua 书籍和资源
 
+### Online resources
+
 * [Programming in Lua (first edition)](http://www.lua.org/pil/contents.html) 已有第二版.
 * [Lua 5.1 reference manual](http://www.lua.org/manual/5.1/)
-* Beginning Lua Programming (Wrox, 2007)
-* Game Development with Lua (Charles River Media, 2005)
+* [Learn Lua in 15 Minutes](http://tylerneylon.com/a/learn-lua/)
+* [Awesome Lua - tutorial section](https://github.com/LewisJEllis/awesome-lua#tutorials)
+
+### Books
+* [Programming in Lua](https://www.amazon.com/gp/product/8590379868/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0) - Programming in Lua is the official book about the language, providing a solid base to any programmer who wants to use Lua. Authored by Roberto Ierusalimschy, the chief architect of the language.
+* [Lua programming gems](https://www.amazon.com/Programming-Gems-Luiz-Henrique-Figueiredo/dp/8590379841) - This collection of articles record some of the existing wisdom and practice on how to program well in Lua.
+* [Lua 5.1 reference manual](https://www.amazon.com/gp/product/8590379833/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i4) - Also available online (see above)
+* [Beginning Lua Programming](https://www.amazon.com/Beginning-Lua-Programming-Kurt-Jung/dp/0470069171)
 
 ## 语法
 

+ 32 - 32
docs/zh/manuals/macos.md

@@ -1,22 +1,22 @@
 ---
-title: Defold development for the macOS platform
-brief: This manual describes how to build and run Defold applications on macOS
+title: macOS 平台游戏开发
+brief: 本教程介绍了在 macOS 平台上编译和运行 Defold 游戏的方法
 ---
 
-# macOS development
+# macOS 开发
 
-Developing Defold applications for the macOS platform is a straight forward process with very few considerations to make.
+为 macOS 平台开发游戏非常简单, 有几件事需要注意.
 
-## Project settings
+## 项目配置
 
-macOS specific application configuration is done from the [OSX section](/manuals/project-settings/#osx) of the *game.project* settings file.
+macOS 相关选项位于 *game.project* 配置文件的 [OSX 部分](/manuals/project-settings/#osx).
 
-## Application icon
+## 应用图标
 
-The application icon used for a macOS game must be in the .icns format. You can easily create a .icns file from a set of .png files collected as an iconset. Follow the [official instructions for creating a .icns file](https://developer.apple.com/library/archive/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html). Brief summary of the steps involved are:
+macOS 图标只支持 .icns 格式. 可以使用一组.png文件生成一个.icns图标集. 参照 [官方 .icns 文件生成方法](https://developer.apple.com/library/archive/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Optimizing/Optimizing.html). 其主要步骤有:
 
-* Create an iconset folder, eg `game.iconset`
-* Copy icon files to the created folder:
+* 新建图标集文件夹, 比如 `game.iconset`
+* 把图片文件放入上述文件夹里:
 
     * `icon_16x16.png`
     * `[email protected]`
@@ -29,22 +29,22 @@ The application icon used for a macOS game must be in the .icns format. You can
     * `icon_512x512.png`
     * `[email protected]`
 
-* Convert the .iconset folder to a .icns file using the `iconutil` command line tool:
+* 使用命令行工具 `iconutil` 把文件夹转化成图标集:
 
 ```
 iconutil -c icns -o game.icns game.iconset
 ```
 
-## Publishing your application
-You can publish your application to the Mac App Store, using a 3rd party store or portal such as Steam or itch.io or on your own through a website. Before publishing your application you need to prepare it for submission. The following steps are required regardless of how you intend to distribute the application:
+## 发布游戏应用
+可以把游戏发布到 Mac App Store, 第三方软件商店或者像 Steam 和 itch.io 这样的门户网站, 当然也可以放在自己的网站上. 发布之前做好提交准备. 无论发布到哪, 下面这些都是应该要考虑的事情:
 
-* 1) Make sure that anyone is able to run your game by adding the execute permissions (the default is that only the file owner has execute permissions):
+* 1) 添加运行权限以便所有玩家都能运行游戏 (默认文件所有者拥有运行权限):
 
 ```
 $ chmod +x Game.app/Contents/MacOS/Game
 ```
 
-* 2) Create an entitlements file specifying the permissions required by your game. For most games the following permissions are enough:
+* 2) 建立 entitlements 文件表明游戏所需权限. 例如:
 
 ```xml
 <?xml version="1.0" encoding="UTF-8"?>
@@ -61,33 +61,33 @@ $ chmod +x Game.app/Contents/MacOS/Game
 </plist>
 ```
 
-  * `com.apple.security.cs.allow-jit` - Indicates whether the app may create writable and executable memory using the MAP_JIT flag
-  * `com.apple.security.cs.allow-unsigned-executable-memory` - Indicates whether the app may create writable and executable memory without the restrictions imposed by using the MAP_JIT flag
-  * `com.apple.security.cs.allow-dyld-environment-variables` - Indicates whether the app may be affected by dynamic linker environment variables, which you can use to inject code into your app’s process
+  * `com.apple.security.cs.allow-jit` - 让游戏可以使用 MAP_JIT 标识写入和运行内存内容
+  * `com.apple.security.cs.allow-unsigned-executable-memory` - 让游戏可以不必严格使用 MAP_JIT 标识也能写入和运行内存内容
+  * `com.apple.security.cs.allow-dyld-environment-variables` - 让游戏接受动态连接环境变量以便可以向游戏进程注入代码
 
-Some applications may also need additional entitlements. The Steamworks extension needs this extra entitlement:
+根据自己的游戏情况增减项目. 比如 Steamworks 扩展库需要如下权限:
 
 ```
 <key>com.apple.security.cs.disable-library-validation</key>
 <true/>
 ```
 
-    * `com.apple.security.cs.disable-library-validation` - Indicates whether the app may load arbitrary plug-ins or frameworks, without requiring code signing.
+    * `com.apple.security.cs.disable-library-validation` - 让游戏可以载入任意插件和库而不需要它们的代码签名.
 
-All of the entitlements that can be granted to an application are listed in the official [Apple developer documentation](https://developer.apple.com/documentation/bundleresources/entitlements).
+应用可以设置的一切权限都列在 [Apple 开发者文档](https://developer.apple.com/documentation/bundleresources/entitlements).
 
-* 3) Sign your game using `codesign`:
+* 3) 使用 `codesign` 为游戏签名:
 
 ```
 $ codesign --force --sign "Developer ID Application: Company Name" --options runtime --deep --timestamp --entitlements entitlement.plist Game.app
 ```
 
-## Publishing outside the Mac App Store
-Apple requires all software distributed outside the Mac App Store to be notarized by Apple in order to run by default on macOS Catalina. Refer to the [official documentation](https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow) to learn how to add notarization to a scripted build environment outside of Xcode. Brief summary of the steps involved are:
+## 发布到 Mac App Store 以外的地方
+Apple 要求发布到 Mac App Store 以外的应用必须加入苹果认证才能在 macOS Catalina 上运行. 关于命令行编译环境加入认证的方法参考 [官方文档](https://developer.apple.com/documentation/Xcode/notarizing_macos_software_before_distribution/customizing_the_notarization_workflow). 大体步骤是:
 
-* 1) Follow the above steps of adding permissions and signing the application.
+* 1) 完成上述添加权限和签名的工作.
 
-* 2) Zip and upload your game for notarization using `altool`.
+* 2) 使用 `altool` 命令行工具上传游戏包来添加苹果认证.
 
 ```
 $ xcrun altool --notarize-app
@@ -101,22 +101,22 @@ altool[16765:378423] No errors uploading 'Game.zip'.
 RequestUUID = 2EFE2717-52EF-43A5-96DC-0797E4CA1041
 ```
 
-* 3) Check the status of your submission using the returned request UUID from the call to `altool --notarize-app`:
+* 3) 使用 `altool --notarize-app` 命令行工具检查这个 UUID 的应用状态:
 
 ```
 $ xcrun altool --notarization-info 2EFE2717-52EF-43A5-96DC-0797E4CA1041
                -u "AC_USERNAME"
 ```
 
-* 4) Wait until the status becomes `success` and staple the notarization ticket to the game:
+* 4) 等到状态变为 `success` 然后把证书打入游戏包:
 
 ```
 $ xcrun stapler staple "Game.app"
 ```
 
-* 5) Your game is now ready for distribution.
+* 5) 完成之后就可以发布了. --苹果之壁(莲)
 
-## Publishing to the Mac App Store
-The process when publishing to the Mac App Store is well documented in the [Apple Developer documentation](https://developer.apple.com/macos/submit/). Make sure to add permissions and codesign the application as described above before submitting.
+## 发布到 Mac App Store
+这在 [Apple 开发者文档](https://developer.apple.com/macos/submit/) 里已经详细说明. 注意提交前要确保已加入权限和签名.
 
-Note: The game does not have to be notarized when publishing to the Mac App Store.
+注意: 发布到 Mac App Store 不需要任何认证.

+ 38 - 32
docs/zh/manuals/material.md

@@ -50,31 +50,37 @@ Tags
 着色器常量, 或称 "uniforms" 是从引擎传输给顶点和片元着色器程序的数据. 要使用常量,您可以在材质文件中将其定义为一个 *顶点常量* 属性或 *片元常量* 属性。需要在着色器程序中定义相应的 `uniform` 变量。材质中可以设置以下常量:
 
 CONSTANT_TYPE_WORLD
-: The world matrix. Use to transform vertices into world space. For some component types, the vertices are already in world space when they arrive to the vertex program (due to batching). In those cases multiplying with the world matrix in the shader will yield the wrong results.
+: 世界矩阵. 用来把顶点转换为世界坐标. 有的组件类型, 由于合批的应用它们到达顶点着色程序时已经是世界坐标的了. 在这些情况下,用着色器程序把世界矩阵再乘一遍就会产生错误的结果.
 
 CONSTANT_TYPE_VIEW
-: The view matrix. Use to transform vertices to view (camera) space.
+: 视图矩阵. 用于转换顶点为视口(相机)空间坐标.
 
 CONSTANT_TYPE_PROJECTION
-: The projection matrix. Use to transform vertices to screen space.
+: 映射矩阵. 用于将顶点转换为屏幕空间坐标.
 
 CONSTANT_TYPE_VIEWPROJ
-: A matrix with the view and projection matrices already multiplied.
+: 视口与其映射矩阵相乘后的矩阵.
 
 CONSTANT_TYPE_WORLDVIEW
-: A matrix with the world and view projection matrices already multiplied.
+: 世界与视口映射矩阵相乘后的矩阵.
 
 CONSTANT_TYPE_NORMAL
-: A matrix to compute normal orientation. The world transform might include non-uniform scaling, which breaks the orthogonality of the combined world-view transform. The normal matrix is used to avoid issues with the direction when transforming normals. (The normal matrix is the transpose inverse of the world-view matrix).
+: 用于计算法方向的矩阵. 世界移动转换可能包含非等比缩放, 这样会打破世界-视口转换的正交性. 变换法线时使用发方向可以避免这个问题. (法矩阵是世界-视口矩阵的转置逆).
 
 CONSTANT_TYPE_USER
-: A vector4 constant that you can use for any custom data you want to pass into your shader programs. You can set the initial value of the constant in the constant definition, but it is mutable through the functions `.set_constant()` and `.reset_constant()` for each component type (`sprite`, `model`, `spine`, `particlefx` and `tilemap`). Changing a material constant of a single component instance [breaks render batching and will result in additional draw calls](/manuals/render/#draw-calls-and-batching).
+: 一个 vector4 常量用以向你的着色程序传递自定义数据. 定义时可以赋初值, 可以通过各组件 (`sprite`, `model`, `spine`, `particlefx` 和 `tilemap`) 的 `.set_constant()` 和 `.reset_constant()` 函数来改变其值. 改变单个组件实例的材质参数会 [打破合批增加drawcall](/manuals/render/#draw-calls-and-batching).
+<br>举例:
+```lua
+go.set("#sprite", "tint", vmath.vector4(1,0,0,1))
+
+go.animate("#sprite", "tint", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2)
+```
 
-## Samplers
+## 采样器
 
-Samplers are used to sample the color information from a texture (a tile source or atlas). The color information can then be used for calculations in the shader program.
+采样器用于从纹理 (瓷砖图源或者图集) 中取得颜色数据. 颜色数据用于在着色器程序中参与计算.
 
-Sprite, tilemap, GUI and particle effect components automatically gets a `sampler2D` set. The first declared `sampler2D` in the shader program is automatically bound to the image referenced in the graphics component. Therefore there is currently no need to specify any samplers in the materials file for those components. Furthermore, those component types currently only support a single texture. (If you need multiple textures in a shader, you can use [`render.enable_texture()`](/ref/render/#render.enable_texture) and set texture samplers manually from your render script.)
+Sprite, tilemap, GUI 和 particle effect 组件自动获得 `sampler2D` 集. 着色程序里第一个声明的 `sampler2D` 与可视组件所引用的图片自动绑定. 也就是说这些组件不用特地指定材质文件. 而且目前这些组件只支持一个纹理. (如需在着色器中使用多纹理, 可以使用 [`render.enable_texture()`](/ref/render/#render.enable_texture) 在渲染脚本中手动设置采样器.)
 
 ![Sprite sampler](images/materials/sprite_sampler.png){srcset="images/materials/[email protected] 2x"}
 
@@ -88,11 +94,11 @@ void main()
 }
 ```
 
-You can specify a component's sampler settings by adding the sampler by name in the materials file. If you don't set up your sampler in the materials file, the global *graphics* project settings are used.
+在材质文件中添加取样器名就指定了一个采样器. 要是材质文件里没有指定, 会使用项目全局设置里的 *graphics* 设置.
 
 ![Sampler settings](images/materials/my_sampler.png){srcset="images/materials/[email protected] 2x"}
 
-For model components, you need to specify your samplers in the material file with the settings you want. The editor will then allow you to set textures for any model component that use the material:
+对于3D模型组件, 还要在材质文件里设置采样器属性. 之后编辑器会让你选择使用该材质的3D模型纹理:
 
 ![Model samplers](images/materials/model_samplers.png){srcset="images/materials/[email protected] 2x"}
 
@@ -111,31 +117,31 @@ void main()
 
 ![Model](images/materials/model.png){srcset="images/materials/[email protected] 2x"}
 
-## Sampler settings
+## 采样器设置
 
 Name
-: The name of the sampler. This name should match the `sampler2D` declared in the fragment shader.
+: 采样器名. 需要与片元着色器中定义的 `sampler2D` 变量名相匹配.
 
-Wrap U/W
-: The wrap mode for the U and V axes:
+Wrap U/V
+: U V 轴向上的包裹模式:
 
-  - `WRAP_MODE_REPEAT` will repeat texture data outside the range [0,1].
-  - `WRAP_MODE_MIRRORED_REPEAT` will repeat texture data outside the range [0,1] but every second repetition is mirrored.
-  - `WRAP_MODE_CLAMP_TO_EDGE` will set texture data for values greater than 1.0 to 1.0, and any values less than 0.0 is set to 0.0---i.e. the edge pixels will be repeated to the edge.
+  - `WRAP_MODE_REPEAT` [0,1] 范围之外重复纹理.
+  - `WRAP_MODE_MIRRORED_REPEAT` [0,1] 范围之外重复纹理, 但是再次重复时使用镜像的纹理.
+  - `WRAP_MODE_CLAMP_TO_EDGE` 把大于 1.0 的值设置为 1.0, 小于 0.0 的值设置为 0.0---也就是说边缘的纹理会扩展开去.
 
 Filter Min/Mag
-: The filtering for magnification and minification. Nearest filtering requires less computation than linear interpolation, but can result in aliasing artifacts. Linear interpolation often provides smoother results:
+: 缩放过滤. 就近过滤比线性插值过滤省资源, 但是可能产生不良效果. 一般线性插值过滤结果比较平滑:
 
-  - `FILTER_MODE_NEAREST` uses the texel with coordinates nearest the center of the pixel.
-  - `FILTER_MODE_LINEAR` sets a weighted linear average of the 2x2 array of texels that lie nearest to the center of the pixel.
-  - `FILTER_MODE_NEAREST_MIPMAP_NEAREST` chooses the nearest texel value within an individual mipmap.
-  - `FILTER_MODE_NEAREST_MIPMAP_LINEAR` selects the nearest texel in the two nearest best choices of mipmaps and then interpolates linearly between these two values.
-  - `FILTER_MODE_LINEAR_MIPMAP_NEAREST` interpolates linearly within an individual mipmap.
-  - `FILTER_MODE_LINEAR_MIPMAP_LINEAR` uses linear interpolation to compute the value in each of two maps and then interpolates linearly between these two values.
+  - `FILTER_MODE_NEAREST` 使用位于像素中心最近的图素.
+  - `FILTER_MODE_LINEAR` 使用位于像素中心最近的的2x2图素矩阵的加权线性平均值.
+  - `FILTER_MODE_NEAREST_MIPMAP_NEAREST` 使用位于单个mipmap上最近的图素值.
+  - `FILTER_MODE_NEAREST_MIPMAP_LINEAR` 在最近的两个mipmap中选出最近的两个图素再进行线性插值.
+  - `FILTER_MODE_LINEAR_MIPMAP_NEAREST` 在单个mipmap里线性插值.
+  - `FILTER_MODE_LINEAR_MIPMAP_LINEAR` 使用线性插值分别计算两个mipmap再把两个结果进行线性插值.
 
-## Constants buffers
+## 常量缓存
 
-When the rendering pipeline draws, it pulls constant values from a default system constants buffer. You can create a custom constants buffer to override the default constants and instead set shader program uniforms programmatically in the render script:
+渲染管线工作时, 默认会从系统常量缓存中拉取数据. 也可以建立自定义缓存再把着色器参数在渲染脚本里填充进缓存里去:
 
 ```lua
 self.constants = render.constant_buffer() -- <1>
@@ -143,8 +149,8 @@ self.constants.tint = vmath.vector4(1, 0, 0, 1) -- <2>
 ...
 render.draw(self.my_pred, self.constants) -- <3>
 ```
-1. Create a new constants buffer
-2. Set the `tint` constant to bright red
-3. Draw the predicate using our custom constants
+1. 新建常量缓存
+2. 设置 `tint` 常量为白色
+3. 使用自定义常量进行渲染
 
-Note that the buffer's constant elements are referenced like an ordinary Lua table, but you can't iterate over the buffer with `pairs()` or `ipairs()`.
+注意常量缓存就是一个普通的 Lua 表, 只是不能使用 `pairs()` 或 `ipairs()` 来进行迭代.

+ 20 - 13
docs/zh/manuals/mesh.md

@@ -1,11 +1,11 @@
 ---
-title: Defold 中的3D模型
-brief: 本教程介绍了如何在你的 Defold 游戏中添加3D模型.
+title: Defold 中的3D网格
+brief: 本教程介绍了如何在你的 Defold 游戏中添加3D网格.
 ---
 
 # Mesh 组件
 
-Defold 本质是3D的. 即使 2D 材质也是以 3D 方法进行渲染, 再通过正交投射显示在屏幕上. Defold 也可以使用全3D素材, 也可以在运行时建立3D模型. 纯3D还是混合2D、3D游戏根据需要随意创作.
+Defold 本质是3D的. 即使 2D 材质也是以 3D 方法进行渲染, 再通过正交投射显示在屏幕上. Defold 也可以使用全3D素材, 也可以在运行时建立3D网格. 纯3D还是混合2D、3D游戏根据需要随意创作.
 
 ## 新建 Mesh 组件
 
@@ -23,10 +23,10 @@ Mesh 组件包含一些列属性:
 除了 *Id*, *Position* 和 *Rotation*, 还有如下属性:
 
 *Material*
-: 3D模型材质.
+: 3D网格材质.
 
 *Vertices*
-: 描述3D模型各种流顶点信息的缓冲文件.
+: 描述3D网格各种流顶点信息的缓冲文件.
 
 *Primitive Type*
 : Lines, Triangles 还是 Triangle Strip.
@@ -38,23 +38,30 @@ Mesh 组件包含一些列属性:
 : *法线* 流. 流在顶点着色器输入数据时自动提供.
 
 *tex0*
-: 3D模型的纹理.
+: 3D网格的纹理.
 
 ## 编辑时操作
 
-3D模型组件建立好之后就可以使用编辑器和 *Scene Editor* 工具, 像普通游戏对象一样, 随意进行旋转缩放.
+3D网格组件建立好之后就可以使用编辑器和 *Scene Editor* 工具, 像普通游戏对象一样, 随意进行旋转缩放.
 
 ## 运行时操作
 
-可以使用 Defold 缓存在运行时修改3D模型.
+可以使用 Defold 缓存在运行时修改3D网格.
+
+## 材质常量
+
+{% include shared/material-constants.md component='mesh' variable='tint' %}
+
+`tint`
+: 3D网格颜色 (`vector4`). 四元数 x, y, z, 和 w 分别对应红, 绿, 蓝和不透明度.
 
 ## 顶点的局部/世界坐标空间
-如果3D模型材质的坐标空间设为局部坐标空间, 则数据会原封不动传入着色器, 这样通常要在着色器程序里进行GPU顶点/法线的转换.
+如果3D网格材质的坐标空间设为局部坐标空间, 则数据会原封不动传入着色器, 这样通常要在着色器程序里进行GPU顶点/法线的转换.
 
-如果3D模型材质的坐标空间设为世界坐标空间, 则必须要么提供默认的 “位置” 和 “法线”, 流, 要么在编辑3D模型时, 在下拉菜单中选择好. 这样便于引擎把同样是世界坐标系的3D模型进行数据合批.
+如果3D网格材质的坐标空间设为世界坐标空间, 则必须要么提供默认的 “位置” 和 “法线”, 流, 要么在编辑3D网格时, 在下拉菜单中选择好. 这样便于引擎把同样是世界坐标系的3D网格进行数据合批.
 
 ## 举例
-关于3D模型操作及示例项目和代码片段请参考 [这个论坛帖子](https://forum.defold.com/t/mesh-component-in-defold-1-2-169-beta/65137).
+关于3D网格操作及示例项目和代码片段请参考 [这个论坛帖子](https://forum.defold.com/t/mesh-component-in-defold-1-2-169-beta/65137).
 
 用三角形建立方块的例子:
 
@@ -78,7 +85,7 @@ local vertices = {
 	0, 1, 0
 }
 
--- 用位置流建立3D模型缓存
+-- 用位置流建立3D网格缓存
 local buf = buffer.create(#vertices / 3, {
 	{ name = hash("position"), type=buffer.VALUE_TYPE_FLOAT32, count = 3 }
 })
@@ -89,7 +96,7 @@ for i, value in ipairs(vertices) do
 	positions[i] = vertices[i]
 end
 
--- 用三角形数据建立方块3D模型
+-- 用三角形数据建立方块3D网格
 local res = go.get("#mesh", "vertices")
 resource.set_buffer(res, buf)
 ```

+ 6 - 0
docs/zh/manuals/message-passing.md

@@ -149,6 +149,12 @@ message_id
 对于 `message` 参数的表的大小有硬性限制. 限制最大2KB. 没有具体用来测试表大小的函数但是可以通过插入表之前和之后分别调用 `collectgarbage("count")` 来判断表占用内存的大小.
 :::
 
+### 简化符
+
+Defold 提供两种简化写法用来简化消息传递时需要输入的完整地址:
+
+:[Shorthands](../shared/url-shorthands.md)
+
 ## 接收消息
 
 接收消息由 `on_message()` 函数完成. 函数接收4个参数:

+ 3 - 3
docs/zh/manuals/model.md

@@ -95,12 +95,12 @@ go.animate("#model", "cursor", go.PLAYBACK_LOOP_PINGPONG, 1, go.EASING_LINEAR, 1
 在内置材质文件夹里有一个3D模型材质. 如果需要自定义材质, 请参考 [材质文档](/manuals/material). [着色器教程](/manuals/shader) 介绍了着色器程序的工作方式.
 
 
-### 材质属性
+## 材质常量
 
-模型的默认材质属性可以用 `model.set_constant()` 和 `model.reset_constant()` 方法来设置和重置 (详情参见 [材质教程](/manuals/material/#vertex-and-fragment-constants)):
+{% include shared/material-constants.md component='model' variable='tint' %}
 
 `tint`
-: 模型的染色 (`vector4`). 四元数 x, y, z, 和 w 代表染色的红, 绿, 蓝 和不透明度. 参见 [这个例子的 API 用法](/ref/model/#model.set_constant:url-constant-value).
+: 3D网格颜色 (`vector4`). 四元数 x, y, z, 和 w 分别对应红, 绿, 蓝和不透明度.
 
 
 ## 渲染

+ 1 - 1
docs/zh/manuals/models.md

@@ -1,6 +1,6 @@
 ---
 title: 废弃的 3D 模型教程
-brief: 教程已过时
+brief: 教程已过时
 ---
 
 # 模型

+ 7 - 57
docs/zh/manuals/networking.md

@@ -1,64 +1,14 @@
 ---
 title: Defold 联网
-brief: 本教程介绍了如何连接远程服务器以建立其他各种连接.
+brief: 本教程介绍了如何连接远程服务器以建立各种连接.
 ---
 
-# 联网
-
-游戏需要连接各种后台服务器的情况很常见, 比如为了记录分数, 匹配对战玩家或者在云端存档. 还有的游戏有点对点交互的功能, 而不必连接中央服务器. 网络连接和数据交换可以用多种方式实现:
-
-* [HTTP Requests](#http-requests)
-* [Socket connections](#socket-connections)
-* [WebSocket connections](#websocket-connections)
-
-
-## HTTP 请求
-
-Defold 能使用 `http.request()` 函数来建立 HTTP 请求. 比如:
-
-```Lua
-local function handle_response(self, id, response)
-	print(response.status, response.response)
-end
-
-http.request("https://www.defold.com", "GET", handle_response)
-```
-
-这样就建立了一个到 https://www.defold.com 的 HTTP GET 请求. 这个函数是异步的所以请求同时游戏并不卡住等待响应. 当服务器发回响应数据后会进入设置好的回调函数. 回调函数接收了相应包含的所有信息, 包括状态码和响应头. 同样可以建立 HTTP POST 请求来向服务器发送数据也能设置请求头信息. 更多详情请见 [API 教程](/ref/http/).
-
-::: 注意
-为了提高效率, HTTP 请求会自动缓存在客户端. 缓存文件保存在一个叫 `defold/http-cache` 的文件夹里, 其路径根据操作系统不同而不同. 一般来说不必关心缓存的存在, 除非你需要手动清除缓存文件. macOS 系统路径是 `%HOME%/Library/Application Support/Defold/http-cache/` , Windows 系统路径是 `%APP_DATA%/defold/http-cache`.
-:::
 
-## Socket 连接
-
-Defold 包含 [LuaSocket 库](http://w3.impa.br/~diego/software/luasocket/) 用来创建 TCP 和 UDP socket 连接. 创建socket连接, 发送数据和接收响应需要调用这些函数:
-
-```Lua
-local client = socket.tcp()
-client:connect("127.0.0.1", 8123)
-client:settimeout(0)
-client:send("foobar")
-local response = client:receive("*l")
-```
-
-这样就建立好了一个 TCP socket, 连接到了 IP 127.0.0.1 (localhost) 的端口 8123. 把超时设置成 0 就是建立成非阻塞式的socket, 然后它在socket上发送了 "foobar" 消息. 最后它读取了一行socket响应数据 (读字节直到出现换行符). 注意此代码没有做错误处理. LuaSocket的更多功能详情请见 [API 文档](/ref/socket/). [官方 LuaSocket 文档](http://w3.impa.br/~diego/software/luasocket/) 同样包含了该库的许多使用实例. 此外这里也有许多实例和工具模块 [DefNet 库](https://github.com/britzl/defnet/).
-
-
-## WebSocket 连接
-
-Defold 不提供现成的建立 WebSocket 连接的方法. 对于 WebSocket 联网功能推荐使用 [Defold-WebSocket 扩展](https://github.com/britzl/defold-websocket).
-
-# 游戏服务器
-
-使用 HTTP 请求可以让你能够和互联网上各种各样的服务器交互, 但是通常不会这么简单的发送 HTTP 请求. 通常你需要做一些认证和数据序列化之类的操作. 当然手动操作也可以, 但是我们有很多现成的服务插件可以使用. 使用这些插件能简化许多操作:
+# 联网
 
-* [AWS SDK](https://github.com/britzl/aws-sdk-lua) - 让游戏能够使用 Amazon Web Services
-* [Colyseus](https://github.com/colyseus/colyseus-defold) - 网游客户端
-* [Firebase Analytics](https://github.com/defold/extension-firebase-analytics) - 让游戏能够使用 Firebase Analytics
-* [Google Analytics](https://github.com/britzl/defold-googleanalytics) - 让游戏能够使用 Google Analytics
-* [Google Play Game Services](https://github.com/defold/extension-gpgs) - 让游戏能够使用 Google Play Game Services 来进行用户认证和云端存档
-* [PlayFab](https://github.com/PlayFab/LuaSdk) - 让游戏能够使用 用户认证, 玩家匹配, 跟踪分析, 云端存档等等功能
-* [Steamworks](https://github.com/britzl/steamworks-defold/) - 让游戏能够使用 Steam 支持
+如今带后台服务的游戏并不新奇了, 也许需要向后台传送分数, 匹配玩家或者在云端存档. 许多游戏带点对点交流的功能, 以便客户端之间能够直接对话, 而不需要中央服务器. 网络连接与数据交换有许多种协议和标准. 详情请见:
 
-可以在 [资源大厅](https://www.defold.com/assets/) 找到更多扩展程序!
+* [HTTP 请求](/manuals/http-requests)
+* [Socket 连接](/manuals/socket-connections)
+* [WebSocket 连接](/manuals/websocket-connections)
+* [在线服务](/manuals/online-services)

+ 20 - 20
docs/zh/manuals/nintendo-switch.md

@@ -1,42 +1,42 @@
 ---
-title: Defold development for Nintendo Switch
-brief: This manual describes how to get Nintendo Switch access
+title: 使用 Defold 开发 Nintendo Switch 游戏
+brief: 本教程介绍了 Nintendo Switch 开发许可
 ---
 
-# Sign up for Nintendo Switch development
+# 注册为 Nintendo Switch 开发者
 
-Support for the Nintendo Switch platform is not included in the standard version of Defold. In order to get access to Nintendo Switch support in Defold you need to:
+标准版 Defold 不含 Nintendo Switch 开发工具. 如果需要使用 Defold 开发 Nintendo Switch 游戏, 你需要:
 
-1. Become a Defold community donor with Nintendo Switch access included in your membership tier, and
-2. Become a registered game developer for Nintendo platforms.
+1. 注册为 Defold 社区赞助者, 赞助者权益中包含 Nintendo Switch 开发权力.
+2. 在 Nintendo 注册为开发者.
 
 
-## Become a Defold community donor with Nintendo Switch access
+## 注册为 Defold 社区赞助者享受 Nintendo Switch 开发权
 
-You become a Defold community donor on the [Defold community donation page](/community-donations/). You can become a donor with Nintendo Switch access using either GitHub Sponsors or Patreon. Pay attention to the available tiers and select one which includes Nintendo Switch access.
+在 [Defold 社区捐款平台](/community-donations/) 上捐一定数量的款, 你就成为了一名拥有 Nintendo Switch 开发权的会员. 注意有些捐款选项不含 Nintendo Switch 开发权.
 
 ![](images/nintendo-switch/register-defold.png)
 
-## Register as a game developer for Nintendo platforms
+## 在 Nintendo 注册为开发者
 
-You register as a game developer for Nintendo platforms at the [Nintendo Developer Portal](https://developer.nintendo.com/register):
+去到 [Nintendo 开发者中心](https://developer.nintendo.com/register) 注册成为游戏开发者:
 
 ![](images/nintendo-switch/register-nintendo.png)
 
-When you register you will get access to Nintendo developer tools and resources to create and publish games and applications for current Nintendo platforms.
+完成 Nintendo 开发者注册你就可以得到 Nintendo 平台的资源与开发工具, 也有权在 Nintendo 平台上发布自己的游戏.
 
 
-### Request Defold access
+### Defold 支持申请
 
-When you have been approved by Nintendo you need to log in to the Nintendo Developer Portal and visit the Tools and Middleware page and sign up for Defold access. When you register for Defold access we will get an email from Nintendo verifying you as a registered Nintendo developer. We will then proceed to verify you as a community donor with Nintendo Switch access included in your membership tier.
+当你成功注册为 Nintendo 开发者之后首先要去 Nintendo 开发者中心下载必要工具然后在中间件页面申请 Defold 支持. 提交申请之后你会收到来自 Nintendo 的电子邮件用以确认你的 Nintendo 开发者身份. 然后 Defold 会对你的赞助者 Nintendo Switch 开发权进行核实.
 
-When we have verified you as a donor with Nintendo Switch access we will provide you with the access to the following:
+已经核实我们会提供下列工具:
 
-* Versions of the Defold editor and the Defold command line tools (bob.jar) with support for bundling to the Nintendo Switch platform.
-* Private forum group where you are able to get Nintendo Switch specific support.
-* Nintendo Switch specific documentation
-* API reference to Nintendo Switch specific engine functionality.
+* Defold 编辑器及其命令行工具 (bob.jar) 包含 Nintendo Switch 发布功能的特别版.
+* Nintendo Switch 技术支持私人讨论组.
+* Nintendo Switch 相关文档.
+* Nintendo Switch 相关引擎API.
 
 
-## FAQ
-:[Nintendo Switch FAQ](../shared/nintendo-switch-faq.md)
+## 问答
+:[Nintendo Switch 问答](../shared/nintendo-switch-faq.md)

+ 17 - 17
docs/zh/manuals/online-services.md

@@ -1,25 +1,25 @@
 ---
-title: Online Services
-brief: This manual explains how to connect to different game and backend services.
+title: 在线服务
+brief: 本教程介绍了接入第三方服务的方法.
 ---
-# Game services
+# 游戏服务
 
-Using HTTP requests and socket connections allows you to connect to and interact with thousands of different services on the internet, but in most cases there's more to it than simply making an HTTP request. You usually need to use some kind of authentication, the request data may need to be formatted in a certain way and the response may need to be parsed before it can be used. This can of course be done manually by you but there are also extensions and libraries to take care of this sort of thing for you. Below you'll find a list of some extensions that can be used to more easily interact with specific backend services:
+使用 HTTP 请求和 socket 连接可以使你的游戏与网上各种各样的服务进行交互, 但是通常光是 HTTP 请求远远不够. 比如用户认证, 请求数据可能需要加密, 服务端需要解密. 这些可以手动去做但是网上也有许多服务和库来帮你做这些事. 下表列出了一些带扩展支持的第三方网络后台服务:
 
-## General purpose
-* [Colyseus](https://defold.com/assets/colyseus/) - Multiplayer game client
-* [Nakama](https://defold.com/assets/nakama/) - Add authentication, matchmaking, analytics, cloud save, multiplayer, chat and more to your game
-* [PlayFab](https://defold.com/assets/playfabsdk/) - Add authentication, matchmaking, analytics, cloud save and more to your game
-* [AWS SDK](https://github.com/britzl/aws-sdk-lua) - Use Amazon Web Services from within your game
+## 一般常见
+* [Colyseus](https://defold.com/assets/colyseus/) - 多人在线客户端
+* [Nakama](https://defold.com/assets/nakama/) - 包含玩家认证, 玩家匹配, 统计分析, 云端存取, 多人在线, 聊天等各种功能
+* [PlayFab](https://defold.com/assets/playfabsdk/) - 包含玩家认证, 玩家匹配, 统计分析, 云端存取等各种功能
+* [AWS SDK](https://github.com/britzl/aws-sdk-lua) - 亚马逊服务器客户端
 
-## Authentication, leaderboards, achievements
-* [Google Play Game Services](https://defold.com/assets/googleplaygameservices/) - Use Google Play Game Services to authenticate and use cloud save in your game
-* [Steamworks](https://defold.com/assets/steamworks/) - Add Steam support to your game
+## 玩家认证, 排行榜, 成就系统
+* [Google Play Game Services](https://defold.com/assets/googleplaygameservices/) - Google Play 游戏服务客户端, 包含玩家认证, 云端存取等功能
+* [Steamworks](https://defold.com/assets/steamworks/) - Steam 服务客户端
 * [Apple GameKit Game Center](https://defold.com/assets/gamekit/)
 
-## Analytics
-* [Firebase Analytics](https://defold.com/assets/googleanalyticsforfirebase/) - Add Firebase Analytics to your game
-* [Game Analytics](https://gameanalytics.com/docs/item/defold-sdk) - Add GameAnalytics to your game
-* [Google Analytics](https://defold.com/assets/gameanalytics/) - Add Google Analytics to your game
+## 统计分析
+* [Firebase Analytics](https://defold.com/assets/googleanalyticsforfirebase/) - Firebase 统计分析系统
+* [Game Analytics](https://gameanalytics.com/docs/item/defold-sdk) - GameAnalytics 统计分析系统
+* [Google Analytics](https://defold.com/assets/gameanalytics/) - Google Analytics 统计分析系统
 
-Check the [Asset Portal](https://www.defold.com/assets/) for even more extensions!
+更多请关注 [资源中心](https://www.defold.com/assets/)

+ 3 - 0
docs/zh/manuals/optimization.md

@@ -26,6 +26,9 @@ Defold 编译和打包时建立了一个依赖树. 编译系统从 *game.project
 
 为了更好的分析包体空间占用可以在编译时 [生成编译报告](/manuals/bundling/#build-reports). 通常声音和图片占游戏空间最大部分.
 
+### 缩减引擎
+可以使用 [application manifest 文件](https://defold.com/manuals/project-settings/#app-manifest) 去掉引擎中不需要的功能. 比如游戏不用物理效果就去掉物理引擎. 使用 [Manifestation 在线工具](https://britzl.github.io/manifestation/) 可以方便配置和生成这个文件.
+
 ### 声音优化
 Defold 支持 .ogg 和 .wav 文件其中 .ogg 一般用于音乐 .wav 一般用于音效. Sounds 必须是 16-bit 采样率 44100 所以编码前就要对其做好优化. 可以使用第三方软件降低音质或者把 .wav 转换成 .ogg.
 

+ 4 - 0
docs/zh/manuals/particlefx.md

@@ -237,3 +237,7 @@ The default particle effect material has the following constants that can be cha
 
 `tint`
 : The color tint of the particle effect (`vector4`). The vector4 is used to represent the tint with x, y, z, and w corresponding to the red, green, blue and alpha tint. Refer to the [API reference for an example](/ref/particlefx/#particlefx.set_constant:url-constant-value).
+
+## 相关项目配置
+
+在 *game.project* 文件里有些关于粒子效果的 [设置项目](/manuals/project-settings#particle-fx).

+ 42 - 23
docs/zh/manuals/physics.md

@@ -1,5 +1,5 @@
 ---
-title: Physics in Defold
+title: Defold 中的物理系统
 brief: Defold includes physics engines for 2D and 3D. They allow you to simulate Newtonian physics interactions between different types of collision objects. This manual explains how this works.
 ---
 
@@ -131,6 +131,21 @@ The shape will not be drawn in the editor. You can [enable Physics debugging](/m
 :::
 
 
+### Scaling collision shapes
+
+It is possible to let the collision object and its shapes inherit the scale of the game object. Check the [Allow Dynamic Transforms](/manuals/project-settings/#allow-dynamic-transforms) checkbox in the Physics section of *game.project* to enable this. Note that only uniform scaling is supported and that the smallest scale value will be used if the scale isn't uniform.
+
+
+### Rotating collision shapes
+
+### Rotating collision shapes in 3D physics
+Collision shapes in 3D physics can be rotated around all axis.
+
+
+### Rotating collision shapes in 2D physics
+Collision shapes in 2D physics can only be rotated around the z-axis. Rotation around the x or y axis will yield incorrect results and should be avoided, even when rotating 180 degrees to essentially flip the shape along the x or y axis. To flip a physics shape it is recommended to use [`physics.set_hlip(url, flip)`](/ref/stable/physics/?#physics.set_hflip:url-flip) and [`physics.set_vlip(url, flip)`](/ref/stable/physics/?#physics.set_vflip:url-flip).
+
+
 ### Units used by the physics engine simulation
 
 The physics engine simulates Newtonian physics and it is designed to work well with meters, kilograms and seconds (MKS) units. Furthermore, the physics engine is tuned to work well with moving objects of a size in the 0.1 to 10 meters range (static objects can be larger) and by default the engine treats 1 unit (pixel) as 1 meter. This conversion between pixels and meters is convenient on a simulation level, but from a game creation perspective it isn't very useful. With default settings a collision shape with a size of 200 pixels would be treated as having a size of 200 meters which is well outside of the recommended range, at least for a moving object. In general it is required that the physics simulation is scaled for it to work well with the typical size of objects in a game. The scale of the physics simulation can be changed in `game.project` via the [physics scale setting](/manuals/project-settings/#physics). Setting this value to for instance 0.02 would mean that 200 pixels would be treated as a 4 meters. Do note that the gravity (also changed in `game.project`) has to be increased to accommodate for the change in scale.
@@ -208,7 +223,7 @@ For a game or application where you need to separate objects perfectly, the `"co
 
 Triggers are light weight collision objects. Thay are similar to ray casts in that they read the physics world as opposed to interacting with it.
 
-In a trigger collision `"collision_response"` messages are sent. In addition, triggers also send a special `"trigger_response"` message when the collision begins and end. The message has the following fields:
+In a trigger collision `"collision_response"` messages are sent. In addition, triggers also send a special `"trigger_response"` message when the collision begins and ends. The message has the following fields:
 
 `other_id`
 : the id of the instance the collision object collided with (`hash`).
@@ -216,27 +231,6 @@ In a trigger collision `"collision_response"` messages are sent. In addition, tr
 `enter`
 : `true` if the interaction was an entry into the trigger, `false` if it was an exit. (`boolean`).
 
-## Ray casts
-
-Ray casts are used to read the physics world along a linear ray. To cast a ray into the physics world, you provide a start and end position as well as a set of collision groups to test against.
-
-If the ray hits a physics object you will get information about the object it hit. Rays intersect with dynamic, kinematic and static objects. They do not interact with triggers.
-
-```lua
-function update(self, dt)
-  -- request ray cast
-  local my_start = vmath.vector3(0, 0, 0)
-  local my_end = vmath.vector3(100, 1000, 1000)
-  local my_groups = { hash("my_group1"), hash("my_group2") }
-
-  local result = physics.raycast(my_start, my_end, my_groups)
-  if result then
-      -- act on the hit (see 'ray_cast_response' message for all values)
-      print(result.id)
-  end
-end
-```
-
 ## Resolving kinematic collisions
 
 Using kinematic collision objects require you to resolve collisions yourself and move the objects as a reaction. A naive implementation of separating two colliding objects looks like this:
@@ -320,6 +314,31 @@ function on_message(self, message_id, message, sender)
 end
 ```
 
+## Ray casts
+
+Ray casts are used to read the physics world along a linear ray. To cast a ray into the physics world, you provide a start and end position as well as a set of collision groups to test against.
+
+If the ray hits a physics object you will get information about the object it hit. Rays intersect with dynamic, kinematic and static objects. They do not interact with triggers.
+
+```lua
+function update(self, dt)
+  -- request ray cast
+  local my_start = vmath.vector3(0, 0, 0)
+  local my_end = vmath.vector3(100, 1000, 1000)
+  local my_groups = { hash("my_group1"), hash("my_group2") }
+
+  local result = physics.raycast(my_start, my_end, my_groups)
+  if result then
+      -- act on the hit (see 'ray_cast_response' message for all values)
+      print(result.id)
+  end
+end
+```
+
+::: sidenote
+Ray casts will ignore collision objects that contain the starting point of the ray. This is a limitation in Box2D.
+:::
+
 ## Joints
 
 Defold supports joints for 2D physics. A joint connects two collision objects using some kind of constraint. The supported joint types are:

+ 226 - 223
docs/zh/manuals/project-settings.md

@@ -15,55 +15,55 @@ brief: 本教程介绍了如何在 Defold 中进行项目配置工作.
 
 ## Project
 
-Title
-#### 项目标题.
+#### Title
+项目标题.
 
-Version
-#### 版本.
+#### Version
+版本.
 
-Write Log
-#### 选中时, 游戏引擎会在项目根目录记录 *log.txt* 日志. 运行于 iOS 时, 日志文件可以通过 iTunes 和 *Apps* 页的 *File Sharing* 部分访问. 在 Android 上, 日志文件保存在应用的外存中. 在运行 *dmengine* 开发应用时, 可以通过以下命令查看日志:
+#### Write Log
+选中时, 游戏引擎会在项目根目录记录 *log.txt* 日志. 运行于 iOS 时, 日志文件可以通过 iTunes 和 *Apps* 页的 *File Sharing* 部分访问. 在 Android 上, 日志文件保存在应用的外存中. 在运行 *dmengine* 开发应用时, 可以通过以下命令查看日志:
 
 ```bash
 $ adb shell cat /mnt/sdcard/Android/data/com.defold.dmengine/files/log.txt
 ```
 
-Compress Archive
-#### 打包时启用压缩. 注意此设置除了 Android 都有效, 因为apk已经是压缩档了.
+#### Compress Archive
+打包时启用压缩. 注意此设置除了 Android 都有效, 因为apk已经是压缩档了.
 
-Dependencies
-#### 项目的 *Library URL* 列表. 详情请见 [Libraries 教程](/manuals/libraries/).
+#### Dependencies
+项目的 *Library URL* 列表. 详情请见 [Libraries 教程](/manuals/libraries/).
 
-Custom Resources
-#### 项目中包含的以逗号分隔的资源列表. 如指定的是目录, 则目录下所有文件及其子目录都会包含进去. 这些资源可以通过 [`sys.load_resource()`](/ref/sys/#sys.load_resource) 载入.
+#### Custom Resources
+项目中包含的以逗号分隔的资源列表. 如指定的是目录, 则目录下所有文件及其子目录都会包含进去. 这些资源可以通过 [`sys.load_resource()`](/ref/sys/#sys.load_resource) 载入.
 
-Bundle Resources
-#### 需要根据平台单独打包的以逗号分隔的资源目录列表. 目录必须是以项目根目录开始的绝对路径, 比如像 `/res`. 资源目录里要包含 `platform`, 或者 `architecure-platform` 的子目录.
+#### Bundle Resources
+需要根据平台单独打包的以逗号分隔的资源目录列表. 目录必须是以项目根目录开始的绝对路径, 比如像 `/res`. 资源目录里要包含 `platform`, 或者 `architecure-platform` 的子目录.
 
   支持的 platform 有 `ios`, `android`, `osx`, `win32`, `linux`, `web`.
 
   允许名叫 `common` 的子目录, 用以容纳平台间共享的资源.
 
-Bundle Exclude Resources
-#### 项目中排除的以逗号分隔的资源列表.
+#### Bundle Exclude Resources
+项目中排除的以逗号分隔的资源列表.
 
 ## Bootstrap
 
-Main Collection
-#### 打开应用启动的起始集合, 默认 `/logic/main.collection`.
+#### Main Collection
+打开应用启动的起始集合, 默认 `/logic/main.collection`.
 
-Render
-#### 指定使用哪个渲染文件, 它决定了渲染流程, 默认 `/builtins/render/default.render`.
+#### Render
+指定使用哪个渲染文件, 它决定了渲染流程, 默认 `/builtins/render/default.render`.
 
 ## Library
 
-Include Dirs
-#### 使用库共享机制从项目中共享出去的以逗号分隔的目录列表.
+#### Include Dirs
+使用库共享机制从项目中共享出去的以逗号分隔的目录列表.
 
 ## Script
 
-Shared State
-#### 打开则共享脚本的Lua状态, 默认关闭.
+#### Shared State
+打开则共享脚本的Lua状态, 默认关闭.
 
 ## Engine
 
@@ -72,35 +72,32 @@ Shared State
 
 ## Display
 
-Width
-#### 应用窗口像素为单位宽度, 默认 `960`.
+#### Width
+应用窗口像素为单位宽度, 默认 `960`.
 
-Height
-#### 应用窗口像素为单位高度, 默认 `640`.
+#### Height
+应用窗口像素为单位高度, 默认 `640`.
 
-High Dpi
-#### 开启高dpi后台缓存来支持超高清. 技术上就是以 *Width* 和 *Height* 设置的双倍进行渲染, 但是脚本和属性使用的逻辑分辨率不变.
+#### High Dpi
+开启高dpi后台缓存来支持超高清. 技术上就是以 *Width* 和 *Height* 设置的双倍进行渲染, 但是脚本和属性使用的逻辑分辨率不变.
 
-Samples
-#### 超采样抗锯齿所使用的采样数量. 窗口提示是 GLFW_FSAA_SAMPLES. 默认是 `0`, 相当于关闭抗锯齿.
+#### Samples
+超采样抗锯齿所使用的采样数量. 窗口提示是 GLFW_FSAA_SAMPLES. 默认是 `0`, 相当于关闭抗锯齿.
 
-Fullscreen
-#### 设置应用启动是否使用全屏. 如果关闭, 应用会以窗口形式启动.
+#### Fullscreen
+设置应用启动是否使用全屏. 如果关闭, 应用会以窗口形式启动.
 
-Frame Cap
-#### 如果 `Vsync` 开启, 则为锁帧频率匹配最接近的交换间隔. 否则的话依据锁帧设置计时器, 0 代表不锁帧. 此设置相当于 `display.update_frequency`.
+#### Frame Cap
+如果 `Vsync` 开启, 则为锁帧频率匹配最接近的交换间隔. 否则的话依据锁帧设置计时器, 0 代表不锁帧. 此设置相当于 `display.update_frequency`.
 
-Vsync
-#### 垂直同步, 根据硬件的帧率进行刷新. 可以被驱动程序或者操作系统平台设置覆盖.
+#### Vsync
+垂直同步, 根据硬件的帧率进行刷新. 可以被驱动程序或者操作系统平台设置覆盖.
 
-Variable Dt (deprecated)
-#### 弃用. 如果开启, 编译时将会开启 `Vsync` 同时设置 `Frame Cap` 为 0.
+#### Display Profiles
+指定使用哪个显示样式文件, 默认 `/builtins/render/default.display_profilesc`.  详情请见 [GUI 排版教程](/manuals/gui-layouts/#creating-display-profiles).
 
-Display Profiles
-#### 指定使用哪个显示样式文件, 默认 `/builtins/render/default.display_profilesc`.  详情请见 [GUI 排版教程](/manuals/gui-layouts/#creating-display-profiles).
-
-Dynamic Orientation
-#### 开启的话会在设备转动时动态切换横竖显示方向. 注意开发用app(指dmengine)不参考此设置.
+#### Dynamic Orientation
+开启的话会在设备转动时动态切换横竖显示方向. 注意开发用app(指dmengine)不参考此设置.
 
 ## 渲染
 
@@ -118,208 +115,214 @@ Dynamic Orientation
 
 ## Physics
 
-Type
-#### 使用何种物理引擎, `2D` (默认) 还是 `3D`.
+#### Type
+使用何种物理引擎, `2D` (默认) 还是 `3D`.
+
+#### Gravity Y
+延Y轴的重力加速度, 默认是 `-10` (自然重力加速度)
 
-Gravity Y
-#### 延Y轴的重力加速度, 默认是 `-10` (自然重力加速度)
+#### Debug
+设置物理是否显示debug线.
 
-Debug
-#### 设置物理是否显示debug线.
+#### Debug Alpha
+debug线的不透明度, `0`--`1`. 默认是 `0.9`.
 
-Debug Alpha
-#### debug线的不透明度, `0`--`1`. 默认是 `0.9`.
+#### World Count
+可以同时存在的物理世界最大数目, 默认是`4`. 如果需要使用 collection proxies 载入更多物理世界可以提高此设置. 请注意每个物理世界都要占用相应的内存.
 
-World Count
-#### 可以同时存在的物理世界最大数目, 默认是`4`. 如果需要使用 collection proxies 载入更多物理世界可以提高此设置. 请注意每个物理世界都要占用相应的内存.
+#### Gravity X
+延X轴的重力加速度, 默认是 `0`.
 
-Gravity X
-#### 延X轴的重力加速度, 默认是 `0`.
+#### Gravity Z
+延Z轴的重力加速度, 默认是 `0`.
 
-Gravity Z
-#### 延Z轴的重力加速度, 默认是 `0`.
+#### Scale
+设定物理世界与游戏世界的数值映射比例, `0.01`--`1.0`. 如果设置为 `0.02`, 相当于物理引擎视50个游戏单位为1米 ($1 / 0.02$). 默认值是 `1.0`.
 
-Scale
-#### 设定物理世界与游戏世界的数值映射比例, `0.01`--`1.0`. 如果设置为 `0.02`, 相当于物理引擎视50个游戏单位为1米 ($1 / 0.02$). 默认值是 `1.0`.
+#### Allow Dynamic Transforms
+设定物理世界碰撞物体是否进行像游戏对象同等的缩放.
 
-Debug Scale
-#### 设置物理元物体画多大, 比如原向量和法线,  默认是`30`.
+#### Debug Scale
+设置物理元物体画多大, 比如原向量和法线,  默认是`30`.
 
-Max Collisions
-#### 设置向脚本报告多少个碰撞, 默认是 `64`.
+#### Max Collisions
+设置向脚本报告多少个碰撞, 默认是 `64`.
 
-Max Contacts
-#### 设置向脚本报告多少碰撞点, 默认是 `128`.
+#### Max Contacts
+设置向脚本报告多少碰撞点, 默认是 `128`.
 
-Contact Impulse Limit
-#### 设置小于多大的碰撞冲量会被忽略, 默认是 `0.0`.
+#### Contact Impulse Limit
+设置小于多大的碰撞冲量会被忽略, 默认是 `0.0`.
 
-Ray Cast Limit 2d
-#### 每帧中2d射线最大请求数量. 默认是 `64`.
+#### Ray Cast Limit 2d
+每帧中2d射线最大请求数量. 默认是 `64`.
 
-Ray Cast Limit 3d
-#### 每帧中3d射线最大请求数量. 默认是 `128`.
+#### Ray Cast Limit 3d
+每帧中3d射线最大请求数量. 默认是 `128`.
 
-Trigger Overlap Capacity
-#### 物理 trigger 的最大重叠数量. 默认是 `16`.
+#### Trigger Overlap Capacity
+物理 trigger 的最大重叠数量. 默认是 `16`.
 
 ## Graphics
 
-Default Texture Min Filter
-#### 设置缩小过滤方式, `linear` (默认) 或者 `nearest`.
+#### Default Texture Min Filter
+设置缩小过滤方式, `linear` (默认) 或者 `nearest`.
 
-Default Texture Mag Filter
-#### 设置放大过滤方式, `linear` (默认) 或者 `nearest`.
+#### Default Texture Mag Filter
+设置放大过滤方式, `linear` (默认) 或者 `nearest`.
 
-Max Draw Calls
-#### 渲染请求最大数目, 默认是 `1024`.
+#### Max Draw Calls
+渲染请求最大数目, 默认是 `1024`.
 
-Max Characters:
-#### 在渲染缓冲区预加载字符数目, 也就是每帧最多显示多少字符, 默认是 `8192`.
+#### Max Characters:
+在渲染缓冲区预加载字符数目, 也就是每帧最多显示多少字符, 默认是 `8192`.
 
-Max Debug Vertices
-#### debug顶点最大数目. 用于物理形状渲染与其他一些功能, 默认是 `10000`.
+#### Max Debug Vertices
+debug顶点最大数目. 用于物理形状渲染与其他一些功能, 默认是 `10000`.
 
-Texture Profiles
-#### 项目使用的纹理档配置文件, 默认是 `/builtins/graphics/default.texture_profiles`.
+#### Texture Profiles
+项目使用的纹理档配置文件, 默认是 `/builtins/graphics/default.texture_profiles`.
 
 ## Input
 
-Repeat Delay
-#### 按下输入保持时等待多少秒后开始算作重复输入, 默认是 `0.5`.
+#### Repeat Delay
+按下输入保持时等待多少秒后开始算作重复输入, 默认是 `0.5`.
 
-Repeat Interval
-#### 按下并保持时重复输入的时间间隔, 默认是 `0.2`.
+#### Repeat Interval
+按下并保持时重复输入的时间间隔, 默认是 `0.2`.
 
-Gamepads
-#### 手柄设置文件的引用, 用于映射手柄到 OS 的输入信号, 默认是 `/builtins/input/default.gamepads`.
+#### Gamepads
+手柄设置文件的引用, 用于映射手柄到 OS 的输入信号, 默认是 `/builtins/input/default.gamepads`.
 
-Game Binding
-#### 输入设置文件的引用, 用于映射硬件输入到游戏行为, 默认是 `/input/game.input_binding`.
+#### Game Binding
+输入设置文件的引用, 用于映射硬件输入到游戏行为, 默认是 `/input/game.input_binding`.
 
-Use Accelerometer
-#### 开启后游戏引擎会在每帧接收加速度计数据. 关闭会获得少许性能提升, 默认开启.
+#### Use Accelerometer
+开启后游戏引擎会在每帧接收加速度计数据. 关闭会获得少许性能提升, 默认开启.
 
 ## Resource
 
-Http Cache
-#### 开启后, 会开启HTTP缓存用于设备上的游戏引擎从缓存中快速导入网络数据, 默认关闭.
+#### Http Cache
+开启后, 会开启HTTP缓存用于设备上的游戏引擎从缓存中快速导入网络数据, 默认关闭.
 
-Uri
-#### 项目编译数据地址, URI 格式.
+#### Uri
+项目编译数据地址, URI 格式.
 
-Max Resources
-#### 一次可以加载资源的最大数目, 默认是 `1024`.
+#### Max Resources
+一次可以加载资源的最大数目, 默认是 `1024`.
 
 ## Network
 
-Http Timeout
-#### HTTP超时秒数. 设置为 `0` 则关闭超时, 默认关闭.
+#### Http Timeout
+HTTP超时秒数. 设置为 `0` 则关闭超时, 默认关闭.
 
 ## Collection
 
-Max Instances
-#### 一个集合里容纳游戏对象实例的最大数目, 默认是`1024`.
+#### Max Instances
+一个集合里容纳游戏对象实例的最大数目, 默认是`1024`.
 
 ## Sound
 
-Gain
-#### 全局增益 (音量), `0`--`1`, 默认值是 `1`.
+#### Gain
+全局增益 (音量), `0`--`1`, 默认值是 `1`.
 
-Max Sound Data
-#### 声音资源的最大数目, 也就是运行时声音文件使用数目, 默认是 `128`.
+#### Max Sound Data
+声音资源的最大数目, 也就是运行时声音文件使用数目, 默认是 `128`.
 
-Max Sound Buffers
-#### (目前未使用) 同一时间声音缓冲最大数目, 默认是 `32`.
+#### Max Sound Buffers
+(目前未使用) 同一时间声音缓冲最大数目, 默认是 `32`.
 
-Max Sound Sources
-#### (目前未使用) 同一时间声音音源最大数目, 默认是 `16`.
+#### Max Sound Sources
+(目前未使用) 同一时间声音音源最大数目, 默认是 `16`.
 
-Max Sound Instances
-#### 同一时间声音实例最大数目, 也就是实际同时播放声音最大数目. 默认是 `256`.
+#### Max Sound Instances
+同一时间声音实例最大数目, 也就是实际同时播放声音最大数目. 默认是 `256`.
 
 ## Sprite
 
-Max Count
-#### 每个集合最大sprite数目, 默认是 `128`.
+#### Max Count
+每个集合最大sprite数目, 默认是 `128`.
 
-Subpixels
-#### 开启后允许sprite不与像素对齐, 默认开启.
+#### Subpixels
+开启后允许sprite不与像素对齐, 默认开启.
 
 ## Tilemap
 
-Max Count
-#### 每个集合的瓷砖地图最大数目, 默认是 `16`.
+#### Max Count
+每个集合的瓷砖地图最大数目, 默认是 `16`.
 
-Max Tile Count
-#### 每个集合可同时显示的瓷砖最大数目, 默认是 `2048`.
+#### Max Tile Count
+每个集合可同时显示的瓷砖最大数目, 默认是 `2048`.
 
 ## Spine
 
-Max Count
-#### spine 模型最大数目, 默认是 `128`.
+#### Max Count
+spine 模型最大数目, 默认是 `128`.
 
 ## GUI
 
-Max Count
-#### GUI 组件最大数目, 默认是 `64`.
+#### Max Count
+GUI 组件最大数目, 默认是 `64`.
 
-Max Particlefx Count
-#### 同一时间粒子发射器最大数目, 默认是 `64`.
+#### Max Particlefx Count
+同一时间粒子发射器最大数目, 默认是 `64`.
 
-Max Particle Count
-#### 同一时间粒子最大数目, 默认是 `1024`.
+#### Max Particle Count
+同一时间粒子最大数目, 默认是 `1024`.
 
 ## Label
 
-Max Count
-#### label 最大数目, 默认是 `64`.
+#### Max Count
+label 最大数目, 默认是 `64`.
 
-Subpixels
-#### 开启后允许 lables 不与像素对齐, 默认开启.
+#### Subpixels
+开启后允许 lables 不与像素对齐, 默认开启.
 
 ## Particle FX
 
-Max Count
-#### 同一时间粒子发射器最大数目, 默认是 `64`.
+#### Max Count
+同一时间粒子发射器最大数目, 默认是 `64`.
 
-Max Particle Count
-#### 同一时间粒子最大数目, 默认是 `1024`.
+#### Max Particle Count
+同一时间粒子最大数目, 默认是 `1024`.
 
 ## Collection proxy
 
-Max Count
-#### 集合代理最大数目, 默认是 `8`.
+#### Max Count
+集合代理最大数目, 默认是 `8`.
 
 ## Collection factory
 
-Max Count
-#### 集合工厂最大数目, 默认是 `128`.
+#### Max Count
+集合工厂最大数目, 默认是 `128`.
 
 ## Factory
 
-Max Count
-#### 游戏对象工厂最大数目, 默认是 `128`.
+#### Max Count
+游戏对象工厂最大数目, 默认是 `128`.
 
 ## iOS
 
-App Icon 57x57--180x180
-#### 用于应用图标的图片 (.png) 文件, 宽高分辨率表示为 `W` &times; `H`.
+#### App Icon 57x57--180x180
+用于应用图标的图片 (.png) 文件, 宽高分辨率表示为 `W` &times; `H`.
+
+#### Launch Screen
+Storyboard 文件 (.storyboard). 其创建方法详情请见 [iOS 教程](/manuals/ios/#creating-a-storyboard).
 
-Launch Image 320x480--2436x1125
-#### 用于应用启动图的图片 (.png) 文件, 宽高分辨率表示为 `W` &times; `H`. iOS 基于启动图选择分辨率.
+#### Launch Image 320x480--2436x1125
+用于应用启动图的图片 (.png) 文件, 宽高分辨率表示为 `W` &times; `H`. iOS 基于启动图选择分辨率.
 
-Pre Rendered Icons
-#### (iOS 6 及更早) 设置图标是否预渲染. 如果关闭则图标自动添加平滑高光效果.
+#### Pre Rendered Icons
+(iOS 6 及更早) 设置图标是否预渲染. 如果关闭则图标自动添加平滑高光效果.
 
-Bundle Identifier
-#### 打包id使得 iOS 认识你的应用的版本更新. 你的打包 ID 必须在 Apple 注册且确保应用唯一性. iOS 与 OS X 应用不可以使用同一id.
+#### Bundle Identifier
+打包id使得 iOS 认识你的应用的版本更新. 你的打包 ID 必须在 Apple 注册且确保应用唯一性. iOS 与 OS X 应用不可以使用同一id.
 
-Info.plist
-#### 如果设置了, 则打包应用时使用此 info.plist 文件.
+#### Info.plist
+如果设置了, 则打包应用时使用此 info.plist 文件.
 
-Entitlements
-#### 如果设置了, 则覆盖引用档文件 (.entitlements, .xcent, .plist) 中定义的通用权限.
+#### Entitlements
+如果设置了, 则覆盖引用档文件 (.entitlements, .xcent, .plist) 中定义的通用权限.
 
 #### Default Language
 如果用户没有指定 `Localizations` 列表里的语言, 则使用此处设置的语言 (见 [CFBundleDevelopmentRegion](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/20001431-130430)).
@@ -329,115 +332,115 @@ Entitlements
 
 ## Android
 
-App Icon 36x36--192x192
-#### 用于应用图标的图片 (.png) 文件, 宽高分辨率表示为 `W` &times; `H`.
+#### App Icon 36x36--192x192
+用于应用图标的图片 (.png) 文件, 宽高分辨率表示为 `W` &times; `H`.
 
-Push Icon Small--LargeXxxhdpi
-#### 用于Android上客户推送通知图标的图片 (.png) 文件. 图标会自动应用于本地与远程推送通知. 如果未设置默认使用应用图标.
+#### Push Icon Small--LargeXxxhdpi
+用于Android上客户推送通知图标的图片 (.png) 文件. 图标会自动应用于本地与远程推送通知. 如果未设置默认使用应用图标.
 
-Push Field Title
-#### 指定用于通知标题的酬载 JSON 域. 保留空白则默认推送应用名作为标题.
+#### Push Field Title
+指定用于通知标题的酬载 JSON 域. 保留空白则默认推送应用名作为标题.
 
-Push Field Text
-#### 指定用于通知文本的酬载 JSON 域. 保留空白则默认推送 `alert` 域的文本, iOS 同样如此.
+#### Push Field Text
+指定用于通知文本的酬载 JSON 域. 保留空白则默认推送 `alert` 域的文本, iOS 同样如此.
 
-Version Code
-#### 表示应用版本号的整数值. 随着后续更新增大此值.
+#### Version Code
+表示应用版本号的整数值. 随着后续更新增大此值.
 
-Package
-#### 包id.
+#### Package
+包id.
 
-Gcm Sender Id
-#### Google Cloud Messaging Sender Id. 此值由 Google 签发, 设置后才能开启推送通知.
+#### Gcm Sender Id
+Google Cloud Messaging Sender Id. 此值由 Google 签发, 设置后才能开启推送通知.
 
-Manifest
-#### 如果设置了, 则编译时使用指定 Android manifest XML 文件.
+#### Manifest
+如果设置了, 则编译时使用指定 Android manifest XML 文件.
 
-Iap Provider
-#### 指定使用哪个应用商店. 合法值是 `Amazon` 和 `GooglePlay`, 默认是 `GooglePlay`.
+#### Iap Provider
+指定使用哪个应用商店. 合法值是 `Amazon` 和 `GooglePlay`, 默认是 `GooglePlay`.
 
-Input Method
-#### 指定获取 Android 设备键盘输入的方式. 合法值是 `KeyEvent` (老方法) 和 `HiddenInputField` (新方法). 默认是 `KeyEvent`.
+#### Input Method
+指定获取 Android 设备键盘输入的方式. 合法值是 `KeyEvent` (老方法) 和 `HiddenInputField` (新方法). 默认是 `KeyEvent`.
 
-Immersive Mode
-#### 如果开启, 则隐藏导航条和状态条并且让你的应用获取屏幕上所有触碰信息.
+#### Immersive Mode
+如果开启, 则隐藏导航条和状态条并且让你的应用获取屏幕上所有触碰信息.
 
-Debuggable
-#### 指定应用是否可以使用诸如 [GAPID](https://github.com/google/gapid) 或者 [Android Studio](https://developer.android.com/studio/profile/android-profiler) 之类的工具来调试. 这将开启 Android manifest 的 `android:debuggable` 选项.
+#### Debuggable
+指定应用是否可以使用诸如 [GAPID](https://github.com/google/gapid) 或者 [Android Studio](https://developer.android.com/studio/profile/android-profiler) 之类的工具来调试. 这将开启 Android manifest 的 `android:debuggable` 选项.
 
 ## MacOS / OS X
 
-App Icon
-#### 用于MacOS应用图标的图片 (.png) 文件.
+#### App Icon
+用于MacOS应用图标的图片 (.png) 文件.
 
-Info.plist
-#### 如果设置了, 则编译时使用指定的 info.plist 文件.
+#### Info.plist
+如果设置了, 则编译时使用指定的 info.plist 文件.
 
-Bundle Identifier
-#### 打包id使得 OS X 认识你的应用的版本更新. 你的打包 ID 必须在 Apple 注册且确保应用唯一性. iOS 与 OS X 应用不可以使用同一id.
+#### Bundle Identifier
+打包id使得 OS X 认识你的应用的版本更新. 你的打包 ID 必须在 Apple 注册且确保应用唯一性. iOS 与 OS X 应用不可以使用同一id.
 
 ## Windows
 
-App Icon
-#### 用于Windows应用图标的图片 (.ico) 文件. 对于如何创建图标文件详情请见 [Windows 教程](/manuals/windows).
+#### App Icon
+用于Windows应用图标的图片 (.ico) 文件. 对于如何创建图标文件详情请见 [Windows 教程](/manuals/windows).
 
-Iap Provider
-#### 指定使用哪个应用商店. 合法值是 `None` 和 `Gameroom`, 默认是 `None`.
+#### Iap Provider
+指定使用哪个应用商店. 合法值是 `None` 和 `Gameroom`, 默认是 `None`.
 
 ## HTML5
 
-Heap Size
-#### 指定Emscripten所使用的堆大小 (兆字节) . 默认值是 256MB.
+#### Heap Size
+指定Emscripten所使用的堆大小 (兆字节) . 默认值是 256MB.
 
-.html Shell
-#### 指定编译时使用的 HTML 文件. 默认是 `/builtins/manifests/web/engine_template.html`.
+#### .html Shell
+指定编译时使用的 HTML 文件. 默认是 `/builtins/manifests/web/engine_template.html`.
 
-Custom .css
-#### 指定编译时使用的 CSS 文件. 默认是 `/builtins/manifests/web/light_theme.css`.
+#### Custom .css
+指定编译时使用的 CSS 文件. 默认是 `/builtins/manifests/web/light_theme.css`.
 
-Splash Image
-#### 如果设置了, 则在打包时使用指定的溅射屏幕图片代替Defold Logo.
+#### Splash Image
+如果设置了, 则在打包时使用指定的溅射屏幕图片代替Defold Logo.
 
-Archive Location Prefix
-#### 指定打包 HTML5 时游戏数据是否拆分为多个数据包文件. 游戏启动时, 这些数据文件会被读入内存. 使用此设置指定数据包的位置, 默认值是 `archive`.
+#### Archive Location Prefix
+指定打包 HTML5 时游戏数据是否拆分为多个数据包文件. 游戏启动时, 这些数据文件会被读入内存. 使用此设置指定数据包的位置, 默认值是 `archive`.
 
-Archive Location Suffix
-#### 指定数据包文件的后缀. 比如说适用于, 来自 CDN 的强制非缓存文件 (比如后缀 `?version2`).
+#### Archive Location Suffix
+指定数据包文件的后缀. 比如说适用于, 来自 CDN 的强制非缓存文件 (比如后缀 `?version2`).
 
-Engine Arguments
-#### 传到游戏引擎里的参数列表.
+#### Engine Arguments
+传到游戏引擎里的参数列表.
 
-Show Fullscreen Button
-#### 在 `index.html` 文件中开启全屏按钮. 默认是 `true`.
+#### Show Fullscreen Button
+在 `index.html` 文件中开启全屏按钮. 默认是 `true`.
 
-Show Made With Defold
-####  在 `index.html` 文件中开启 Defold 链接. 默认是 `true`.
+#### Show Made With Defold
+ 在 `index.html` 文件中开启 Defold 链接. 默认是 `true`.
 
-Scale Mode
-#### 指定游戏 canvas 所使用的缩放方式. 默认是 `Downscale Fit`.
+#### Scale Mode
+指定游戏 canvas 所使用的缩放方式. 默认是 `Downscale Fit`.
 
 ## IAP
 
-Auto Finish Transactions
-#### 开启后自动完成 IAP 交易. 如果关闭, 在交易成功后你需要手动调用 `iap.finish()` , 默认开启.
+#### Auto Finish Transactions
+开启后自动完成 IAP 交易. 如果关闭, 在交易成功后你需要手动调用 `iap.finish()` , 默认开启.
 
 ## Live update
 
-Private Key
-#### 如果设置了, 则在编译热更新内容时使用指定的私匙. 如果不设置, 则自动生成一个私匙.
+#### Private Key
+如果设置了, 则在编译热更新内容时使用指定的私匙. 如果不设置, 则自动生成一个私匙.
 
-Public Key
-#### 如果设置了, 则在编译热更新内容时使用指定的公匙. 如果不设置, 则自动生成一个私匙.
+#### Public Key
+如果设置了, 则在编译热更新内容时使用指定的公匙. 如果不设置, 则自动生成一个私匙.
 
 ## Native extension
 
-_App Manifest_
-#### 如果设置了, 则在自定义引擎编译时使用指定的 manifest. 此设置可以让你移除引擎不必要的部分来减小包体. 注意此设置尚在测试中. 使用方法详情请见 [这个帖子](https://forum.defold.com/t/native-extensions/4946/142).
+#### _App Manifest_
+如果设置了, 则在自定义引擎编译时使用指定的 manifest. 此设置可以让你移除引擎不必要的部分来减小包体. 注意此设置尚在测试中. 使用方法详情请见 [这个帖子](https://forum.defold.com/t/native-extensions/4946/142).
 
 ## Profiler
 
-Track Cpu
-#### 如果开启, 则在编译版本中开启 CPU profiling. 通常, 你只能在 debug 版本中进行调试.
+#### Track Cpu
+如果开启, 则在编译版本中开启 CPU profiling. 通常, 你只能在 debug 版本中进行调试.
 
 ## File format
 

+ 1 - 290
docs/zh/manuals/push.md

@@ -3,293 +3,4 @@ title: Defold 的 iOS 和 Android 推送通知
 brief: 本教程介绍了如何配置和实现游戏中的本地和远程 iOS 与 Android 平台的推送通知.
 ---
 
-# 推送通知
-
-推送通知作为 [原生扩展](/manuals/extensions/) 在 iOS 和 Android 设备上用来给玩家提示修改和更新之类的信息. iOS 和 Android 实现方法基本一样但是也有一些平台相关的东西需要注意.
-
-推送通知为了找到从服务器到目标设备的通路, 需要得到应用的一些信息. 最复杂的部分包括用于校验客户端接收通知的合法性的应用安全信息. 还需要用于 Apple 或者 Google 校验你发送通知合法性的服务器安全信息. 最后, 推送通知的时候, 你需要知道到用户设备的唯一路径. 为此你需要指定设备的唯一 token (用来分辨用户).
-
-## 安装扩展
-
-使用之前要在 `game.project` 文件里配置扩展依赖. 最新稳定版依赖的 URL 是:
-
-```
-https://github.com/defold/extension-push/archive/master.zip
-```
-
-推荐使用 [指定版本](https://github.com/defold/extension-push/releases) 的zip包链接作为依赖.
-
-```
-https://github.com/defold/extension-firebase-core/archive/master.zip
-```
-
-API 文档在 [推送通知扩展项目](https://defold.github.io/extension-push/) 页上.
-
-## iOS 配置
-
-::: 注意
-为了更好地使用 Apple Push Notification 服务, 最好先熟读 [Apple 的官方文档](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html).
-:::
-
-iOS 上, 推送通知需要做以下准备:
-
-* 要为 App ID 开启推送通知.
-* 需要包含此 App ID 的应用提供商档案.
-* 还需要一个 SSL 证书用来把数据从消息服务应用发送到 Apple 服务器.
-
-准备就绪后登录到 [Apple 开发者中心](https://developer.apple.com/membercenter). 找到 AppID 打开通知推送服务.
-
-![AppID push notifications](images/push/push_ios_app_id.png)
-
-记得创建推送服务 SSL 证书:
-
-![APN SSL certificate](images/push/push_ios_certificate.png)
-
-从你的服务器往通知推送服务器发送数据时需要这个证书. 开发调试时, 可以先在本地安装这个证书然后运行 [APNS-Pusher](https://github.com/KnuffApp/APNS-Pusher) 或者 [NWPusher](https://github.com/noodlewerk/NWPusher) 之类的测试工具.
-
-记得创建包含要推送通知 AppID 的供应商档案, 并且在档案中设置好开发设备. 可以在 "Member Center" 页面或者 Xcode 中进行这些操作.
-
-![Provisioning profile](images/push/push_ios_provisioning_profile.png)
-
-注意 Apple 的沙盒服务器可能需要一段时间更新信息, 通知推送功能也许不能马上使用. 要有耐心.
-
-推送通知测试代码如下:
-
-<a name="above-code"></a>
-```lua
-local function push_listener(self, payload, origin)
-    -- 通知到达这里.
-    pprint(payload)
-end
-
-function init(self)
-    local sysinfo = sys.get_sys_info()
-    if sysinfo.system_name == "Android" then
-        msg.post("#", "push_android")
-    elseif sysinfo.system_name == "iPhone OS" then
-        msg.post("#", "push_ios")
-    end
-end
-
-function on_message(self, message_id, message)
-    if message_id == hash("push_ios") then
-        local alerts = {push.NOTIFICATION_BADGE, push.NOTIFICATION_SOUND, push.NOTIFICATION_ALERT}
-        push.register(alerts, function (self, token, error)
-            if token then
-                local t = ""
-                for i = 1,#token do
-                    t = t .. string.format("%02x", string.byte(token, i))
-                end
-                -- 打印设备token
-                print(t)
-            else
-                -- 错误
-                print(error.error)
-            end
-        end)
-        push.set_listener(push_listener)
-    elseif message_id == hash("push_android") then
-        push.register(nil, function (self, token, error)
-            if token then
-                -- 打印设备token
-                print(token)
-            else
-                -- 错误
-                print(error.error)
-            end
-        end)
-        push.set_listener(push_listener)
-    end
-end
-```
-
-如果一切顺利通知监听器会被注册然后打印出设备的 token:
-
-```txt
-DEBUG:SCRIPT: 1f8ba7869b84b10df69a07aa623cd7f55f62bca22cef61b51fedac643ec61ad8
-```
-
-如果运行的是测试应用, 你现在就可以尝试使用设备token和通知服务SSL证书向你的设备推送通知了.
-
-![Pusher test](images/push/push_ios_pusher.png)
-
-通知发送之后会被测试应用接收, 进入 `push_listener()` 函数:
-
-```txt
-DEBUG:SCRIPT:
-{
-  aps = {
-    badge = 42,
-    alert = Testing.. (1),
-    sound = default,
-  }
-}
-```
-
-同时 iOS 桌面会提示通知:
-
-![iOS notification](images/push/push_ios_notification.png)
-
-如果要在图标上显示计数角标, 可以使用 `push.set_badge_count()` 函数.
-
-## Android 配置
-
-::: 注意
-建议首先阅读 Firebase Cloud Messaging 服务文档. 文档在这里 https://firebase.google.com/docs/cloud-messaging/
-:::
-
-Android 上, 推送通知需要做以下准备:
-
-* Firebase CM Sender ID 和应用 ID. 这些id会打包到应用中去.
-* 用于使用 Firebase 服务的服务器 API Key.
-
-::: 注意
-如果你的应用使用了 Google Cloud Messaging 平台, 现在需要导入 Firebase Cloud Messaging 平台中. 把应用从 Google dashboard 导入到 Firebase 即可. 导入后 *sender id* 保持不变, 你的 `game.project` 文件需要更新使用 `Firebase Application ID` (见下文).
-:::
-
-基本配置很简单. 登录 [https://console.firebase.google.com](https://console.firebase.google.com), 选择或者新建应用. 然后进入 *Grow* 的 *Cloud Messaging* 页面.
-
-![Adding Cloud Messaging to a Firebase project](images/push/push_fcm_add_cm.png)
-
-点击 Android 图标开始配置通知推送.
-
-
-![Configure Cloud Messaging for Android](images/push/push_fcm_configure_android.png)
-
-根据提示, 输入 Defold 游戏项目使用的包名.
-
-![Android cloud services info](images/push/push_fcm_register.png)
-
-下载 `google-services.json`, 我们需要这个文件里面的一些信息.
-
-![Google Cloud Messaging sender ID](images/push/push_fcm_download_json.png)
-
-下面两步可以跳过, *Add Firebase SDK* 和 *Run your app to verify installation*. SDK 已打包进 Defold, 无需手动添加.
-
-用文本编辑器打开 `google-services.json` 文件, 找到 *`project_number`* 和 *`mobilesdk_app_id`*. 把这俩id考入 `game.project` 文件, 对应 *android* 部分, `Gcm Sender Id` (`project_number`) 和 `Fcm Application Id` (`mobilesdk_app_id`).
-
-```
-{
-  "project_info": {
-    "project_number": "123456789123",
-    "firebase_url": "https://project-name-ki7h7.firebaseio.com",
-    "project_id": "project-name-ki7h7",
-    "storage_bucket": "project-name-ki7h7.appspot.com"
-  },
-  "client": [
-    {
-      "client_info": {
-        "mobilesdk_app_id": "1:123456789123:android:c1de85bbda9bc512",
-        "android_client_info": {
-          "package_name": "my.package.name"
-        }
-      },
-
-```
-
-![Settings applied to game.project](images/push/push_fcm_game_project.png)
-
-至此客户端准备就绪. [上面测试ios时用的代码](#above-code) 对 Android 同样有效. 运行并记录设备 token.
-
-```txt
-DEBUG:SCRIPT: APA91bHkcKm0QHAMUCEQ_Dlpq2gzset6vh0cz46kDDV6230C5rFivyWZMCxGXcjxRDKg1PK4z1kWg3xnUVqSDiO_4_RiG8b8HeYJfaoW1ho4ukWYXjq5RE0Sy-JTyrhqRusUP_BxRTcE
-```
-
-发送通知之前需要一个 Firebase 服务认证 key. 这个 key 位于 Firebase dashboard 的 *Settings* 的 *Cloud Messaging* 页面中.
-
-![Server Key location](images/push/push_fcm_server_key.png)
-
-一切准备就绪. 可以通过使用 Web API 的 *curl* 命令测试推送功能:
-
-```sh
-$ curl  -X POST  -H "Content-type: application/json"  -H 'Authorization: key=SERVER_KEY' -d '{"registration_ids" : ["TOKEN_ID"], "data": {"alert": "Hello"}}' https://fcm.googleapis.com/fcm/send
-```
-
-注意把 `SERVER_KEY` 和 `TOKEN_ID` 替换成你记录下的key和token.
-
-## 本地通知
-
-除了远程推送还可以使用本地通知推送. 下面是本地通知的示例:
-
-```lua
--- 3秒后推送本地通知
-local payload = '{"data" : {"field" : "Some value", "field2" : "Other value"}}'
-id, err = push.schedule(3, "A notification!", "Hello there", payload, { action = "get going" })
-```
-
-通知安排调用返回唯一id以便后续使用. `push.schedule()` 函数的最后一个参数不同平台有不同内容:
-
-action
-: (iOS 有效). 这个值用来设置通知右键标题或者用来替换解锁提示  "slide to unlock" 中的 "unlock" 字样.
-
-badge_count
-: (iOS 有效). 图标计数角标. 设置为0清除角标.
-
-priority
-: (Android 有效). 优先级决定了UI如何展示通知. 有以下5个等级:
-
-  - push.PRIORITY_MIN
-  - push.PRIORITY_LOW
-  - push.PRIORITY_DEFAULT
-  - push.PRIORITY_HIGH
-  - push.PRIORITY_MAX
-
-  如果不指定, 默认使用最大优先级.
-
-## 本地通知查看
-
-API 提供了两个函数用来查看当前安排下的本地通知.
-
-```lua
-n = push.get_scheduled(id)
-pprint(n)
-```
-
-这个表里记录了通知相关的详细信息:
-
-```txt
-DEBUG:SCRIPT:
-{
-  payload = {"data":{"field":"Some value","field2":"Other value"}},
-  title = A notification!,
-  priority = 2,
-  seconds = 19.991938,
-  message = Hello there,
-}
-```
-
-注意 `seconds` 是指离通知推送还差多少秒. 还有一个函数可以查看当前安排下的 _所有_ 通知:
-
-```lua
-all_n = push.get_all_scheduled()
-pprint(all_n)
-```
-
-结果是通知id与其内容对应的表:
-
-```txt
-DEBUG:SCRIPT:
-{
-  0 = {
-    payload = {"data":{"field":"Some value","field2":"Other value"}},
-    title = A notification!,
-    priority = 2,
-    seconds = 6.009774,
-    message = Hey hey,
-  }
-  1 = {
-    payload = {"data":{"field":"Some value","field2":"Other value"}},
-    title = Another notification!,
-    priority = 2,
-    seconds = 12.652521,
-    message = Hello there,
-  }
-  2 = {
-    payload = {"data":{"field":"Some value","field2":"Other value"}},
-    title = Hey, much notification!,
-    priority = 2,
-    seconds = 15.553719,
-    message = Please answer!,
-  }
-}
-```
+[本教程已移动到这里](/extension-push)

+ 106 - 107
docs/zh/manuals/render.md

@@ -3,148 +3,147 @@ title: Defold 中的渲染过程
 brief: 本教程介绍了 Defold 的渲染流程及其编程方法.
 ---
 
-# Render
+# 渲染
 
-引擎在屏幕上显示的每个对象:精灵,模型,图块,粒子或GUI节点均由渲染器绘制。渲染器的核心是控制渲染流程的渲染脚本。默认情况下,每个2D对象均使用指定混合和正确Z深度来进行绘制-因此,除了顺序和简单混合之外您可能不需要了解渲染。对于大多数2D游戏,默认流程功能良好,但是您的游戏可能有特殊要求。在这种情况下,Defold允许您编写量身定制的渲染程序。
+引擎在屏幕上显示的每个对象:精灵,模型,图块,粒子或GUI节点均由渲染器绘制。渲染器的核心是控制渲染流程的渲染脚本。默认情况下,每个2D均使用指定混合和正确Z深度来进行绘制-因此,除了顺序和简单混合之外您可能不需要了解渲染。对于大多数2D游戏,默认流程功能良好,但是您的游戏可能有特殊要求。在这种情况下,Defold允许您编写量身定制的渲染程序。
 
-### Render pipeline - What, when and where?
+### 渲染管线是什么东东?
 
-The render pipeline controls what to render, when to render it and also where to render it. What to render is controlled by [render predicates](#render-predicates). When to render a predicate is controlled in the [render script](#the-render-script) and where to render a predicate is controlled by the [view projection](#default-view-projection).
+渲染管线决定了渲染什么, 何时渲染以及渲染哪里. 渲染什么由 [渲染优先级](#render-predicates) 决定. 什么时候渲染由 [渲染脚本](#the-render-script) 决定, 渲染哪里由 [视口映射](#default-view-projection) 决定.
 
 
-## The default render
+## 默认渲染器
 
-The render file contains a reference to the current render script as well as custom materials that should be made available in the render script (use with [`render.enable_material()`](/ref/render/#render.enable_material))
+渲染文件保存有当前渲染脚本的引用, 还确定了该渲染脚本可以使用的材质 (使用 [`render.enable_material()`](/ref/render/#render.enable_material) 函数)
 
-At the heart of the rendering pipeline is the _render script_. This is a Lua script with the functions `init()`, `update()` and `on_message()` and it is primarily used to interact with the underlying OpenGL rendering API. The render script has a special place in the lifecycle of your game. Details can be found in the [Application lifecycle documentation](/manuals/application-lifecycle).
+渲染管线的核心就是 _渲染脚本_. 它是包含 `init()`, `update()` 与 `on_message()` 函数的 Lua 脚本, 主要用于与 OpenGL 渲染 API 的底层交互. 渲染脚本生命周期有其特殊之处. 详情请见 [应用生命周期教程](/manuals/application-lifecycle).
 
-In the "Builtins" folder of your projects you can find the default render resource ("default.render") and the default render script ("default.render_script").
+在 "Builtins" 文件夹中放有默认渲染器资源文件 ("default.render") 和默认渲染脚本 ("default.render_script").
 
 ![Builtin render](images/render/builtin.png){srcset="images/render/[email protected] 2x"}
 
-To set up a custom renderer:
+使用自定义渲染器:
 
-1. Copy the files "default.render" and "default.render_script" to a location in your project hierarchy. You can, of course, create a render script from scratch but it is a good idea to start with a copy of the default script, especially if you are new to Defold and/or OpenGL ES rendering.
+1. 把 "default.render" 和 "default.render_script" 复制到项目目录某个位置. 当然自己从头开始写也没问题, 但是拷贝出来能有个参考, 尤其是对于 Defold 或 OpenGL ES 渲染编写的新手来说.
 
-2. Edit your copy of the "default.render" file and change the *Script* property to refer to your copy of the render script.
+2. 编辑 "default.render" 文件, 指定 *Script* 项为自定义的脚本.
 
-3. Change the *Render* property (under *bootstrap*) in the "game.project" settings file to refer to your copy of the "default.render" file.
+3. 在 "game.project" 的 *bootstrap* 部分里的 *Render* 项上设置刚才修改好的 "default.render" 文件.
 
 
-## Render predicates
+## 渲染优先级
 
-To be able to control the draw order of objects, you create render _predicates_. A predicate declares what should be drawn based on a selection of material _tags_.
+可视对象的渲染顺序, 是基于渲染 _优先级_ 的. 优先级的确定基于材质 _标签_.
 
-Each object that is drawn onto the screen has a material attached to it that controls how the object should be drawn to the screen. In the material, you specify one or more _tags_ that should be associated with the material.
+可是对象都有材质用以确定如何在屏幕上进行绘制. 材质之中, 可以指定一个或多个 _标签_ 与材质相对应.
 
-In your render script, you can then create a *render predicate* and specify which tags should belong to that predicate. When you tell the engine to draw the predicate, each object with a material containing a tag matching the list specified for the predicate will be drawn.
+渲染脚本中, 就可以决定什么样的标签拥有什么样的 *渲染优先级*. 引擎渲染时, 材质基于标签队列被赋予渲染优先级.
 
 ![Render predicate](images/render/render_predicate.png){srcset="images/render/[email protected] 2x"}
 
-A detailed description on how materials work can be found in the [Material documentation](/manuals/material).
+关于材质详情请见 [材质教程](/manuals/material).
 
 
-## Default view projection
+## 默认视口映射
 
-The default render script is configured to use an orthographic projection suitable for 2D games. It provides three different orthographic projections: `Stretch` (default), `Fixed Fit` and `Fixed`.
+默认渲染脚本使用2D游戏常用的正交映射. 填充方式有三种: `Stretch` (默认), `Fixed Fit` 和 `Fixed`.
 
-You can also use a perspective projection suitable for 3D games, as provided by a camera component.
+做3D游戏的话, 可以使用摄像机组件提供的透视映射渲染方法.
 
-The camera component can be used for both orthographic and perspective projections to change the view matrix (basically which part of the game world that is rendered). Learn more about the camera component in the [Camera manual](/manuals/camera).
+摄像机组件既可以设置为正交也可以设置为透视来改变视口矩阵 (简单地说就是游戏世界哪部分需要被渲染). 关于摄像机组件详情请见 [摄像机教程](/manuals/camera).
 
-### Stretch projection
+### Stretch
 
-The stretch projection will always draw an area of your game that is equal to the dimensions set in "game.project", even when the window is resized. If the aspect ratio changes it will result in game content being stretched either vertically or horizontally:
+无论应用窗口怎样改变, 渲染视口大小总是等于在 "game.project" 里面设置的分辨率. 所以一旦宽高比例改变, 就会造成视口拉伸现象:
 
 ![Stretch projection](images/render/stretch_projection.png)
 
-*Stretch projection with original window size*
+*原窗口大小*
 
 ![Stretch projection when resized](images/render/stretch_projection_resized.png)
 
-*Stretch projection with the window stretched horizontally*
+*横向拉伸*
 
-The stretch projection is the default projection but if you have changed from it and need to switch back you do it by sending a message to the render script:
+视口拉伸是默认选项, 其对应命令脚本是:
 
 ```lua
 msg.post("@render:", "use_stretch_projection", { near = -1, far = 1 })
 ```
 
-### Fixed fit projection
+### Fixed Fit
 
-Just like the stretch projection the fixed fit projection will always show an area of the game that is equal to the dimensions set in "game.project", but if the window is resized and the aspect ratio changes the game content will retain the original aspect ratio and additional game content will be shown vertically or horizontally:
+跟 Stretch 一样 Fixed Fit 也是使用 "game.project" 里设置的分辨率, 不同的是一旦窗口大小改变游戏内容会缩放但是始终保持原比例, 这样一来本来不应被渲染的内容也可能会被显示出来:
 
 ![Fixed fit projection](images/render/fixed_fit_projection.png)
 
-*Fixed with projection with original window size*
+*原窗口大小*
 
 ![Fixed fit projection when resized](images/render/fixed_fit_projection_resized.png)
 
-*Fixed with projection with the window stretched horizontally*
+*横向拉伸*
 
 ![Fixed fit projection when smaller](images/render/fixed_fit_projection_resized_smaller.png)
 
-*Fixed with projection with the window reduced to 50% of original size*
+*窗体缩小一半*
 
-You enable the fixed fit projection by sending a message to the render script:
+等比缩放对应命令脚本是:
 
 ```lua
 msg.post("@render:", "use_fixed_fit_projection", { near = -1, far = 1 })
 ```
 
-### 固定映射
+### fixed
 
-The fixed projection will retain the original aspect ratio and render your game content with a fixed zoom level. This means that it if the zoom level is set to something other than 100% it will show more or less than the area of the game defined by the dimensions in "game.project":
+以一个固定倍数按比例缩放视口. 也就是说倍数不是 100% 的话就会自行多显示或少显示内容, 而不按照 "game.project" 的设定分辨率渲染:
 
 ![Fixed projection](images/render/fixed_projection_zoom_2_0.png)
 
-*Fixed projection with zoom set to 2*
+*缩放倍数为2*
 
 ![Fixed projection](images/render/fixed_projection_zoom_0_5.png)
 
-*Fixed projection with zoom set to 0.5*
+*缩放倍数为0.5*
 
 ![Fixed projection](images/render/fixed_projection_zoom_2_0_resized.png)
 
-*Fixed projection with zoom set to 2 and window reduced to 50% of original size*
+*缩放倍数为2窗体缩小一半*
 
-You enable the fixed projection by sending a message to the render script:
+其对应命令脚本是:
 
 ```lua
 msg.post("@render:", "use_fixed_projection", { near = -1, far = 1, zoom = 2 })
 ```
 
-### Perspective projection
+### 透视映射
 
-The perspective projection is suitable for 3D games where game objects are rendered with a perspective and where the size of objects vary depending on the distance from an imagined eye/camera position.
+透视用来制作 3D 游戏, 游戏对象大小取决于与摄像机距离的远近.
 
-You enable the perspective projection provided from a camera component by sending a message to the render script:
+其命令脚本是:
 
 ```lua
 msg.post("@render:", "use_camera_projection")
 ```
 
 
-## Coordinate systems
+## 坐标系统
 
-When components are rendered you usually talk of in which coordinate system the components are rendered. In most games you have some components drawn in world space and some in screen space.
+提到渲染就不得不说其基于的坐标系统. 一般游戏都有世界坐标系和屏幕坐标系.
 
-GUI components and their nodes are usually drawn in the screen space coordinate, with the bottom left corner of the screen having coordinate (0,0) and the top right corner is (screen width, screen height). The screen space coordinate system is never offset or in some other way translated by a camera. This will keep the GUI nodes always drawn on screen regardless of how the world is rendered.
+GUI 组件节点基于屏幕坐标系渲染, 屏幕左下角是坐标原点 (0,0) 右上角是最大值 (screen width, screen height). 游戏和摄像机如何改变都不会改变屏幕坐标系. 这样就能保证用户界面不受游戏世界的影响.
 
-Sprites, tilemaps and other components used by game objects that exist in your game world are usually drawn in the world space coordinate system. If you make no modifications to your render script and use no camera component to change the view projection this coordinate system is the same as the screen space coordinate system, but as soon as you add a camera and either move it around or change the view projection the two coordinate systems will deviate. When the camera is moving the lower left corner of the screen will be offset from (0, 0) so that other parts of the world is rendered. If the projection changes the coordinates will be both translated (ie offset from 0, 0) and modified by a scale factor.
+Sprite, 瓷砖地图和其他游戏组件都是使用游戏世界坐标系. 既不改变渲染脚本又不使用摄像机组件改变映射方式的话游戏世界坐标系和屏幕坐标系数值上是相同的, 但是一旦视口移动或者映射方式改变, 两者就会偏离. 摄像机移动时屏幕坐标原点 (0, 0) 会跟着改变. 映射方式改变原点和偏移量都会由于缩放系数而改变.
 
 
-## The render script
+## 渲染脚本
 
-Below is the code for a custom render script that is a slightly modified version of the built-in one.
+下面展示一个对默认渲染脚本稍经修改的版本.
 
 init()
-: The function `init()` is used to set up the predicates, the view and clear color. These variables will be used during the actual rendering.
+: 函数 `init()` 用来设定优先级, 视口和视口颜色. 这些渲染时都会被用到.
 
   ```lua
   function init(self)
-      -- Define the render predicates. Each predicate is drawn by itself and
-      -- that allows us to change the state of OpenGL between the draws.
+      -- 定义渲染优先级. 每个优先级的绘制不相干所以绘制时可以任意修改 OpenGL 的状态.
       self.tile_pred = render.predicate({"tile"})
       self.gui_pred = render.predicate({"gui"})
       self.text_pred = render.predicate({"text"})
@@ -157,36 +156,36 @@ init()
       self.clear_color.z = sys.get_config("render.clear_color_blue", 0)
       self.clear_color.w = sys.get_config("render.clear_color_alpha", 0)
 
-      -- Define a view matrix to use. If we have a camera object, it will
-      -- send "set_view_projection" messages to the render script and we
-      -- can update the view matrix with the value the camera provides.
+      -- 视口矩阵. 如果使用了摄像机, 摄像机就会
+      -- 把 "set_view_projection" 信息发送给渲染脚本
+      -- 以便我们根据摄像机提供的参数更新视口矩阵.
       self.view = vmath.matrix4()
   end
   ```
 
 update()
-: The `update()` function is called once each frame. Its function is to perform the actual drawing by calling the underlying OpenGL ES APIs (OpenGL Embedded Systems API). To properly understand what's going on in the `update()` function, you need to understand how OpenGL works. There are many great resources on OpenGL ES available. The official site is a good starting place. You find it at https://www.khronos.org/opengles/
+: 函数 `update()` 每帧都会被调用. 用于调用底层 OpenGL ES API (OpenGL 嵌入系统 API) 以实现渲染. 想了解 `update()` 函数, 先要了解 OpenGL 工作原理. 对于 OpenGL ES 有许多教程. 官方网站就是个不错的学习之地. 参考 https://www.khronos.org/opengles/
 
-  This example contains the setup necessary to draw 3D models. The `init()` function defined a `self.model_pred` predicate. Elsewhere a material with the tag "model" has been created. There are also some model components that use the material:
+  本例中函数里设置了渲染 3D 模型必须的两部分内容. `init()` 定义了 `self.model_pred` 优先级. 含有 "model" 标签的材质被建立. 以及使用此材质的模型组件:
 
   ```lua
   function update(self)
-      -- Set the depth mask which allows us to modify the depth buffer.
+      -- 设置深度蒙版以便修改深度缓存.
       render.set_depth_mask(true)
 
-      -- Clear the color buffer with the clear color value and set the depth buffer to 1.0.
-      -- The normal depth values are between 0.0 (near) and 1.0 (far) so maximizing the values
-      -- throughout the buffer means that every pixel you draw will be nearer than 1.0 and thus
-      -- it will be properly drawn and depth testing will work from thereon.
+      -- 使用背景清空渲染缓存然后设置其深度为 1.0.
+      -- 通常深度范围为 0.0 (近端) 到 1.0 (远端) 要全包括所以设置为 1.0
+      -- 缓存只保持并渲染比 1.0 近的物体
+      -- 这样的配置就很合乎逻辑.
       render.clear({[render.BUFFER_COLOR_BIT] = self.clear_color, [render.BUFFER_DEPTH_BIT] = 1, [  render.BUFFER_STENCIL_BIT] = 0})  
 
-      -- Set the viewport to the window dimensions.
+      -- 视口大小设置为窗体大小.
       render.set_viewport(0, 0, render.get_window_width(), render.get_window_height())
 
-      -- Set the view to the stored view value (can be set by a camera object)
+      -- 填充视口 (摄像机会自动填充)
       render.set_view(self.view)
 
-      -- Render 2D space
+      -- 渲染 2D 空间
       render.set_depth_mask(false)
       render.disable_state(render.STATE_DEPTH_TEST)
       render.disable_state(render.STATE_STENCIL_TEST)
@@ -194,21 +193,21 @@ update()
       render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE_MINUS_SRC_ALPHA)
       render.disable_state(render.STATE_CULL_FACE)
 
-      -- Set the projection to orthographic and only render between -200 and 200 Z-depth
+      -- 设定正交映射及Z轴范围为 -200 到 200
       render.set_projection(vmath.matrix4_orthographic(0, render.get_width(), 0,   render.get_height(), -200, 200))  
 
       render.draw(self.tile_pred)
       render.draw(self.particle_pred)
 
-      -- Render 3D space, but still orthographic
-      -- Face culling and depth test should be enabled
+      -- 渲染 3D 空间, 此时仍是正交映射
+      -- 需要打开面剔除和深度测试
       render.enable_state(render.STATE_CULL_FACE)
       render.enable_state(render.STATE_DEPTH_TEST)
       render.set_depth_mask(true)
       render.draw(self.model_pred)
       render.draw_debug3d()
 
-      -- Render the GUI last
+      -- 最后渲染 GUI
       render.set_view(vmath.matrix4())
       render.set_projection(vmath.matrix4_orthographic(0, render.get_window_width(), 0,   render.get_window_height(), -1, 1))  
 
@@ -222,56 +221,56 @@ update()
   end
   ```
 
-So far this is a simple and straightforward render script. It draws in the same manner every single frame. However, it is sometimes desirable to be able to introduce state into the render script and perform different operations depending on the state. It may also be desirable to communicate with the render script from other parts of the game code.
+上面是一个简单版的渲染脚本. 每帧工作都一样. 然而有些时候需要对不同的游戏状态进行不同的渲染操作. 可能还需要与游戏代码脚本进行交互.
 
 on_message()
-: A render script can define an `on_message()` function and receive messages from other parts of your game or app. A common case where an external component sends information to the render script is the _camera_. A camera component that has acquired camera focus will automatically send its view and projection to the render script each frame. This message is named `"set_view_projection"`:
+: 渲染脚本有一个 `on_message()` 函数用来接收游戏其他脚本发来的消息. 典型的例子比如 _摄像机_. 摄像机组件每一帧都把视口和映射发给渲染脚本. 消息名为 `"set_view_projection"`:
 
   ```lua
   function on_message(self, message_id, message)
       if message_id == hash("clear_color") then
-          -- Someone sent us a new clear color to be used.
+          -- 根据消息命令清空屏幕.
           self.clear_color = message.color
       elseif message_id == hash("set_view_projection") then
-          -- The camera component that has camera focus will sent set_view_projection
-          -- messages to the @render socket. We can use the camera information to
-          -- set view (and possibly projection) of the rendering.
-          -- Currently, we're rendering orthogonally so there's no need for camera
-          -- projection.
+          -- 焦点摄像机每一帧都发送 set_view_projection
+          -- 消息到 @render 端口. 使用摄像机发来的数据可以
+          -- 设置渲染视口 (及映射).
+          -- 这里使用默认正交映射所以
+          -- 不使用消息传输映射.
           self.view = message.view
       end
   end
   ```
 
-  However, any script of GUI script can send messages to the render script though the special `@render` socket:
+  GUI 脚本同样可以向 `@render` 端口发送消息:
 
   ```lua
-  -- Change the clear color.
+  -- 更改清屏颜色.
   msg.post("@render:", "clear_color", { color = vmath.vector4(0.3, 0.4, 0.5, 0) })
   ```
 
-## System messages
+## 系统消息
 
 `"set_view_projection"`
-: This message is sent from camera components that has acquired camera focus.
+: 焦点摄像机发给渲染脚本的消息.
 
 `"window_resized"`
-: The engine will send this message on changes of the window size. You can listen to this message to alter rendering when the target window size changes. On desktop this means that the actual game window has been resized and on mobile devices this message is sent whenever an orientation change happens.
+: 窗体大小变化时系统发送给渲染脚本的消息. 监听此消息以便在窗体大小变化时采取相应的渲染方案. 桌面设备窗口大小改变和移动设备屏幕方向改变都会触发此消息发送.
 
   ```lua
   function on_message(self, message_id, message)
     if message_id == hash("window_resized") then
-      -- The window was resized. message.width and message.height contain the new dimensions.
+      -- 窗体变化. message.width 与 message.height 保存了变化后的窗体尺寸.
       ...
     end
   end
   ```
 
 `"draw_line"`
-: Draw debug line. Use to visualize ray_casts, vectors and more. Lines are drawn with the `render.draw_debug3d()` call.
+: 调试用画线. 可以用来检查射线, 向量等等. 线的绘制调用了 `render.draw_debug3d()` 函数.
 
   ```lua
-  -- draw a white line
+  -- 绘制白线
   local p1 = vmath.vector3(0, 0, 0)
   local p2 = vmath.vector3(1000, 1000, 0)
   local col = vmath.vector4(1, 1, 1, 1)
@@ -279,49 +278,49 @@ on_message()
   ```
 
 `"draw_text"`
-: Draw debug text. Use to print debug information. The text is drawn with the built in "system_font" font. The system font has a material with tag "text" and is rendered with other text in the default render script.
+: 调试用文字绘制. 可以用来展示一些调试信息. 文字使用自带 "system_font" 字体. 使用材质标签 "text" 于渲染脚本里进行绘制.
 
   ```lua
-  -- draw a text message
+  -- 文字信息绘制
   local pos = vmath.vector3(500, 500, 0)
   msg.post("@render:", "draw_text", { text = "Hello world!", position = pos })  
   ```
 
-The visual profiler accessible through the `"toggle_profile"` message sent to the `@system` socket is not part of the scriptable renderer. It is drawn separate from your render script.
+可视分析器通过发送 `"toggle_profile"` 消息到 `@system` 端口显示出来, 它不是在渲染脚本里进行绘制的, 而是在系统内部其他脚本里进行绘制的.
 
 
-## Draw calls and batching
+## Draw call 与合批
 
-A draw call is the term used to describe the process of setting up the GPU to draw an object to the screen using a texture and a material with optional additional settings. This process is usually resource intensive and it is recommended that the number of draw calls are as few as possible. You can measure the number of the draw calls and the time it takes to render them using the [built-in profiler](/manuals/profiling/).
+Draw call 众所周知是调用 GPU 使用指定材质和纹理以及各种参数设置进行一次屏幕渲染的过程. 这个过程比较耗时所以游戏 draw call 数量应该尽可能地小. 可以使用 [内置分析器](/manuals/profiling/) 来查看 draw call 数量与耗时.
 
-Defold will try to batch render operation to reduce the number of draw calls according to a set of rules defined below. The rules differ between GUI components and all other component types.
+Defold 基于下列规则自动进行合批渲染操作以达到减少 draw call 的目的. 其中 GUI 组件与其他组件类型的规则不同.
 
 
-### Batch rules for non-GUI components
+### 非 GUI 组件合批
 
-Rendering is done based on z-order, from low to high. The engine will start by sorting the list of things to draw and iterate from low to high z-values. Each object in the list will be grouped into the same draw call as the previous object if the following conditions are met:
+渲染基于Z轴位置, 从小到大进行. 引擎会将物体按照Z轴位置由小到大排序. 如果一个物体遇到以下情形, 就把当前物体与上一个物体打包合批在一个 draw call 中渲染:
 
-* Belongs to the same collection proxy
-* Is of the same component type (sprite, particle fx, tilemap etc)
-* Uses the same texture (atlas or tile source)
-* Has the same material
-* Has the same shader constants (such as tint)
+* 属于同一个集合代理
+* 属于同一种组件类型 (都是 sprite, particle fx, tilemap 等等)
+* 使用同一个纹理 (图集或者瓷砖图源)
+* 使用同一个材质
+* 使用同一个材质参数值 (例如 tint)
 
-This means that if two sprite components in the same collection proxy has adjacent or the same z-value (and thus comes next to each other in the sorted list), use the same texture, material and constants they will be grouped into the same draw call.
+注意两个物体要满足上述全部条件才能进行合批操作.
 
 
-### Batch rules for GUI components
+### GUI 组件合批
 
-Rendering of the nodes in a GUI component are done from top to bottom of the node list. Each node in the list will be grouped into the same draw call as the previous node if the following conditions are met:
+GUI 组件按照节点树从上到下进行渲染. 如果一个节点遇到以下情形, 就把当前节点与上一个节点打包合批在一个 draw call 中渲染:
 
-* Is of the same type (box, text, pie etc)
-* Uses the same texture (atlas or tile source)
-* Has the same blend mode.
-* Has the same font (only for text nodes)
-* Has the same stencil settings
+* 属于同一种组件类型 (都是 box, text, pie 等等)
+* 使用同一个纹理 (图集或者瓷砖图源)
+* 使用同一种混合模式.
+* 使用同一个字体 (仅针对文本节点)
+* 使用同样的绘制参数
 
-::: sidenote
-Rendering of nodes are done per component. This means that nodes from different GUI components will not be batched.
+::: 注意
+节点按组件逐个渲染. 也就是说不同 GUI 组件的节点不会合批.
 :::
 
-The ability to arrange nodes in hierarchies makes it easy to group nodes into manageable units. But hierarchies can effectively break batch rendering if you mix different node types. It is possible to more effectively batch GUI nodes while maintaining node hierarchies using GUI layers. You can read more about GUI layers and how they affect draw calls in the [GUI manual](/manuals/gui#layers-and-draw-calls).
+节点树直观的反映用户界面节点的关系. 但是这种树形结构有可能会打破合批. 树形结构下 GUI 要使节点高效渲染推荐使用 GUI 层. 关于层的使用及其对合批的影响详见 [GUI 教程](/manuals/gui#layers-and-draw-calls).

+ 19 - 2
docs/zh/manuals/script.md

@@ -3,7 +3,7 @@ title: 使用脚本编写游戏逻辑
 brief: 本教程介绍了如何使用脚本组件加入游戏逻辑
 ---
 
-#  脚本
+# 脚本
 
 脚本组件使用 [Lua 编程语言](/manuals/lua) 编程. 脚本像其他 [组件](/manuals/components) 一样附加到游戏对象上, Defold 会在引擎声明循环周期中运行这些 Lua 代码.
 
@@ -66,11 +66,28 @@ Defold 把 Lua 脚本作为引擎生命周期的一部分来执行并且向脚
 `on_message(self, message_id, message, sender)`
 : 当使用 [`msg.post()`](/ref/msg#msg.post) 把消息发送到脚本组件上时, 接收方组件的脚本中此函数被调用.
 
+    ```lua
+    function on_message(self, message_id, message, sender)
+        if message_id == hash("increase_score") then
+            self.total_score = self.total_score + message.score
+        end
+    end
+    ```
+    
 `on_input(self, action_id, action)`
 : 如果组件掌握输入焦点 (见 [`acquire_input_focus`](/ref/go/#acquire_input_focus)) 那么当输入触发时此函数被引擎调用.
 
+
+    ```lua
+    function on_input(self, action_id, action)
+        if action_id == hash("touch") and action.pressed then
+            print("Touch", action.x, action.y)
+        end
+    end
+    ```
+    
 `on_reload(self)`
-: 当使用编辑器的热重载功能 (<kbd>Edit ▸ Reload Resource</kbd>) 重载脚本时此函数被调用. 这对于调试, 测试和微调看效果等需求非常方便.
+: 当使用编辑器的热重载功能 (<kbd>Edit ▸ Reload Resource</kbd>) 重载脚本时此函数被调用. 这对于调试, 测试和微调看效果等需求非常方便. 详情请见 [热重载教程](/manuals/hot-reload).
 
   ```lua
   function on_reload(self)

+ 1 - 1
docs/zh/manuals/shader.md

@@ -1,6 +1,6 @@
 ---
 title: Defold 中的着色器编程
-brief: This manual describes vertex and fragment shaders in detail and how to use them in Defold.
+brief: 本教程介绍了顶点和片元着色器及其在 Defold 中的使用方法.
 ---
 
 # Shaders

+ 7 - 7
docs/zh/manuals/socket-connections.md

@@ -1,11 +1,11 @@
 ---
-title: Socket connections
-brief: This manual explains how to connect to create socket connections.
+title: Socket 连接
+brief: 本教程介绍了建立 socket 连接的方法.
 ---
 
-## Socket connections
+## Socket 连接
 
-Defold includes the [LuaSocket library](http://w3.impa.br/~diego/software/luasocket/) for creating TCP and UDP socket connections. Example of how to create a socket connection, sending some data and reading a response:
+Defold 包含 [LuaSocket 库](http://w3.impa.br/~diego/software/luasocket/) 来建立 TCP 和 UDP socket 连接. 比如说, 上传和读取数据的例子:
 
 ```Lua
 local client = socket.tcp()
@@ -15,8 +15,8 @@ client:send("foobar")
 local response = client:receive("*l")
 ```
 
-This will create a TCP socket, connect it to IP 127.0.0.1 (localhost) and port 8123. It will set timeout to 0 to make the socket non-blocking and it will send the string "foobar" over the socket. It will also read a line of data (bytes ending with a newline character) from the socket. Note that the above example doesn't contain any kind of error handling.
+这样就建立了一个 TCP socket 并连接到 IP 127.0.0.1 (localhost) 的 8123 端口. 超时为 0 确保 socket 不会卡住程序, 然后上传 "foobar" 信息数据. 然后再读取一行服务器的回复 (读取字节直到换行符). 注意本例没有考虑错误处理.
 
-### API Reference and examples
+### API 文档与示例
 
-Refer to the [API reference](/ref/socket/) to learn more about the functionality available via LuaSocket. The [official LuaSocket documentation](http://w3.impa.br/~diego/software/luasocket/) also contains many examples of how to work with the library. There is also some examples and helper modules in the [DefNet library](https://github.com/britzl/defnet/).
+请参考 [API 文档](/ref/socket/) 了解 LuaSocket 功能. 在 [官方 LuaSocket 教程](http://w3.impa.br/~diego/software/luasocket/) 中也含有库的许多用例. 在 [DefNet 库](https://github.com/britzl/defnet/) 里也有许多示例和帮助信息.

+ 4 - 0
docs/zh/manuals/sound.md

@@ -182,3 +182,7 @@ msg.post("/sound_gate#script", "play_gated_sound", { soundcomponent = "/sounds#e
 ::: 注意
 对于 `play_sound` 消息没法过滤因为该消息由 Defold 引擎内部保留. 如果使用引擎保留消息名会造成运行不正确.
 :::
+
+## 相关项目配置
+
+在 *game.project* 文件里有些关于声音组件的 [设置项目](/manuals/project-settings#sound).

+ 1 - 1
docs/zh/manuals/spine.md

@@ -9,7 +9,7 @@ _Spine_ 是由 Esoteric Software 开发的第三方动画工具, 可以让你使
 
 Defold 实现了 [Spine JSON 格式](http://esotericsoftware.com/spine-json-format) 的运行时和动画表达.
 
-Defold 支持了主要的 Spine 动画功能, 包括反向运动 (IK).
+Defold 支持了主要的 Spine 动画功能, 包括反向运动 (IK).
 
 ::: 注意
 目前, Defold 不支持翻转 X 或者 Y 轴的动画关键帧. Defold 只支持骨骼驱动的网格动画, 不支持单个三角形顶点动画. 一定要做的话就用骨骼 100% 绑定一个三角形来做骨骼动画.

+ 7 - 3
docs/zh/manuals/spinemodel.md

@@ -82,9 +82,13 @@ Spine模型可以使用 `go.get()` 和 `go.set()` 方法修改其属性:
 `skin`
 : 当前组件的皮肤 (`hash`).
 
-## 材质属性
+## 材质常量
 
-Spine模型的默认材质属性可以用 `spine.set_constant()` 和 `spine.reset_constant()` 方法来设置和重置. (详情参见 [材质教程](/manuals/material/#vertex-and-fragment-constants)):
+{% include shared/material-constants.md component='spine' variable='tint' %}
 
 `tint`
-: Spine材质的染色 (`vector4`). 四元数 x, y, z, 和 w 代表染色的红, 绿, 蓝 和不透明度. 参见 [这个例子的 API 用法](/ref/spine/#spine.set_constant:url-constant-value).
+: 3D网格颜色 (`vector4`). 四元数 x, y, z, 和 w 分别对应红, 绿, 蓝和不透明度.
+
+## 相关项目配置
+
+在 *game.project* 文件里有些关于Spine模型的 [设置项目](/manuals/project-settings#spine).

+ 7 - 3
docs/zh/manuals/sprite.md

@@ -57,9 +57,13 @@ Sprite 组件使用 [图集](/manuals/atlas) 或者 [瓷砖图源](/manuals/tile
 `size`
 : Sprite大小 (`vector3`) (只读).
 
-## 材质属性
+## 材质常量
 
-sprite的默认材质属性可以用 `sprite.set_constant()` 和 `sprite.reset_constant()` 方法来设置和重置. (详情参见 [材质教程](/manuals/material/#vertex-and-fragment-constants)):
+{% include shared/material-constants.md component='sprite' variable='tint' %}
 
 `tint`
-: sprite染色 (`vector4`). 四元数 x, y, z, 和 w 代表染色的红, 绿, 蓝 和不透明度. 参见 [这个例子的 API 用法](/ref/sprite/#sprite.set_constant:url-constant-value).
+: 3D网格颜色 (`vector4`). 四元数 x, y, z, 和 w 分别对应红, 绿, 蓝和不透明度.
+
+## 相关项目配置
+
+在 *game.project* 文件里有些关于Sprite的 [设置项目](/manuals/project-settings#sprite).

+ 3 - 3
docs/zh/manuals/texture-profiles.md

@@ -1,9 +1,9 @@
 ---
-title: Texture profiles in Defold
-brief:  Defold supports automatic texture processing and compression of image data. This manual describes the available functionality.
+title: Defold 中的纹理档案
+brief: Defold supports automatic texture processing and compression of image data. This manual describes the available functionality.
 ---
 
-# Texture profiles
+# 纹理档案
 
 Defold supports automatic texture processing and compression of image data (in *Atlas*, *Tile sources*, *Cubemaps* and stand-alone textures used for models, GUI etc).
 

+ 7 - 3
docs/zh/manuals/tilemap.md

@@ -89,9 +89,13 @@ end
 `material`
 : 瓷砖地图材质 (`hash`). 可以使用 `go.set()` 方法指定瓷砖地图材质. 参见 [这个例子的 API 用法](/ref/tilemap/#material).
 
-### 材质属性
+### 材质常量
 
-材质可以使用 `tilemap.set_constant()` 和 `tilemap.reset_constant()` 方法设置和重置一系列属性 (详情参见 [材质教程](/manuals/material/#vertex-and-fragment-constants)):
+{% include shared/material-constants.md component='tilemap' variable='tint' %}
 
 `tint`
-: 瓷砖地图染色 (`vector4`). 四元数 x, y, z, 和 w 代表染色的红, 绿, 蓝 和不透明度. 参见 [这个例子的 API 用法](/ref/tilemap/#tilemap.set_constant:url-constant-value).
+: 3D网格颜色 (`vector4`). 四元数 x, y, z, 和 w 分别对应红, 绿, 蓝和不透明度.
+
+## 相关项目配置
+
+在 *game.project* 文件里有些关于瓷砖地图的 [设置项目](/manuals/project-settings#tilemap).

+ 36 - 36
docs/zh/manuals/web-monetization.md

@@ -1,36 +1,36 @@
 ---
-title: Web Monetization in Defold
-brief: Web Monetization is an exciting new and non-intrusive way for game developers to monetize their web games while at the same time offering premium content to their paying players.
+title: Defold 网页游戏盈利
+brief: 网页游戏盈利是用网页游戏获利的一种手段, 开发者获利的同时玩家获得更高级的游戏内容.
 ---
 
-# Web Monetization
+# 网页游戏盈利
 
-[Web Monetization](https://webmonetization.org/) is an open technology that allows someone viewing a webpage or playing a web game to stream very small payments (micropayments) to the creator in real time. It is an exciting new and non-intrusive way for game developers to monetize their web games while at the same time offering premium content to their paying players.
+[Web Monetization](https://webmonetization.org/) 是一种开放的技术手段, 能让浏览网站或者玩网页游戏的用户向作者进行 (超小额度) 付款而且实时到账. 这给网页游戏开发者一条新的生财之道, 同时付款的玩家会获得额外的高端游戏内容.
 
-Web Monetization is being [proposed as a W3C standard](https://discourse.wicg.io/t/proposal-web-monetization-a-new-revenue-model-for-the-web/3785). It is based on the [Interledger](https://interledger.org/) protocol which is an open, neutral protocol for transferring money of any currency, including digital currencies such as Bitcoin.
+网页微支付 [已被提名为 W3C 标准](https://discourse.wicg.io/t/proposal-web-monetization-a-new-revenue-model-for-the-web/3785). 它基于 [Interledger](https://interledger.org/) 协议, 一种开放的, 中立的任意货币转账协议, 包括比特币这样的数字货币.
 
 
-## How does it work?
+## 如何工作?
 
-Three things are required in order to send and receive payments:
+转账要满足以下需求:
 
-1. A player must have an account with a **Web Monetization Provider** - The provider streams payments from the player.
-2. The developer must have a **Web Monetization Wallet** - The wallet holds received payments.
-3. The developer must add a **Payment Pointer** on the webpage containing content that should be monetized - The payment pointer tells the provider which wallet to send the money to.
+1. 玩家必须持有 **Web Monetization Provider** 账户 - 玩家付款的账户.
+2. 开发者必须持有 **Web Monetization Wallet** 账户 - 开发者收款的账户.
+3. 开发者必须在网页上放置 **Payment Pointer** 其中包含需要付费才能得到的内容 - 支付点用来确定把款项发往哪个钱包.
 
 
-### Web Monetization Providers
+### 网页支付账户
 
-Players must have an account with a Web Monetization Provider to be able to stream payments to game developers:
+玩家必须持有网页支付提供商提供账户以便向游戏开发者付款:
 
 [![Coil logo](images/web-monetization/coil_logo.svg)](https://coil.com)
 
-Coil is currently the only provider but others will likely be available in the future
+目前 Coil 是唯一的网页支付服务提供商, 以后会越来越多.
 
 
-### Web Monetization Wallets
+### 网页钱包账户
 
-Game developers must have a Web Monetization enabled wallet to hold received payments. There are several different services which provide wallets with support for Web Monetization:
+开发者必须持有网页支付钱包以便接收付款. 已经有许多服务提供商提供网页钱包服务:
 
 [![Uphold logo](images/web-monetization/uphold_logo.svg)](https://www.uphold.com/signup)
 
@@ -39,57 +39,57 @@ Game developers must have a Web Monetization enabled wallet to hold received pay
 [![Stronghold logo](images/web-monetization/stronghold_logo.svg)](https://stronghold.co/real-time-payments#coil)
 
 
-### Payment Pointers
+### 支付点
 
-The wallet provider will assign a payment pointer to the wallet. The payment pointer is a public address for a wallet that can be shared with anyone that wants to make a payment to the owner of the wallet. Learn more at [paymentpointers.org](https://paymentpointers.org/). The format of a payment pointer is similar to a URL, but starts with a $:
+钱包提供商把支付点与钱包对应. 支付点是钱包的收款地址, 它可以被随意公开出去. 详情请见 [paymentpointers.org](https://paymentpointers.org/). 支付点就像一个网络连接, 但是是由 $ 开头:
 
 ```
 $ilp.uphold.com/QkG86UgXzKq8
 ```
 
-The payment pointer is added to the website content using a `<meta>` tag in the `<head>` of the website:
+支付点要加入到网页 `<head>` 标签中的 `<meta>` 标签里:
 
 ```html
 <meta name="monetization" content="$ilp.uphold.com/QkG86UgXzKq8">
 ```
 
 
-## How to set up Web Monetization in Defold
+## 在 Defold 中配置支付点 
 
-Enabling Web Monetization in a Defold game is a straightforward process. The steps involved depend on if you are adding Web Monetization to an existing project or if you are starting a new project.
+在 Defold 游戏中使用网页支付功能是个简单的过程. 新建项目和已有项目的配置方法略有不同.
 
 
-### Starting a new project
+### 新建项目
 
-If you are starting a new project it is recommended that you use the Web Monetization project template from the Defold editor Welcome screen. The Web Monetization template includes the [Web Monetization extension](https://github.com/defold/extension-webmonetization) and it will automatically set up the payment pointer in the generated webpage for your game:
+如果是新建项目强烈建议你使用 Defold 欢迎屏幕里的网页支付项目模板. 这个模板包含了 [网页支付原生扩展](https://github.com/defold/extension-webmonetization), 还能为你的网页游戏自动添加支付点:
 
 ![Web Monetization template](images/web-monetization/web-monetization-template.png)
 
-Next step is to register for a [Web Monetization enabled wallet](/manuals/web-monetization/#web-monetization-wallets) and add your payment pointer to the Web Monetization section of the **game.project** file:
+下一步注册 [网页支付钱包](/manuals/web-monetization/#web-monetization-wallets) 然后在 **game.project** 文件的 Web Monetization 部分将支付点与钱包挂接:
 
 ![Adding payment pointer to game.project](images/web-monetization/payment-pointer.png)
 
 
-### Adding Web Monetization to an existing project
+### 已有项目
 
-Start by registering for a [Web Monetization enabled wallet](/manuals/web-monetization/#web-monetization-wallets) and add your payment pointer to the webpage:
+首先注册 [网页支付钱包](/manuals/web-monetization/#web-monetization-wallets) 然后手动在网页中加入支付点:
 
 ```html
 <meta name="monetization" content="YOUR_PAYMENT_POINTER">
 ```
 
-Next you need to add the [Web Monetization extension](https://github.com/defold/extension-webmonetization) as a [project dependency](http://www.defold.com/manuals/libraries/). Open the **game.project** file and in the [Dependencies field in the Project section](https://defold.com/manuals/project-settings/#dependencies) add:
+下一步将 [网页支付原生扩展](https://github.com/defold/extension-webmonetization) 作为 [项目依赖库](http://www.defold.com/manuals/libraries/) 加入. 打开 **game.project** 文件, 找到 Project 部分的 [Dependencies 项](https://defold.com/manuals/project-settings/#dependencies) 加入:
 
 ```
 https://github.com/defold/extension-webmonetization/archive/master.zip
 ```
 
 
-## How to use Web Monetization in Defold
+## Defold 网页支付用法
 
-When you have the Web Monetization extension and payment pointer added to your project you are ready to start using Web Monetization in your game. The API consosts of only two functions:
+在项目中加入扩展包和支付点之后就可以使用它了. 它的 API 包含两个部分:
 
-Check if a player is monetized (ie is streaming payments to you):
+检查玩家付款 (或者正在付款):
 
 ```lua
 local monetized = webmonetization.is_monetized()
@@ -98,7 +98,7 @@ if monetized then
 end
 ```
 
-Set up a listener to get updates on the current monetization state of the player:
+设置监听器跟踪付款进度:
 
 ```lua
 webmonetization.set_listener(function(self, event)
@@ -115,10 +115,10 @@ end)
 ```
 
 
-## Best practices
+## 最佳实践
 
-* Offer exclusive content to web monetized players. What you offer depends on the type of game. Some examples:
-  * New skins or other cosmetic changes such as unique in-game decals or stickers
-  * New game modes
-  * Additional levels
-* If your game contains ads you should also consider removing the ads for web monetized players
+* 为付费玩家提供值钱的内容. 不同游戏类型有所不同. 比如:
+  * 独一无二的皮肤或装束
+  * 新的人物模型
+  * 新的关卡
+* 如果游戏包含广告还可以考虑为付费玩家去掉广告

+ 3 - 5
docs/zh/manuals/websocket-connections.md

@@ -1,7 +1,5 @@
 ---
-title: WebSocket connections
-brief: This manual explains how to use WebSocket connections.
+title: WebSocket 连接
+brief: 本教程介绍了 WebSocket 连接的使用方法.
 ---
-## WebSocket connections
-
-Defold doesn't contain any out of the box solution for creating WebSocket connections. For WebSocket connectivity it is recommended to use the [Defold-WebSocket extension](https://defold.com/assets/websocket/).
+本教程已移至 [这里](/extension-websocket).

+ 2 - 305
docs/zh/manuals/webview.md

@@ -1,309 +1,6 @@
 ---
 title: Defold 的 WebViews
-brief: "WebViews 可以在你的手机上显示一个网页层. 同时支持在后台运行用户定义的js代码. 本教程介绍了 Defold 的官方 WebView 扩展, API 和功能."
+brief: WebViews 可以在你的手机上显示一个网页层. 同时支持在后台运行用户定义的js代码. 本教程介绍了 Defold 的官方 WebView 扩展, API 和功能.
 ---
 
-# WebViews
-WebView 提供了一套特殊的 API 用来在手机上显示一个网页层. 首先让我们来实现一个简单的 webview.
-然后我们会讨论如何使用一套简单的控制按钮控制这个 webview.
-
-## 安装扩展
-
-在你的 `game.project` 文件中设置 webview 依赖.
-最新版本位于如下 URL:
-```
-https://github.com/defold/extension-webview/archive/master.zip
-```
-
-API文档位于 [扩展首页](https://defold.github.io/extension-webview/).
-
-## 打开 webview
-使用 `webview.create` 就能创建一个网页层, 并且返回一个唯一id. 下文中我们把这个 ID 称为 `webview_id`,
-多个 `webview` 之间进行交互时会用到这个id. 也就是说创建和维护多个 webview 是可行的.
-
-`webview.create` 带着一个函数参数, 待会儿我们再来仔细看看这个回调, 现在先给它留空.
-```lua
-local webview_id = webview.create(function()
-        -- 目前无代码
-    end)
-```
-默认状况下新建的 webview 都是不可见的, 因为它还没有加载任何内容. 其主要功能就是显示网页, 现在就来加载个超酷的网页吧!
-
-调用 `webview.open` 函数, 第一个参数就是上文的那个 `webview_id`, 第二个参数是要打开的URL.
-
-```lua
-local request_id = webview.open(webview_id, "http://www.defold.com") --广告无处不在
-```
-
-这个函数返回网页请求的id, 这个id我们稍后也会用到.
-
-如果一切顺利你将看到神奇的网页占满了屏幕, 就是 Defold 官方首页.
-
-::: 注意
-要在 iOS 里访问的网页必须遵循在 `Info.plist` 文件中的 `NSAppTransportSecurity` 里面设置好的键值对.
-```
-<key>NSAllowsArbitraryLoads</key>
-<true/>
-```
-
-开发的时候可以随便设置, 但是发布到 App Store 之后就只能通过使用 `NSExceptionDomains` 键代替. 这有点超出本教程讨论范围,
-详情可以参考 [Apple 开发者文档](https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35).
-:::
-
-## 回调函数
-Just opening web pages inside a webview might be sufficient in most cases, but what happens if the
-URL isn't accessible or something unforeseen happens while loading? Perhaps we want to show a
-notification to the user if we encounter an error, or we want to perform some action if a user
-navigates away from the web page. Thankfully the webview extension has functionality to trigger
-events when errors, navigations and success occur! They are exposed through the callback function we
-pass as argument to the `webview.create` call.
-
-The callback function should have the following signature:
-```lua
-function callback(self, webview_id, request_id, type, data)
-```
-
-* **`self`** - This is the script instance from where the callback was set.
-* **`webview_id`** - The callback can be reused for multiple webview instances, this argument let's
-you keep track of from which instance the event originates from.
-* **`request_id`** - Likewise, you can trigger multiple `webview.open` calls, and the request id
-allows you to know which of the requests the event was triggered from.
-* **`type`** - An enum describing what kind of event happened, we will go through them below in
-*Callback types*.
-* **`data`** - A table containing different information depending on what type of event occurred.
-
-#### Callback types
-The `type` argument of the callback are always set to one of the following enums:
-
-* **`webview.CALLBACK_RESULT_URL_LOADING`** - When a navigation occurs inside the webview, the
-loading event is triggered. This can happen either if you call `webview.open` or the user clicks
-on a link that would result in a new URL being loaded. The result of the callback dictates if the
-navigation is allowed. If you return `false` the navigation will be blocked, any other return value
-will allow the navigation. To decide if the navigation should be allowed or not, you can inspect
-the `url` field in the `data` table, also supplied in the callback.
-* **`webview.CALLBACK_RESULT_URL_ERROR`** and **`webview.CALLBACK_RESULT_EVAL_ERROR`** - In case of
-errors loading the URL, or errors when trying to evaluate JavaScript (we will go into details below
-in *Running JavaScript*), an error event will be triggered. The `result` field in the `data` table
-contains more information about the error, as a string.
-* **`webview.CALLBACK_RESULT_URL_OK`** and **`webview.CALLBACK_RESULT_EVAL_OK`** - When a URL
-navigation or JavaScript execution was successful, an ok event will be triggered. In the case of
-a successful JavaScript evaluation the result will be available in the `result` field of the `data`
-table.
-
-Now that we know a bit more of how the callback is called, let's create a more advanced example.
-
-Imagine if we want to show some player feedback webpage, where the player can report feedback about
-the game through a HTML form. We want to know if the URL couldn't be loaded, instead of an empty
-page we want to show some ingame notification and close the webview. And we probably don't want the
-player to be able to navigate away from the form.
-
-Our updated `webview.create` call and callback could looks something like this:
-```lua
-local player_feedback_url = "https://example.com/my_game_name/customer_feedback"
-
-local function webview_callback(self, webview_id, request_id, type, data)
-    if type == webview.CALLBACK_RESULT_URL_ERROR then
-        -- An error occurred!
-        -- Let's close the webview and set a label with some helpful text!
-        webview.destroy(webview_id)
-        label.set_text("#label", "Player feedback not available at this moment.")
-
-    elseif type == webview.CALLBACK_RESULT_URL_LOADING then
-        -- Make sure the player isn't navigating away from the feedback URL.
-        if data.url ~= player_feedback_url then
-            return false
-        end
-    end
-end
-
-local feedback_webview = webview.create(webview_callback)
-webview.open(feedback_webview, player_feedback_url)
-```
-
-This will result in a full screen webview being shown, loading a remote web page with our player
-feedback form. Depending of how we setup our player feedback webpage it will look something like
-this:
-
-![Player feedback web page](images/webview/webview_player_feedback1.png)
-
-Note: In our example we also included a link to google.com, just to verify that blocking any navigation
-that would lead away from our webpage.
-
-We now have our first working player feedback prototype! But what should happen once the player has
-provided feedback? Maybe the player changes their mind and don't want to provide any feedback,
-how do they get back to your game? Lastly, a full screen webview might not be the best option in
-this case, perhaps we still want to show that the game is still running in the background! We will
-cover solutions for these issues in the *Running JavaScript* and
-*Visibility and positioning control* sections below.
-
-## Opening and displaying a custom HTML page
-Before we continue with handling positioning/sizing and being able to close the webview, let's make
-it a bit easier to iterate on the HTML page without having to update our webserver with each change.
-
-With `webview.open_raw` we can provide a HTML source directly instead of loading it from a remote
-URL. This means that even if the webserver is down, or the player have a slow internet connection,
-we can still show the feedback form.
-
-The first argument to `webview.open_raw` is just like `webview.open`, the `webview_id`. The second
-argument is a string with raw HTML source, instead of an URL as in the previous function.
-
-Let's recreate the previous example but inline the HTML directly in our Lua source:
-```lua
-local feedback_html = [[
-<html>
-<script type="text/javascript">
-    function closeWebview() {
-        // TODO
-    }
-    function submitFeedback() {
-        // do something with the feedback here
-        // ...
-    }
-</script>
-<body>
-    <center>
-    <h4>Hello Player!</h4>
-    <p>Please provide some feedback for my awesome game!</p>
-    <form>
-        <label>Game feedback:<br><textarea placeholder="Is it fun? What can be improved?" style="width: 300px; height: 80px"></textarea></label><br>
-        <input type="button" onclick="submitFeedback()" value="Submit feedback">
-        <br>
-        <input type="button" onclick="closeWebview()" value="Cancel">
-    </form>
-</center>
-</body>
-</html>
-]]
-
-local function webview_callback(self, webview_id, request_id, type, data)
-    -- ...
-end
-
-local webview_id = webview.create(webview_callback)
-webview.open_raw(webview_id, feedback_html)
-```
-
-This should give us a similar webview as in the previous example, with the added benefit that we
-can edit the HTML directly in our game source code. **Note:** The contents of `webview_callback` has
-only been removed for readability.
-
-Since we know that the HTML source is going to grow a bit once we start adding JavaScript code and
-CSS, it now makes sense to separate the HTML data into its own file and load it dynamically during
-runtime using [`sys.load_resource`](https://www.defold.com/ref/sys/#sys.load_resource:filename).
-This also means that we more easily can view the HTML file in a desktop browser while we are
-developing.
-
-Let's create a new directory (`custom_resources`), and a HTML file (`feedback.html`) with the data
-instead and set the `feedback_html` variable dynamically instead.
-
-```lua
-local feedback_html = sys.load_resource("/custom_resources/feedback.html")
--- ...
-webview.open_raw(webview_id, feedback_html)
-```
-
-## Visibility and positioning control
-Now let's tackle the issue of the webview being full screen.
-
-To get a more immersive interaction we might want the webview only cover the upper part of the
-screen. We can use the `webview.set_position` function to both set the position and width of a
-webview. Passing in `-1` as either width or height will make the webview take up the full space on the
-corresponding axis.
-
-```lua
-local webview_id = webview.create(webview_callback)
--- Position: top left corner of screen (0, 0)
--- Size: we want full with, but only 500px height
-webview.set_position(webview_id, 0, 0, -1, 500)
-```
-
-![Resized feedback page](images/webview/webview_player_feedback2.png)
-
-If the user is on a device with poor performance, the page might not load instantly and display as
-white while loading. This might be jarring to our player, so let's hide the webview until the page
-has loaded. This also gives us the opportunity to show a loading indication in-game to reassure the
-player that the game is actually doing something.
-
-To hide the webview we can pass along an options table to the third argument of our
-`webview.open_raw` (or `webview.open`) call, with the field `hidden` set to `true`. The default
-value of this field is `false` as we have seen before, once we opened a URL or HTML the webview
-was immediately visible.
-
-```lua
-webview.open_raw(webview_id, feedback_html, {hidden = true})
-```
-
-To make sure the webview successfully loaded the URL or HTML we want to wait for the callback to
-trigger with an event of type `webview.CALLBACK_RESULT_URL_OK`. Once we get this we know that we can
-unhide the webview, which can be accomplished with the `webview.set_visible` function.
-
-Let's update our callback with this new logic:
-```lua
-local function webview_callback(self, webview_id, request_id, type, data)
-    if type == webview.CALLBACK_RESULT_URL_OK then
-        -- No errors, let's present the webview!
-        webview.set_visible(webview_id, 1)
-    elseif type == webview.CALLBACK_RESULT_URL_ERROR then
-        -- ...
-```
-
-## Running JavaScript
-Now we have managed to fix most of our issues, but one last thing is still unsolved; being able to
-close the webview.
-
-We have already seen and used the function that will close and remove the webview in our callback
-when we encounter an error, `webview.destroy`. But we need a way from inside the webview to trigger
-the function call. Thankfully we there is a way from Lua to call JavaScript that will run inside the
-webview and read the result. With this we should be able to poll for changes inside the webview.
-
-Let's start with adding some state inside the JavaScript tag of the HTML that we can change when
-the buttons are pressed on the web page.
-```js
-var shouldClose = false;
-function closeWebview() {
-    shouldClose = true;
-}
-function submitFeedback() {
-    // do something with the feedback here
-    // ...
-    closeWebview();
-}
-
-```
-
-Now once the player presses either the "Submit feedback" or "Cancel" button we update the
-`shouldClose` variable.
-
-Now somewhere in our Lua script we need to check for this state and call `webview.destroy`. A naive
-place would be to check for this every frame, in our `update` function.
-
-```lua
-function update(self, dt)
-    if not self.closeCheckRequest then
-        self.closeCheckRequest = webview.eval(webview_id, "shouldClose")
-    end
-end
-```
-
-It's important to note here that the result from `webview.eval` is not the result from the
-JavaScript being evaluated, but a *request id*. We need to update our callback to check against this
-request id, and inspect the `data.result` field, which is where the actual JavaScript result will be
-stored.
-
-```lua
-local function webview_callback(self, webview_id, request_id, type, data)
-    if type == webview.CALLBACK_RESULT_EVAL_OK and
-        request_id == self.closeCheckRequest then
-
-        -- Compare the JavaScript result, if it's "true" we should
-        -- close the webview!
-        if data.result == "true" then
-            webview.destroy(webview_id)
-        end
-
-    elseif type == webview.CALLBACK_RESULT_URL_OK then
-        -- ...
-```
-
-Now we know if a form button was pressed from inside the webview and the player is able to get back
-to the game!
+本教程已移至 [这里](/extension-webview).

+ 2 - 2
docs/zh/manuals/windows.md

@@ -17,5 +17,5 @@ Windows游戏的图标要使用 .ico 格式. 你可以拿一个 .png 文件, 使
 
 ![Windows icon sizes](images/windows/windows-icon.png)
 
-## FAQ
-:[Windows FAQ](../shared/windows-faq.md)
+## 问答
+:[Windows 问答](../shared/windows-faq.md)

+ 1 - 1
docs/zh/manuals/working-offline.md

@@ -1,6 +1,6 @@
 ---
 title: 断网工作
-brief: 教程介绍了在离线状态下使用依赖库尤其是使用原生扩展的方法
+brief: 教程介绍了在离线状态下使用依赖库尤其是使用原生扩展的方法
 ---
 
 # 断网工作

+ 3 - 6
docs/zh/shared/blend-modes.md

@@ -1,13 +1,10 @@
 *Blend Mode* 属性定义了可视组件如何与其后面的图像混合. 以下列举了支持的混合模式及其混合算法:
 
 Alpha
-: 普通混合: a~0~ * rgb~0~ + (1 - a~0~) * rgb~1~
+: 普通混合: `src.a * src.rgb + (1 - src.a) * dst.rgb`
 
 Add
-: 使用相应的 sprite 像素颜色值提亮背景: rgb~0~ + rgb~1~
-
-Add Alpha (废弃!)
-: 使用相应的可见 sprite 像素颜色值提亮背景: a~0~ * rgb~0~ + rgb~1~
+: 使用相应的 sprite 像素颜色值提亮背景: `src.rgb + dst.rgb`
 
 Multiply
-: 使用相应的 sprite 像素颜色值调暗背景: rgb~0~ * rgb~1~
+: 使用相应的 sprite 像素颜色值调暗背景: `src.rgb * dst.rgb`

+ 1 - 1
docs/zh/shared/install.md

@@ -1,6 +1,6 @@
 ## 下载
 
- [Defold 下载页](https://defold.com/download/) 就能看到许多操作系统对应版本的下载按钮 macOS, Windows 还有 Linux (Ubuntu) 的:
+打开 [Defold 下载页](https://defold.com/download/) 就能看到许多操作系统对应版本的下载按钮 macOS, Windows 还有 Linux (Ubuntu) 的:
 
 ![download editor](../shared/images/editor_download.png)
 

+ 6 - 0
docs/zh/shared/material-constants.md

@@ -0,0 +1,6 @@
+
+默认 {{ include.component }} 材质常量可以使用 [go.set()](/ref/stable/go/#go.set) 或 [go.animate()](/ref/stable/go/#go.animate) 来修改 (参考 [材质教程](/manuals/material/#vertex-and-fragment-constants)). 例如:
+```lua
+go.set("#{{ include.component }}", "{{ include.variable }}", vmath.vector4(1,0,0,1))
+go.animate("#{{ include.component }}", "{{ include.variable }}", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(1,0,0,1), go.EASING_LINEAR, 2)
+```

+ 0 - 393
docs/zh/tutorials/15-puzzle.md

@@ -1,393 +0,0 @@
----
-title: Building a 15 puzzle game in Defold
-brief: If you are new to Defold, this guide will help you to lab with a few of the building blocks in Defold and run script logic.
----
-
-# The classic 15 puzzle
-
-This well-known puzzle became popular in America during the 1870s. The goal of the puzzle is to organize the tiles on the board by sliding them horizontally and vertically. The puzzle starts from a position where the tiles have been scrambled.
-
-The most common version of the puzzle shows the numbers 1--15 on the tiles. However, you can make the puzzle a bit more challenging by making the tiles part of an image. Before we begin, try to solve the puzzle. Click on a tile adjacent to the empty square to slide the tile to the empty position.
-
-## Creating the project
-
-1. Start Defold.
-2. Select *New Project* on the left.
-3. Select the *From Template* tab.
-4. Select *Empty Project*
-5. Select a location for the project on your local drive.
-6. Click *Create New Project*.
-
-Open the *game.project* settings file and set the dimensions of the game to 512⨉512. These dimensions will match the image you are going to use.
-
-![display settings](images/15-puzzle/display_settings.png)
-
-The next step is to download a suitable image for the puzzle. Pick any square image but make sure to scale it to 512 by 512 pixels. If you don't want to go out and search for an image, here's one:
-
-![Mona Lisa](images/15-puzzle/monalisa.png)
-
-Download the image, then drag it to the *main* folder of your project.
-
-## Representing the grid
-
-Defold contains a built-in *Tilemap* component that is perfect for visualizing the puzzle board. Tilemaps allow you to set and read individual tiles, which is all you need for this project.
-
-But before you create the tilemap, you need a *Tilesource* that the tilemap will pull its tile images from.
-
-<kbd>Right click</kbd> the *main* folder and select <kbd>New ▸ Tile Source</kbd>. Name the new file "monalisa.tilesource".
-
-Set the tile *Width* and *Height* properties to 128. This will split the 512⨉512 pixel image into 16 tiles. The tiles will be numbered 1--16 when you put them on the tilemap.
-
-![Tile source](images/15-puzzle/tilesource.png)
-
-Next, <kbd>Right click</kbd> the *main* folder and select <kbd>New ▸ Tile Map</kbd>. Name the new file "grid.tilemap".
-
-Defold needs you to initialize the grid. To do that, select the "layer1" layer and paint the 4⨉4 grid of tiles just to the top-right of origin. It does not really matter what you set the tiles to. You will write code in a bit that will set the content of these tiles automatically.
-
-![Tile map](images/15-puzzle/tilemap.png)
-
-## Putting the pieces together
-
-Open *main.collection*. <kbd>Right click</kbd> the root node in the *Outline* and select <kbd>Add Game Object</kbd>. Set the *Id* property of the new game object to "game".
-
-<kbd>Right click</kbd> the game object and select <kbd>Add Component File</kbd>. Select the file *grid.tilemap*.
-
-<kbd>Right click</kbd> the game object and select <kbd>Add Component ▸ Label</kbd>. Set the *Id* property of the label to "done" and its *Text* property to "Well done". Move the label to the center of the tilemap.
-
-Set the Z position of the label to 1 to make sure it's drawn on top of the grid.
-
-![Main collection](images/15-puzzle/main_collection.png)
-
-Next, create a Lua script file for the puzzle logic: <kbd>right click</kbd> the *main* folder and select <kbd>New ▸ Script</kbd>. Name the new file "game.script".
-
-Then <kbd>Right click</kbd> the game object called "game" in *main.collection* and select <kbd>Add Component File</kbd>. Select the file *game.script*.
-
-Run the game. You should see the grid as you drew it and the label with the "Well done" message on top.
-
-## The puzzle logic
-
-Now you have all the pieces in place so the rest of the tutorial will be spent putting together the puzzle logic.
-
-The script will carry its own representation of the board tiles, separate from the tilemap. That is because it is possible to make it easier to operate on. Instead of storing the tiles in a 2 dimensional array, the tiles are stored as a one dimensional list in a Lua table. The list contains the tile number in sequence, starting from the top left corner of the grid all the way to the bottom right:
-
-```lua
--- The completed board looks like this:
-self.board = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}
-```
-
-The code that takes such a list of tiles and draws it on our tilemap is pretty simple but needs to convert the position in the list to a x and y position:
-
-```lua
--- Draw a table list of tiles onto a 4x4 tilemap
-local function draw(t)
-    for i=1, #t do
-        local y = 5 - math.ceil(i/4) -- <1>
-        local x = i - (math.ceil(i/4) - 1) * 4
-        tilemap.set_tile("#tilemap","layer1",x,y,t[i])
-    end
-end
-```
-1. In tilemaps, the tile with x-value 1 and y-value 1 is at the bottom left. Therefore the y position needs to be inverted.
-
-You can check that the function works as intended by creating a test `init()` function:
-
-```lua
-function init(self)
-    -- An inverted board, for test
-    self.board = {15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}
-    draw(self.board)
-end
-```
-
-With the tiles in a Lua table list, scrambling the order is super easy. The code just runs through each element in the list and switches each tile with another randomly chosen tile:
-
-```lua
--- Swap two items in a table list
-local function swap(t, i, j)
-    local tmp = t[i]
-    t[i] = t[j]
-    t[j] = tmp
-    return t
-end
-
--- Randomize the order of a the elements in a table list
-local function scramble(t)
-    for i=1, #t do
-        t = swap(t, i, math.random(#t))
-    end
-    return t
-end
-```
-
-Before moving on, there's a thing about the 15 puzzle that you really need to consider: if you randomize the tile order like you are doing above, there is a 50% chance that the puzzle is *impossible* to solve.
-
-This is bad news since you definitely don't want to present the player with a puzzle that cannot be solved.
-
-Fortunately, it is possible to figure out whether a setup is solvable or not. Here's how:
-
-## Solvability
-
-In order to figure out if a position in a 4⨉4 puzzle is solvable, two pieces of information are needed:
-
-1. The number of "inversions" in the setup. An inversion is when a tile precedes another tile with a lower number on it. For example, given the list `{1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 11, 10, 13, 14, 15, 0}`, it has 3 inversions:
-
-    - the number 12 has 11 and 10 following it, giving 2 inversions.
-    - the number 11 has 10 following it, giving 1 more inversion.
-
-    (Note that the solved puzzle state has zero inversions)
-
-2. The row where the empty square is (denoted by `0` in the list).
-
-These two numbers can be calculated with the following functions:
-
-```lua
--- Count the number of inversions in a list of tiles
-local function inversions(t)
-    local inv = 0
-    for i=1, #t do
-        for j=i+1, #t do
-            if t[i] > t[j] and t[j] ~= 0 then -- <1>
-                inv = inv + 1
-            end
-        end
-    end
-    return inv
-end
-```
-1. Note that the empty square does not count.
-
-```lua
--- Find the x and y position of a given tile
-local function find(t, tile)
-    for i=1, #t do
-        if t[i] == tile then
-            local y = 5 - math.ceil(i/4) -- <1>
-            local x = i - (math.ceil(i/4) - 1) * 4
-            return x,y
-        end
-    end
-end
-```
-1. Y position from the bottom.
-
-Now, given these two numbers it is possible to tell if a puzzle state is solvable or not. A 4⨉4 board state is *solvable* if:
-
-- If the empty square is on an *odd* row (1 or 3 counting from the bottom) and the number of inversions is *even*.
-- If the empty square is on an *even* row (2 or 4 counting from the bottom) and the number of inversions is *odd*.
-
-## How does this work?
-
-Each legal move moves a piece by switching its place with the empty square either horizontally or vertically.
-
-Moving a piece horizontally does not change the number of inversions, nor does it change the row number where you find the empy square.
-
-Moving a piece vertically, however, changes the parity of the number of inversions (from odd to even, or from even to odd). It also changes the parity of the empty square row.
-
-For example:
-
-![sliding a piece](images/15-puzzle/slide.png)
-
-This move changes the tile order from:
-
-`{ ... 0, 11, 2, 13, 6 ... }`
-
-to
-
-`{ ... 6, 11, 2, 13, 0 ... }`
-
-The new state adds 3 inversions as follows:
-
-- The number 6 adds 1 inversion (the number 2 is now after 6)
-- The number 11 loses 1 inversion (the number 6 is now before 11)
-- The number 13 loses 1 inversion (the number 6 is now before 13)
-
-The possible ways the number of inversions can change by a vertical slide is by ±1 or ±3.
-
-The possible ways the empty square row can change by a vertical slide is by ±1.
-
-In the final state of the puzzle, the empty square is in the lower right corner (the *odd* row 1) and the number of inversions is the *even* value 0. Each legal move either leave these two values intact (horizontal move) or switches their polarity (vertical move). No legal move can ever make the polarity of the inversions and the empty square row *odd*, *odd* or *even*, *even*.
-
-Any puzzle state where the two numbers are both odd or both even is therefore impossible to solve.
-
-Here is the code that checks for solvability:
-
-```lua
--- Is the given table list of 4x4 tiles solvable?
-local function solvable(t)
-    local x,y = find(t, 0)
-    if y % 2 == 1 and inversions(t) % 2 == 0 then
-        return true
-    end
-    if y % 2 == 0 and inversions(t) % 2 == 1 then
-        return true
-    end
-    return false    
-end
-```
-
-## User input
-
-The only thing left to do now is to make the puzzle interactive.
-
-Create an `init()` function that does all the runtime setup using the functions created above:
-
-```lua
-function init(self)
-    msg.post(".", "acquire_input_focus") -- <1>
-    math.randomseed(socket.gettime()) -- <2>
-    self.board = scramble({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}) -- <3>
-    while not solvable(self.board) do -- <4>
-        self.board = scramble(self.board)
-    end
-    draw(self.board) -- <5>
-    self.done = false -- <6>
-    msg.post("#done", "disable") -- <7>
-end
-```
-1. Tell the engine that this game object should receive input.
-2. Seed the randomizer.
-3. Create an initial random state for the board.
-4. If the state is unsolvable, scramble again.
-5. Draw the board.
-6. Set a completion flag to track winning state.
-7. Disable the completion message label.
-
-Open */input/game.input_bindings* and add a new *Mouse Trigger*. Set the name of the action to "press":
-
-![input](images/15-puzzle/input.png)
-
-Go back to the script and create an `on_input()` function.
-
-```lua
--- Deal with user input
-function on_input(self, action_id, action)
-    if action_id == hash("press") and action.pressed and not self.done then -- <1>
-        local x = math.ceil(action.x / 128) -- <2>
-        local y = math.ceil(action.y / 128)
-        local ex, ey = find(self.board, 0) -- <3>
-        if math.abs(x - ex) + math.abs(y - ey) == 1 then -- <4>
-            self.board = swap(self.board, (4-ey)*4+ex, (4-y)*4+x) -- <5>
-            draw(self.board) -- <6>
-        end
-        ex, ey = find(self.board, 0)
-        if inversions(self.board) == 0 and ex == 4 then -- <7>
-            self.done = true
-            msg.post("#done", "enable")
-        end
-    end
-end
-```
-1. If there is a mouse button press and the game is still running, do the following.
-2. Calculate the x and y square that the user has clicked.
-3. Find the current location of the empty (0) square.
-4. If the clicked square is on the square is right above, below, left or right of the empty one, do the following:
-5. Switch the tiles on the clicked square and the empty one.
-6. Redraw the updated board.
-7. If the number of inversions on the board is 0, meaning that everything is in the right order, and the empty square is at the rightmost column (it must be on the last row for the inversions to be 0) then the puzzle is solved so do the following:
-8. Set the completion flag.
-9. Enable/show the completion message.
-
-And that's it! You are done, the puzzle game is complete!
-
-## The complete script
-
-Here is the complete script code for reference:
-
-```lua
-local function inversions(t)
-    local inv = 0
-    for i=1, #t do
-        for j=i+1, #t do
-            if t[i] > t[j] and t[j] ~= 0 then
-                inv = inv + 1
-            end
-        end
-    end
-    return inv
-end
-
-local function find(t, tile)
-    for i=1, #t do
-        if t[i] == tile then
-            local y = 5 - math.ceil(i/4)
-            local x = i - (math.ceil(i/4) - 1) * 4
-            return x,y
-        end
-    end
-end
-
-local function solvable(t)
-    local x,y = find(t, 0)
-    if y % 2 == 1 and inversions(t) % 2 == 0 then
-        return true
-    end
-    if y % 2 == 0 and inversions(t) % 2 == 1 then
-        return true
-    end
-    return false    
-end
-
-local function scramble(t)
-    for i=1, #t do
-        local tmp = t[i]
-        local r = math.random(#t)
-        t[i] = t[r]
-        t[r] = tmp
-    end
-    return t
-end
-
-local function swap(t, i, j)
-    local tmp = t[i]
-    t[i] = t[j]
-    t[j] = tmp
-    return t
-end
-
-local function draw(t)
-    for i=1, #t do
-        local y = 5 - math.ceil(i/4)
-        local x = i - (math.ceil(i/4) - 1) * 4
-        tilemap.set_tile("#tilemap","layer1",x,y,t[i])
-    end
-end
-
-function init(self)
-    msg.post(".", "acquire_input_focus")
-    math.randomseed(socket.gettime())
-    self.board = scramble({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0})   
-    while not solvable(self.board) do
-        self.board = scramble(self.board)
-    end
-    draw(self.board)
-    self.done = false
-    msg.post("#done", "disable")
-end
-
-function on_input(self, action_id, action)
-    if action_id == hash("press") and action.pressed and not self.done then
-        local x = math.ceil(action.x / 128)
-        local y = math.ceil(action.y / 128)
-        local ex, ey = find(self.board, 0)
-        if math.abs(x - ex) + math.abs(y - ey) == 1 then
-            self.board = swap(self.board, (4-ey)*4+ex, (4-y)*4+x)
-            draw(self.board)
-        end
-        ex, ey = find(self.board, 0)
-        if inversions(self.board) == 0 and ex == 4 then
-            self.done = true
-            msg.post("#done", "enable")
-        end
-    end
-end
-
-function on_reload(self)
-    self.done = false
-    msg.post("#done", "disable")    
-end
-```
-
-## Further exercises
-
-1. Make a 5⨉5 puzzle, then a 6⨉5 one. Make sure the solvability checks work generally.
-2. Add sliding animations. Tiles cannot be moved separately from the tilemap so you will have to come up with a way of solving that. Perhaps a separate tilemap that only contains the sliding piece?

+ 0 - 27
docs/zh/tutorials/astronaut.md

@@ -1,27 +0,0 @@
----
-title: Walking astronaut tutorial
-brief: In this beginner's tutorial you learn how to capture player input and make a character move and animate. You will also learn about game objects, components and collections
-github: https://github.com/defold/tutorial-astronaut
----
-
-# Walking astronaut tutorial
-
-In this beginner's tutorial you learn how to capture player input and make a character move and animate. You will also learn about the core building blocks in Defold: game objects, components and collections.
-
-The tutorial is integrated with the Defold editor and easily accessible:
-
-1. Start Defold.
-2. Select *New Project* on the left.
-3. Select the *From Tutorial* tab.
-4. Select the "Walking astronaut tutorial"
-5. Select a location for the project on your local drive and click *Create New Project*.
-
-![new project](images/new-astronaut.png){srcset="images/[email protected] 2x"}
-
-The editor automatically opens the "README" file from the project root, containing the full tutorial text.
-
-![icon](images/icon-tutorial.svg){.icon} [You can also read the full tutorial text on Github](https://github.com/defold/tutorial-astronaut)
-
-If you get stuck, head over to the [Defold Forum](//forum.defold.com) where you will get help from the Defold team and many friendly users.
-
-Happy Defolding!

+ 0 - 226
docs/zh/tutorials/car.md

@@ -1,226 +0,0 @@
----
-title: Building a simple car in Defold.
-brief: If you are new to Defold, this guide will help you getting your bearings right in the editor. It also explains the basic ideas and the most common building blocks in Defold - game objects, collections, scripts and sprites.
----
-
-# Building a car
-
-If you are new to Defold, this guide will help you getting your bearings right in the editor. It also explains the basic ideas and the most common building blocks in Defold: Game objects, Collections, Scripts and Sprites.
-
-We're going to start from an empty project and work step by step to a very small, playable application. At the end you will hopefully have a feel for how Defold works and you will be ready to tackle a more extensive tutorial or dive right into the manuals.
-
-## The editor
-
-Start by creating a [new project](/manuals/project-setup/) and opening it in the editor. If you double-click the file *main/main.collection* the file will open up:
-
-![Editor overview](../manuals/images/editor/editor2_overview.png)
-
-The editor consists of the following main areas:
-
-Assets pane
-: This is a view of all files in your project. Different file types have different icons. Double click on a file to open in in a designated editor for that file type. The special read-only folder *builtins* is common for all projects and include useful items like a default render script, a font, materials for rendering various components and other things.
-
-Main Editor View
-: Depending on which filetype you're editing, this view will show an editor for that type. Most commonly used is the Scene editor that you see here. Each open file is shown in a separate tab.
-
-Changed Files
-: Contains a list of all the edits you have made in your branch since last synchronization. So if you see anything in this pane, you have changes that are not on the server yet. You can open a text-only diff and revert changes through this view.
-
-Outline
-: The content of the currently edited file in a hierarchical view. You can add, delete, modify and select objects and components through this view.
-
-Properties
-: The properties set on the currently selected object or component.
-
-Console
-: When running the game, this view captures output (logging, errors, debug info etc) coming from the game engine, and also any custom `print()` and `pprint()` debug messages from your scripts. If your app or game won't start the console is the first thing to check. Behind the console are a set of tabs displaying error information as well as a curve editor that is used when building particle effects.
-
-## Running the game
-
-The "Empty" project template actually isn't completely empty. As you've already seen, it contains one game object with a simple image. Select <kbd>Project ▸ Build and Launch</kbd> to build the project and launch the game.
-
-![Build and launch](images/car/start_build_and_launch.png)
-
-It's perhaps not very exciting, but it's a running Defold game application and we can easily modify it into something more interesting. So let's do that.
-
-First of all, let's clean the file *main.collection* of the one game object it contains. Select "logo" in the *Outline* view, right-click and select *Delete*. That's it. If you run the game again, the application window will be totally black.
-
-![Delete game object](images/car/start_delete_go.png)
-
-## Assembling the car
-
-The first thing we're going to do is to create a new collection. A collection is a container of game objects that you have placed and put into position. Collections are most commonly used to build game levels but they are very useful whenever you need to reuse groups and/or hierarchies of game objects that belong together. It might be helpful to think about collections as a kind of prefab.
-
-Click on the *main* folder in the *Assets pane*, then right-click and select <kbd>New ▸ Collection File</kbd>. You can also select <kbd>File ▸ New ▸ Collection File</kbd> from the main menu.
-
-![New Collection file](images/car/start_new_collection.png)
-
-Name the new collection file *car.collection* and open it. We're going to use this new, empty collection to build a small car out of a couple of game objects. A game object is a container of components (like sprites, sounds, logic scripts etc) that you use to build your game. Each game object is uniquely identified in the game by its id. Game objects can communicate with each other through message passing, but more on that later.
-
-Also, it's possible to create a game object in place in a collection, as we did here. That results in a one-of-a-kind object. You can copy that object but each copy is separate---changing one does not affect the others. This means that if you create 10 copies of a game object and realize that you want to change them all, you will need to edit all 10 instances of the object. Therefore, in place created game objects should be used for objects that you do not intend to make a lot of copies of.
-
-However, a game object that is stored in a _file_ works as a blueprint. When you place instances of a file stored game object in a collection each object is placed _by reference_---it is a clone based on the blueprint. If you decide you need to change the blueprint, every single placed game object based on that blueprint is instantly updated.
-
-![Add car gameobject](images/car/start_add_car_gameobject.png)
-
-Select the root "Collection" node in the *Outline* view, right-click and select <kbd>Add Game Object</kbd>. A new game object with the id "go" will appear in the collection. Mark it and set its id to "car" in the *Properties* view. So far, "car" is very uninteresting. It is empty, has neither visual representation nor any logic. To add a visual representation, we need to add a sprite _component_.
-
-Components are used to extend game objects with presence (graphics, sound) and functionality (spawn factories, collisions, scripted behaviors). A component can't exist by itself but has to reside inside a game object. Components are usually defined in place in the same file as the game object. However, if you want to reuse a component you can store it in a separate file (like you can with game objects) and include it as a reference in any game object file. Some component types (Lua scripts, for instance) has to be placed in a separate component file and then included as reference in your objects.
-
-Note that you do not manipulate components directly---you can move, rotate, scale and animate properties of game objects that in turn contain components.
-
-![Add car component](images/car/start_add_car_component.png)
-
-Select the "car" game object, right-click and select <kbd>Add Component</kbd>, then select *Sprite* and click *Ok*. If you mark the sprite in the *Outline* view you will see that it needs a few properties set:
-
-Image
-: This requires an image source for the sprite. Create an atlas image file by marking "main" in the *Assets pane* view, right-clicking and selecting <kbd>New ▸ Atlas File</kbd>. Name the new atlas file *sprites.atlas* and double click it to open it in the atlas editor. Save the following two image files to your computer and drag them into *main* in the *Assets pane* view. Now you can mark the Atlas root node in the atlas editor, right click and select <kbd>Add Images</kbd>. Add the car and the tire image to the atlas and save. Now you can select *sprites.atlas* as the image source for the sprite component in the "car" game object in the "car" collection.
-
-Images for our game:
-
-![Car image](images/car/start_car.png)
-![Tire image](images/car/start_tire.png)
-
-Add these images to the atlas:
-
-![Sprites atlas](images/car/start_sprites_atlas.png)
-
-![Sprite properties](images/car/start_sprite_properties.png)
-
-Default Animation
-: Set this to "car" (or whatever you named the car image). Each sprite needs a default animation that is played when it is shown in the game. When you add images to an atlas, Defold conveniently creates one-frame (still) animations for each image file.
-
-## Completing the car
-
-Continue by adding two more game objects in the collection. Call them "left_wheel" and "right_wheel" and put a sprite component in each, showing the tire image that we added to *sprites.atlas*. Then grab the wheel game objects and drop them onto "car" to make them children under "car". Game objects that are children under other game objects will be attached to their parent when the parent moves. They can be moved individually as well, but all motion happens relative to the parent object. For the tires this is perfect since we want them to stick to the car and we can just rotate them slightly left and right as we steer the car. A collection can contain any number of game objects, side by side or arranged into complex parent-child trees, or a mix.
-
-Move the tire game objects into place by selecting them and then choosing <kbd>Scene ▸ Move Tool</kbd>. Grab the arrow handlebars, or the center green square to move the object to a good spot. The final thing we need to do is to make sure that the tires are drawn below the car. We do that by setting the Z component of the position to -0.5. Every visual item in a game is drawn from the back to front, sorted on their Z value. An object with a Z-value of 0 will be drawn on top of an object with a Z-value of -0.5. Since the default Z-value of the car game object is 0, the new value on the tire objects will put them under the car image.
-
-![Car collection complete](images/car/start_car_collection_complete.png)
-
-The last piece of the puzzle is a _script_ to control the car. A script is a component that contains a program that defines game object behaviors. With scripts you can specify the rules of your game, how objects should respond to various interactions (with the player as well as other objects). All scripts are written in the Lua programming language. To be able to work with Defold, you or someone on your team needs to learn how to program in Lua.
-
-Mark "main" in the *Assets pane*, right-click and select <kbd>New ▸ Script File</kbd>. Name the new file *car.script*, then add it to the "car" game object by marking "car" in the *Outline* view, right click and select <kbd>Add Component File</kbd>. Select *car.script* and click *OK*. Save the collection file.
-
-Double click *car.script* and edit the script so it contains the following:
-
-```lua
--- car.script
--- Constants
-local turn_speed = 0.1                           -- Slerp factor
-local max_steer_angle_left = vmath.quat_rotation_z(math.pi / 6)     -- 30 degrees
-local max_steer_angle_right = vmath.quat_rotation_z(-math.pi / 6)   -- -30 degrees
-local wheels_vector = vmath.vector3(0, 72, 0)               -- Vector from center of back and front wheel pairs
-
-function init(self)
-    -- Send a message to the render script (see builtins/render/default.render_script) to set the clear color.
-    -- This changes the background color of the game. The vector4 contains color information
-    -- by channel from 0-1: Red = 0.2. Green = 0.2, Blue = 0.2 and Alpha = 1.0
-    msg.post("@render:", "clear_color", { color = vmath.vector4(0.2, 0.2, 0.2, 1.0) } )
-
-    -- Acquire input focus so we can react to input
-    msg.post(".", "acquire_input_focus")
-
-    -- Some variables
-    self.steer_angle = vmath.quat()
-    self.direction = vmath.quat()
-
-    -- Velocity and acceleration are car relative (not rotated)
-    self.velocity = vmath.vector3()
-    self.acceleration = vmath.vector3()
-end
-
-function update(self, dt)
-    -- Calculate new velocity based on current acceleration
-    self.velocity = self.velocity + self.acceleration * dt
-
-    -- Calculate the new positions of front and back wheels
-    local front_vel = vmath.rotate(self.steer_angle, self.velocity)
-    local new_front_pos = vmath.rotate(self.direction, wheels_vector + front_vel)
-    local new_back_pos = vmath.rotate(self.direction, self.velocity)
-
-    -- Calculate the car's new direction
-    local new_dir = vmath.normalize(new_front_pos - new_back_pos)
-    self.direction = vmath.quat_rotation_z(math.atan2(new_dir.y, new_dir.x) - math.pi / 2)
-
-    -- Update position based on current velocity and direction
-    local pos = go.get_position()
-    pos = pos + vmath.rotate(self.direction, self.velocity)
-    go.set_position(pos)
-
-    -- Set the game object's rotation to the direction
-    go.set_rotation(self.direction)
-end
-
-function on_message(self, message_id, message, sender)
-    if message_id == hash("left") then
-        -- Interpolate the steering angle.
-        self.steer_angle = vmath.slerp(turn_speed, self.steer_angle, max_steer_angle_left)
-        go.set_rotation(self.steer_angle, "left_wheel")
-        go.set_rotation(self.steer_angle, "right_wheel")
-    elseif message_id == hash("right") then
-        -- Interpolate the steering angle.
-        self.steer_angle = vmath.slerp(turn_speed, self.steer_angle, max_steer_angle_right)
-        go.set_rotation(self.steer_angle, "left_wheel")
-        go.set_rotation(self.steer_angle, "right_wheel")
-    elseif message_id == hash("set_acceleration") then
-        -- Set acceleration y component (car relative) to the message data field "acc".
-        self.acceleration.y = message.acc
-    end
-end
-
-function on_input(self, action_id, action)
-    if action_id == hash("left") then
-        msg.post("#", "left")
-    elseif action_id == hash("right") then
-        msg.post("#", "right")
-    elseif action_id == hash("accelerate") and action.value == 1 then
-        msg.post("#", "set_acceleration", { acc = 10 })
-    elseif action_id == hash("accelerate") and action.value == 0 then
-        msg.post("#", "set_acceleration", { acc = 0 })
-    elseif action_id == hash("brake") and action.value == 1 then
-        msg.post("#", "set_acceleration", { acc = -10 })
-    elseif action_id == hash("brake") and action.value == 0 then
-        msg.post("#", "set_acceleration", { acc = 0 })
-    end
-end
-```
-
-Don't forget to save your edits. The script contains 5 parts:
-
-Constants
-: At the top we define a couple of local variables that we use as constants throughout the script. This is optional but usually a good practice since it makes changes of the values easier.
-
-`init()`
-: The function `init()` is run when the game object that the script component exists in is brought to life in the game. This function is usually used to set up internal variables, that we add to the game object "self" that is passed to the function. Any variable added to "self" will be kept through the lifetime of the game object. This script sends two messages during initialization. The first is to the rendering system, which sets the background color for the game. The second message is sent to the game object harboring the script ("." is shorthand for that) asking the game object to start receiving input.
-
-`update()`
-: This function is called once each frame (i.e. 60 times a second) during the lifetime of the game object. We use the function to calculate the speed and direction of the car based on the rotation of the car and the tires. The parameter "dt" is the current timestep (1/60 of a second in this case) and we use that to scale the calculations right. The way steering is computed is an approximation but yields pretty good results if the steering angles are not too extreme. After the calculations, the script updates the position of the game object. This affects all components in the game object (the car body sprite) as well as any child game objects (the tires).
-
-`on_message()`
-: This function is called whenever a message arrives to the script component. We check what message is arriving and take proper action, setting game object variables to new values. If steering left or right, we interpolate with `vmath.slerp()` against the max values, if we are accelerating or decelerating both are handled by the message "set_acceleration" and a message value "acc" with the value of acceleration, positive or negative.
-
-`on_input()`
-: Since this game object listens to input (through the message "acquire_input_focus" in `init()` we receive input actions. Input are mapped from actual key, mouse, touch or game pad input to input "actions". We react to steering, accelerate and brake actions. When these actions arrive we send messages to the script component itself ("#" is shorthand for that) and through the logic in `on_message()` the car reacts. Now, we could just as well have skipped `on_message()` and put all logic straight into `on_input()` but there are benefits to using messages like we do. By allowing the car object to react to messages we can move the input handling to a different place, or perhaps add an AI driver somewhere that could drive the car through messages.
-
-## Input
-
-There is no input actions set up yet, so let's fix that. Open the file */input/game.input_bindings* and add *key_trigger* bindings for "accelerate", "brake", "left" and "right". We set them to the arrow keys (KEY_LEFT, KEY_RIGHT, KEY_UP and KEY_DOWN):
-
-![Input bindings](images/car/start_input_bindings.png)
-
-## Adding the car to the game
-
-Now the car is ready to roll. We have created it inside "car.collection" but it does not yet exist in the game. That is because the engine currently loads "main.collection" on startup. To fix that we simply have to add *car.collection* to *main.collection*. Open *main.collection*, mark the "Collection" root node in the *Outline* view, right-click and select <kbd>Add Collection From File</kbd>, select *car.collection* and click *OK*. Now the contents of the *car.collection* will be placed in *main.collection* as new instances. If you change the content of *car.collection*, each instance of the collection will be updated automatically when the game is built.
-
-![Adding the car collection](images/car/start_adding_car_collection.png)
-
-## Trying the final game
-
-Now, select <kbd>Project ▸ Build And Launch</kbd> from the main menu and take your new car for a spin!
-
-If you want you can try to add more instances of *car.collection* to *main.collection*. Each instance is a clone of what's inside *car.collection* with the exact same behavior. Each one listens to input and reacts to the same messages.
-
-That concludes this introductory tutorial. Now go ahead and dive into Defold. We have lots of [manuals and tutorials](/learn) prepared to guide you, and if you get stuck, you are very welcome to the [forum](//forum.defold.com).
-
-Happy Defolding!

+ 0 - 28
docs/zh/tutorials/colorslide.md

@@ -1,28 +0,0 @@
----
-title: Colorslide tutorial
-brief: In this medium difficulty tutorial you build an in-game GUI, a GUI screen for level selection and a start screen for a simple multi level mobile game.
-github: https://github.com/defold/tutorial-colorslide
----
-
-# Colorslide tutorial
-
-In this medium difficulty tutorial you build an in-game GUI, a GUI screen for level selection and a start screen for a simple multi level mobile game.
-
-The tutorial is integrated with the Defold editor and easily accessible:
-
-1. Start Defold.
-2. Select *New Project* on the left.
-3. Select the *From Tutorial* tab.
-4. Select the "Colorslide tutorial"
-5. Select a location for the project on your local drive and click *Create New Project*.
-
-![new project](images/new-colorslide.png){srcset="images/[email protected] 2x"}
-
-The editor automatically opens the "README" file from the project root, containing the full tutorial text.
-
-![icon](images/icon-tutorial.svg){.icon} [You can also read the full tutorial text on Github](https://github.com/defold/tutorial-colorslide)
-
-If you get stuck, head over to the [Defold Forum](//forum.defold.com) where you will get help from the Defold team and many friendly users.
-
-Happy Defolding!
-

+ 0 - 35
docs/zh/tutorials/getting-started.md

@@ -1,35 +0,0 @@
----
-title: Getting started with Defold
-brief: This tutorial explains how to get started doing tutorials in Defold.
----
-
-# Getting started
-
-The Defold engine and editor are powerful tools with a lot of features and functionality to learn. To help you on your way we have created a variety of tutorials. Many of the tutorials are available directly from within the editor which makes them very easy to get started with.
-
-## Starting a tutorial from the editor
-
-When you run the Defold editor, you are presented with a project selection and creation screen. From here you can easily select which tutorial you want to try out:
-
-1. Start Defold.
-2. Select *New Project* on the left.
-3. Select the *From Tutorial* tab.
-4. Select a tutorial that you are interested in.
-5. Select a location for the project on your local drive.
-6. Click *Create New Project*.
-
-![create project](images/getting-started/new-project.png){srcset="images/getting-started/[email protected] 2x"}
-
-The editor now automatically downloads the tutorial project, opens it in the editor and opens the tutorial text (the "README" file in the project root).
-
-![tutorial text](images/getting-started/tutorial-text.png)
-
-Now follow the tutorial text! If you want to get back to the text, <kbd>double click</kbd> the "README" file in the *Assets* view. You can also <kbd>right click</kbd> the tab of open files and select <kbd>Move to Other Tab Pane</kbd> to view the tutorial text side by side with the file you are working on.
-
-![side by side](images/getting-started/side-by-side.png)
-
-If you are totally new to Defold, you might also want to check out the [editor introduction](/manuals/editor).
-
-If you ever get stuck, please head over to the [Defold Forum](//forum.defold.com) where you will get help from the Defold developers and many friendly users.
-
-Happy Defolding!

+ 0 - 460
docs/zh/tutorials/grading.md

@@ -1,460 +0,0 @@
----
-title: Grading shader tutorial
-brief: In this tutorial you will create a full screen post effect in Defold.
----
-
-# Grading tutorial
-
-In this tutorial we are going to create a color grading  full screen post effect. The basic rendering method used is widely applicable for various types of post effects like blur, trails, glow, color adjustments and so on.
-
-It is assumed that you know your way around the Defold editor, and that you have basic understanding of GL shaders and the Defold rendering pipeline. If you need to read up on these subjects, check out [our Shader manual](/manuals/shader/) and the [Render manual](/manuals/render/).
-
-## Render targets
-
-With the default render script, each visual component (sprite, tilemap, particle effect, GUI etc) is rendered directly to the graphics card's *frame buffer*. The hardware then cause the graphics to appear on the screen. The actual drawing of a component's pixels is done by a GL *shader program*. Defold ships with a default shader program for each component type that draws the pixel data to the screen untouched. Normally, this is the behavior you want---your images should appear on the screen as they were originally conceived.
-
-You can replace a component's shader program with one that modifies the pixel data, or creates wholly new pixel colors programmatically. The [Shadertoy tutorial](/tutorials/shadertoy) teaches you how to do that.
-
-Now let's say that you want to render your whole game in black-and-white. One possible solution is to modify the individual shader program for each components type so that each shader desaturates pixel colors. Currently, Defold ships with 6 built-in materials and 6 vertex and fragment shader program pairs so it will take a fair amount of work. Furthermore, any subsequent changes or effect additions has to be made to each shader program.
-
-A much more flexible approach is to instead do the rendering in two separate steps:
-
-![Render target](images/grading/render_target.png)
-
-1. Draw all components as usual, but draw them to an off-screen buffer instead of the usual frame buffer. You do this by drawing to something called a *render target*.
-2. Draw a square polygon to the frame buffer and use the pixel data stored in the render target as the polygon's texture source. Also make sure that the square polygon is stretched to cover the whole screen.
-
-With this method, we are able to read the resulting visual data and modify it before it hits the screen. By adding shader programs to step 2 above, we can easily achieve full screen effects. Let's see how to set this up in Defold.
-
-## Setting up a custom renderer
-
-We need to modify the built-in render script and add the new rendering functionality. The default render script is a good starting point so start by copying it:
-
-1. Copy */builtins/render/default.render_script*: In the *Asset* view, right click *default.render_script*, select <kbd>Copy</kbd> then right click *main* and select <kbd>Paste</kbd>. Right click the copy and select <kbd>Rename...</kbd> and give it a suitable name, like "grade.render_script".
-2. Create a new render file called */main/grade.render* by right clicking *main* in the *Asset* view and selecting <kbd>New ▸ Render</kbd>.
-3. Open *grade.render* and set its *Script* property to "/main/grade.render_script".
-
-   ![grade.render](images/grading/grade_render.png)
-
-4. Open *game.project* and set *Render* to "/main/grade.render".
-
-   ![game.project](images/grading/game_project.png)
-
-Now the game is set up to run with a new render pipeline that we can modify. To test that our render script copy is used by the engine, run your game, then do a modification to the render script that will give a visual result, and then reload the script. For example, you can disable the drawing of tiles and sprites, then press <kbd>⌘ + R</kbd> to hot-relad the "broken" render script into the running game:
-
-```lua
-...
-
-render.set_projection(vmath.matrix4_orthographic(0, render.get_width(), 0, render.get_height(), -1, 1))
-
--- render.draw(self.tile_pred) -- <1>
-render.draw(self.particle_pred)
-render.draw_debug3d()
-
-...
-```
-1. Comment out drawing of the "tile" predicate, which includes all sprites and tiles. This line of code can be found around line 33 in the render script file.
-
-If the sprites and tiles disappear by this simple test you know that the game runs your render script. If everything works as expected you can undo the change to the render script.
-
-## Drawing to an off-screen target
-
-Now, let's modify the render script so that it draws to the off-screen render target instead of the frame buffer. First we need to create the render target:
-
-```lua
-function init(self)
-    self.tile_pred = render.predicate({"tile"})
-    self.gui_pred = render.predicate({"gui"})
-    self.text_pred = render.predicate({"text"})
-    self.particle_pred = render.predicate({"particle"})
-
-    self.clear_color = vmath.vector4(0, 0, 0, 0)
-    self.clear_color.x = sys.get_config("render.clear_color_red", 0)
-    self.clear_color.y = sys.get_config("render.clear_color_green", 0)
-    self.clear_color.z = sys.get_config("render.clear_color_blue", 0)
-    self.clear_color.w = sys.get_config("render.clear_color_alpha", 0)
-
-    self.view = vmath.matrix4()
-
-    local color_params = { format = render.FORMAT_RGBA,
-                       width = render.get_width(),
-                       height = render.get_height() } -- <1>
-    local target_params = {[render.BUFFER_COLOR_BIT] = color_params }
-
-    self.target = render.render_target("original", target_params) -- <2>
-end
-```
-1. Set up color buffer parmeters for the render target. We use the game's target resolution.
-2. Create the render target with the color buffer parameters.
-
-Now we just need to wrap the original rendering code with `render.enable_render_target()` and `render.disable_render_target()`:
-
-```lua
-function update(self)
-  render.enable_render_target(self.target) -- <1>
-
-  render.set_depth_mask(true)
-  render.set_stencil_mask(0xff)
-  render.clear({[render.BUFFER_COLOR_BIT] = self.clear_color, [render.BUFFER_DEPTH_BIT] = 1, [render.BUFFER_STENCIL_BIT] = 0})
-
-  render.set_viewport(0, 0, render.get_width(), render.get_height()) -- <2>
-  render.set_view(self.view)
-  ...
-
-  render.disable_render_target(self.target) -- <3>
-end
-```
-1. Enable the render target. From now on, every call to `render.draw()` will draw to our off-screen render target's buffers.
-2. All original drawing code in `update()` is left as is, apart from the viewport which is set to the render target's resolution.
-3. At this point, all the game's graphics has been drawn to the render target. So it's time to disable it.
-
-That's all we need to do. If you run the game now it will draw everything to the render target. But since we now drawing nothing to the frame-buffer we will only see a black screen.
-
-## Something to fill the screen with
-
-To draw the pixels in the render target's color buffer onto the screen, we need to set something up that we can texture with the pixel data. For that purpose we are going to use a flat, quadratic 3D model.
-
-Create a quadratic plane mesh in Blender (or any other 3D modelling program). Set the vertex coordinates to -1 and 1 on the X-axis and -1 and 1 on the Y axis. Blender has the Z-axis up by default so you need to rotate the mesh 90° around the X-axis. You should also make sure that you generate correct UV-coordinates for the mesh. In Blender, enter Edit Mode with the mesh selected, then select <kbd>Mesh ▸ UV unwrap... ▸ Unwrap</kbd>.
-
-![game.project](images/grading/quad_blender.png)
-
-1. Export the model as a Collada file called *quad.dae* and drag it into your Defold project.
-2. Open *main.collection* and create a new game object called "grade".
-3. Add a Model component to the "grade" game object.
-3. Set the *Mesh* property of the model component to the *quad.dae* file.
-
-Leave the game object unscaled at origin. Later, when we render the quad we will project it so it fills the whole screen. But first we need a material and shader programs for the quad:
-
-1. Create a new material and call it *grade.material* by right clicking *main* in the *Asset* view and selecting <kbd>New ▸ Material</kbd>.
-2. Create a vertex shader program called *grade.vp* and a fragment shader program called *grade.fp* by right clicking *main* in the *Asset* view and selecting <kbd>New ▸ Vertex program</kbd> and <kbd>New ▸ Fragment program</kbd>.
-3. Open *grade.material* and set the *Vertex program* and *Fragment program* properties to the new shader program files.
-4. Add a *Vertex constant* named "view_proj" of type `CONSTANT_TYPE_VIEWPROJ`. This is the view and projection matrix used in the vertex program for the quad vertices.
-5. Add a *Sampler* called "original". This will be used to sample pixels from the off-screen render target color buffer.
-6. Add a *Tag* called "grade". We will make a new *render predicate* in the render script matching this tag to draw the quad.
-
-   ![grade.material](images/grading/grade_material.png)
-
-7. Open *main.collection*, select the model component in game object "grade" and set its *Material* property to "/main/grade.material".
-
-   ![model properties](images/grading/model_properties.png)
-
-8. The vertex shader program can be left as created from the base template:
-
-    ```glsl
-    // grade.vp
-    uniform mediump mat4 view_proj;
-
-    // positions are in world space
-    attribute mediump vec4 position;
-    attribute mediump vec2 texcoord0;
-
-    varying mediump vec2 var_texcoord0;
-
-    void main()
-    {
-      gl_Position = view_proj * vec4(position.xyz, 1.0);
-      var_texcoord0 = texcoord0;
-    }
-    ```
-
-9. In the fragment shader program, instead of setting `gl_FragColor` to the sampled color value directly, let's perform a simple color manipulation. We do this mainly to make sure everything works as expected so far:
-
-    ```glsl
-    // grade.fp
-    varying mediump vec4 position;
-    varying mediump vec2 var_texcoord0;
-
-    uniform lowp sampler2D original;
-
-    void main()
-    {
-      vec4 color = texture2D(original, var_texcoord0.xy);
-      // Desaturate the color sampled from the original texture
-      float grey = color.r * 0.3 + color.g * 0.59 + color.b * 0.11;
-      gl_FragColor = vec4(grey, grey, grey, 1.0);
-    }
-    ```
-
-Now we have the quad model in place with its material and shaders. We just have to draw it to the screen frame buffer.
-
-## Texturing with the off-screen buffer
-
-We need to add a render predicate to the render script so we can draw the quad model. Open *grade.render_script* and edit the `init()` function:
-
-```lua
-function init(self)
-    self.tile_pred = render.predicate({"tile"})
-    self.gui_pred = render.predicate({"gui"})
-    self.text_pred = render.predicate({"text"})
-    self.particle_pred = render.predicate({"particle"})
-    self.grade_pred = render.predicate({"grade"}) -- <1>
-
-    ...
-end
-```
-1. Add a new predicate matching the "grade" tag that we set in *grade.material*.
-
-After the render target's color buffer has been filled in `update()` we set up a view and a projection that make the quad model fill the whole screen. We then use the render target's color buffer as the quad's texture:
-
-```lua
-function update(self)
-  render.enable_render_target(self.target)
-
-  ...
-
-  render.disable_render_target(self.target)
-
-  render.clear({[render.BUFFER_COLOR_BIT] = self.clear_color}) -- <1>
-
-  render.set_viewport(0, 0, render.get_window_width(), render.get_window_height()) -- <2>
-  render.set_view(vmath.matrix4()) -- <3>
-  render.set_projection(vmath.matrix4())
-
-  render.enable_texture(0, self.target, render.BUFFER_COLOR_BIT) -- <4>
-  render.draw(self.grade_pred) -- <5>
-  render.disable_texture(0, self.target) -- <6>
-end
-```
-1. Clear the frame buffer. Note that the previous call to `render.clear()` affects the render target, not the screen frame buffer.
-2. Set the viewport to match the window size.
-3. Set the view to the identity matrix. This means camera is at origin looking straight along the Z axis. Also set the projection to the identity matrix causing the the quad to be projected flat across the whole screen.
-4. Set texture slot 0 to the color buffer of the render target. We have sampler "original" at slot 0 in our *grade.material* so the fragment shader will sample from the render target.
-5. Draw the predicate we created matching any material with the tag "grade". The quad model uses *grade.material* which sets that tag---thus the quad will be drawn.
-6. After drawing, disable texture slot 0 since we are done drawing with it.
-
-Now let's run the game and see the result:
-
-![desaturated game](images/grading/desaturated_game.png)
-
-## Color grading
-
-Colors are expressed as three component values where each component dictates the amount of red, green or blue a color consist of. The full color spectrum from black, through red, green, blue, yellow and pink to white can be fit into a cube shape:
-
-![color cube](images/grading/color_cube.png)
-
-Any color that can be displayed on screen can be found in this color cube. The basic idea of color grading is to use such a color cube, but with altered colors, as a 3D *lookup table*.
-
-For each pixel:
-
-1. Look up its color's position in the color cube (based on the red, green and blue values).
-2. *Read* what color the graded cube has stored in that location.
-3. Draw the pixel in the read color instead of the original color.
-
-We can do this in our fragment shader:
-
-1. Sample the color value for each pixel in the off-screen buffer.
-2. Look up the color position of the sampled pixel in a color-graded color cube.
-3. Set the output fragment color to the looked up value.
-
-![render target grading](images/grading/render_target_grading.png)
-
-## Representing the lookup table
-
-Open GL ES 2.0 does not support 3D textures so we need to figure out another way to represent the 3D color cube. A common way of doing that is to slice the cube along the Z-axis (blue) and lay each slice side by side in a 2-dimensional grid. Each of the 16 slices contains a 16⨉16 pixel grid. We store this in a texture that we can read from in the fragment shader with a sampler:
-
-![lookup texture](images/grading/lut.png)
-
-The resulting texture contains 16 cells (one for each blue color intensity) and within each cell 16 red colors along the X axis and 16 green colors along the Y axis. The texture represents the whole 16 million color RGB color space in just 4096 colors---merely 4 bits of color depth. By most standards this lousy but thanks to a feature of GL graphics hardware we can get very high color accuracy back. Let's see how.
-
-## Looking up colors
-
-To look up a color is a matter of checking the blue component and figure out which cell to pick the red and green values from. The formula for finding the cell with the right red-green color set is simple:
-
-$$
-cell = \left \lfloor{B \times (N - 1)} \right \rfloor
-$$
-
-Here `B` is the blue component value between 0 and 1 and `N` is the total number of cells. In our case the cell number will be in the range `0`--`15` where cell `0` contains all colors with the blue component at `0` and cell `15` all colors with the blue component at `1`.
-
-For example, the RGB value `(0.63, 0.83, 0.4)` is found in the cell containing all the colors with a blue value of `0.4`, which is cell number 6. Knowing that, the lookup of the final texture coordinates based on the green and red values is straightforward:
-
-![lut lookup](images/grading/lut_lookup.png)
-
-Note that we need to treat red and green values `(0, 0)` as being in the *center* of the bottom left pixel and the values `(1.0, 1.0)` as being in the *center* of the top right pixel.
-
-::: sidenote
-The reason we read starting at the center of the lower left pixel and up to the center of the top right one is that we don't want any pixels outside of the current cell to affect the sampled value. See below about filtering.
-:::
-
-When sampling at these specific coordinates on the texture we see that we end up right between 4 pixels. So what color value will GL tell us that point has?
-
-![lut filtering](images/grading/lut_filtering.png)
-
-The answer depends on how we have specified the sampler's *filtering* in the material.
-
-- If the sampler filtering is `NEAREST`, GL will get return the color value of the nearest pixel value (position value rounded down). In the above case GL will return the color value at position `(0.60, 0.80)`. For our 4 bit lookup texture it means that we will quantize the color values into just 4096 colors in total.
-
-- If the sampler filtering is `LINEAR`, GL will return the *interpolated* color value. GL will mix a color based on the distance to the pixels around the sample position. In the above case, GL will return a color that is 25% of each of the 4 pixels around the sample point.
-
-By using linear filtering we thus eliminate color quantization and get very good color precision out of a pretty small lookup table.
-
-## Implementing the lookup
-
-Let's implement the texture lookup in the fragment shader:
-
-1. Open *grade.material*.
-2. Add a second sampler called "lut" (for lookup table).
-3. Set the *Filter min* property to `FILTER_MODE_MIN_LINEAR` and the *Filter mag* property to `FILTER_MODE_MAG_LINEAR`.
-
-    ![lut sampler](images/grading/material_lut_sampler.png)
-
-4. Download the following lookup table texture (*lut16.png*) and add it to your project.
-
-    ![16 colors lut lookup table](images/grading/lut16.png)
-
-5. Open *main.collection* and set the *lut* texture property to the downloaded lookup texture.
-
-    ![quad model lut](images/grading/quad_lut.png)
-
-6. Finally, open *grade.fp* so we can add support for color lookup:
-
-    ```glsl
-    varying mediump vec4 position;
-    varying mediump vec2 var_texcoord0;
-
-    uniform lowp sampler2D original;
-    uniform lowp sampler2D lut; // <1>
-
-    #define MAXCOLOR 15.0 // <2>
-    #define COLORS 16.0
-    #define WIDTH 256.0
-    #define HEIGHT 16.0
-
-    void main()
-    {
-        vec4 px = texture2D(original, var_texcoord0.xy); // <3>
-
-        float cell = floor(px.b * MAXCOLOR); // <4>
-
-        float half_px_x = 0.5 / WIDTH; // <5>
-        float half_px_y = 0.5 / HEIGHT;
-
-        float x_offset = half_px_x + px.r / COLORS * (MAXCOLOR / COLORS);
-        float y_offset = half_px_y + px.g * (MAXCOLOR / COLORS); // <6>
-
-        vec2 lut_pos = vec2(cell / COLORS + x_offset, y_offset); // <7>
-
-        vec4 graded_color = texture2D(lut, lut_pos); // <8>
-
-        gl_FragColor = graded_color; // <9>
-    }
-    ```
-    1. Declare the sampler `lut`.
-    2. Constants for max color (15 since we start from 0), number of colors per channel and lookup texture width and height.
-    3. Sample a pixel color (called `px`) from the original texture (the off-screen render target color buffer).
-    4. Calculate which cell to read color from based on the blue channel value of `px`.
-    5. Calculate half pixel offsets so we read from pixel centers.
-    6. Calculate the X and Y offset on the texture based on the red and green values of `px`.
-    7. Calculate the final sample position on the lookup texture.
-    8. Sample the resulting color from the lookup texture.
-    9. Set the color on the quad's texture to the resulting color.
-
-Currently, the lookup table texture just returns the same color values that we look up. This means that the game should render with its original coloring:
-
-![world original look](images/grading/world_original.png)
-
-So far it looks like we have done everything right, but there is a problem lurking beneath the surface. Look what happens when we add a sprite with a gradient test texture:
-
-![blue banding](images/grading/blue_banding.png)
-
-The blue gradient shows some really ugly banding. Why is that?
-
-## Interpolating the blue channel
-
-The problem with banding in the blue channel is that GL is unable to perform any blue channel interpolation when reading the color from the texture. We preselect a particular cell to read from based on the blue color value, and that's it. For instance, if the blue channel contains a value anywhere in the range `0.400`--`0.466`, the value does not matter---we will always sample the final color from cell number 6 where the blue channel is set to `0.400`.
-
-To get better blue channel resolution, we can implement the interpolation ourselves. If the blue value is in between the value of two adjacent cells, we can sample from both of these cells and then mix the colors. For example, if the blue value is `0.420` we should sample from cell number 6 *and* from cell number 7 and then mix the colors.
-
-So, we should read from two cells:
-
-$$
-cell_{low} = \left \lfloor{B \times (N - 1)} \right \rfloor
-$$
-
-and:
-
-$$
-cell_{high} = \left \lceil{B \times (N - 1)} \right \rceil
-$$
-
-Then we sample color values from each of these cells and interpolate the colors linearly, according to the formula:
-
-$$
-color = color_{low} \times (1 - C_{frac}) + color_{high} \times C_{frac}
-$$
-
-Here `color`~low~ is the color sampled from the lower (leftmost) cell and `color`~high~ is the color sampled from the higher (rightmost) cell. The GLSL function `mix()` performs this linear interpolation for us.
-
-The value `C`~frac~ above is the fractional part of the blue channel value scaled to the `0`--`15` color range:
-
-$$
-C_{frac} = B \times (N - 1) - \left \lfloor{B \times (N - 1)} \right \rfloor
-$$
-
-Again, there is a GLSL function that gives us the fractional part of a value. It's called `frac()`. The final implementation in the fragment shader (*grade.fp*) is quite straightforward:
-
-```glsl
-varying mediump vec4 position;
-varying mediump vec2 var_texcoord0;
-
-uniform lowp sampler2D original;
-uniform lowp sampler2D lut;
-
-#define MAXCOLOR 15.0
-#define COLORS 16.0
-#define WIDTH 256.0
-#define HEIGHT 16.0
-
-void main()
-{
-  vec4 px = texture2D(original, var_texcoord0.xy);
-
-    float cell = px.b * MAXCOLOR;
-
-    float cell_l = floor(cell); // <1>
-    float cell_h = ceil(cell);
-
-    float half_px_x = 0.5 / WIDTH;
-    float half_px_y = 0.5 / HEIGHT;
-    float r_offset = half_px_x + px.r / COLORS * (MAXCOLOR / COLORS);
-    float g_offset = half_px_y + px.g * (MAXCOLOR / COLORS);
-
-    vec2 lut_pos_l = vec2(cell_l / COLORS + r_offset, g_offset); // <2>
-    vec2 lut_pos_h = vec2(cell_h / COLORS + r_offset, g_offset);
-
-    vec4 graded_color_l = texture2D(lut, lut_pos_l); // <3>
-    vec4 graded_color_h = texture2D(lut, lut_pos_h);
-
-    // <4>
-    vec4 graded_color = mix(graded_color_l, graded_color_h, fract(cell));
-
-    gl_FragColor = graded_color;
-}
-```
-1. Calculate the two adjacent cells to read from.
-2. Calculate two separate lookup positions, one for each cell.
-3. Sample the two colors from the cell positions.
-3. Mix the colors linearly according to the fraction of `cell`, which is the scaled blue color value.
-
-Running the game again with the test texture now yields much better results. The banding on the blue channel is gone:
-
-![blue no banding](images/grading/blue_no_banding.png)
-
-## Grading the lookup texture
-
-Okay, that was a lot of work to draw something that looks exactly like the original game world. But this setup allows us to do something really cool. Hang on now!
-
-1. Take a screenshot of the game in its unaffected form.
-2. Open the screenshot in your favorite image manipulation program.
-3. Apply any number of color adjustments (brightness, contrast, color curves, white balance, exposure etc, etc).
-
-    ![world in Affinity](images/grading/world_graded_affinity.png)
-
-4. Apply the same color adjustments to the lookup table texture file (*lut16.png*).
-5. Save the color adjusted lookup table texture file.
-6. Replace the texture *lut16.png* used in your Defold project with the color adjusted one.
-7. Run the game!
-
-![world graded](images/grading/world_graded.png)
-
-Joy!

+ 0 - 145
docs/zh/tutorials/hud.md

@@ -1,145 +0,0 @@
----
-title: HUD code sample
-brief: In this sample, you learn effects for score counting.
----
-# HUD
-
-<iframe width="560" height="315" src="https://www.youtube.com/embed/bcU9PCrPAeY" frameborder="0" allowfullscreen></iframe>
-
-In this sample, we demonstrate effects for score counting. The scores appear randomly over the screen, simulating a game where the player obtains scores at different positions.
-
-The scores float for a while after they appear. To achieve this, we set the scores to transparent and then fade in their color. We also animate them upwards. This is done in `on_message()` below.
-
-Then they move up to the total score in the top of the screen where they are summed up.
-They are also slightly fading out while moving up. This is done in `float_done()`.
-
-When they have reached the top score, their amounts are added to a target score that the total score counts up towards. This is done in `swoosh_done()`.
-
-When the script is updated, it checks if the target score has been increased and the total score needs to be counted up. When this is true, the total score is incremented by a smaller step.
-The scale of the total score is then animated to give a bouncing effect. This is done in `update()`.
-
-Each time the total is incremented, we spawn an amount of smaller stars and animate them out from the total score. The stars are spawned, animated and deleted in `spawn_stars()`, `fade_out_star()` and `delete_star()`.
-
-```lua
--- file: hud.gui_script
--- how fast the score counts up per second
-local score_inc_speed = 1000
-
-function init(self)
-    -- the target score is the current score in the game
-    self.target_score = 0
-    -- the current score being counted up towards the target score
-    self.current_score = 0
-    -- the score as displayed in the hud
-    self.displayed_score = 0
-    -- keep a reference to the node displaying the score for later use below
-    self.score_node = gui.get_node("score")
-end
-
-local function delete_star(self, star)
-    -- star has finished animation, delete it
-    gui.delete_node(star)
-end
-
-local function fade_out_star(self, star)
-    -- fade out the star before deletion
-    gui.animate(star, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 0), gui.EASING_INOUT, 0.2, 0.0, delete_star)
-end
-
-local function spawn_stars(self, amount)
-    -- position of the score node, to be used for placing the stars
-    local p = gui.get_position(self.score_node)
-    -- distance from the position where the star is spawned
-    local start_distance = 0
-    -- distance where the star stops
-    local end_distance = 240
-    -- angle distance between each star in the star circle
-    local angle_step = 2 * math.pi / amount
-    -- randomize start angle
-    local angle = angle_step * math.random()
-    for i=1,amount do
-        -- increment the angle by the step to get an even distribution of stars
-        angle = angle + angle_step
-        -- direction of the star movement
-        local dir = vmath.vector3(math.cos(angle), math.sin(angle), 0)
-        -- start/end positions of the star
-        local start_p = p + dir * start_distance
-        local end_p = p + dir * end_distance
-        -- create the star node
-        local star = gui.new_box_node(vmath.vector3(start_p.x, start_p.y, 0), vmath.vector3(30, 30, 0))
-        -- set its texture
-        gui.set_texture(star, "star")
-        -- set to transparent
-        gui.set_color(star, vmath.vector4(1, 1, 1, 0))
-        -- fade in
-        gui.animate(star, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_OUT, 0.2, 0.0, fade_out_star)
-        -- animate position
-        gui.animate(star, gui.PROP_POSITION, end_p, gui.EASING_NONE, 0.55)
-    end
-end
-
-function update(self, dt)
-    -- check if the score needs to be updated
-    if self.current_score < self.target_score then
-        -- increment the score for this timestep to grow towards the target score
-        self.current_score = self.current_score + score_inc_speed * dt
-        -- clamp the score so it doesn't grow past the target score
-        self.current_score = math.min(self.current_score, self.target_score)
-        -- floor the score so it can be displayed without decimals
-        local floored_score = math.floor(self.current_score)
-        -- check if the displayed score should be updated
-        if self.displayed_score ~= floored_score then
-            -- update displayed score
-            self.displayed_score = floored_score
-            -- update the text of the score node
-            gui.set_text(self.score_node, string.format("%d p", self.displayed_score))
-            -- set the scale of the score node to be slightly bigger than normal
-            local s = 1.3
-            gui.set_scale(self.score_node, vmath.vector3(s, s, s))
-            -- then animate the scale back to the original value
-            s = 1.0
-            gui.animate(self.score_node, gui.PROP_SCALE, vmath.vector3(s, s, s), gui.EASING_OUT, 0.2)
-            -- spawn stars
-            spawn_stars(self, 4)
-        end
-    end
-end
-
--- this function stores the added score so that the displayed score can be counted up in the update function
-local function swoosh_done(self, node)
-    -- retrieve score from node
-    local amount = tonumber(gui.get_text(node))
-    -- increase the target score, see the update function for how the score is updated to match the target score
-    self.target_score = self.target_score + amount
-    -- remove the temp score
-    gui.delete_node(node)
-end
-
--- this function animates the node from having floated first to swoosh away towards the displayed total score
-local function float_done(self, node)
-    local duration = 0.2
-    -- swoosh away towards the displayed score
-    gui.animate(node, gui.PROP_POSITION, gui.get_position(self.score_node), gui.EASING_IN, duration, 0.0, swoosh_done)
-    -- also fade out partially during the swoosh
-    gui.animate(node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 0.6), gui.EASING_IN, duration)
-end
-
-function on_message(self, message_id, message, sender)
-    -- register added score, this message could be sent by anyone wanting to increment the score
-    if message_id == hash("add_score") then
-        -- create a new temporary score node
-        local node = gui.new_text_node(message.position, tostring(message.amount))
-        -- use the small font for it
-        gui.set_font(node, "small_score")
-        -- initially transparent
-        gui.set_color(node, vmath.vector4(1, 1, 1, 0))
-        gui.set_outline(node, vmath.vector4(0, 0, 0, 0))
-        -- fade in
-        gui.animate(node, gui.PROP_COLOR, vmath.vector4(1, 1, 1, 1), gui.EASING_OUT, 0.3)
-        gui.animate(node, gui.PROP_OUTLINE, vmath.vector4(0, 0, 0, 1), gui.EASING_OUT, 0.3)
-        -- float
-        local offset = vmath.vector3(0, 20, 0)
-        gui.animate(node, gui.PROP_POSITION, gui.get_position(node) + offset, gui.EASING_NONE, 0.5, 0.0, float_done)
-    end
-end
-```

BIN
docs/zh/tutorials/images/15-puzzle/display_settings.png


BIN
docs/zh/tutorials/images/15-puzzle/input.png


BIN
docs/zh/tutorials/images/15-puzzle/main_collection.png


BIN
docs/zh/tutorials/images/15-puzzle/monalisa.png


BIN
docs/zh/tutorials/images/15-puzzle/slide.png


BIN
docs/zh/tutorials/images/15-puzzle/tilemap.png


BIN
docs/zh/tutorials/images/15-puzzle/tilesource.png


BIN
docs/zh/tutorials/images/car/start_add_car_component.png


BIN
docs/zh/tutorials/images/car/start_add_car_gameobject.png


BIN
docs/zh/tutorials/images/car/start_adding_car_collection.png


BIN
docs/zh/tutorials/images/car/start_build_and_launch.png


BIN
docs/zh/tutorials/images/car/start_car.png


BIN
docs/zh/tutorials/images/car/start_car_collection_complete.png


BIN
docs/zh/tutorials/images/car/start_delete_go.png


BIN
docs/zh/tutorials/images/car/start_input_bindings.png


BIN
docs/zh/tutorials/images/car/start_new_collection.png


BIN
docs/zh/tutorials/images/car/start_sprite_properties.png


BIN
docs/zh/tutorials/images/car/start_sprites_atlas.png


BIN
docs/zh/tutorials/images/car/start_tire.png


BIN
docs/zh/tutorials/images/getting-started/new-project.png


BIN
docs/zh/tutorials/images/getting-started/[email protected]


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä