Created
November 7, 2011 00:58
-
-
Save itsbth/1343935 to your computer and use it in GitHub Desktop.
Uploaded by UploadToGist for Sublime Text 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| local Vector | |
| do | |
| local V_MT, sqrt, type, unpack, setmetatable = {}, math.sqrt, type, unpack, setmetatable | |
| V_MT.__index = V_MT | |
| function V_MT:__add(b) | |
| return Vector(self.x + b.x, self.y + b.y) | |
| end | |
| function V_MT:__sub(b) | |
| return Vector(self.x - b.x, self.y - b.y) | |
| end | |
| function V_MT:__mul(b) | |
| return Vector(self.x * b, self.y * b) | |
| end | |
| function V_MT:__div(b) | |
| return Vector(self.x / b, self.y / b) | |
| end | |
| function V_MT:__tostring() | |
| return ("{%f, %f}"):format(self.x, self.y) | |
| end | |
| function V_MT:length() | |
| return math.sqrt(self.x * self.x + self.y * self.y) | |
| end | |
| function V_MT:length2() | |
| return self.x * self.x + self.y * self.y | |
| end | |
| function V_MT:normalized() | |
| return self / self:length() | |
| end | |
| function Vector(x, y) | |
| if type(x) == 'table' then | |
| if x.x then | |
| x, y = x.x, x.y | |
| else | |
| x, y = unpack(x) | |
| end | |
| end | |
| return setmetatable({x = x or 0, y = y or 0}, V_MT) | |
| end | |
| end | |
| local Particle, ParticleSystem | |
| do | |
| local PT_PROTO = {} | |
| PT_PROTO.__index = PT_PROTO | |
| function PT_PROTO:init(data) | |
| data = data or {} | |
| self.birth = love.timer.getMicroTime() | |
| self.lifetime = data.lifetime | |
| self.vel = data.vel or Vector(0, 0) | |
| if self.setup then self:setup(data) end | |
| end | |
| function PT_PROTO:think(dt) | |
| self.pos = self.pos + self.vel * dt | |
| self.age = love.timer.getMicroTime() - self.birth | |
| if self.lifetime < self.age then | |
| if not (self.death and self:death()) then | |
| self.dead = true | |
| end | |
| end | |
| if self.update then self:update(dt) end | |
| end | |
| function Particle(tbl) | |
| tbl.__index = tbl | |
| setmetatable(tbl, PT_PROTO) | |
| return function (system, pos, ...) | |
| local part = {system, pos = pos} | |
| setmetatable(part, tbl) | |
| if part.init then part:init(...) end | |
| return part | |
| end | |
| end | |
| local PS_MT = {} | |
| PS_MT.__index = PS_MT | |
| function PS_MT:create(pos, ...) | |
| self.particles[#self.particles + 1] = self:pt_create(pos, ...) | |
| end | |
| function PS_MT:draw() | |
| for _, v in ipairs(self.particles) do | |
| if v and not v.dead then v:draw() end | |
| end | |
| end | |
| function PS_MT:think(dt) | |
| for _, v in ipairs(self.particles) do | |
| if v and not v.dead then v:think(dt) end | |
| end | |
| end | |
| function PS_MT:trim() | |
| -- XXX: skips one particle per particle removed | |
| for i = 1, #self.particles do | |
| -- TODO: Break out of loop if self.particles[i] == nil? | |
| if self.particles[i] and self.particles[i].dead then | |
| table.remove(self.particles, i) | |
| end | |
| end | |
| end | |
| function ParticleSystem(new_part) | |
| local ps = {pt_create = new_part, particles = {}} | |
| setmetatable(ps, PS_MT) | |
| return ps | |
| end | |
| end | |
| Explosion = Particle { | |
| setup = function (self, data) | |
| self.elapsed = 0 | |
| self.color = data.color | |
| end, | |
| draw = function (self) | |
| local r, t = (1 - (love.timer.getMicroTime() - self.birth) / self.lifetime), self.pos - self.vel:normalized() * 0.5 | |
| if r < 0.1 then r = 1 end | |
| self.color[4] = 255 * r | |
| love.graphics.setColor(self.color) | |
| love.graphics.line(self.pos.x, self.pos.y, t.x, t.y) | |
| end, | |
| update = function (self, dt) | |
| if self.age > 0.1 and not self.slowdown then | |
| self.vel = self.vel / 200 | |
| self.slowdown = true | |
| end | |
| end | |
| } | |
| Rocket = Particle { | |
| setup = function (self, data) | |
| self.emitter = data.emitter | |
| self.sound = data.sound | |
| self.trail = {self.pos.x, self.pos.y} | |
| end, | |
| update = function (self, dt) | |
| self.vel.y = self.vel.y + 100*dt*dt | |
| self.trail[#self.trail + 1] = self.pos.x | |
| self.trail[#self.trail + 1] = self.pos.y | |
| end, | |
| draw = function (self) | |
| --local endp = self.pos - self.vel / 2 | |
| love.graphics.setColor(255, 255, 255) | |
| love.graphics.line(self.trail) | |
| end, | |
| death = function (self) | |
| local color = {math.random() * 255, math.random() * 255, math.random() * 255} | |
| for i = 1, 1000 do | |
| local ang, vel = math.random() * 2 * math.pi, math.random() * 500 | |
| vel = Vector(math.sin(ang), math.cos(ang)) * vel | |
| self.emitter:create(self.pos, { | |
| vel = vel, | |
| lifetime = 5 + math.random() * 3, | |
| color = color | |
| }) | |
| end | |
| love.audio.play(self.sound) | |
| end | |
| } | |
| local explosions, rockets, boom, nr | |
| function love.load() | |
| explosions = ParticleSystem(Explosion) | |
| rockets = ParticleSystem(Rocket) | |
| boom = love.sound.newSoundData("explosion.ogg") | |
| nr = 0 | |
| end | |
| function love.update(dt) | |
| if nr < love.timer.getMicroTime() then | |
| local mpos, spos, ttl = Vector(50 + math.random() * (love.graphics.getWidth() - 100), 50 + math.random() * 100), Vector(math.random() * love.graphics.getWidth(), love.graphics.getHeight()), 3 + math.random() * 2 | |
| rockets:create(spos, { | |
| emitter = explosions, | |
| vel = (mpos - spos) / ttl, | |
| lifetime = ttl, | |
| sound = love.audio.newSource(boom) | |
| }) | |
| nr = love.timer.getMicroTime() + math.random() * 3 | |
| end | |
| explosions:think(dt) | |
| explosions:trim() | |
| rockets:think(dt) | |
| rockets:trim() | |
| end | |
| function love.draw() | |
| rockets:draw() | |
| explosions:draw() | |
| end | |
| function love.mousepressed(x, y, button) | |
| local mpos, spos, ttl = Vector(x, y), Vector(math.random() * love.graphics.getWidth(), love.graphics.getHeight()), 3 + math.random() * 2 | |
| rockets:create(spos, { | |
| emitter = explosions, | |
| vel = (mpos - spos) / ttl, | |
| lifetime = ttl, | |
| sound = love.audio.newSource(boom) | |
| }) | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment