123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- local function Swarm() --constructor and class definition at once
- local this = {}
- --stores objects in swarm
- local swarm = {}
- local swarm_end_pointer = 0
- --compresses the table that stores the swarm, freeing the indexes
- --taken up by removed objectRefs
- --example:
- -- swarm = {obj1, obj4, nil, obj3, nil, obj4}
- -- swarm_end_pointer = 6
- -- becomes
- -- swarm = {obj1, obj4, obj4, obj3}
- -- swarm_end_pointer = 4
- function this:cleanup()
- local last = swarm_end_pointer
- local i = 1
- while i < last
- do
- local si = swarm[i]
- if si and not si.removed
- then
- i = i + 1
- else
- local sl = swarm[last]
- if sl and not sl.removed
- then
- swarm[i] = sl
- swarm[last] = nil
- last = last - 1
- i = i + 1
- else
- swarm[last] = nil
- last = last - 1
- end
- end
- end
- --set last to 0 if the swarm is empty
- local sl = swarm[last]
- if last == 1 and (not sl or sl.removed)
- then
- swarm[last] = nil
- last = 0
- end
- swarm_end_pointer = last
- end
- --adds an object to the swarm
- function this:signup(entity)
- swarm_end_pointer = swarm_end_pointer + 1
- swarm[swarm_end_pointer] = entity
- end
- --removes an object from the swarm
- function this:checkout(entity)
- for i = 0, swarm_end_pointer
- do
- if swarm[i] == entity
- then
- swarm[i] = nil
- return
- end
- end
- end
- --applies a function to all members of the swarm
- function this:alert(pos, radius, func)
- local nilvals = 0
- for i = 1, swarm_end_pointer
- do
- local entity = swarm[i]
- if entity and not entity.removed
- then
- local opos = entity.object:get_pos()
- if opos --we need to double check for when the entity is removed
- then
- local distance = vector.distance(pos, opos)
- if distance < radius or radius == 0
- then
- func(entity, distance)
- end
- else --entity has been removed
- nilvals = nilvals + 1
- end
- else
- --count nilvals to check if table should be cleaned
- nilvals = nilvals + 1
- end
- end
- --TODO: there's propably a better multiplier
- if nilvals * 2 > swarm_end_pointer or nilvals > 20
- then
- this:cleanup()
- end
- end
- return this
- end
- --[[
- --Testing stuff
- local swarm = Swarm()
- for i = 1, 6
- do
- swarm:signup(i)
- end
- local clk = os.clock()
- swarm:cleanup()
- print((os.clock() - clk) * 1000)
- --]]
- return Swarm
|