|
|
@@ -0,0 +1,149 @@
|
|
|
+-- Pre-hash some strings string since they will be used a lot
|
|
|
+local TRIGGER_EVENT = hash("trigger_event")
|
|
|
+local GROUP_BULLET = hash("bullet")
|
|
|
+local GROUP_ENEMY = hash("enemy")
|
|
|
+
|
|
|
+-- 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
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+-- Helper function to spawn given enemy by its type:
|
|
|
+local function spawn_enemy(self, 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
|
|
|
+ local id = factory.create("#enemyfactory", position)
|
|
|
+
|
|
|
+ -- set animation of the sprite to the one defined by enemy properties
|
|
|
+ local sprite_url = msg.url(nil, id, "sprite")
|
|
|
+ sprite.play_flipbook(sprite_url, properties.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
|
|
|
+ local speed = vmath.vector3(properties.speed)
|
|
|
+ speed.x = speed.x * math.random(-1, 1)
|
|
|
+
|
|
|
+ -- store enemy
|
|
|
+ self.enemies[id] = {
|
|
|
+ id = id,
|
|
|
+ health = properties.health_points,
|
|
|
+ speed = speed,
|
|
|
+ is_random = properties.is_random,
|
|
|
+ timer = 1
|
|
|
+ }
|
|
|
+end
|
|
|
+
|
|
|
+function init(self)
|
|
|
+ -- Acquire input focus here, so we can handle inputs:
|
|
|
+ msg.post(".", "acquire_input_focus")
|
|
|
+ self.enemies = {}
|
|
|
+
|
|
|
+ -- listen to physics events
|
|
|
+ -- in this case we care about trigger events between
|
|
|
+ -- enemies and bullets
|
|
|
+ physics.set_event_listener(function(self, events)
|
|
|
+ for _,event in ipairs(events) do
|
|
|
+ local event_type = event.type
|
|
|
+ if event_type == TRIGGER_EVENT then
|
|
|
+ -- get the bullet id and enemy id if the colliding objects belong to
|
|
|
+ -- groups "bullet" and "enemy"
|
|
|
+ -- this is the Lua way of writing a ternary operator
|
|
|
+ local bullet_id = (event.a.group == GROUP_BULLET and event.a.id) or (event.b.group == GROUP_BULLET and event.b.id)
|
|
|
+ local enemy_id = (event.a.group == GROUP_ENEMY and event.a.id) or (event.b.group == GROUP_ENEMY and event.b.id)
|
|
|
+
|
|
|
+ -- not really necessary in this example but we might as well
|
|
|
+ -- double-check that the detected collision was for a bullet and enemy
|
|
|
+ if bullet_id and enemy_id then
|
|
|
+ -- remove the bullet
|
|
|
+ go.delete(bullet_id)
|
|
|
+
|
|
|
+ -- get the enemy from the managed enemies list
|
|
|
+ local enemy = self.enemies[enemy_id]
|
|
|
+
|
|
|
+ -- Remove one health point
|
|
|
+ enemy.health = enemy.health - 1
|
|
|
+
|
|
|
+ -- When no health points left - remove this ship
|
|
|
+ if enemy.health == 0 then
|
|
|
+ go.delete(enemy_id)
|
|
|
+ self.enemies[enemy_id] = nil
|
|
|
+
|
|
|
+ -- Play particlefx for damage taken:
|
|
|
+ particlefx.play(msg.url(nil, enemy_id, "boom"))
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end)
|
|
|
+end
|
|
|
+
|
|
|
+
|
|
|
+function update(self, dt)
|
|
|
+ for id,enemy in pairs(self.enemies) do
|
|
|
+ -- Update enemy position based on its current speed:
|
|
|
+ local pos = go.get_position(id)
|
|
|
+ pos = pos + enemy.speed * dt
|
|
|
+ go.set_position(pos, id)
|
|
|
+
|
|
|
+ -- Bounce enemy off "walls":
|
|
|
+ if pos.x > 600 or pos.x < 50 then
|
|
|
+ enemy.speed.x = -enemy.speed.x
|
|
|
+ end
|
|
|
+
|
|
|
+ -- Remove enemy if it goes out of screen:
|
|
|
+ if pos.y < -50 then
|
|
|
+ go.delete(id)
|
|
|
+ self.enemies[id] = nil
|
|
|
+ end
|
|
|
+
|
|
|
+ -- If enemy has random movement decrease timer to
|
|
|
+ -- randomly switch horizontal speed every second
|
|
|
+ if enemy.is_random then
|
|
|
+ enemy.timer = enemy.timer - dt
|
|
|
+ if enemy.timer < 0 then
|
|
|
+ enemy.timer = enemy.timer + 1
|
|
|
+ enemy.speed.x = math.random(-1, 1) * enemy.speed.x
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+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(self, "random")
|
|
|
+ elseif action_id == hash("key_2") and action.released then
|
|
|
+ spawn_enemy(self, "diagonal")
|
|
|
+ elseif action_id == hash("key_3") and action.released then
|
|
|
+ spawn_enemy(self, "straight")
|
|
|
+ end
|
|
|
+end
|