Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ParticleSim = class()
- function ParticleSim:init()
- self.particles = {}
- self.types = {}
- self.pEllipses = {}
- self.spawnerTypes = {
- "touch_began",
- "touch_move",
- "touch_ended",
- "loop_random_pos",
- "loop_set_pos",
- "chance_random_pos",
- "chance_set_pos"
- }
- self.behaviorTypes = {
- "timeout",
- "chance_timeout",
- "spawn_particle",
- "chance_spawn_particle",
- "loop_spawn_particle",
- "wander",
- "move_straight",
- "gravity",
- "timeout_radius",
- "loop_change_direction",
- "chance_change_direction",
- "init_velocity"
- }
- self.timer = 0
- self.remove = {}
- end
- function ParticleSim:newType(name)
- if self.types[name] == nil then
- self.types[name] = {
- ["drawLayers"] = {},
- ["spawners"] = {},
- ["slowdown"] = 0.9,
- ["behaviors"] = {
- ["default"] = {},
- ["spawn"] = {},
- ["duplicate"] = {},
- ["despawn"] = {}
- }
- }
- end
- end
- function ParticleSim:setSlowdown(t, s)
- self:newType(t)
- self.types[t]["slowdown"] = s
- end
- function ParticleSim:addDrawLayer(name, col, size, layer, cVariation, sVariation)
- self:newType(name)
- local cv = 0
- if cVariation ~= nil then
- cv = cVariation
- end
- local sv = 0
- if sVariation ~= nil then
- sv = sVariation
- end
- table.insert(self.types[name]["drawLayers"], {col, size, layer, cv, sv})
- end
- function ParticleSim:addSpawner(name, spawner, params)
- self:newType(name)
- local isValid = false
- for k, v in pairs(self.spawnerTypes) do
- if v == spawner then
- isValid = true
- end
- end
- if isValid then
- table.insert(self.types[name]["spawners"], {[spawner] = params})
- end
- end
- function ParticleSim:addBehavior(name, behavior, params, trigger)
- self:newType(name)
- local isValid = false
- for k, v in pairs(self.behaviorTypes) do
- if v == behavior then
- isValid = true
- end
- end
- local t
- if trigger ~= "spawn" and trigger ~= "duplicate" and trigger ~= "despawn" then
- t = "default"
- else
- t = trigger
- end
- if isValid then
- table.insert(self.types[name]["behaviors"][t], {[behavior] = params})
- end
- end
- function ParticleSim:doSpawners()
- for t, d in pairs(self.types) do
- for bn, tb in pairs(d["spawners"]) do
- -- Touch began
- if tb["touch_began"] ~= nil then
- if CurrentTouch.state == BEGAN then
- self:addParticle(t, CurrentTouch.x, CurrentTouch.y, 0, 0)
- end
- end
- -- Touch moved
- if tb["touch_move"] ~= nil then
- if CurrentTouch.state == MOVING then
- self:addParticle(t, CurrentTouch.x, CurrentTouch.y, 0, 0)
- end
- end
- -- Touch ended
- if tb["touch_ended"] ~= nil then
- if CurrentTouch.state == ENDED then
- self:addParticle(t, CurrentTouch.x, CurrentTouch.y, 0, 0)
- end
- end
- -- Loop at random postion
- if tb["loop_random_pos"] ~= nil then
- if tb["loop_random_pos"]["time"] == nil then
- tb["loop_random_pos"]["time"] = 20
- end
- if self.timer % tb["loop_random_pos"]["time"] == 0 then
- self:addParticle(t, math.random(0, WIDTH), math.random(0, HEIGHT), 0, 0)
- end
- end
- -- Loop at set postion
- if tb["loop_set_pos"] ~= nil then
- if tb["loop_set_pos"]["time"] == nil then
- tb["loop_set_pos"]["time"] = 20
- end
- if tb["loop_set_pos"]["x"] == nil then
- tb["loop_set_pos"]["x"] = WIDTH / 2
- end
- if tb["loop_set_pos"]["y"] == nil then
- tb["loop_set_pos"]["y"] = HEIGHT / 2
- end
- if self.timer % tb["loop_set_pos"]["time"] == 0 then
- self:addParticle(t, tb["loop_set_pos"]["x"], tb["loop_set_pos"]["y"], 0, 0)
- end
- end
- -- Random chance at random postion
- if tb["chance_random_pos"] ~= nil then
- if tb["chance_random_pos"]["chance"] == nil then
- tb["chance_random_pos"]["chance"] = 15
- end
- if math.random(1, tb["chance_random_pos"]["chance"]) == 1 then
- self:addParticle(t, math.random(0, WIDTH), math.random(0, HEIGHT), 0, 0)
- end
- end
- -- Random chance at set postion
- if tb["chance_set_pos"] ~= nil then
- if tb["chance_set_pos"]["chance"] == nil then
- tb["chance_set_pos"]["chance"] = 15
- end
- if tb["chance_set_pos"]["x"] == nil then
- tb["chance_set_pos"]["x"] = WIDTH / 2
- end
- if tb["chance_set_pos"]["y"] == nil then
- tb["chance_set_pos"]["y"] = HEIGHT / 2
- end
- if math.random(1, tb["chance_set_pos"]["chance"]) == 1 then
- self:addParticle(t, tb["chance_set_pos"]["x"], tb["chance_set_pos"]["y"], 0, 0)
- end
- end
- end
- end
- end
- function ParticleSim:addParticle(t, x, y, xv, yv)
- local isValid = false
- for k, v in pairs(self.types) do
- if k == t then
- isValid = true
- end
- end
- if isValid then
- local va = {}
- for k, v in pairs(self.types[t]["drawLayers"]) do
- local c = v[4]
- local s = v[5]
- table.insert(va, {math.random(-s, s), math.random(-c, c), math.random(-c, c), math.random(-c, c), math.random(-c, c)})
- end
- table.insert(self.particles, {
- ["type"] = t,
- ["pos"] = vec2(x, y),
- ["vel"] = vec2(xv, yv),
- ["data"] = self:copyTWithRandomizers(self.types[t]),
- ["var"] = self:copyT(va)
- })
- end
- end
- function ParticleSim:getPEllipses()
- for _, p in pairs(self.particles) do
- local pes = p["data"]["drawLayers"]
- for k, pe in pairs(pes) do
- local c = color(pe[1].r, pe[1].g, pe[1].b, pe[1].a)
- c.r = c.r + p["var"][k][2]
- c.g = c.g + p["var"][k][3]
- c.b = c.b + p["var"][k][4]
- c.a = c.a + p["var"][k][5]
- self:addPEllipse(p["pos"], c, pe[2] + p["var"][k][1], pe[3])
- end
- end
- end
- function ParticleSim:addPEllipse(pos, col, size, layer)
- if self.pEllipses[layer] == nil then
- self.pEllipses[layer] = {}
- end
- table.insert(self.pEllipses[layer], {pos, col, size})
- end
- function ParticleSim:drawPEllipses()
- self.pEllipses = {}
- self:getPEllipses()
- if self.pEllipses ~= {} then
- local min = 9999
- while min < 1000000000000 do
- min = 1000000000000
- for k, v in pairs(self.pEllipses) do
- if k < min then
- min = k
- end
- end
- if self.pEllipses[min] ~= nil then
- for _, v in pairs(self.pEllipses[min]) do
- pushStyle()
- fill(v[2])
- noStroke()
- ellipse(v[1].x, v[1].y, v[3], v[3])
- popStyle()
- end
- end
- self.pEllipses[min] = nil
- end
- end
- end
- function ParticleSim:pBehavior(i, t, tri)
- local d = self.particles[i]
- for bn, tb in pairs(self.particles[i]["data"]["behaviors"][t]) do
- if tri then
- if d["spawnTimer"] == nil then
- d["spawnTimer"] = 0
- else
- d["spawnTimer"] = d["spawnTimer"] + 1
- end
- if d["spawnTimer"] <= 1 then
- if tri then
- self:pBehavior(i, "spawn", false)
- end
- end
- end
- -- Delete particles after a set amount of time
- if tb["timeout"] ~= nil then
- if tb["timeout"]["currentTime"] == nil then
- tb["timeout"]["currentTime"] = 0
- else
- tb["timeout"]["currentTime"] = tb["timeout"]["currentTime"] + 1
- end
- if tb["timeout"]["time"] == nil then
- tb["timeout"]["time"] = 120
- end
- if tb["timeout"]["currentTime"] == tb["timeout"]["time"] then
- table.insert(self.remove, i)
- if tri then
- self:pBehavior(i, "despawn", false)
- end
- end
- end
- -- Delete particles at random each frame
- if tb["chance_timeout"] ~= nil then
- if tb["chance_timeout"]["chance"] == nil then
- tb["chance_timeout"]["chance"] = 100
- end
- if math.random(1, tb["chance_timeout"]["chance"]) == 1 then
- table.insert(self.remove, i)
- if tri then
- self:pBehavior(i, "despawn", false)
- end
- end
- end
- -- Spawn particles from other particles
- if tb["spawn_particle"] ~= nil then
- if tb["spawn_particle"]["type"] == nil then
- tb["spawn_particle"]["type"] = d["type"]
- end
- if tb["spawn_particle"]["time"] == nil then
- tb["spawn_particle"]["time"] = 100
- end
- if tb["spawn_particle"]["currentTime"] == nil then
- tb["spawn_particle"]["currentTime"] = 0
- else
- tb["spawn_particle"]["currentTime"] = tb["spawn_particle"]["currentTime"] + 1
- end
- if tb["spawn_particle"]["amount"] == nil then
- tb["spawn_particle"]["amount"] = 1
- end
- if tb["spawn_particle"]["currentTime"] == tb["spawn_particle"]["time"] then
- for i = 1, tb["spawn_particle"]["amount"] do
- self:addParticle(tb["spawn_particle"]["type"], d["pos"].x, d["pos"].y, d["vel"].x, d["vel"].y)
- end
- if tri then
- self:pBehavior(i, "duplicate", false)
- end
- end
- end
- -- Spawn particles from other particles with a chance
- if tb["chance_spawn_particle"] ~= nil then
- if tb["chance_spawn_particle"]["type"] == nil then
- tb["chance_spawn_particle"]["type"] = d["type"]
- end
- if tb["chance_spawn_particle"]["chance"] == nil then
- tb["chance_spawn_particle"]["chance"] = 50
- end
- if tb["chance_spawn_particle"]["amount"] == nil then
- tb["chance_spawn_particle"]["amount"] = 1
- end
- if math.random(1, tb["chance_spawn_particle"]["chance"]) == 1 then
- for i = 1, tb["chance_spawn_particle"]["amount"] do
- self:addParticle(tb["chance_spawn_particle"]["type"], d["pos"].x, d["pos"].y, d["vel"].x, d["vel"].y)
- end
- if tri then
- self:pBehavior(i, "duplicate", false)
- end
- end
- end
- -- Spawn particles from other particles on an interval
- if tb["loop_spawn_particle"] ~= nil then
- if tb["loop_spawn_particle"]["type"] == nil then
- tb["loop_spawn_particle"]["type"] = d["type"]
- end
- if tb["loop_spawn_particle"]["time"] == nil then
- tb["loop_spawn_particle"]["time"] = 50
- end
- if tb["loop_spawn_particle"]["currentTime"] == nil then
- tb["loop_spawn_particle"]["currentTime"] = 1
- else
- tb["loop_spawn_particle"]["currentTime"] = tb["loop_spawn_particle"]["currentTime"] + 1
- end
- if tb["loop_spawn_particle"]["amount"] == nil then
- tb["loop_spawn_particle"]["amount"] = 1
- end
- if tb["loop_spawn_particle"]["currentTime"] % tb["loop_spawn_particle"]["time"] == 0 then
- for i = 1, tb["loop_spawn_particle"]["amount"] do
- self:addParticle(tb["loop_spawn_particle"]["type"], d["pos"].x, d["pos"].y, d["vel"].x, d["vel"].y)
- end
- if tri then
- self:pBehavior(i, "duplicate", false)
- end
- end
- end
- -- Move around randomly
- if tb["wander"] ~= nil then
- if tb["wander"]["amount"] == nil then
- tb["wander"]["amount"] = 2
- end
- local move = vec2(tb["wander"]["amount"], 0)
- move = move:rotate(math.rad(math.random(0, 359)))
- d["vel"] = d["vel"] + move
- end
- -- Move in a straight line
- if tb["move_straight"] ~= nil then
- if tb["move_straight"]["dir"] == nil then
- tb["move_straight"]["dir"] = 90
- end
- if tb["move_straight"]["speed"] == nil then
- tb["move_straight"]["speed"] = 2
- end
- local move = vec2(tb["move_straight"]["speed"], 0)
- move = move:rotate(math.rad(tb["move_straight"]["dir"]))
- d["vel"] = d["vel"] + move
- end
- -- Apply gravity
- if tb["gravity"] ~= nil then
- if tb["gravity"]["x"] == nil then
- tb["gravity"]["x"] = 0
- end
- if tb["gravity"]["y"] == nil then
- tb["gravity"]["y"] = -0.07
- end
- if tb["gravity"]["xv"] == nil then
- tb["gravity"]["xv"] = 0
- else
- tb["gravity"]["xv"] = tb["gravity"]["xv"] + tb["gravity"]["x"]
- end
- if tb["gravity"]["yv"] == nil then
- tb["gravity"]["yv"] = 0
- else
- tb["gravity"]["yv"] = tb["gravity"]["yv"] + tb["gravity"]["y"]
- end
- d["vel"] = d["vel"] + vec2(tb["gravity"]["xv"], tb["gravity"]["yv"])
- end
- -- Delete a particle if it goes too far from the center of the screen
- if tb["timeout_radius"] ~= nil then
- if tb["timeout_radius"]["radius"] == nil then
- tb["timeout_radius"]["radius"] = 750
- end
- if vec2(WIDTH / 2, HEIGHT / 2):dist(d["pos"]) > tb["timeout_radius"]["radius"] then
- table.insert(self.remove, i)
- if tri then
- self:pBehavior(i, "despawn", false)
- end
- end
- end
- -- Have a particle change direction periodically
- if tb["loop_change_direction"] ~= nil then
- if tb["loop_change_direction"]["time"] == nil then
- tb["loop_change_direction"]["time"] = 30
- end
- if tb["loop_change_direction"]["currentTime"] == nil then
- tb["loop_change_direction"]["currentTime"] = 1
- else
- tb["loop_change_direction"]["currentTime"] = tb["loop_change_direction"]["currentTime"] + 1
- end
- if tb["loop_change_direction"]["direction"] == nil then
- tb["loop_change_direction"]["direction"] = math.random(0, 359)
- end
- if tb["loop_change_direction"]["speed"] == nil then
- tb["loop_change_direction"]["speed"] = 0.5
- end
- if tb["loop_change_direction"]["currentTime"] % tb["loop_change_direction"]["time"] == 0 then
- tb["loop_change_direction"]["direction"] = math.random(0, 359)
- end
- local move = vec2(tb["loop_change_direction"]["speed"], 0)
- move = move:rotate(math.rad(tb["loop_change_direction"]["direction"]))
- d["vel"] = d["vel"] + move
- end
- -- Have a particle chance direction with a chance
- if tb["chance_change_direction"] ~= nil then
- if tb["chance_change_direction"]["chance"] == nil then
- tb["chance_change_direction"]["chance"] = 30
- end
- if tb["chance_change_direction"]["speed"] == nil then
- tb["chance_change_direction"]["speed"] = 0.5
- end
- if tb["chance_change_direction"]["direction"] == nil then
- tb["chance_change_direction"]["direction"] = math.random(0, 359)
- end
- if math.random(1, tb["chance_change_direction"]["chance"]) == 1 then
- tb["chance_change_direction"]["direction"] = math.random(0, 359)
- end
- local move = vec2(tb["chance_change_direction"]["speed"], 0)
- move = move:rotate(math.rad(tb["chance_change_direction"]["direction"]))
- d["vel"] = d["vel"] + move
- end
- if tb["init_velocity"] ~= nil then
- if tb["init_velocity"]["x"] == nil then
- tb["init_velocity"]["x"] = 0
- end
- if tb["init_velocity"]["y"] == nil then
- tb["init_velocity"]["y"] = 10
- end
- if tb["init_velocity"]["time"] == nil then
- tb["init_velocity"]["time"] = 0
- else
- tb["init_velocity"]["time"] = tb["init_velocity"]["time"] + 1
- end
- if tb["init_velocity"]["time"] == 0 then
- d["vel"] = vec2(tb["init_velocity"]["x"], tb["init_velocity"]["y"])
- end
- end
- end
- -- Do movement
- d["vel"] = d["vel"] * self.types[d["type"]]["slowdown"]
- d["pos"] = d["pos"] + d["vel"]
- end
- function ParticleSim:doBehaviors()
- self.remove = {}
- for t, d in pairs(self.particles) do
- self:pBehavior(t, "default", true)
- end
- for k, v in pairs(self.remove) do
- self.particles[v] = nil
- end
- end
- function ParticleSim:draw()
- self.timer = self.timer + 1
- self:doBehaviors()
- self:doSpawners()
- self:drawPEllipses()
- end
- function ParticleSim:copyT(t)
- local ret = {}
- for k, v in pairs(t) do
- if type(v) == "table" then
- ret[k] = self:copyT(v)
- else
- ret[k] = v
- end
- end
- return ret
- end
- function ParticleSim:copyTWithRandomizers(t)
- local ret = {}
- for k, v in pairs(t) do
- if type(v) == "table" then
- if #v == 2 and type(v[1]) == "number" and type(v[2]) == "number" then
- local mi, ma
- if v[1] > v[2] then
- mi = v[2]
- ma = v[1]
- else
- mi = v[1]
- ma = v[2]
- end
- ret[k] = math.random(mi * 1000, ma * 1000) / 1000
- else
- ret[k] = self:copyTWithRandomizers(v)
- end
- else
- ret[k] = v
- end
- end
- return ret
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement