spawner.script 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. -- Pre-hash some strings string since they will be used a lot
  2. local TRIGGER_EVENT = hash("trigger_event")
  3. local GROUP_BULLET = hash("bullet")
  4. local GROUP_ENEMY = hash("enemy")
  5. -- Define different properties for different enemies:
  6. local ENEMY_TYPES = {
  7. random = {
  8. sprite = hash("ufoGreen"),
  9. health_points = 1,
  10. speed = vmath.vector3(40, -100, 0),
  11. is_random = true
  12. },
  13. diagonal = {
  14. sprite = hash("enemyRed2"),
  15. health_points = 2,
  16. speed = vmath.vector3(120, -80, 0),
  17. is_random = false
  18. },
  19. straight = {
  20. sprite = hash("enemyBlue4"),
  21. health_points = 3,
  22. speed = vmath.vector3(0, -40, 0),
  23. is_random = false
  24. }
  25. }
  26. -- Helper function to spawn given enemy by its type:
  27. local function spawn_enemy(self, enemy_type)
  28. -- Select properties of the enemy by type:
  29. local properties = ENEMY_TYPES[enemy_type]
  30. -- Set initial position of the spawned ship.
  31. local position = go.get_position()
  32. -- This will make the position one out of (-180, -90, 0, 90, 180):
  33. position.x = position.x + math.random(-2,2) * 90
  34. -- create enemy
  35. local id = factory.create("#enemyfactory", position)
  36. -- set animation of the sprite to the one defined by enemy properties
  37. local sprite_url = msg.url(nil, id, "sprite")
  38. sprite.play_flipbook(sprite_url, properties.sprite)
  39. -- Add randomness to horizontal direction - this way enemy horizontal speed may be inverted or cleared:
  40. -- -1 * self.speed.x - inverted direction
  41. -- 0 * self.speed.x - cleared direction
  42. -- 1 * self.speed.x - regular direction
  43. local speed = vmath.vector3(properties.speed)
  44. speed.x = speed.x * math.random(-1, 1)
  45. -- store enemy
  46. self.enemies[id] = {
  47. id = id,
  48. health = properties.health_points,
  49. speed = speed,
  50. is_random = properties.is_random,
  51. timer = 1
  52. }
  53. end
  54. function init(self)
  55. -- Acquire input focus here, so we can handle inputs:
  56. msg.post(".", "acquire_input_focus")
  57. self.enemies = {}
  58. -- listen to physics events
  59. -- in this case we care about trigger events between
  60. -- enemies and bullets
  61. physics.set_event_listener(function(self, events)
  62. for _,event in ipairs(events) do
  63. local event_type = event.type
  64. if event_type == TRIGGER_EVENT then
  65. -- get the bullet id and enemy id if the colliding objects belong to
  66. -- groups "bullet" and "enemy"
  67. -- this is the Lua way of writing a ternary operator
  68. local bullet_id = (event.a.group == GROUP_BULLET and event.a.id) or (event.b.group == GROUP_BULLET and event.b.id)
  69. local enemy_id = (event.a.group == GROUP_ENEMY and event.a.id) or (event.b.group == GROUP_ENEMY and event.b.id)
  70. -- not really necessary in this example but we might as well
  71. -- double-check that the detected collision was for a bullet and enemy
  72. if bullet_id and enemy_id then
  73. -- remove the bullet
  74. go.delete(bullet_id)
  75. -- get the enemy from the managed enemies list
  76. local enemy = self.enemies[enemy_id]
  77. -- Remove one health point
  78. enemy.health = enemy.health - 1
  79. -- When no health points left - remove this ship
  80. if enemy.health == 0 then
  81. go.delete(enemy_id)
  82. self.enemies[enemy_id] = nil
  83. -- Play particlefx for damage taken:
  84. particlefx.play(msg.url(nil, enemy_id, "boom"))
  85. end
  86. end
  87. end
  88. end
  89. end)
  90. end
  91. function update(self, dt)
  92. for id,enemy in pairs(self.enemies) do
  93. -- Update enemy position based on its current speed:
  94. local pos = go.get_position(id)
  95. pos = pos + enemy.speed * dt
  96. go.set_position(pos, id)
  97. -- Bounce enemy off "walls":
  98. if pos.x > 600 or pos.x < 50 then
  99. enemy.speed.x = -enemy.speed.x
  100. end
  101. -- Remove enemy if it goes out of screen:
  102. if pos.y < -50 then
  103. go.delete(id)
  104. self.enemies[id] = nil
  105. end
  106. -- If enemy has random movement decrease timer to
  107. -- randomly switch horizontal speed every second
  108. if enemy.is_random then
  109. enemy.timer = enemy.timer - dt
  110. if enemy.timer < 0 then
  111. enemy.timer = enemy.timer + 1
  112. enemy.speed.x = math.random(-1, 1) * enemy.speed.x
  113. end
  114. end
  115. end
  116. end
  117. function on_input(self, action_id, action)
  118. -- React to different key presses with spawning different enemies:
  119. if action_id == hash("key_1") and action.released then
  120. spawn_enemy(self, "random")
  121. elseif action_id == hash("key_2") and action.released then
  122. spawn_enemy(self, "diagonal")
  123. elseif action_id == hash("key_3") and action.released then
  124. spawn_enemy(self, "straight")
  125. end
  126. end