浏览代码

War battles tutorial complete but not proofread.
Rebuilt all tutorial builds and explicitly set engine version on pages.
Fix in 2dgraphics manual.

Mikael Säker 8 年之前
父节点
当前提交
ddf6896ccd
共有 85 个文件被更改,包括 452 次插入27 次删除
  1. 1 1
      docs/assets/car/archive_files.json
  2. 二进制
      docs/assets/car/game.arcd0
  3. 二进制
      docs/assets/car/game.arci0
  4. 二进制
      docs/assets/car/game.darc0
  5. 二进制
      docs/assets/car/game.dmanifest0
  6. 1 0
      docs/assets/car/game.projectc0
  7. 二进制
      docs/assets/car/game.public.der0
  8. 0 0
      docs/assets/dmengine.js
  9. 0 0
      docs/assets/dmengine_1_2_106.js
  10. 1 1
      docs/assets/magic-link/archive_files.json
  11. 二进制
      docs/assets/magic-link/game.arcd0
  12. 二进制
      docs/assets/magic-link/game.arcd1
  13. 二进制
      docs/assets/magic-link/game.arci0
  14. 二进制
      docs/assets/magic-link/game.darc0
  15. 二进制
      docs/assets/magic-link/game.darc1
  16. 二进制
      docs/assets/magic-link/game.dmanifest0
  17. 4 1
      docs/assets/magic-link/game.projectc0
  18. 二进制
      docs/assets/magic-link/game.public.der0
  19. 1 1
      docs/assets/platformer/archive_files.json
  20. 二进制
      docs/assets/platformer/game.arcd0
  21. 二进制
      docs/assets/platformer/game.arcd1
  22. 二进制
      docs/assets/platformer/game.arcd2
  23. 二进制
      docs/assets/platformer/game.arcd3
  24. 二进制
      docs/assets/platformer/game.arcd4
  25. 二进制
      docs/assets/platformer/game.arcd5
  26. 二进制
      docs/assets/platformer/game.arcd6
  27. 二进制
      docs/assets/platformer/game.arci0
  28. 二进制
      docs/assets/platformer/game.darc0
  29. 二进制
      docs/assets/platformer/game.darc1
  30. 二进制
      docs/assets/platformer/game.darc2
  31. 二进制
      docs/assets/platformer/game.darc3
  32. 二进制
      docs/assets/platformer/game.darc4
  33. 二进制
      docs/assets/platformer/game.darc5
  34. 二进制
      docs/assets/platformer/game.darc6
  35. 二进制
      docs/assets/platformer/game.dmanifest0
  36. 二进制
      docs/assets/platformer/game.public.der0
  37. 1 1
      docs/assets/runner/archive_files.json
  38. 二进制
      docs/assets/runner/game.arcd0
  39. 二进制
      docs/assets/runner/game.arcd1
  40. 二进制
      docs/assets/runner/game.arci0
  41. 二进制
      docs/assets/runner/game.darc0
  42. 二进制
      docs/assets/runner/game.dmanifest0
  43. 1 1
      docs/assets/runner/game.projectc0
  44. 二进制
      docs/assets/runner/game.public.der0
  45. 1 1
      docs/assets/shadertoy/archive_files.json
  46. 二进制
      docs/assets/shadertoy/game.dmanifest0
  47. 1 1
      docs/assets/shadertoy/game.projectc0
  48. 二进制
      docs/assets/shadertoy/game.public.der0
  49. 1 1
      docs/assets/side-scroller/archive_files.json
  50. 二进制
      docs/assets/side-scroller/game.arcd0
  51. 二进制
      docs/assets/side-scroller/game.arci0
  52. 二进制
      docs/assets/side-scroller/game.darc0
  53. 二进制
      docs/assets/side-scroller/game.dmanifest0
  54. 二进制
      docs/assets/side-scroller/game.public.der0
  55. 1 0
      docs/assets/war-battles/archive_files.json
  56. 二进制
      docs/assets/war-battles/game.arcd0
  57. 二进制
      docs/assets/war-battles/game.arci0
  58. 二进制
      docs/assets/war-battles/game.dmanifest0
  59. 20 0
      docs/assets/war-battles/game.projectc0
  60. 二进制
      docs/assets/war-battles/game.public.der0
  61. 二进制
      docs/assets/war-battles/preview.jpg
  62. 7 5
      docs/en/manuals/2dgraphics.md
  63. 11 0
      docs/en/manuals/animation.md
  64. 1 1
      docs/en/tutorials/car.md
  65. 二进制
      docs/en/tutorials/images/war-battles/done.png
  66. 二进制
      docs/en/tutorials/images/war-battles/explosion_animation.png
  67. 二进制
      docs/en/tutorials/images/war-battles/fire_rocket_2.png
  68. 二进制
      docs/en/tutorials/images/war-battles/fire_rocket_3.png
  69. 二进制
      docs/en/tutorials/images/war-battles/fire_rockets.png
  70. 二进制
      docs/en/tutorials/images/war-battles/flip_rocket.png
  71. 二进制
      docs/en/tutorials/images/war-battles/main_gui.png
  72. 二进制
      docs/en/tutorials/images/war-battles/rocket_collision.png
  73. 二进制
      docs/en/tutorials/images/war-battles/tank_animation.png
  74. 二进制
      docs/en/tutorials/images/war-battles/tank_collision.png
  75. 二进制
      docs/en/tutorials/images/war-battles/tanks.png
  76. 二进制
      docs/en/tutorials/images/war-battles/text_font.png
  77. 二进制
      docs/en/tutorials/images/war-battles/ui.png
  78. 二进制
      docs/en/tutorials/images/war-battles/ui_script.png
  79. 1 1
      docs/en/tutorials/magic-link.md
  80. 1 1
      docs/en/tutorials/platformer.md
  81. 1 1
      docs/en/tutorials/runner.md
  82. 1 1
      docs/en/tutorials/shadertoy.md
  83. 1 1
      docs/en/tutorials/side-scroller.md
  84. 389 5
      docs/en/tutorials/war-battles.md
  85. 5 2
      docs/sass/preview-md.sass

+ 1 - 1
docs/assets/car/archive_files.json

@@ -1 +1 @@
-{"content":[{"name":"game.projectc","size":228,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.darc","size":22996,"pieces":[{"name":"game.darc0","offset":0}]}]}
+{"content":[{"name":"game.projectc","size":244,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.arci","size":928,"pieces":[{"name":"game.arci0","offset":0}]},{"name":"game.arcd","size":20960,"pieces":[{"name":"game.arcd0","offset":0}]},{"name":"game.dmanifest","size":1553,"pieces":[{"name":"game.dmanifest0","offset":0}]},{"name":"game.public.der","size":162,"pieces":[{"name":"game.public.der0","offset":0}]}]}

二进制
docs/assets/car/game.arcd0


二进制
docs/assets/car/game.arci0


二进制
docs/assets/car/game.darc0


二进制
docs/assets/car/game.dmanifest0


+ 1 - 0
docs/assets/car/game.projectc0

@@ -1,5 +1,6 @@
 [project]
 title = Getting started
+dependencies = 
 
 [bootstrap]
 main_collection = /main/main.collectionc

二进制
docs/assets/car/game.public.der0


文件差异内容过多而无法显示
+ 0 - 0
docs/assets/dmengine.js


文件差异内容过多而无法显示
+ 0 - 0
docs/assets/dmengine_1_2_106.js


+ 1 - 1
docs/assets/magic-link/archive_files.json

@@ -1 +1 @@
-{"content":[{"name":"game.projectc","size":414,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.darc","size":3137432,"pieces":[{"name":"game.darc0","offset":0},{"name":"game.darc1","offset":2097152}]}]}
+{"content":[{"name":"game.projectc","size":455,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.arci","size":3888,"pieces":[{"name":"game.arci0","offset":0}]},{"name":"game.arcd","size":3079673,"pieces":[{"name":"game.arcd0","offset":0},{"name":"game.arcd1","offset":2097152}]},{"name":"game.dmanifest","size":9288,"pieces":[{"name":"game.dmanifest0","offset":0}]},{"name":"game.public.der","size":162,"pieces":[{"name":"game.public.der0","offset":0}]}]}

二进制
docs/assets/magic-link/game.arcd0


二进制
docs/assets/magic-link/game.arcd1


二进制
docs/assets/magic-link/game.arci0


二进制
docs/assets/magic-link/game.darc0


二进制
docs/assets/magic-link/game.darc1


二进制
docs/assets/magic-link/game.dmanifest0


+ 4 - 1
docs/assets/magic-link/game.projectc0

@@ -1,5 +1,5 @@
 [project]
-title = magic_link
+title = Magic Link
 
 [bootstrap]
 main_collection = /main/main.collectionc
@@ -31,3 +31,6 @@ max_count = 512
 [android]
 package = com.example.linker
 
+[library]
+include_dirs = def-magic-link
+

二进制
docs/assets/magic-link/game.public.der0


+ 1 - 1
docs/assets/platformer/archive_files.json

@@ -1 +1 @@
-{"content":[{"name":"game.projectc","size":317,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.darc","size":14546436,"pieces":[{"name":"game.darc0","offset":0},{"name":"game.darc1","offset":2097152},{"name":"game.darc2","offset":4194304},{"name":"game.darc3","offset":6291456},{"name":"game.darc4","offset":8388608},{"name":"game.darc5","offset":10485760},{"name":"game.darc6","offset":12582912}]}]}
+{"content":[{"name":"game.projectc","size":317,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.arci","size":5248,"pieces":[{"name":"game.arci0","offset":0}]},{"name":"game.arcd","size":14497420,"pieces":[{"name":"game.arcd0","offset":0},{"name":"game.arcd1","offset":2097152},{"name":"game.arcd2","offset":4194304},{"name":"game.arcd3","offset":6291456},{"name":"game.arcd4","offset":8388608},{"name":"game.arcd5","offset":10485760},{"name":"game.arcd6","offset":12582912}]},{"name":"game.dmanifest","size":9345,"pieces":[{"name":"game.dmanifest0","offset":0}]},{"name":"game.public.der","size":162,"pieces":[{"name":"game.public.der0","offset":0}]}]}

二进制
docs/assets/platformer/game.arcd0


二进制
docs/assets/platformer/game.arcd1


二进制
docs/assets/platformer/game.arcd2


二进制
docs/assets/platformer/game.arcd3


二进制
docs/assets/platformer/game.arcd4


二进制
docs/assets/platformer/game.arcd5


二进制
docs/assets/platformer/game.arcd6


二进制
docs/assets/platformer/game.arci0


二进制
docs/assets/platformer/game.darc0


二进制
docs/assets/platformer/game.darc1


二进制
docs/assets/platformer/game.darc2


二进制
docs/assets/platformer/game.darc3


二进制
docs/assets/platformer/game.darc4


二进制
docs/assets/platformer/game.darc5


二进制
docs/assets/platformer/game.darc6


二进制
docs/assets/platformer/game.dmanifest0


二进制
docs/assets/platformer/game.public.der0


+ 1 - 1
docs/assets/runner/archive_files.json

@@ -1 +1 @@
-{"content":[{"name":"game.projectc","size":375,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.darc","size":1595204,"pieces":[{"name":"game.darc0","offset":0}]}]}
+{"content":[{"name":"game.projectc","size":378,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.arci","size":6448,"pieces":[{"name":"game.arci0","offset":0}]},{"name":"game.arcd","size":2144408,"pieces":[{"name":"game.arcd0","offset":0},{"name":"game.arcd1","offset":2097152}]},{"name":"game.dmanifest","size":14545,"pieces":[{"name":"game.dmanifest0","offset":0}]},{"name":"game.public.der","size":162,"pieces":[{"name":"game.public.der0","offset":0}]}]}

二进制
docs/assets/runner/game.arcd0


二进制
docs/assets/runner/game.arcd1


二进制
docs/assets/runner/game.arci0


二进制
docs/assets/runner/game.darc0


二进制
docs/assets/runner/game.dmanifest0


+ 1 - 1
docs/assets/runner/game.projectc0

@@ -2,7 +2,7 @@
 title = platformer
 
 [bootstrap]
-main_collection = /main/main.collectionc
+main_collection = /level/level1.collectionc
 
 [input]
 game_binding = /input/game.input_bindingc

二进制
docs/assets/runner/game.public.der0


+ 1 - 1
docs/assets/shadertoy/archive_files.json

@@ -1 +1 @@
-{"content":[{"name":"game.projectc","size":237,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.arci","size":848,"pieces":[{"name":"game.arci0","offset":0}]},{"name":"game.arcd","size":2296,"pieces":[{"name":"game.arcd0","offset":0}]},{"name":"game.dmanifest","size":1438,"pieces":[{"name":"game.dmanifest0","offset":0}]},{"name":"game.public.der","size":162,"pieces":[{"name":"game.public.der0","offset":0}]}]}
+{"content":[{"name":"game.projectc","size":236,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.arci","size":848,"pieces":[{"name":"game.arci0","offset":0}]},{"name":"game.arcd","size":2296,"pieces":[{"name":"game.arcd0","offset":0}]},{"name":"game.dmanifest","size":1438,"pieces":[{"name":"game.dmanifest0","offset":0}]},{"name":"game.public.der","size":162,"pieces":[{"name":"game.public.der0","offset":0}]}]}

二进制
docs/assets/shadertoy/game.dmanifest0


+ 1 - 1
docs/assets/shadertoy/game.projectc0

@@ -1,5 +1,5 @@
 [project]
-title = My project
+title = Shadertoy
 version = 0.1
 
 [bootstrap]

二进制
docs/assets/shadertoy/game.public.der0


+ 1 - 1
docs/assets/side-scroller/archive_files.json

@@ -1 +1 @@
-{"content":[{"name":"game.projectc","size":226,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.darc","size":1492624,"pieces":[{"name":"game.darc0","offset":0}]}]}
+{"content":[{"name":"game.projectc","size":226,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.arci","size":3168,"pieces":[{"name":"game.arci0","offset":0}]},{"name":"game.arcd","size":1519171,"pieces":[{"name":"game.arcd0","offset":0}]},{"name":"game.dmanifest","size":5779,"pieces":[{"name":"game.dmanifest0","offset":0}]},{"name":"game.public.der","size":162,"pieces":[{"name":"game.public.der0","offset":0}]}]}

二进制
docs/assets/side-scroller/game.arcd0


二进制
docs/assets/side-scroller/game.arci0


二进制
docs/assets/side-scroller/game.darc0


二进制
docs/assets/side-scroller/game.dmanifest0


二进制
docs/assets/side-scroller/game.public.der0


+ 1 - 0
docs/assets/war-battles/archive_files.json

@@ -0,0 +1 @@
+{"content":[{"name":"game.projectc","size":236,"pieces":[{"name":"game.projectc0","offset":0}]},{"name":"game.arci","size":1888,"pieces":[{"name":"game.arci0","offset":0}]},{"name":"game.arcd","size":143174,"pieces":[{"name":"game.arcd0","offset":0}]},{"name":"game.dmanifest","size":3184,"pieces":[{"name":"game.dmanifest0","offset":0}]},{"name":"game.public.der","size":162,"pieces":[{"name":"game.public.der0","offset":0}]}]}

二进制
docs/assets/war-battles/game.arcd0


二进制
docs/assets/war-battles/game.arci0


二进制
docs/assets/war-battles/game.dmanifest0


+ 20 - 0
docs/assets/war-battles/game.projectc0

@@ -0,0 +1,20 @@
+[project]
+title = My project
+version = 0.1
+
+[bootstrap]
+main_collection = /main/main.collectionc
+
+[input]
+game_binding = /input/game.input_bindingc
+
+[display]
+width = 720
+height = 720
+
+[physics]
+scale = 0.02
+
+[script]
+shared_state = 1
+

二进制
docs/assets/war-battles/game.public.der0


二进制
docs/assets/war-battles/preview.jpg


+ 7 - 5
docs/en/manuals/2dgraphics.md

@@ -193,15 +193,17 @@ You can attach physics to the Tile Map to do collision detection or physics simu
 
 ## Changing tiles from script
 
-You can change the content of a Tile Map dynamically while your game is running. To do so, send [`set_tile`](/ref/tilemap#set_tile) messages to the Tile Map:
+You can change the content of a Tile Map dynamically while your game is running. To do so, call the [`tilemap.set_tile()`](/ref/tilemap/#tilemap.set_tile) function:
 
 ```lua
 -- Replace the two door-tiles with "open door" tiles.
 -- The door is two tiles, one on top of the other.
-local doorpos = vmath.vector3(174, 305, 0)
-msg.post("/level#tilemap", "set_tile", { layer_id = hash("layer1"), position = doorpos, tile = 58 })
--- Upper part of door can be adressed with same position and "dy" set to 1.
-msg.post("/level#tilemap", "set_tile", { layer_id = hash("layer1"), position = doorpos, tile = 46, dy = 1 })
+local x = 3
+local y = 4
+-- Lower part of door
+tilemap.set_tile("/level#tilemap", "layer1", x, y, 58)
+-- Upper part of door
+tilemap.set_tile("/level#tilemap", "layer1", x, y+1, 46)
 ```
 
 ## Adding a Tile Map to your game

+ 11 - 0
docs/en/manuals/animation.md

@@ -335,6 +335,17 @@ The corresponding value to use when calling `go.animate()` are `go.EASING_LINEAR
 
 For `gui.animate()` the values are named `gui.EASING_LINEAR`, `gui.EASING_INBACK`, `gui.EASING_OUTBACK` and so forth.
 
+```linechart
+{
+  "labels": [1, "Tuesday", "Wednesday", "Thursday", "Friday"],
+  "series": [
+    [12, 9, 7, 8, 5],
+    [2, 1, 3.5, 7, 3],
+    [1, 3, 4, 5, 6]
+  ]
+}
+```
+
 ![Linear interpolation](images/properties/easing_linear.png){.inline}
 ![In back](images/properties/easing_inback.png){.inline}
 ![Out back](images/properties/easing_outback.png){.inline}

+ 1 - 1
docs/en/tutorials/car.md

@@ -241,7 +241,7 @@ Now, select <kbd>Project ▸ Build And Launch</kbd> from the main menu and take
     </button>
     <script src="//storage.googleapis.com/defold-doc/assets/dmloader.js">
     </script>
-    <script src="//storage.googleapis.com/defold-doc/assets/dmengine.js" async>
+    <script src="//storage.googleapis.com/defold-doc/assets/dmengine_1_2_106.js" async>
     </script>
     <script>
         /* Load app on click in container. */

二进制
docs/en/tutorials/images/war-battles/done.png


二进制
docs/en/tutorials/images/war-battles/explosion_animation.png


二进制
docs/en/tutorials/images/war-battles/fire_rocket_2.png


二进制
docs/en/tutorials/images/war-battles/fire_rocket_3.png


二进制
docs/en/tutorials/images/war-battles/fire_rockets.png


二进制
docs/en/tutorials/images/war-battles/flip_rocket.png


二进制
docs/en/tutorials/images/war-battles/main_gui.png


二进制
docs/en/tutorials/images/war-battles/rocket_collision.png


二进制
docs/en/tutorials/images/war-battles/tank_animation.png


二进制
docs/en/tutorials/images/war-battles/tank_collision.png


二进制
docs/en/tutorials/images/war-battles/tanks.png


二进制
docs/en/tutorials/images/war-battles/text_font.png


二进制
docs/en/tutorials/images/war-battles/ui.png


二进制
docs/en/tutorials/images/war-battles/ui_script.png


+ 1 - 1
docs/en/tutorials/magic-link.md

@@ -17,7 +17,7 @@ This tutorial is written as a step-by-step guide where we build the game on a co
         START GAME <span class="icon"></span>
     </button>
     <script src="//storage.googleapis.com/defold-doc/assets/dmloader.js"></script>
-    <script src="//storage.googleapis.com/defold-doc/assets/dmengine.js" async></script>
+    <script src="//storage.googleapis.com/defold-doc/assets/dmengine_1_2_106.js" async></script>
     <script>
         /* Load app on click in container. */
         document.getElementById("game-button").onclick = function (e) {

+ 1 - 1
docs/en/tutorials/platformer.md

@@ -15,7 +15,7 @@ In this article, we go through the implementation of a basic tile-based 2D platf
     START GAME <span class="icon"></span>
   </button>
   <script src="//storage.googleapis.com/defold-doc/assets/dmloader.js"></script>
-  <script src="//storage.googleapis.com/defold-doc/assets/dmengine.js" async></script>
+  <script src="//storage.googleapis.com/defold-doc/assets/dmengine_1_2_106.js" async></script>
   <script>
       /* Load app on click in container. */
       document.getElementById("game-button").onclick = function (e) {

+ 1 - 1
docs/en/tutorials/runner.md

@@ -15,7 +15,7 @@ In this tutorial we start with an empty project and build a complete runner game
     START GAME <span class="icon"></span>
   </button>
   <script type='text/javascript' src="//storage.googleapis.com/defold-doc/assets/dmloader.js"></script>
-  <script type='text/javascript' src="//storage.googleapis.com/defold-doc/assets/dmengine.js" async></script>
+  <script type='text/javascript' src="//storage.googleapis.com/defold-doc/assets/dmengine_1_2_106.js" async></script>
   <script type='text/javascript'>
       /* Load app on click in container. */
       document.getElementById("game-button").onclick = function (e) {

+ 1 - 1
docs/en/tutorials/shadertoy.md

@@ -255,7 +255,7 @@ You can view the results here:
     START GAME <span class="icon"></span>
   </button>
   <script type='text/javascript' src="//storage.googleapis.com/defold-doc/assets/dmloader.js"></script>
-  <script type='text/javascript' src="//storage.googleapis.com/defold-doc/assets/dmengine_1_2_103.js" async></script>
+  <script type='text/javascript' src="//storage.googleapis.com/defold-doc/assets/dmengine_1_2_106.js" async></script>
   <script type='text/javascript'>
       /* Load app on click in container. */
       document.getElementById("game-button").onclick = function (e) {

+ 1 - 1
docs/en/tutorials/side-scroller.md

@@ -17,7 +17,7 @@ The game is extremely simple. The player controls a space ship and is supposed t
     START GAME <span class="icon"></span>
   </button>
   <script src="//storage.googleapis.com/defold-doc/assets/dmloader.js"></script>
-  <script src="//storage.googleapis.com/defold-doc/assets/dmengine.js" async></script>
+  <script src="//storage.googleapis.com/defold-doc/assets/dmengine_1_2_106.js" async></script>
   <script>
       /* Load app on click in container. */
       document.getElementById("game-button").onclick = function (e) {

+ 389 - 5
docs/en/tutorials/war-battles.md

@@ -7,6 +7,37 @@ brief: In this tutorial you will create a small shooter game. This is a good sta
 
 This tutorial goes through all the steps needed to create a small playable game in Defold. You do not need to have any prior experience with Defold, but if you have done some programming in Lua, Javascript, Python or similar, that will help.
 
+To get an idea about what you will build, you can try the result here:
+
+<div id="game-container" class="game-container">
+    <img id="game-preview" src="//storage.googleapis.com/defold-doc/assets/war-battles/preview.jpg"/>
+    <canvas id="game-canvas" tabindex="1" width="720" height="720">
+    </canvas>
+    <button id="game-button">
+        START GAME <span class="icon"></span>
+    </button>
+    <script src="//storage.googleapis.com/defold-doc/assets/dmloader.js"></script>
+    <script src="//storage.googleapis.com/defold-doc/assets/dmengine_1_2_106.js" async></script>
+    <script>
+        /* Load app on click in container. */
+        document.getElementById("game-button").onclick = function (e) {
+            var extra_params = {
+                archive_location_filter: function( path ) {
+                    return ("//storage.googleapis.com/defold-doc/assets/war-battles" + path + "");
+                },
+                load_done: function() {},
+                game_start: function() {
+                    var e = document.getElementById("game-preview");
+                    e.parentElement.removeChild(e);
+                }
+            }
+            Module.runApp("game-canvas", extra_params);
+            document.getElementById("game-button").style.display = 'none';
+            document.getElementById("game-button").onclick = null;
+        };
+    </script>
+</div>
+
 ## Setting up the project
 
 You need to create an empty project in Defold and download the asset package.
@@ -265,9 +296,9 @@ Consider the main collection for a second. Now it contains two game objects: the
 
 1. <kbd>Right click</kbd> the folder *main* in the *Assets* view and select <kbd>New ▸ Game object</kbd>. Name this file *rocket.go*. Note that by creating this file, you do not create a game object but a file can be used as a *blueprint* when creating an actual game object.
 
-2. Drag the folder *buildings/turret-rocket* in the asset package to the *main* folder in the *Assets* view.
+2. Drag the folder *buildings/turret-rocket* from the asset package to the *main* folder in the *Assets* view.
 
-3. Open *sprites.atlas* and create a new animation group (right click the root node and select <kbd>New ▸ Animation group</kbd>).
+3. Open *sprites.atlas* and create a new animation group (right click the root node and select <kbd>New ▸ Animation group</kbd>). Name the animation "rocket".
 
 4. Add the three rocket images to the animation group and set the *Fps* property to a value that makes the animation look good when you preview.
 
@@ -291,20 +322,373 @@ Now you have a basic rocket game object blueprint. The next step is to add funct
 
     ![input](images/war-battles/input_bindings_fire.png)
 
-5. Open *main/player.script* and scroll down to the `on_input()` function. Add a fourth `elseif` for the case where the function is called with the "fire" action:
+5. Open *main/player.script* and add a flag to track if the player is firing in the `init()` function:
+
+    ```lua
+    function init(self)
+        msg.post("#", "acquire_input_focus")
+    
+        self.moving = false
+        self.firing = false -- <1>
+        
+        self.input = vmath.vector3()
+        self.dir = vmath.vector3(0, 1, 0)
+        self.speed = 50
+    end
+    ```
+    1. Whenever the player is firing this value will be set to `true`.
+
+6. Add what should happen when the flag is set in `update()`. The factory should create a new game object instance:
+
+    ```lua
+    function update(self, dt)
+        if self.moving then
+            local pos = go.get_position()
+            pos = pos + self.dir * self.speed * dt
+            go.set_position(pos)
+        end
+        
+        if self.firing then
+            factory.create("#rocketfactory") -- <1>
+        end
+        
+        self.input.x = 0
+        self.input.y = 0
+        
+        self.moving = false
+        self.firing = false -- <2>
+    end
+    ```
+    1. If the `firing` flag is true, tell the factory component called "rocketfactory" that you just created to spawn a new game object.
+    2. Set the flag to false. This flag will be set in `on_input()` each frame the player presses the fire key.
+
+7. Scroll down to the `on_input()` function. Add a fourth `elseif` for the case where the function is called with the "fire" action:
 
     ```lua
         ...
         elseif action_id == hash("right") then
             self.input.x = 1
         elseif action_id == hash("fire") and action.pressed then
-            factory.create("#rocketfactory")
+            self.firing = true
+        end
+        ...
+    ```
+
+If you run the game now you should be able to move around and drop rockets all over the map by hammering the fire key. This is a good start, now you only need to fix three things:
+
+1. When the rocket is spawned, it should be oriented in the player's direction and it should move straight ahead.
+2. The rocket should explode after a second or so.
+
+Let's do these things one by one:
+
+## Setting the direction of the rocket
+
+1. Open *main/player.script* and scroll down to the `on_input()` function.
+
+    ```lua
+        ...
+        elseif action_id == hash("right") then
+            self.input.x = 1
+        elseif action_id == hash("fire") and action.pressed then
+            local angle = math.atan2(self.dir.y, self.dir.x) -- <1>
+            local rot = vmath.quat_rotation_z(angle) -- <2>
+            local props = { dir = self.dir } -- <3>
+            factory.create("#rocketfactory", nil, rot, props) -- <4>
         end
 
         ...
     ```
+    1. Compute the angle (in radians) of the player.
+    2. Create a quaternion for that angular rotation around Z.
+    3. Create a table containing property values to pass to the rocket. The player's direction is the only data the rocket needs.
+    3. Add explicit position (`nil`, the rocket will spawn at the player's position), rotation (the calculated quaternion) and spawn property values.
+
+    Note that the rocket needs a movement direction in addition to the game object rotation (`rot`). It would be possible to make the rocket calculate its movement vector based on its rotation, but it is easier and more flexible to separate the two values. For instance, with a separate rotation it is possible to add rotation wobble to the rocket without it affecting the movement direction.
 
+3.  <kbd>Right click</kbd> the folder *main* in the *Assets* view and select <kbd>New ▸ Script</kbd>. Name the new script file "rocket.script". Replace the code of the file with the following:
+
+    ```lua
+    go.property("dir", vmath.vector3()) -- <1>
+    
+    function init(self)
+        self.speed = 200 -- <2>
+    end
+    
+    function update(self, dt)
+        local pos = go.get_position() -- <3>
+        pos = pos + self.dir * self.speed * dt -- <4>
+        go.set_position(pos) -- <5>
+    end
+    ```
+    1. Define a new script property named `dir` and initialize the property with a default empty vector (`vmath.vector3()`). The default value can be overrided by passing values to the `factory.create()` function. The current property value is accessed as `self.dir`.
+    2. A rocket speed value, expressed in pixels per second.
+    3. Get the current rocket position.
+    4. Calculate a new position based on the old position, the movement direction (unit vector) and the speed.
+    5. Set the new position.
+
+4. Open *rocket.go* and <kbd>Right click</kbd> the root in the *Outline* and select <kbd>Add component ▸ Script</kbd>. Select "rocket.script" for the component.
+
+5. Run the game and try the new mechanic. Notice that the rockets fly in the right direction but are oriented 180 degrees wrong.
+
+    ![fire rockets](images/war-battles/fire_rockets.png)
+
+6. Open *sprites.atlas*, select the "rocket" animation and click the *Flip horizontal* property.
+
+    ![flip rocket](images/war-battles/flip_rocket.png)
+
+7. Run the game again to verify that everything looks ok.
+
+    ![fire rockets](images/war-battles/fire_rocket_2.png)
+
+Now you only need to make the rockets explode.
 
 ## Explosions
 
-## 
+1. Drag the folder *fx/explosion* from the asset package to the main folder in the Assets view.
+
+2. Open *sprites.atlas* and create a new animation group (right click the root node and select <kbd>New ▸ Animation group</kbd>). Call the animation "explosion".
+
+3. Add the nine explosion images to the animation group and set the *Fps* property to a value that makes the animation look good when you preview. Also make sure that this animation has the *Playback* property set to `Once Forward`.
+
+    ![explosion animation](images/war-battles/explosion_animation.png)
+
+4. Open *main/rocket.script* and scroll down to the `init()` function and change it to:
+
+    ```lua
+    function init(self)
+        self.speed = 200
+        self.life = 1 -- <1>
+    end
+    ```
+    1. This value will act as a timer to track the lifetime of the rocket.
+
+5. Scroll down to the `update()` function and change it to:
+
+    ```lua
+    function update(self, dt)
+        local pos = go.get_position()
+        pos = pos + self.dir * self.speed * dt
+        go.set_position(pos)
+        
+        self.life = self.life - dt -- <1>
+        if self.life < 0 then -- <2>
+            self.life = 1000 -- <3>
+            go.set_rotation(vmath.quat()) -- <4>
+            self.speed = 0 -- <5>
+            msg.post("#sprite", "play_animation", { id = hash("explosion") }) -- <6>
+        end
+    end
+    ```
+    1. Decrease the life timer with delta time. It will decrease with 1.0 per second.
+    2. When the life timer has reached zero.
+    3. Set the life timer to a large value so this code won't run every subsequent update.
+    4. Set the game object rotation to 0, otherwise the explosion graphics will be rotated.
+    5. Set the movement speed to 0, otherwise the explosion graphics will move.
+    6. Play the "explosion" animation on the game object's "sprite" component.
+
+6. Below the `update()` function, add a new `on_message()` function:
+
+    ```lua
+    function on_message(self, message_id, message, sender) -- <1>
+        if message_id == hash("animation_done") then -- <2>
+            go.delete() -- <3>
+        end 
+    end
+    ```
+    1. The function `on_message()` gets called whenever a message is posted to this script component.
+    2. If the message posted has the hashed name (or id) "animation_done", then. The engine runtime sends back this message when a sprite animation initiated with "play_animation" has finished playing.
+    3. When the animation is done, delete the current game object.
+
+Run the game. Now it starts feeling like the embryo for a nice little game, don't you think?
+
+![fire rockets](images/war-battles/fire_rocket_3.png)
+
+But now you need something to fire the rockets at. Enter tanks!
+
+## The tank game object
+
+1. <kbd>Right click</kbd> the folder *main* in the *Assets* view and select <kbd>New ▸ Game object</kbd>. Name this file *tank.go*. Like the rocket game object, this is a file that can be used as a *blueprint* when creating the actual tank game objects.
+
+2. Drag the folder *units/tank* from the asset package to the *main* folder in the *Assets* view.
+
+3. Open *sprites.atlas* and create a new animation group (right click the root node and select <kbd>New ▸ Animation group</kbd>). Name the animation "tank-down".
+
+4. Add the two downwards facing images (*/main/tank/down/1.png* and */main/tank/down/2.png*) to the animation and set it's *Fps* value to something that looks good.
+
+    ![tank animation](images/war-battles/tank_animation.png)
+
+5. Open *tank.go* and <kbd>Right click</kbd> the root in the *Outline* and select <kbd>Add component ▸ Sprite</kbd>.
+
+6. Set the *Image* property of the sprite to "/main/sprites.atlas" and the *Default animation* to "tank-down".
+
+7. Open *main.collection*
+
+8. <kbd>Right click</kbd> the root node of the collection in the *Outline* and select <kbd>Add Game Object File</kbd>. Select *tank.go* as blueprint for the new game object.
+
+9. Create a few more tanks and position them on the map with the *Move Tool*. Make sure to set the Z position to 1.0 so they are rendered on top of the map.
+
+    ![tanks](images/war-battles/tanks.png)
+
+Run the game and check that the tanks look okay. You will notice that the rockets fly straight through the tanks so the next step is to add collision between the tanks and the rockets. To do this you need to add a new component to the tank and the rocket game object:
+
+## Adding collision objects
+
+1. Open *tank.go* and <kbd>Right click</kbd> the root in the *Outline* and select <kbd>Add component ▸ Collision Object</kbd>.
+
+2. Set the *Type* property to "Kinematic". This means that the physics engine will not simulate any gravity or collision on this object. Instead it will detect collisions and leave it to you to code the response.
+
+3. Set the *Group* property to "tanks" and *Mask* to "rockets". This causes this game object to detect collisions against object in the group "rockets" that has the mask set to "tanks".
+
+4. <kbd>Right click</kbd> the "collisionobject" component in the *Outline* and select <kbd>Add Shape ▸ Box</kbd>. Set the size of the box shape to match the tank graphics.
+
+    ![tank collision](images/war-battles/tank_collision.png)
+
+6. Open *rocket.go* and <kbd>Right click</kbd> the root in the *Outline* and select <kbd>Add component ▸ Collision Object</kbd>.
+
+7. Set the *Type* property to "Kinematic".
+
+8. Set the *Group* property to "rockets" and *Mask* to "tanks". This causes this game object to detect collisions against object in the group "tanks" that has the mask set to "rockets". Since that is what you set the group and mask to in *tank.go* the rockets and tanks will interact physically.
+
+    ![rocket collision](images/war-battles/rocket_collision.png)
+
+Now the engine will detect when these game objects intersect and send messages to them when that happens. The last piece of the puzzle is an addition to the rocket's script.
+
+## Reacting to collisions
+
+1. Open *rocket.script* and scroll down to the `update()` function. There are a couple of things to do here:
+
+    ```lua
+    local function explode(self) -- <1>
+        self.life = 1000
+        go.set_rotation(vmath.quat())
+        self.speed = 0
+        msg.post("#sprite", "play_animation", { id = hash("explosion") })       
+    end
+    
+    function update(self, dt)
+        local pos = go.get_position()
+        pos = pos + self.dir * self.speed * dt
+        go.set_position(pos)
+        
+        self.life = self.life - dt
+        if self.life < 0 then
+            explode(self) -- <2>
+        end
+    end
+    
+    function on_message(self, message_id, message, sender)
+        if message_id == hash("animation_done") then
+            go.delete()
+        elseif message_id == hash("collision_response") then -- <3>
+            explode(self) -- <4>
+            go.delete(message.other_id) -- <5>
+        end
+    end
+    ```
+    1. Since you want the rocket to explode either when the timer runs out (in `update()`) or when the rocket hits a tank (in `on_message()`) you should break out that piece of code to avoid duplication. There are a few options, the easiest is probably to just create a local function. The function is declared `local` meaning it only exist for the rocket script. Therefore it must be placed before it is used, above `update()`, this is how Lua's scoping rules work. Also note that you should pass `self` as a parameter to the function to be able to access `self.life` etc.
+    2. The code that used to live here has been moved to the `explode()` function.
+    3. The engine sends a message called "collision_response" when the shapes collide, if the group and mask pairing is correct.
+    4. Call the `explode()` function if there is a collision.
+    5. Finally delete the tank. You get the id of the game object the rocket collided with in the `message.other_id` variable.
+
+And now you can run the game and try to destroy some tanks. The tanks aren't very interesting enemies, but they should nevertheless give you some score.
+
+## Scoring GUI
+
+1. Drag the the file *fonts/04B_03.TTF* from the asset pack folder to the *main* folder in the *Assets* view.
+
+2. <kbd>Right click</kbd> the folder *main* in the *Assets* view and select <kbd>New ▸ Font</kbd>. Name this file *text.font*.
+
+    ![text font](images/war-battles/text_font.png)
+
+3. <kbd>Right click</kbd> the folder *main* in the *Assets* view and select <kbd>New ▸ Gui</kbd>. Name this file *ui.gui*. It will contain the user interface where you will place the score counter.
+
+4. Open *ui.gui*. <kbd>Right click</kbd> *Fonts* in the *Outline* view and select <kbd>Add ▸ Fonts</kbd>. Select the */main/text.font* file.
+
+5. <kbd>Right click</kbd> *Nodes* in the *Outline* view and select <kbd>Add ▸ Text</kbd>.
+
+6. Select the new text node in the outline and set its *Id* property to "score", its *Text* property to "SCORE: 0", its *Font* property to the font "text" and its *Pivot* property to "West".
+
+7. Place the text node in the top left corner of the screen.
+
+    ![ui gui](images/war-battles/ui.png)
+
+8. <kbd>Right click</kbd> the folder *main* in the *Assets* view and select <kbd>New ▸ Gui Script</kbd>. Name this file *ui.gui_script*.
+
+9. Go back to *ui.gui* and select the root node in the *Outline*. Set the *Script* property to the file */main/ui.gui_script* that you just created. Now if we add this Gui as a component to a game object the script will run for the component.
+
+10. Open *main.collection*.
+
+11. <kbd>Right click</kbd> the root node of the collection in the *Outline* and select <kbd>Add game object</kbd>.
+
+11. Set the id of the game object to "gui", then <kbd>Right click</kbd> it and select <kbd>Add Component File</kbd>. Select the file */main/ui.gui*.
+
+    ![main gui](images/war-battles/main_gui.png)
+
+Now there is a score counter on screen. You only need to add functionality in the Gui script so the score can be updated.
+
+## Updating the score
+
+1. Open *ui.gui_script*
+
+2. Replace the template code with the following:
+
+    ```lua
+    function init(self)
+        self.score = 0 -- <1>
+    end
+    
+    function on_message(self, message_id, message, sender)
+        if message_id == hash("add_score") then -- <2>
+            self.score = self.score + message.score -- <3>
+            local scorenode = gui.get_node("score") -- <4>
+            gui.set_text(scorenode, "SCORE: " .. self.score) -- <5>
+        end 
+    end
+    ```
+    1. Store the current score in `self`. Start from 0.
+    2. Reaction to a message named "add_score".
+    3. Increase the current score value in `self` with the value passed in the message.
+    4. Get hold of the text node named "score" that you created in the Gui.
+    5. Update the text of the node to the string "SCORE: " and the current score value concatenated to the end of the string.
+
+3. Open *rocket.script* and scroll down to the `on_message()` function where you need to add a line of code:
+
+    ```lua
+    function on_message(self, message_id, message, sender)
+        if message_id == hash("animation_done") then
+            go.delete()
+        elseif message_id == hash("collision_response") then
+            explode(self)
+            go.delete(message.other_id)
+            msg.post("/gui#gui", "add_score", {score = 100}) -- <1>
+        end
+    end
+    ```
+    1. Post a message named "add_score" to the component "gui" in the game object named "gui" at the root of the main collection. Pass along a table where the entry `score` has been set to 100.
+
+4. Try the game!
+
+![done](images/war-battles/done.png)
+
+Well done! We hope you enjoyed this tutorial and that it was helpful.
+
+## What next?
+
+To get to know Defold better, we suggest that you to continue working with this little game. Here are a few good exercises:
+
+1. Add directional animations for the player character. Tip, add a function called `update_animation(self)` to the `update()` function and change the animation depending on the value of the `self.dir` vector. It is also worth remembering that if you send a "play_animation" message each frame to a sprite, the animation will restart from the beginning, each frame---so you should only send "play_animation" when the animation should change.
+
+2. Add an "idle" state to the player character so it only plays a walking animation when moving.
+
+3. Make the tanks spawn dynamically. Look at how the rockets are spawned and do a similar setup for the tanks. You might want to create a new game object in the main collection with a script that controls the tank spawning.
+
+4. Make the tanks patrol the map. One simple option is to have the tank pick a random point on the map and move towards that point. When it is within a short distance of the point, it picks a new point.
+
+5. Make the tanks chase the player. One option is to add a new collision object to the tank with a spherical shape. If the player collides with the collision object, have the tank drive towards the player.
+
+6. Make the tanks fire at the player.
+
+7. Add sound effects.
+
+If you are stuck, please head over to the [Defold Forum](//forum.defold.com) where you can talk to the Defold developers and many friendly users.

+ 5 - 2
docs/sass/preview-md.sass

@@ -1,5 +1,8 @@
-@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro');
-@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro');
+@import url('https://fonts.googleapis.com/css?family=Source+Sans+Pro')
+@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro')
+@import url('//cdn.jsdelivr.net/chartist.js/latest/chartist.min.css')
+@import url('//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css')
+
 @font-face
   font-family: 'fontello'
   src: url('//www.defold.com/static/fonts/fontello.eot')

部分文件因为文件数量过多而无法显示