Ver Fonte

Added bullet and knockback examples

Björn Ritzl há 3 anos atrás
pai
commit
40501388d8

BIN
assets/images/enemyBlack1.png


BIN
assets/images/playerShip1_red.png


+ 8 - 0
assets/sprites.atlas

@@ -66,6 +66,14 @@ images {
   image: "/assets/images/green_button03.png"
   sprite_trim_mode: SPRITE_TRIM_MODE_OFF
 }
+images {
+  image: "/assets/images/playerShip1_red.png"
+  sprite_trim_mode: SPRITE_TRIM_MODE_OFF
+}
+images {
+  image: "/assets/images/enemyBlack1.png"
+  sprite_trim_mode: SPRITE_TRIM_MODE_OFF
+}
 animations {
   id: "bee"
   images {

+ 38 - 2
examples/_main/loader.go

@@ -209,9 +209,9 @@ embedded_components {
   }
 }
 embedded_components {
-  id: "basics/spawn"
+  id: "factory/basic"
   type: "collectionproxy"
-  data: "collection: \"/examples/basics/spawn/spawn.collection\"\n"
+  data: "collection: \"/examples/factory/basic/basicfactory.collection\"\n"
   "exclude: false\n"
   ""
   position {
@@ -910,3 +910,39 @@ embedded_components {
     w: 1.0
   }
 }
+embedded_components {
+  id: "factory/bullets"
+  type: "collectionproxy"
+  data: "collection: \"/examples/factory/bullets/bullets.collection\"\n"
+  "exclude: false\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}
+embedded_components {
+  id: "physics/knockback"
+  type: "collectionproxy"
+  data: "collection: \"/examples/physics/knockback/knockback.collection\"\n"
+  "exclude: false\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}

+ 3 - 2
examples/_main/menu.gui_script

@@ -100,9 +100,10 @@ end
 
 function init(self)
 	self.index = {}
-	self.index["basics"] = { "message_passing", "parent_child", "spawn", "z_order" }
+	self.index["basics"] = { "message_passing", "parent_child", "z_order" }
+	self.index["factory"] = { "basic", "bullets" }
 	self.index["movement"] = { "simple_move", "follow", "move_to", "move_forward", "movement_speed", "look_at" }
-	self.index["physics"] = { "dynamic", "kinematic", "raycast", "trigger", "hinge_joint", "pendulum"}
+	self.index["physics"] = { "dynamic", "kinematic", "raycast", "trigger", "hinge_joint", "pendulum", "knockback"}
 	self.index["animation"] = { "spinner", "flipbook", "chained_tween", "basic_tween", "spine", "cursor" }
 	self.index["gui"] = { "button", "stencil", "load_texture", "progress", "pointer_over", "color", "slice9" }
 	self.index["input"] = { "move", "text", "down_duration", "mouse_and_touch" }

+ 2 - 2
examples/basics/spawn/spawn.collection → examples/factory/basic/basicfactory.collection

@@ -4,7 +4,7 @@ embedded_instances {
   id: "bunny"
   data: "components {\n"
   "  id: \"script\"\n"
-  "  component: \"/examples/basics/spawn/bunny.script\"\n"
+  "  component: \"/examples/factory/basic/bunny.script\"\n"
   "  position {\n"
   "    x: 0.0\n"
   "    y: 0.0\n"
@@ -94,7 +94,7 @@ embedded_instances {
   "embedded_components {\n"
   "  id: \"carrotfactory\"\n"
   "  type: \"factory\"\n"
-  "  data: \"prototype: \\\"/examples/basics/spawn/carrot.go\\\"\\n"
+  "  data: \"prototype: \\\"/examples/factory/basic/carrot.go\\\"\\n"
   "load_dynamically: false\\n"
   "\"\n"
   "  position {\n"

+ 7 - 5
examples/basics/spawn/bunny.script → examples/factory/basic/bunny.script

@@ -4,19 +4,21 @@ end
 
 function on_input(self, action_id, action)
 	if action_id == hash("touch") and action.pressed then -- <2>
-		local pos = go.get_position()
-		pos.x = pos.x + 100 -- <3>
+		local pos = vmath.vector3(action.x, action.y, 0) -- <3>
 		local carrot_id = factory.create("#carrotfactory", pos) -- <4>
-		go.animate(carrot_id, "position.x", go.PLAYBACK_ONCE_FORWARD, 720, go.EASING_LINEAR, 3) -- <5>
+		go.animate(carrot_id, "euler.z", go.PLAYBACK_ONCE_FORWARD, 360, go.EASING_LINEAR, 1, 0, function()   -- <5>
+			go.delete(carrot_id)  -- <6>
+		end)
 	end
 end
 
 --[[
 1. Acquire input focus so we get input from the engine.
 2. If the user clicks.
-3. Calculate a spawning position.
+3. Set the spawning position to the mouse click position.
 4. Tell the component "carrotfactory" ("#" denotes a component in the
    current game object) to spawn a game object according to its prototype.
    The function returns the id of the new game object.
-5. Animate the position of the new game object.
+5. Rotate the new game object.
+6. Delete the game object
 --]]

+ 0 - 15
examples/basics/spawn/carrot.go → examples/factory/basic/carrot.go

@@ -1,18 +1,3 @@
-components {
-  id: "script"
-  component: "/examples/basics/spawn/carrot.script"
-  position {
-    x: 0.0
-    y: 0.0
-    z: 0.0
-  }
-  rotation {
-    x: 0.0
-    y: 0.0
-    z: 0.0
-    w: 1.0
-  }
-}
 embedded_components {
   id: "sprite"
   type: "sprite"

+ 0 - 0
examples/basics/spawn/carrot.png → examples/factory/basic/carrot.png


+ 0 - 0
examples/basics/spawn/carrot.script → examples/factory/basic/carrot.script


+ 0 - 0
examples/basics/spawn/spawn.md → examples/factory/basic/spawn.md


+ 0 - 0
examples/basics/spawn/spawn.png → examples/factory/basic/spawn.png


+ 20 - 0
examples/factory/bullets/bullet.go

@@ -0,0 +1,20 @@
+embedded_components {
+  id: "sprite"
+  type: "sprite"
+  data: "tile_set: \"/assets/sprites.atlas\"\n"
+  "default_animation: \"flame\"\n"
+  "material: \"/builtins/materials/sprite.material\"\n"
+  "blend_mode: BLEND_MODE_ALPHA\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}

+ 149 - 0
examples/factory/bullets/bullets.collection

@@ -0,0 +1,149 @@
+name: "default"
+scale_along_z: 0
+embedded_instances {
+  id: "go"
+  data: "embedded_components {\n"
+  "  id: \"label1\"\n"
+  "  type: \"label\"\n"
+  "  data: \"size {\\n"
+  "  x: 128.0\\n"
+  "  y: 32.0\\n"
+  "  z: 0.0\\n"
+  "  w: 0.0\\n"
+  "}\\n"
+  "scale {\\n"
+  "  x: 0.5\\n"
+  "  y: 0.5\\n"
+  "  z: 1.0\\n"
+  "  w: 0.0\\n"
+  "}\\n"
+  "color {\\n"
+  "  x: 0.0\\n"
+  "  y: 0.5647059\\n"
+  "  z: 0.99215686\\n"
+  "  w: 1.0\\n"
+  "}\\n"
+  "outline {\\n"
+  "  x: 1.0\\n"
+  "  y: 1.0\\n"
+  "  z: 1.0\\n"
+  "  w: 1.0\\n"
+  "}\\n"
+  "shadow {\\n"
+  "  x: 0.0\\n"
+  "  y: 0.0\\n"
+  "  z: 0.0\\n"
+  "  w: 1.0\\n"
+  "}\\n"
+  "leading: 1.0\\n"
+  "tracking: 0.0\\n"
+  "pivot: PIVOT_CENTER\\n"
+  "blend_mode: BLEND_MODE_ALPHA\\n"
+  "line_break: false\\n"
+  "text: \\\"Click/spacebar to pew pew!\\\"\\n"
+  "font: \\\"/assets/text48.font\\\"\\n"
+  "material: \\\"/builtins/fonts/label.material\\\"\\n"
+  "\"\n"
+  "  position {\n"
+  "    x: 360.0\n"
+  "    y: 20.0\n"
+  "    z: 0.0\n"
+  "  }\n"
+  "  rotation {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "    w: 1.0\n"
+  "  }\n"
+  "}\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+  scale3 {
+    x: 1.0
+    y: 1.0
+    z: 1.0
+  }
+}
+embedded_instances {
+  id: "player"
+  data: "components {\n"
+  "  id: \"player\"\n"
+  "  component: \"/examples/factory/bullets/player.script\"\n"
+  "  position {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "  }\n"
+  "  rotation {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "    w: 1.0\n"
+  "  }\n"
+  "}\n"
+  "embedded_components {\n"
+  "  id: \"bulletfactory\"\n"
+  "  type: \"factory\"\n"
+  "  data: \"prototype: \\\"/examples/factory/bullets/bullet.go\\\"\\n"
+  "load_dynamically: false\\n"
+  "\"\n"
+  "  position {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "  }\n"
+  "  rotation {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "    w: 1.0\n"
+  "  }\n"
+  "}\n"
+  "embedded_components {\n"
+  "  id: \"sprite\"\n"
+  "  type: \"sprite\"\n"
+  "  data: \"tile_set: \\\"/assets/sprites.atlas\\\"\\n"
+  "default_animation: \\\"playerShip1_red\\\"\\n"
+  "material: \\\"/builtins/materials/sprite.material\\\"\\n"
+  "blend_mode: BLEND_MODE_ALPHA\\n"
+  "\"\n"
+  "  position {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "  }\n"
+  "  rotation {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "    w: 1.0\n"
+  "  }\n"
+  "}\n"
+  ""
+  position {
+    x: 360.0
+    y: 100.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+  scale3 {
+    x: 1.0
+    y: 1.0
+    z: 1.0
+  }
+}

+ 9 - 0
examples/factory/bullets/bullets.md

@@ -0,0 +1,9 @@
+---
+title: Shoot bullets
+brief: This example shows how to dynamically spawn bullet game objects using a factory component.
+scripts: player.script
+---
+
+This example shows how to dynamically spawn bullet game objects using a factory component and how to also move and delete the bullets.
+
+Combine this example with some of the examples from the movement and physics categories to create a shoot 'em up game!

+ 53 - 0
examples/factory/bullets/player.go

@@ -0,0 +1,53 @@
+components {
+  id: "player"
+  component: "/examples/factory/bullets/player.script"
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}
+embedded_components {
+  id: "sprite"
+  type: "sprite"
+  data: "tile_set: \"/assets/sprites.atlas\"\n"
+  "default_animation: \"playerShip1_red\"\n"
+  "material: \"/builtins/materials/sprite.material\"\n"
+  "blend_mode: BLEND_MODE_ALPHA\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}
+embedded_components {
+  id: "bulletfactory"
+  type: "factory"
+  data: "prototype: \"/examples/factory/bullets/bullet.go\"\n"
+  "load_dynamically: false\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}

+ 26 - 0
examples/factory/bullets/player.script

@@ -0,0 +1,26 @@
+function init(self)
+	-- make sure the script will receive user input
+	msg.post(".", "acquire_input_focus")
+end
+
+function on_input(self, action_id, action)
+	-- mouse or spacebar
+	if (action_id == hash("touch") or action_id == hash("action")) and action.pressed then
+		-- position bullet somewhat offset from the player position
+		local pos = go.get_position()
+		pos.y = pos.y + 50
+
+		-- spawn a bullet
+		local bullet_id = factory.create("#bulletfactory", pos)
+
+		-- animate the bullet
+		local distance = 1000					-- distance in pixels
+		local speed = 800						-- pixels per second
+		local duration = distance / speed		-- time in second to travel the full distance
+		local to = pos.y + distance
+		-- start animation and delete bullet when it has reached its destination
+		go.animate(bullet_id, "position.y", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_LINEAR, duration, 0, function()
+			go.delete(bullet_id)
+		end)
+	end
+end

+ 1 - 1
examples/movement/look_at/look_at.collection

@@ -95,7 +95,7 @@ embedded_instances {
   "pivot: PIVOT_CENTER\\n"
   "blend_mode: BLEND_MODE_ALPHA\\n"
   "line_break: false\\n"
-  "text: \\\"Move with arrow keys (left+right = rotate, up = forward)\\\"\\n"
+  "text: \\\"I will always look at  the mouse pointer\\\"\\n"
   "font: \\\"/assets/text48.font\\\"\\n"
   "material: \\\"/builtins/fonts/label.material\\\"\\n"
   "\"\n"

+ 2 - 0
examples/movement/look_at/look_at.md

@@ -3,3 +3,5 @@ title: Look at
 brief: This example shows how to rotate a game object to look at the mouse cursor
 scripts: look_at.script
 ---
+
+This example shows how to rotate a game object to look at the mouse cursor. It reads the mouse position in `on_input` and uses the mathematical function `math.atan2(x, y)` to calculate the angle between the ray to the point to look at and the positive x-axis. This angle is used to set the rotation of the game object to always look at the mouse position. 

+ 66 - 0
examples/physics/knockback/bullet.go

@@ -0,0 +1,66 @@
+embedded_components {
+  id: "sprite"
+  type: "sprite"
+  data: "tile_set: \"/assets/sprites.atlas\"\n"
+  "default_animation: \"flame\"\n"
+  "material: \"/builtins/materials/sprite.material\"\n"
+  "blend_mode: BLEND_MODE_ALPHA\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}
+embedded_components {
+  id: "collisionobject"
+  type: "collisionobject"
+  data: "collision_shape: \"\"\n"
+  "type: COLLISION_OBJECT_TYPE_KINEMATIC\n"
+  "mass: 0.0\n"
+  "friction: 0.1\n"
+  "restitution: 0.5\n"
+  "group: \"bullet\"\n"
+  "mask: \"enemy\"\n"
+  "embedded_collision_shape {\n"
+  "  shapes {\n"
+  "    shape_type: TYPE_SPHERE\n"
+  "    position {\n"
+  "      x: 0.0\n"
+  "      y: 20.0\n"
+  "      z: 0.0\n"
+  "    }\n"
+  "    rotation {\n"
+  "      x: 0.0\n"
+  "      y: 0.0\n"
+  "      z: 0.0\n"
+  "      w: 1.0\n"
+  "    }\n"
+  "    index: 0\n"
+  "    count: 1\n"
+  "  }\n"
+  "  data: 20.0\n"
+  "}\n"
+  "linear_damping: 0.0\n"
+  "angular_damping: 0.0\n"
+  "locked_rotation: false\n"
+  "bullet: false\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}

+ 81 - 0
examples/physics/knockback/enemy.go

@@ -0,0 +1,81 @@
+components {
+  id: "enemy"
+  component: "/examples/physics/knockback/enemy.script"
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}
+embedded_components {
+  id: "sprite"
+  type: "sprite"
+  data: "tile_set: \"/assets/sprites.atlas\"\n"
+  "default_animation: \"enemyBlack1\"\n"
+  "material: \"/builtins/materials/sprite.material\"\n"
+  "blend_mode: BLEND_MODE_ALPHA\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}
+embedded_components {
+  id: "collisionobject"
+  type: "collisionobject"
+  data: "collision_shape: \"\"\n"
+  "type: COLLISION_OBJECT_TYPE_KINEMATIC\n"
+  "mass: 0.0\n"
+  "friction: 0.1\n"
+  "restitution: 0.5\n"
+  "group: \"enemy\"\n"
+  "mask: \"bullet\"\n"
+  "embedded_collision_shape {\n"
+  "  shapes {\n"
+  "    shape_type: TYPE_SPHERE\n"
+  "    position {\n"
+  "      x: 0.0\n"
+  "      y: 0.0\n"
+  "      z: 0.0\n"
+  "    }\n"
+  "    rotation {\n"
+  "      x: 0.0\n"
+  "      y: 0.0\n"
+  "      z: 0.0\n"
+  "      w: 1.0\n"
+  "    }\n"
+  "    index: 0\n"
+  "    count: 1\n"
+  "  }\n"
+  "  data: 40.0\n"
+  "}\n"
+  "linear_damping: 0.0\n"
+  "angular_damping: 0.0\n"
+  "locked_rotation: false\n"
+  "bullet: false\n"
+  ""
+  position {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+}

+ 29 - 0
examples/physics/knockback/enemy.script

@@ -0,0 +1,29 @@
+-- move game object back and forth from the current position to a target position
+local function move()
+	local pos = go.get_position()
+	local to = vmath.vector3(pos.x, 300, 0)
+	local distance = pos.y - to.y
+	local speed = 40
+	local duration = distance / speed
+	go.animate(".", "position", go.PLAYBACK_LOOP_PINGPONG, to, go.EASING_INOUTQUAD, duration)
+end
+
+function init(self)
+	move()
+end
+
+function on_message(self, message_id, message, sender)
+	if message_id == hash("contact_point_response") then
+		if message.other_group == hash("bullet") then
+			-- delete the bullet
+			go.delete(message.other_id)
+
+			-- get the position of the game object
+			local pos = go.get_position()
+			-- set a pushback direction based on the collision normal
+			local to = pos + message.normal * 30
+			-- knockback animation, then continue moving
+			go.animate(".", "position", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_OUTQUAD, 0.1, 0, move)
+		end
+	end
+end

+ 95 - 0
examples/physics/knockback/knockback.collection

@@ -0,0 +1,95 @@
+name: "default"
+instances {
+  id: "enemy"
+  prototype: "/examples/physics/knockback/enemy.go"
+  position {
+    x: 360.0
+    y: 456.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+  scale3 {
+    x: 1.0
+    y: 1.0
+    z: 1.0
+  }
+}
+scale_along_z: 0
+embedded_instances {
+  id: "player"
+  data: "components {\n"
+  "  id: \"player\"\n"
+  "  component: \"/examples/physics/knockback/player.script\"\n"
+  "  position {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "  }\n"
+  "  rotation {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "    w: 1.0\n"
+  "  }\n"
+  "}\n"
+  "embedded_components {\n"
+  "  id: \"bulletfactory\"\n"
+  "  type: \"factory\"\n"
+  "  data: \"prototype: \\\"/examples/physics/knockback/bullet.go\\\"\\n"
+  "load_dynamically: false\\n"
+  "\"\n"
+  "  position {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "  }\n"
+  "  rotation {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "    w: 1.0\n"
+  "  }\n"
+  "}\n"
+  "embedded_components {\n"
+  "  id: \"sprite\"\n"
+  "  type: \"sprite\"\n"
+  "  data: \"tile_set: \\\"/assets/sprites.atlas\\\"\\n"
+  "default_animation: \\\"playerShip1_red\\\"\\n"
+  "material: \\\"/builtins/materials/sprite.material\\\"\\n"
+  "blend_mode: BLEND_MODE_ALPHA\\n"
+  "\"\n"
+  "  position {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "  }\n"
+  "  rotation {\n"
+  "    x: 0.0\n"
+  "    y: 0.0\n"
+  "    z: 0.0\n"
+  "    w: 1.0\n"
+  "  }\n"
+  "}\n"
+  ""
+  position {
+    x: 360.0
+    y: 100.0
+    z: 0.0
+  }
+  rotation {
+    x: 0.0
+    y: 0.0
+    z: 0.0
+    w: 1.0
+  }
+  scale3 {
+    x: 1.0
+    y: 1.0
+    z: 1.0
+  }
+}

+ 24 - 0
examples/physics/knockback/knockback.md

@@ -0,0 +1,24 @@
+---
+title: Knockback
+brief: This example shows how to create a knockback effect when hit.
+scripts: enemy.script
+---
+
+This example shows how to create a knockback effect when hit. The setup consists of three game objects; one for the player, one for the enemy and one for the bullet that is spawned using a factory (see example on how to spawn bullets).
+
+player
+: The red ship at the bottom. Contains:
+  - A *Sprite* component with the spaceship image.
+  - A *Factory* component to spawn bullet game objects
+  - A script to handle spawning of bullets.
+
+bullet
+: The bullet fired by the player. Contains:
+  - A *Sprite* component with a bullet image.
+  - A *Collision object* component. *Type* is set to `KINEMATIC`. It has a sphere *Shape* matching image.
+
+enemy
+: The black ship at the top. Contains:
+  - A *Sprite* component with the spaceship image.
+  - A *Collision object* component. *Type* is set to `KINEMATIC`. It has a sphere *Shape* matching image.
+  - A script to handle collisions with bullets.

+ 26 - 0
examples/physics/knockback/player.script

@@ -0,0 +1,26 @@
+function init(self)
+	-- make sure the script will receive user input
+	msg.post(".", "acquire_input_focus")
+end
+
+function on_input(self, action_id, action)
+	-- mouse or spacebar
+	if (action_id == hash("touch") or action_id == hash("action")) and action.pressed then
+		-- position bullet somewhat offset from the player position
+		local pos = go.get_position()
+		pos.y = pos.y + 50
+
+		-- spawn a bullet
+		local bullet_id = factory.create("#bulletfactory", pos)
+
+		-- animate the bullet
+		local distance = 1000					-- distance in pixels
+		local speed = 800						-- pixels per second
+		local duration = distance / speed		-- time in second to travel the full distance
+		local to = pos.y + distance
+		-- start animation and delete bullet when it has reached its destination
+		go.animate(bullet_id, "position.y", go.PLAYBACK_ONCE_FORWARD, to, go.EASING_LINEAR, duration, 0, function()
+			go.delete(bullet_id)
+		end)
+	end
+end

+ 0 - 0
assets/tiles/tilesource.png → examples/tilemap/collisions/tilesource.png


+ 4 - 0
input/game.input_binding

@@ -18,6 +18,10 @@ key_trigger {
   input: KEY_BACKSPACE
   action: "backspace"
 }
+key_trigger {
+  input: KEY_SPACE
+  action: "action"
+}
 mouse_trigger {
   input: MOUSE_BUTTON_LEFT
   action: "touch"