diff --git a/factory/spawn_properties/all.texture_profiles b/factory/spawn_properties/all.texture_profiles new file mode 100644 index 0000000..5b0d776 --- /dev/null +++ b/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 + } +} diff --git a/factory/spawn_properties/assets/SourceSansPro-Semibold.ttf b/factory/spawn_properties/assets/SourceSansPro-Semibold.ttf new file mode 100755 index 0000000..5020594 Binary files /dev/null and b/factory/spawn_properties/assets/SourceSansPro-Semibold.ttf differ diff --git a/factory/spawn_properties/assets/images/enemyBlue4.png b/factory/spawn_properties/assets/images/enemyBlue4.png new file mode 100644 index 0000000..b87b1a3 Binary files /dev/null and b/factory/spawn_properties/assets/images/enemyBlue4.png differ diff --git a/factory/spawn_properties/assets/images/enemyRed2.png b/factory/spawn_properties/assets/images/enemyRed2.png new file mode 100644 index 0000000..984e992 Binary files /dev/null and b/factory/spawn_properties/assets/images/enemyRed2.png differ diff --git a/factory/spawn_properties/assets/images/flame.png b/factory/spawn_properties/assets/images/flame.png new file mode 100755 index 0000000..083f8c5 Binary files /dev/null and b/factory/spawn_properties/assets/images/flame.png differ diff --git a/factory/spawn_properties/assets/images/laserRed04.png b/factory/spawn_properties/assets/images/laserRed04.png new file mode 100644 index 0000000..80475f1 Binary files /dev/null and b/factory/spawn_properties/assets/images/laserRed04.png differ diff --git a/factory/spawn_properties/assets/images/meteorGrey_tiny1.png b/factory/spawn_properties/assets/images/meteorGrey_tiny1.png new file mode 100644 index 0000000..2f6589d Binary files /dev/null and b/factory/spawn_properties/assets/images/meteorGrey_tiny1.png differ diff --git a/factory/spawn_properties/assets/images/playerShip1_red.png b/factory/spawn_properties/assets/images/playerShip1_red.png new file mode 100644 index 0000000..e32ea38 Binary files /dev/null and b/factory/spawn_properties/assets/images/playerShip1_red.png differ diff --git a/factory/spawn_properties/assets/images/star2.png b/factory/spawn_properties/assets/images/star2.png new file mode 100644 index 0000000..b2927fb Binary files /dev/null and b/factory/spawn_properties/assets/images/star2.png differ diff --git a/factory/spawn_properties/assets/images/ufoGreen.png b/factory/spawn_properties/assets/images/ufoGreen.png new file mode 100644 index 0000000..4a26785 Binary files /dev/null and b/factory/spawn_properties/assets/images/ufoGreen.png differ diff --git a/factory/spawn_properties/assets/sprites.atlas b/factory/spawn_properties/assets/sprites.atlas new file mode 100644 index 0000000..686c367 --- /dev/null +++ b/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 diff --git a/factory/spawn_properties/assets/text48.font b/factory/spawn_properties/assets/text48.font new file mode 100644 index 0000000..2622c04 --- /dev/null +++ b/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 diff --git a/factory/spawn_properties/collection.png b/factory/spawn_properties/collection.png new file mode 100644 index 0000000..2f8fd10 Binary files /dev/null and b/factory/spawn_properties/collection.png differ diff --git a/factory/spawn_properties/example.md b/factory/spawn_properties/example.md new file mode 100644 index 0000000..9c674bc --- /dev/null +++ b/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! diff --git a/factory/spawn_properties/example/boom.particlefx b/factory/spawn_properties/example/boom.particlefx new file mode 100644 index 0000000..9556971 --- /dev/null +++ b/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 + } + } +} diff --git a/factory/spawn_properties/example/bullet.go b/factory/spawn_properties/example/bullet.go new file mode 100644 index 0000000..a7b6e67 --- /dev/null +++ b/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" + "" +} diff --git a/factory/spawn_properties/example/enemy.go b/factory/spawn_properties/example/enemy.go new file mode 100644 index 0000000..1b9d8fb --- /dev/null +++ b/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" + "" +} diff --git a/factory/spawn_properties/example/enemy.script b/factory/spawn_properties/example/enemy.script new file mode 100644 index 0000000..55295a8 --- /dev/null +++ b/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 diff --git a/factory/spawn_properties/example/ship.script b/factory/spawn_properties/example/ship.script new file mode 100644 index 0000000..c3c3375 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/factory/spawn_properties/example/spawn_properties.collection b/factory/spawn_properties/example/spawn_properties.collection new file mode 100644 index 0000000..a32cffd --- /dev/null +++ b/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 + } +} diff --git a/factory/spawn_properties/example/spawner.script b/factory/spawn_properties/example/spawner.script new file mode 100644 index 0000000..93a9b03 --- /dev/null +++ b/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 diff --git a/factory/spawn_properties/game.project b/factory/spawn_properties/game.project new file mode 100644 index 0000000..d983346 --- /dev/null +++ b/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 + diff --git a/factory/spawn_properties/thumbnail.png b/factory/spawn_properties/thumbnail.png new file mode 100644 index 0000000..c51d1d1 Binary files /dev/null and b/factory/spawn_properties/thumbnail.png differ