Browse Source

122 spawn with script properties (#124)

* Added example for factory with script properties.

* Added thumbnail.

* Changed example to emphasize power of properties more.

* Fixed typos
Pawel 1 month ago
parent
commit
31500dde81

+ 18 - 0
factory/spawn_properties/all.texture_profiles

@@ -0,0 +1,18 @@
+path_settings {
+  path: "**"
+  profile: "Default"
+}
+profiles {
+  name: "Default"
+  platforms {
+    os: OS_ID_GENERIC
+    formats {
+      format: TEXTURE_FORMAT_RGBA
+      compression_level: BEST
+      compression_type: COMPRESSION_TYPE_DEFAULT
+    }
+    mipmaps: false
+    max_texture_size: 0
+    premultiply_alpha: true
+  }
+}

BIN
factory/spawn_properties/assets/SourceSansPro-Semibold.ttf


BIN
factory/spawn_properties/assets/images/enemyBlue4.png


BIN
factory/spawn_properties/assets/images/enemyRed2.png


BIN
factory/spawn_properties/assets/images/flame.png


BIN
factory/spawn_properties/assets/images/laserRed04.png


BIN
factory/spawn_properties/assets/images/meteorGrey_tiny1.png


BIN
factory/spawn_properties/assets/images/playerShip1_red.png


BIN
factory/spawn_properties/assets/images/star2.png


BIN
factory/spawn_properties/assets/images/ufoGreen.png


+ 25 - 0
factory/spawn_properties/assets/sprites.atlas

@@ -0,0 +1,25 @@
+images {
+  image: "/assets/images/flame.png"
+}
+images {
+  image: "/assets/images/playerShip1_red.png"
+}
+images {
+  image: "/assets/images/enemyRed2.png"
+}
+images {
+  image: "/assets/images/enemyBlue4.png"
+}
+images {
+  image: "/assets/images/ufoGreen.png"
+}
+images {
+  image: "/assets/images/laserRed04.png"
+}
+images {
+  image: "/assets/images/meteorGrey_tiny1.png"
+}
+images {
+  image: "/assets/images/star2.png"
+}
+extrude_borders: 2

+ 5 - 0
factory/spawn_properties/assets/text48.font

@@ -0,0 +1,5 @@
+font: "/assets/SourceSansPro-Semibold.ttf"
+material: "/builtins/fonts/font.material"
+size: 48
+outline_alpha: 0.0
+outline_width: 0.0

BIN
factory/spawn_properties/collection.png


+ 70 - 0
factory/spawn_properties/example.md

@@ -0,0 +1,70 @@
+---
+tags: factory
+title: Spawn enemies with script properties
+brief: This example shows how to spawn enemy game objects using a factory component with different properties.
+author: Defold Foundation
+scripts: ship.script, enemy.script, spawner.script
+thumbnail: thumbnail.png
+---
+
+This example shows how to dynamically spawn enemy game objects using a factory component with different properties. The setup consists of three main components: a player ship, enemy spawner, and different enemy types with customizable properties.
+
+Press keys `1`, `2`, or `3` to spawn different enemy types.
+
+Example collection consists of 2 game objects:
+
+![Screenshot showing enemy types and spawner in action](collection.png)
+
+### Ship
+The red ship at the bottom that automatically moves and shoots. Consists of:
+- A *Factory* component `bulletfactory` to spawn bullet game objects
+- A *Script* `ship` that handles automatic movement (ping-pong animation) and bullet spawning every 0.25 seconds
+- A *Sprite* component with the spaceship image
+
+Bullets are simply animated upward and automatically deleted when they reach the top.
+
+### Spawner
+Controls enemy spawning with keyboard input. Consists of:
+- A *Factory* `enemyfactory` to spawn enemies with different properties
+- A *Label* `example_description` with instructions text displayed on top
+- A *Script* `spawner` that spawns enemies.
+
+
+The spawner script defines three different enemy types: `random`, `diagonal`, and `straight`.
+Uses factory to create enemies with specific properties:
+
+```lua
+local properties = ENEMY_TYPES[enemy_type]
+factory.create("#enemyfactory", position, nil, properties)
+```
+
+### Enemy Types
+
+**Random Enemy** (Key 1):
+- Green UFO sprite
+- 1 health point
+- Random horizontal movement that changes every second
+- Speed: 40 horizontal, -100 vertical
+
+**Diagonal Enemy** (Key 2):
+- Red enemy sprite
+- 2 health points
+- Fixed diagonal movement
+- Speed: 120 horizontal, -80 vertical
+
+**Straight Enemy** (Key 3):
+- Blue enemy sprite
+- 3 health points
+- Straight downward movement
+- Speed: 0 horizontal, -40 vertical
+
+### Enemy Script Properties
+Properties defined in `enemy.script` control enemy behavior:
+- `sprite` - Which sprite to display
+- `health_points` - How many hits before destruction
+- `speed` - Movement velocity vector
+- `is_random` - Whether to use random movement changes
+
+When enemies have `go.property` defined in their script, these properties are visible in the *Properties* pane and can be customized per enemy type.
+
+Combine this example with other movement and physics examples to create a complete shoot'em up game!

+ 265 - 0
factory/spawn_properties/example/boom.particlefx

@@ -0,0 +1,265 @@
+emitters {
+  id: "light"
+  mode: PLAY_MODE_ONCE
+  duration: 1.0
+  space: EMISSION_SPACE_WORLD
+  tile_source: "/assets/sprites.atlas"
+  animation: "star2"
+  material: "/builtins/materials/particlefx.material"
+  blend_mode: BLEND_MODE_ADD
+  max_particle_count: 1
+  type: EMITTER_TYPE_CIRCLE
+  properties {
+    key: EMITTER_KEY_SPAWN_RATE
+    points {
+      y: 10.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_SIZE_X
+    points {
+      y: 8.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_SIZE_Y
+    points {
+      y: 12.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_LIFE_TIME
+    points {
+      y: 1.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_SIZE
+    points {
+      y: 20.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_RED
+    points {
+      y: 1.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_GREEN
+    points {
+      y: 1.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_BLUE
+    points {
+      y: 1.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_ALPHA
+    points {
+      y: 1.0
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_SCALE
+    points {
+      y: 1.0
+      t_x: 0.25919977
+      t_y: 0.9658237
+    }
+    points {
+      x: 1.0
+      y: 0.023632
+      t_x: 0.9998886
+      t_y: 0.014926955
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_RED
+    points {
+      y: 1.0
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_GREEN
+    points {
+      y: 1.0
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_BLUE
+    points {
+      y: 1.0
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_ALPHA
+    points {
+      y: 0.0
+      t_x: 0.07194582
+      t_y: 0.99740857
+    }
+    points {
+      x: 0.11320755
+      y: 0.99277455
+      t_x: 0.99418455
+      t_y: 0.10768964
+    }
+    points {
+      x: 0.7112546
+      y: 0.555656
+      t_x: 0.5694311
+      t_y: -0.82203907
+    }
+    points {
+      x: 1.0
+      y: 0.0072254334
+      t_x: 0.4737472
+      t_y: -0.8806609
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_ANGULAR_VELOCITY
+    points {
+      y: 1.0
+    }
+  }
+}
+emitters {
+  id: "debris"
+  mode: PLAY_MODE_ONCE
+  duration: 1.0
+  space: EMISSION_SPACE_WORLD
+  tile_source: "/assets/sprites.atlas"
+  animation: "meteorGrey_tiny1"
+  material: "/builtins/materials/particlefx.material"
+  max_particle_count: 4
+  type: EMITTER_TYPE_CIRCLE
+  properties {
+    key: EMITTER_KEY_SPAWN_RATE
+    points {
+      y: 10.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_SIZE_X
+    points {
+      y: 8.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_SIZE_Y
+    points {
+      y: 12.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_LIFE_TIME
+    points {
+      y: 1.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_SPEED
+    points {
+      y: 50.0
+    }
+    spread: 20.0
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_SIZE
+    points {
+      y: 10.0
+    }
+    spread: 5.0
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_RED
+    points {
+      y: 1.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_GREEN
+    points {
+      y: 1.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_BLUE
+    points {
+      y: 1.0
+    }
+  }
+  properties {
+    key: EMITTER_KEY_PARTICLE_ALPHA
+    points {
+      y: 1.0
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_SCALE
+    points {
+      y: 1.0
+      t_x: 0.25919977
+      t_y: 0.9658237
+    }
+    points {
+      x: 1.0
+      y: 0.00553
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_RED
+    points {
+      y: 1.0
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_GREEN
+    points {
+      y: 1.0
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_BLUE
+    points {
+      y: 1.0
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_ALPHA
+    points {
+      y: 0.0
+      t_x: 0.07194582
+      t_y: 0.99740857
+    }
+    points {
+      x: 0.11320755
+      y: 0.99277455
+      t_x: 0.99418455
+      t_y: 0.10768964
+    }
+    points {
+      x: 0.7112546
+      y: 0.555656
+      t_x: 0.5694311
+      t_y: -0.82203907
+    }
+    points {
+      x: 1.0
+      y: 0.0072254334
+      t_x: 0.4737472
+      t_y: -0.8806609
+    }
+  }
+  particle_properties {
+    key: PARTICLE_KEY_ANGULAR_VELOCITY
+    points {
+      y: 1.0
+    }
+  }
+}

+ 42 - 0
factory/spawn_properties/example/bullet.go

@@ -0,0 +1,42 @@
+embedded_components {
+  id: "sprite"
+  type: "sprite"
+  data: "default_animation: \"laserRed04\"\n"
+  "material: \"/builtins/materials/sprite.material\"\n"
+  "textures {\n"
+  "  sampler: \"texture_sampler\"\n"
+  "  texture: \"/assets/sprites.atlas\"\n"
+  "}\n"
+  ""
+  scale {
+    x: 0.5
+    y: 0.5
+  }
+}
+embedded_components {
+  id: "collisionobject"
+  type: "collisionobject"
+  data: "type: COLLISION_OBJECT_TYPE_TRIGGER\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_BOX\n"
+  "    position {\n"
+  "    }\n"
+  "    rotation {\n"
+  "    }\n"
+  "    index: 0\n"
+  "    count: 3\n"
+  "  }\n"
+  "  data: 3.5\n"
+  "  data: 9.0\n"
+  "  data: 10.0\n"
+  "}\n"
+  "event_collision: false\n"
+  "event_contact: false\n"
+  ""
+}

+ 49 - 0
factory/spawn_properties/example/enemy.go

@@ -0,0 +1,49 @@
+components {
+  id: "enemy"
+  component: "/example/enemy.script"
+}
+components {
+  id: "boom"
+  component: "/example/boom.particlefx"
+}
+embedded_components {
+  id: "sprite"
+  type: "sprite"
+  data: "default_animation: \"ufoGreen\"\n"
+  "material: \"/builtins/materials/sprite.material\"\n"
+  "textures {\n"
+  "  sampler: \"texture_sampler\"\n"
+  "  texture: \"/assets/sprites.atlas\"\n"
+  "}\n"
+  ""
+  scale {
+    x: 0.5
+    y: 0.5
+  }
+}
+embedded_components {
+  id: "collisionobject"
+  type: "collisionobject"
+  data: "type: COLLISION_OBJECT_TYPE_TRIGGER\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"
+  "    }\n"
+  "    rotation {\n"
+  "    }\n"
+  "    index: 0\n"
+  "    count: 1\n"
+  "    id: \"ship\"\n"
+  "  }\n"
+  "  data: 22.5\n"
+  "}\n"
+  "event_collision: false\n"
+  "event_contact: false\n"
+  ""
+}

+ 60 - 0
factory/spawn_properties/example/enemy.script

@@ -0,0 +1,60 @@
+-- Define different properties of the script:
+go.property("sprite", hash("ufoGreen"))
+go.property("health_points", 1)
+go.property("speed", vmath.vector3(100, 100, 0))
+go.property("is_random", true)
+
+function init(self)
+
+	-- Set animation of the sprite to the one defined by its property self.sprite:
+	sprite.play_flipbook("#sprite", self.sprite)
+
+	-- Add randomness to horizontal direction - this way enemy horizontal speed may be inverted or cleared:
+	-- -1 * self.speed.x - inverted direction
+	--  0 * self.speed.x - cleared direction
+	--  1 * self.speed.x - regular direction
+	self.speed.x = math.random(-1, 1) * self.speed.x
+
+	-- If self.is_random boolean property is true:
+	if self.is_random then
+		-- add a timer to randomly switch horizontal speed every second:
+		timer.delay(1, true, function()
+			self.speed.x = math.random(-1, 1) * self.speed.x
+		end)
+	end
+end
+
+function update(self, dt)
+	-- Update enemy position based on its current speed:
+	local pos = go.get_position()
+	pos = pos + self.speed * dt
+	go.set_position(pos)
+
+	-- Bounce enemy off "walls":
+	if pos.x > 600 or pos.x < 50 then
+		self.speed.x = -self.speed.x
+	end
+
+	-- Remove enemy if it goes out of screen:
+	if pos.y < -50 then
+		go.delete()
+	end
+end
+
+function on_message(self, message_id, message, sender)
+
+	-- React to collision with bullet:
+	if message_id == hash("trigger_response") and message.enter then
+
+		-- Remove one health point
+		self.health_points = self.health_points - 1
+
+		-- Play particlefx for damage taken:
+		particlefx.play("#boom")
+
+		-- When no health points left - remove this ship
+		if self.health_points <= 0 then
+			go.delete()
+		end
+	end
+end

+ 18 - 0
factory/spawn_properties/example/ship.script

@@ -0,0 +1,18 @@
+function init(self)
+	-- Animate automatic player position
+	go.animate(".", "position.x", go.PLAYBACK_LOOP_PINGPONG, 620, go.EASING_LINEAR, 6.0)
+
+	-- Create a timer to tick every 0.25 second:
+	timer.delay(0.25, true, function()
+
+		-- Create a simple bullet bullet using the factory
+		local bullet_id = factory.create("#bulletfactory", go.get_position())
+
+		-- Animate the created bullet towards top of screen, where it is deleted
+		if bullet_id then
+			go.animate(bullet_id, "position.y", go.PLAYBACK_ONCE_FORWARD, 600, go.EASING_LINEAR, 1, 0, function()
+				go.delete(bullet_id)
+			end)
+		end
+	end)
+end

+ 80 - 0
factory/spawn_properties/example/spawn_properties.collection

@@ -0,0 +1,80 @@
+name: "default"
+scale_along_z: 0
+embedded_instances {
+  id: "ship"
+  data: "components {\n"
+  "  id: \"ship\"\n"
+  "  component: \"/example/ship.script\"\n"
+  "}\n"
+  "embedded_components {\n"
+  "  id: \"sprite\"\n"
+  "  type: \"sprite\"\n"
+  "  data: \"default_animation: \\\"playerShip1_red\\\"\\n"
+  "material: \\\"/builtins/materials/sprite.material\\\"\\n"
+  "textures {\\n"
+  "  sampler: \\\"texture_sampler\\\"\\n"
+  "  texture: \\\"/assets/sprites.atlas\\\"\\n"
+  "}\\n"
+  "\"\n"
+  "}\n"
+  "embedded_components {\n"
+  "  id: \"bulletfactory\"\n"
+  "  type: \"factory\"\n"
+  "  data: \"prototype: \\\"/example/bullet.go\\\"\\n"
+  "\"\n"
+  "}\n"
+  ""
+  position {
+    x: 100.0
+    y: 50.0
+  }
+}
+embedded_instances {
+  id: "spawner"
+  data: "components {\n"
+  "  id: \"spawner\"\n"
+  "  component: \"/example/spawner.script\"\n"
+  "}\n"
+  "embedded_components {\n"
+  "  id: \"enemyfactory\"\n"
+  "  type: \"factory\"\n"
+  "  data: \"prototype: \\\"/example/enemy.go\\\"\\n"
+  "\"\n"
+  "}\n"
+  "embedded_components {\n"
+  "  id: \"example_description\"\n"
+  "  type: \"label\"\n"
+  "  data: \"size {\\n"
+  "  x: 1024.0\\n"
+  "  y: 256.0\\n"
+  "}\\n"
+  "color {\\n"
+  "  x: 0.0\\n"
+  "  y: 0.5647059\\n"
+  "  z: 0.99215686\\n"
+  "}\\n"
+  "outline {\\n"
+  "  x: 1.0\\n"
+  "  y: 1.0\\n"
+  "  z: 1.0\\n"
+  "}\\n"
+  "text: \\\"Spawn enemies with numeric keys:\\\\n"
+  "\\\"\\n"
+  "  \\\"[1] Random [2] Diagonal [3] Straight\\\"\\n"
+  "font: \\\"/assets/text48.font\\\"\\n"
+  "material: \\\"/builtins/fonts/label.material\\\"\\n"
+  "\"\n"
+  "  position {\n"
+  "    y: 50.0\n"
+  "  }\n"
+  "  scale {\n"
+  "    x: 0.5\n"
+  "    y: 0.5\n"
+  "  }\n"
+  "}\n"
+  ""
+  position {
+    x: 360.0
+    y: 600.0
+  }
+}

+ 54 - 0
factory/spawn_properties/example/spawner.script

@@ -0,0 +1,54 @@
+-- Define different properties for different enemies:
+local ENEMY_TYPES = {
+	random = {
+		sprite = hash("ufoGreen"),
+		health_points = 1,
+		speed = vmath.vector3(40, -100, 0),
+		is_random = true
+	},
+	diagonal = {
+		sprite = hash("enemyRed2"),
+		health_points = 2,
+		speed = vmath.vector3(120, -80, 0),
+		is_random = false
+	},
+	straight = {
+		sprite = hash("enemyBlue4"),
+		health_points = 3,
+		speed = vmath.vector3(0, -40, 0),
+		is_random = false
+	}
+}
+
+function init(self)
+	-- Acquire input focus here, so we can handle inputs:
+	msg.post(".", "acquire_input_focus")
+end
+
+-- Helper function to spawn given enemy by its type:
+local function spawn_enemy(enemy_type)
+
+	-- Select properties of the enemy by type:
+	local properties = ENEMY_TYPES[enemy_type]
+
+	-- Set initial position of the spawned ship.
+	local position = go.get_position()
+
+	-- This will make the position one out of (-180, -90, 0, 90, 180):
+	position.x = position.x + math.random(-2,2) * 90
+
+	-- Create enemy with passed properties
+	factory.create("#enemyfactory", position, nil, properties)
+end
+
+function on_input(self, action_id, action)
+
+	-- React to different key presses with spawning different enemies:
+	if action_id == hash("key_1") and action.released then
+		spawn_enemy("random")
+	elseif action_id == hash("key_2") and action.released then
+		spawn_enemy("diagonal")
+	elseif action_id == hash("key_3") and action.released then
+		spawn_enemy("straight")
+	end
+end

+ 65 - 0
factory/spawn_properties/game.project

@@ -0,0 +1,65 @@
+[project]
+title = Defold-examples
+version = 0.1
+
+[bootstrap]
+main_collection = /example/spawn_properties.collectionc
+
+[input]
+game_binding = /builtins/input/all.input_bindingc
+repeat_interval = 0.05
+
+[display]
+width = 720
+height = 720
+high_dpi = 1
+
+[physics]
+scale = 0.02
+gravity_y = -500.0
+
+[script]
+shared_state = 1
+
+[collection_proxy]
+max_count = 256
+
+[label]
+subpixels = 1
+
+[sprite]
+subpixels = 1
+max_count = 32765
+
+[windows]
+iap_provider = 
+
+[android]
+package = com.defold.examples
+
+[ios]
+bundle_identifier = com.defold.examples
+
+[osx]
+bundle_identifier = com.defold.examples
+
+[html5]
+show_fullscreen_button = 0
+show_made_with_defold = 0
+scale_mode = no_scale
+heap_size = 64
+
+[graphics]
+texture_profiles = /all.texture_profiles
+
+[collection]
+max_instances = 32765
+
+[particle_fx]
+max_emitter_count = 1024
+
+[render]
+clear_color_blue = 0.2
+clear_color_green = 0.1
+clear_color_red = 0.0
+

BIN
factory/spawn_properties/thumbnail.png