ParticleSystems in Rebound
Posted: Sat Mar 30, 2013 4:19 pm
So, I think the particle effects in Rebound (0.8.0 compatible version here) by TechnoCat look really really cool, so thought I'd try to figure out how they work.
Here are some files with the individual particle systems in them for playing around with:
Note: What I describe isn't necessarily exactly what is in the game!
So basically...
love.graphics.setBackgroundColor(30, 30, 30)
And vsync is off.
Paddles!
The paddle's particle systems use this image:
Here are the beginnings of the top part of a paddle:
The "200" in love.graphics.newParticleSystem means this particle system has a maximum of 200 particles.
The setDirection sets the direction in radians, and math.pi/2 points down.
setParticleLife(0.6) means the particles are removed after 0.6 seconds.
setSpread(math.pi/16) sets the initial direction to a direction within the angle of math.pi/16.
This arc shows the angle:
setSizes(1, 0) changes the particle size from full size (1 times the size) at the start of the particle's life, and no size at the end (0 times the size).
setEmissionRate(100) means 100 particles are emitted every second.
setSpeed(0, 400) sets a random speed between 0 and 400.
setColors(r,g,b,128, r/2,g/2,b/2,0) fades the colour from the paddle's colour at half transparency at the start of the particle's life, and half the paddle's colour value completely transparent at the end of the particle's life.
love.graphics.setBlendMode('additive') sets the blend mode to additive.
I think the equation for additive blend mode is this, for each colour component (red, green and blue):
final colour = whatever is already there + (new colour component value * new colour alpha)
(You can check out the other formulas here.)
There is another particle system for each paddle which is pretty much identical except that it's further down and the direction is up. And that's it!
Ball!
The ball, upgrades, and background all use this image in their particle systems:
So, here's a start:
p1 = love.graphics.newParticleSystem(ball, 200)
p1:setEmissionRate(10) -- Temporary!
p1:setSpeed(250) -- Just for demonstration!
p1:setParticleLife(0.5)
The ball has no speed, and the emitter itself is what moves. This means the direction has no effect.
The particles are alive for half a second.
setSizes(1, 0.5)
The particle sizes transition from full size to half size.
setEmissionRate(100)
There are 100 particles emitted per second.
setColors(220,105,20,255, 194,30,18,0)
The colour transitions from opaque orange to a fully transparent red.
And now with additive blending!
love.graphics.setBlendMode('additive')
Now for the the ball's second particle system.
p2 = love.graphics.newParticleSystem(ball, 200)
p2:setEmissionRate(10) -- Temporary!
p2:setParticleLife(0.75)
p2:setSizes(0.25, 1)
p2:setColors(220,105,20,20, 194,30,18,0)
p1:setSpeed(250) -- Just for demonstration!
setSizes(0.25, 1)
setEmissionRate(50)
setColors(r,g,b,255, 194,30,18,0)
The colour fades from the colour of the paddle which it last bounced off, and the same transparent red as in the ball's other particle system.
love.graphics.setBlendMode('additive')
And there's a circle too, also in the same colour as the last bounced paddle.
Here's everything together, it both colours.
Upgrades!
p = love.graphics.newParticleSystem(ball, 200)
p = love.graphics.newParticleSystem(ball, 200)
p:setPosition(x, y)
p:setEmissionRate(10) -- Temporary!
p:setParticleLife(0.5)
p:setSpeed(200)
p:setSizes(1, 0.5)
setEmissionRate(100)
setColors(r,g,b,255, 64,64,128,128)
Colours fade between green (0, 255, 0) or red (255, 0, 0) and a half transparent blue.
love.graphics.setBlendMode('additive')
setTangentialAcceleration(500)
setRadialAcceleration(-1200)
p1:setSpread(2)
The direction of the emitter is rotated in love.update.
And that's it!
Additive blend mode makes the upgrades looks super cool when they overlap.
Background!
Here's one part of the background:
p1 = love.graphics.newParticleSystem(ball, 200)
p1:setSpread(2*math.pi)
p1:setParticleLife(5)
p1:setSpeed(0, 200)
p1:setColors(0,0,0,128, 50,50,50,0)
p1:setEmissionRate(20)
p1:setSizes(1, 4)
p1:setTangentialAcceleration(200)
There are 2 * math.pi radians in a circle, so setSpread(2*math.pi) makes the emitter emit particles in all directions.
Here's the other part:
p2 = love.graphics.newParticleSystem(ball, 200)
p2:setSpread(2*math.pi)
p2:setParticleLife(5)
p2:setSpeed(0, 200)
p2:setColors(0, 0, 0, 128, 50, 50, 50, 0)
p2:setEmissionRate(10)
p2:setSizes(0, 1)
p2:setRadialAcceleration(-10)
setRadialAcceleration(-10) sets some acceleration toward the emitter, making the particles slow down.
And here's the background with both layers:
Here are some files with the individual particle systems in them for playing around with:
Note: What I describe isn't necessarily exactly what is in the game!
So basically...
- Each paddle has two particle systems, each going in opposite directions.
- The ball is made from a circle two particle systems and doesn't have any speed, the effect is created just by moving it. The circle and one of the particle systems changes colour depending on which paddle it bounced off last.
- The upgrades are made from a particle system with its direction being spun around.
- The background is made from two particle systems, one for the rotating larger pieces and one for the slower, finer pieces.
- Additive blend mode makes everything look all glowy.
love.graphics.setBackgroundColor(30, 30, 30)
And vsync is off.
Paddles!
The paddle's particle systems use this image:
Here are the beginnings of the top part of a paddle:
Code: Select all
function love.load()
square = love.graphics.newImage('square.png')
p = love.graphics.newParticleSystem(square, 200)
p:setPosition(x, y)
p:setDirection(math.pi/2)
p:setParticleLife(0.6)
p:setEmissionRate(10) -- Temporary!
p:setSpeed(200) -- Temporary!
love.graphics.setBackgroundColor(30, 30, 30)
end
function love.update(dt)
p:update(dt)
end
function love.draw()
love.graphics.draw(p1, 0, 0)
end
The setDirection sets the direction in radians, and math.pi/2 points down.
setParticleLife(0.6) means the particles are removed after 0.6 seconds.
setSpread(math.pi/16) sets the initial direction to a direction within the angle of math.pi/16.
This arc shows the angle:
setSizes(1, 0) changes the particle size from full size (1 times the size) at the start of the particle's life, and no size at the end (0 times the size).
setEmissionRate(100) means 100 particles are emitted every second.
setSpeed(0, 400) sets a random speed between 0 and 400.
setColors(r,g,b,128, r/2,g/2,b/2,0) fades the colour from the paddle's colour at half transparency at the start of the particle's life, and half the paddle's colour value completely transparent at the end of the particle's life.
love.graphics.setBlendMode('additive') sets the blend mode to additive.
I think the equation for additive blend mode is this, for each colour component (red, green and blue):
final colour = whatever is already there + (new colour component value * new colour alpha)
(You can check out the other formulas here.)
There is another particle system for each paddle which is pretty much identical except that it's further down and the direction is up. And that's it!
Ball!
The ball, upgrades, and background all use this image in their particle systems:
So, here's a start:
p1 = love.graphics.newParticleSystem(ball, 200)
p1:setEmissionRate(10) -- Temporary!
p1:setSpeed(250) -- Just for demonstration!
p1:setParticleLife(0.5)
The ball has no speed, and the emitter itself is what moves. This means the direction has no effect.
The particles are alive for half a second.
setSizes(1, 0.5)
The particle sizes transition from full size to half size.
setEmissionRate(100)
There are 100 particles emitted per second.
setColors(220,105,20,255, 194,30,18,0)
The colour transitions from opaque orange to a fully transparent red.
And now with additive blending!
love.graphics.setBlendMode('additive')
Now for the the ball's second particle system.
p2 = love.graphics.newParticleSystem(ball, 200)
p2:setEmissionRate(10) -- Temporary!
p2:setParticleLife(0.75)
p2:setSizes(0.25, 1)
p2:setColors(220,105,20,20, 194,30,18,0)
p1:setSpeed(250) -- Just for demonstration!
setSizes(0.25, 1)
setEmissionRate(50)
setColors(r,g,b,255, 194,30,18,0)
The colour fades from the colour of the paddle which it last bounced off, and the same transparent red as in the ball's other particle system.
love.graphics.setBlendMode('additive')
And there's a circle too, also in the same colour as the last bounced paddle.
Here's everything together, it both colours.
Upgrades!
p = love.graphics.newParticleSystem(ball, 200)
p = love.graphics.newParticleSystem(ball, 200)
p:setPosition(x, y)
p:setEmissionRate(10) -- Temporary!
p:setParticleLife(0.5)
p:setSpeed(200)
p:setSizes(1, 0.5)
setEmissionRate(100)
setColors(r,g,b,255, 64,64,128,128)
Colours fade between green (0, 255, 0) or red (255, 0, 0) and a half transparent blue.
love.graphics.setBlendMode('additive')
setTangentialAcceleration(500)
setRadialAcceleration(-1200)
p1:setSpread(2)
The direction of the emitter is rotated in love.update.
Code: Select all
d = d - (30*dt)
if d < 0 then
d = d + 2*math.pi
end
p:setDirection(d)
p:update(dt)
Additive blend mode makes the upgrades looks super cool when they overlap.
Background!
Here's one part of the background:
p1 = love.graphics.newParticleSystem(ball, 200)
p1:setSpread(2*math.pi)
p1:setParticleLife(5)
p1:setSpeed(0, 200)
p1:setColors(0,0,0,128, 50,50,50,0)
p1:setEmissionRate(20)
p1:setSizes(1, 4)
p1:setTangentialAcceleration(200)
There are 2 * math.pi radians in a circle, so setSpread(2*math.pi) makes the emitter emit particles in all directions.
Here's the other part:
p2 = love.graphics.newParticleSystem(ball, 200)
p2:setSpread(2*math.pi)
p2:setParticleLife(5)
p2:setSpeed(0, 200)
p2:setColors(0, 0, 0, 128, 50, 50, 50, 0)
p2:setEmissionRate(10)
p2:setSizes(0, 1)
p2:setRadialAcceleration(-10)
setRadialAcceleration(-10) sets some acceleration toward the emitter, making the particles slow down.
And here's the background with both layers: