swarm.lua 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. local function Swarm() --constructor and class definition at once
  2. local this = {}
  3. --stores objects in swarm
  4. local swarm = {}
  5. local swarm_end_pointer = 0
  6. --compresses the table that stores the swarm, freeing the indexes
  7. --taken up by removed objectRefs
  8. --example:
  9. -- swarm = {obj1, obj4, nil, obj3, nil, obj4}
  10. -- swarm_end_pointer = 6
  11. -- becomes
  12. -- swarm = {obj1, obj4, obj4, obj3}
  13. -- swarm_end_pointer = 4
  14. function this:cleanup()
  15. local last = swarm_end_pointer
  16. local i = 1
  17. while i < last
  18. do
  19. local si = swarm[i]
  20. if si and not si.removed
  21. then
  22. i = i + 1
  23. else
  24. local sl = swarm[last]
  25. if sl and not sl.removed
  26. then
  27. swarm[i] = sl
  28. swarm[last] = nil
  29. last = last - 1
  30. i = i + 1
  31. else
  32. swarm[last] = nil
  33. last = last - 1
  34. end
  35. end
  36. end
  37. --set last to 0 if the swarm is empty
  38. local sl = swarm[last]
  39. if last == 1 and (not sl or sl.removed)
  40. then
  41. swarm[last] = nil
  42. last = 0
  43. end
  44. swarm_end_pointer = last
  45. end
  46. --adds an object to the swarm
  47. function this:signup(entity)
  48. swarm_end_pointer = swarm_end_pointer + 1
  49. swarm[swarm_end_pointer] = entity
  50. end
  51. --removes an object from the swarm
  52. function this:checkout(entity)
  53. for i = 0, swarm_end_pointer
  54. do
  55. if swarm[i] == entity
  56. then
  57. swarm[i] = nil
  58. return
  59. end
  60. end
  61. end
  62. --applies a function to all members of the swarm
  63. function this:alert(pos, radius, func)
  64. local nilvals = 0
  65. for i = 1, swarm_end_pointer
  66. do
  67. local entity = swarm[i]
  68. if entity and not entity.removed
  69. then
  70. local opos = entity.object:get_pos()
  71. if opos --we need to double check for when the entity is removed
  72. then
  73. local distance = vector.distance(pos, opos)
  74. if distance < radius or radius == 0
  75. then
  76. func(entity, distance)
  77. end
  78. else --entity has been removed
  79. nilvals = nilvals + 1
  80. end
  81. else
  82. --count nilvals to check if table should be cleaned
  83. nilvals = nilvals + 1
  84. end
  85. end
  86. --TODO: there's propably a better multiplier
  87. if nilvals * 2 > swarm_end_pointer or nilvals > 20
  88. then
  89. this:cleanup()
  90. end
  91. end
  92. return this
  93. end
  94. --[[
  95. --Testing stuff
  96. local swarm = Swarm()
  97. for i = 1, 6
  98. do
  99. swarm:signup(i)
  100. end
  101. local clk = os.clock()
  102. swarm:cleanup()
  103. print((os.clock() - clk) * 1000)
  104. --]]
  105. return Swarm