Here is a little particle engine I’ve made. It can produce effects like trails, explosions, fireworks, trails, shooting stars, flames and much more. It can be slow when animating lots of particles 300+ or less on slower devices. You are free to use the code if you wish
--# Main
-- Main
displayMode(OVERLAY)
function setup()
--_save("explosions","3.0",true)
parameter.watch("FPS")
parameter.watch("#explosions")
parameter.integer("numSparks",10,500,50)
parameter.number("damping",1.01,1.10,1.05)
parameter.number("velocity",0.1,1,0.5)
parameter.integer("MODE",1,3,2)--img,sq,circ
parameter.boolean("constant",false)
parameter.boolean("atTouch",false)
parameter.boolean("Rebound",true)
parameter.number("GRAVITY",0,5)
parameter.integer("Xwind",-10,10,0)
parameter.integer("Ywind",-10,10,0)
explosions = {}
img=readImage("Planet Cute:Star")
print("\
tap for an explosion\
")
print("scroll down to see all the parameters")
print("MODES:\
1=image\
2=square\
3=circle")
end
function draw()
gravity = vec2(0,-GRAVITY)
wind = vec2(Xwind,Ywind)
FPS=1/DeltaTime
background(0)
blendMode(ADDITIVE)
for i =1, #explosions do
explosions[i]:draw(gravity,wind)
end
cullexplosions()
if constant then
explosions[#explosions+1] = Sparks(origin.x,origin.y,numSparks/10,col,nil,30)
end
if not atTouch then origin=vec2(WIDTH/2,HEIGHT/2)end
end
function touched(touch)
if atTouch then origin=vec2(touch.x,touch.y)end
if touch.state == BEGAN and not constant then
explosions[#explosions+1] = Sparks(origin.x,origin.y,numSparks,col,nil,30)
end
end
function cullexplosions()
for i=#explosions,1,-1 do
if not explosions[i].alive then
table.remove(explosions,i)
end
end
end
--# Spark
Spark = class()
function Spark:init(x,y,c,t,size)
self.texture = img
self.size = math.random(size-20,size+20)
self.pos = vec2(x,y)
local vel = vec2(0,self.size*velocity)
self.velocity = vel:rotate(math.random(360))
self.col = color(255, 255, 0, 255)
self.alive = true
self.angle = math.random(360)
self.rotationdirection = math.random(-2,2)
self.damping=damping
--[[
self.IsSquare=Square
self.IsImg=Image
]]
self.type=MODE
end
function Spark:draw(g,w)
local _gravity = g or vec2(0,-1)
local _wind = w or vec2(1,0)
self:move(_gravity,_wind)
pushMatrix()
translate(self.pos.x,self.pos.y)
rotate(self.angle)
if self.type==1 then
tint(self.col)
sprite(self.texture,0,0, self.size)
else
fill(self.col)
if self.type==2 then
rectMode(CENTER)
rect(0,0, self.size,self.size)
else
ellipse(0,0, self.size)
end
end
popMatrix()
end
function Spark:move(g,w)
self.size = self.size / self.damping--math.random(1.1,1.5)
self.col.a = self.col.a /(self.damping)
self.col.r = self.col.r / self.damping
self.col.g = self.col.g / (self.damping^3)
self.velocity = self.velocity / self.damping
self.velocity = self.velocity + g
--self.velocity = self.velocity:rotate(0.1)
self.pos = self.pos + self.velocity
self.pos = self.pos + w
self.pos = self.pos + g
if self.col.a <= 50 then self.alive = false end
self.angle = self.angle + self.rotationdirection*self.velocity:len()
if Rebound then
if self.pos.y<=0 then self.velocity.y=math.max(self.velocity.y,-self.velocity.y)end
if self.pos.y>=HEIGHT then self.velocity.y=math.min(self.velocity.y,-self.velocity.y)end
if self.pos.x<=0 then self.velocity.x=math.max(self.velocity.x,-self.velocity.x)end
if self.pos.x>=WIDTH then self.velocity.x=math.min(self.velocity.x,-self.velocity.x)end
end
end
Sparks = class()
function Sparks:init(x,y,amount,col,img,size)
self.alive = true
self.sparktable={}
for i = 1, amount do
self.sparktable[i]=Spark(x,y,col or color(math.random(200,255), math.random(0,200), 0,255),img,size)
end
end
function Sparks:draw(grav,wind)
for i = 1, #self.sparktable do
self.sparktable[i]:draw(grav,wind)
end
local i = 1
while i <= #self.sparktable do
if not self.sparktable[i].alive then
table.remove(self.sparktable,i)
i = i - 1
end
i = i + 1
end
if #self.sparktable == 0 then self.alive = false end
end