functional, speed controlled by expansionRate
This commit is contained in:
parent
b971734225
commit
e2881ed10a
50
src/Particle.lua
Normal file
50
src/Particle.lua
Normal file
@ -0,0 +1,50 @@
|
||||
local class = require "lib.middleclass"
|
||||
local random = math.random --TODO change out as needed later
|
||||
local floor = math.floor
|
||||
local lg = love.graphics
|
||||
|
||||
local Particle = class("Particle")
|
||||
|
||||
local lifetimeRandomizer = love.math.newRandomGenerator(13--[[os.time()]])
|
||||
local maxLifetime = 10 --NOTE can only used fixed "randomization" as long as maxLifetime is constant ?
|
||||
local lifetimes = {}
|
||||
|
||||
function Particle:initialize(radius, expansionRate)
|
||||
--NOTE radius is used as a box, not an actual radius...
|
||||
--TODO FIX THIS IMMEDIATEITGJE
|
||||
|
||||
if not (radius > 1) then radius = 1 end -- stop randomization errors
|
||||
|
||||
self.x = random(-radius, radius)
|
||||
self.y = random(-radius, radius)
|
||||
self.vx = random(-expansionRate, expansionRate) --TODO make max velocity change based on radius??
|
||||
self.vy = random(-expansionRate, expansionRate)
|
||||
|
||||
self.type = floor(random(radius)) -- number of types should increase over time
|
||||
if self.type > #lifetimes then
|
||||
for i = #lifetimes, self.type do
|
||||
lifetimes[i] = lifetimeRandomizer:random(maxLifetime)
|
||||
end
|
||||
end
|
||||
self.lifetime = lifetimes[self.type]
|
||||
|
||||
--[[ debug
|
||||
for k,v in pairs(lifetimes) do
|
||||
print(k,v)
|
||||
end
|
||||
print(self.lifetime)
|
||||
]]
|
||||
end
|
||||
|
||||
function Particle:update(dt)
|
||||
self.x = self.x + (self.vx * dt)
|
||||
self.y = self.y + (self.vy * dt)
|
||||
--TODO shouldn't this update its life and set self nil here??
|
||||
end
|
||||
|
||||
function Particle:draw()
|
||||
lg.point(self.x + lg.getWidth()/2, self.y + lg.getHeight()/2)
|
||||
--lg.circle("fill", self.x + lg.getWidth()/2, self.y + lg.getHeight()/2, 1)
|
||||
end
|
||||
|
||||
return Particle
|
47
src/Universe.lua
Normal file
47
src/Universe.lua
Normal file
@ -0,0 +1,47 @@
|
||||
local class = require "lib.middleclass"
|
||||
local random = math.random --TODO change out as needed later
|
||||
local lg = love.graphics
|
||||
local Particle = require "Particle"
|
||||
|
||||
local Universe = class("Universe")
|
||||
|
||||
function Universe:initialize(expansionRate)
|
||||
self.expansionRate = expansionRate or 1
|
||||
self.particles = {}
|
||||
self.radius = 0 --2
|
||||
self.time = {
|
||||
nextGeneration = random()
|
||||
}
|
||||
end
|
||||
|
||||
function Universe:update(dt)
|
||||
self.radius = self.radius + (self.expansionRate * dt)
|
||||
|
||||
self.time.nextGeneration = self.time.nextGeneration - (self.expansionRate * dt)
|
||||
while self.time.nextGeneration <= 0 do
|
||||
--TODO make amount spawned modified by radius ?
|
||||
local particle = Particle(self.radius, self.expansionRate)
|
||||
self.particles[particle] = particle
|
||||
self.time.nextGeneration = self.time.nextGeneration + random()
|
||||
end
|
||||
|
||||
for key, particle in pairs(self.particles) do
|
||||
--print(key, particle) --debug
|
||||
particle.lifetime = particle.lifetime - dt
|
||||
if particle.lifetime <= 0 then
|
||||
self.particles[key] = nil
|
||||
else
|
||||
particle:update(dt)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Universe:draw()
|
||||
for _, particle in pairs(self.particles) do
|
||||
particle:draw()
|
||||
end
|
||||
|
||||
lg.circle("line", lg.getWidth()/2, lg.getHeight()/2, self.radius)
|
||||
end
|
||||
|
||||
return Universe
|
3
src/conf.lua
Normal file
3
src/conf.lua
Normal file
@ -0,0 +1,3 @@
|
||||
function love.conf(t)
|
||||
t.console = true
|
||||
end
|
203
src/lib/middleclass.lua
Normal file
203
src/lib/middleclass.lua
Normal file
@ -0,0 +1,203 @@
|
||||
local middleclass = {
|
||||
_VERSION = 'middleclass v3.2.0',
|
||||
_DESCRIPTION = 'Object Orientation for Lua',
|
||||
_URL = 'https://github.com/kikito/middleclass',
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2011 Enrique García Cota
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
local _metamethods = {}
|
||||
for m in ([[ add band bor bxor bnot call concat div eq
|
||||
gc ipairs idiv le len lt metatable mod mode
|
||||
mul pairs pow shl shr sub tostring unm ]]):gmatch("%S+") do
|
||||
_metamethods['__' .. m] = true
|
||||
end
|
||||
|
||||
local function _setClassDictionariesMetatables(aClass)
|
||||
local dict = aClass.__instanceDict
|
||||
dict.__index = dict
|
||||
|
||||
local super = aClass.super
|
||||
if super then
|
||||
local superStatic = super.static
|
||||
setmetatable(dict, { __index = super.__instanceDict })
|
||||
setmetatable(aClass.static, { __index = function(_,k) return rawget(dict,k) or superStatic[k] end })
|
||||
else
|
||||
setmetatable(aClass.static, { __index = function(_,k) return dict[k] end })
|
||||
end
|
||||
end
|
||||
|
||||
local function _propagateMetamethod(aClass, name, f)
|
||||
for subclass in pairs(aClass.subclasses) do
|
||||
if not subclass.__metamethods[name] then
|
||||
subclass.__instanceDict[name] = f
|
||||
_propagateMetamethod(subclass, name, f)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function _updateClassDict(aClass, key, value)
|
||||
if _metamethods[key] then
|
||||
if value == nil then
|
||||
aClass.__metamethods[key] = nil
|
||||
if aClass.super then
|
||||
value = aClass.super.__instanceDict[key]
|
||||
end
|
||||
else
|
||||
aClass.__metamethods[key] = true
|
||||
end
|
||||
|
||||
_propagateMetamethod(aClass, key, value)
|
||||
end
|
||||
|
||||
aClass.__instanceDict[key] = value
|
||||
end
|
||||
|
||||
local function _setClassMetatable(aClass)
|
||||
setmetatable(aClass, {
|
||||
__tostring = function() return "class " .. aClass.name end,
|
||||
__index = aClass.static,
|
||||
__newindex = _updateClassDict,
|
||||
__call = function(self, ...) return self:new(...) end
|
||||
})
|
||||
end
|
||||
|
||||
local function _createClass(name, super)
|
||||
local aClass = { name = name, super = super, static = {}, __mixins = {}, __instanceDict = {}, __metamethods = {} }
|
||||
aClass.subclasses = setmetatable({}, {__mode = "k"})
|
||||
|
||||
_setClassDictionariesMetatables(aClass)
|
||||
_setClassMetatable(aClass)
|
||||
|
||||
return aClass
|
||||
end
|
||||
|
||||
local function _setSubclassMetamethods(aClass, subclass)
|
||||
for m in pairs(_metamethods) do
|
||||
subclass.__instanceDict[m] = aClass.__instanceDict[m]
|
||||
end
|
||||
end
|
||||
|
||||
local function _setDefaultInitializeMethod(aClass, super)
|
||||
aClass.initialize = function(instance, ...)
|
||||
return super.initialize(instance, ...)
|
||||
end
|
||||
end
|
||||
|
||||
local function _includeMixin(aClass, mixin)
|
||||
assert(type(mixin)=='table', "mixin must be a table")
|
||||
for name,method in pairs(mixin) do
|
||||
if name ~= "included" and name ~= "static" then aClass[name] = method end
|
||||
end
|
||||
if mixin.static then
|
||||
for name,method in pairs(mixin.static) do
|
||||
aClass.static[name] = method
|
||||
end
|
||||
end
|
||||
if type(mixin.included)=="function" then mixin:included(aClass) end
|
||||
aClass.__mixins[mixin] = true
|
||||
end
|
||||
|
||||
local Object = _createClass("Object", nil)
|
||||
|
||||
function Object.static:allocate()
|
||||
assert(type(self) == 'table', "Make sure that you are using 'Class:allocate' instead of 'Class.allocate'")
|
||||
return setmetatable({ class = self }, self.__instanceDict)
|
||||
end
|
||||
|
||||
function Object.static:new(...)
|
||||
local instance = self:allocate()
|
||||
instance:initialize(...)
|
||||
return instance
|
||||
end
|
||||
|
||||
function Object.static:subclass(name)
|
||||
assert(type(self) == 'table', "Make sure that you are using 'Class:subclass' instead of 'Class.subclass'")
|
||||
assert(type(name) == "string", "You must provide a name(string) for your class")
|
||||
|
||||
local subclass = _createClass(name, self)
|
||||
_setSubclassMetamethods(self, subclass)
|
||||
_setDefaultInitializeMethod(subclass, self)
|
||||
self.subclasses[subclass] = true
|
||||
self:subclassed(subclass)
|
||||
|
||||
return subclass
|
||||
end
|
||||
|
||||
function Object.static:subclassed(other) end
|
||||
|
||||
function Object.static:isSubclassOf(other)
|
||||
return type(other) == 'table' and
|
||||
type(self) == 'table' and
|
||||
type(self.super) == 'table' and
|
||||
( self.super == other or
|
||||
type(self.super.isSubclassOf) == 'function' and
|
||||
self.super:isSubclassOf(other)
|
||||
)
|
||||
end
|
||||
|
||||
function Object.static:include( ... )
|
||||
assert(type(self) == 'table', "Make sure you that you are using 'Class:include' instead of 'Class.include'")
|
||||
for _,mixin in ipairs({...}) do _includeMixin(self, mixin) end
|
||||
return self
|
||||
end
|
||||
|
||||
function Object.static:includes(mixin)
|
||||
return type(mixin) == 'table' and
|
||||
type(self) == 'table' and
|
||||
type(self.__mixins) == 'table' and
|
||||
( self.__mixins[mixin] or
|
||||
type(self.super) == 'table' and
|
||||
type(self.super.includes) == 'function' and
|
||||
self.super:includes(mixin)
|
||||
)
|
||||
end
|
||||
|
||||
function Object:initialize() end
|
||||
|
||||
function Object:__tostring() return "instance of " .. tostring(self.class) end
|
||||
|
||||
function Object:isInstanceOf(aClass)
|
||||
return type(self) == 'table' and
|
||||
type(self.class) == 'table' and
|
||||
type(aClass) == 'table' and
|
||||
( aClass == self.class or
|
||||
type(aClass.isSubclassOf) == 'function' and
|
||||
self.class:isSubclassOf(aClass)
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function middleclass.class(name, super, ...)
|
||||
super = super or Object
|
||||
return super:subclass(name, ...)
|
||||
end
|
||||
|
||||
middleclass.Object = Object
|
||||
|
||||
setmetatable(middleclass, { __call = function(_, ...) return middleclass.class(...) end })
|
||||
|
||||
return middleclass
|
76
src/main.lua
76
src/main.lua
@ -1,83 +1,17 @@
|
||||
local lg = love.graphics
|
||||
local lm = love.math
|
||||
|
||||
local particularRandomization = lm.newRandomGenerator(os.time())
|
||||
local currentMaxPosition = 2
|
||||
local maxVelocity = 2
|
||||
local lifetimes = {}
|
||||
local particularLifetimes = lm.newRandomGenerator(os.time()*2)
|
||||
local currentMaxType = 2
|
||||
local maxLifetime = 10
|
||||
local Universe = require "Universe"
|
||||
--local Particle = require "Particle"
|
||||
|
||||
local function particular()
|
||||
local self = {}
|
||||
local universe = Universe()
|
||||
|
||||
self.x = particularRandomization:random(currentMaxPosition)
|
||||
self.y = particularRandomization:random(currentMaxPosition)
|
||||
self.vx = particularRandomization:random(maxVelocity)
|
||||
self.vy = particularRandomization:random(maxVelocity)
|
||||
|
||||
self.type = particularRandomization:random(currentMaxType)
|
||||
if self.type > #lifetimes then
|
||||
for i=#lifetimes,self.type do
|
||||
lifetimes[i] = particularLifetimes:random(maxLifetime)
|
||||
end
|
||||
end
|
||||
self.lifetime = lifetimes[self.type]
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
local particles = {}
|
||||
|
||||
local generationTiming = lm.newRandomGenerator(os.time()+100)
|
||||
local nextGeneration = generationTiming:random()
|
||||
local generationTimingCurrentTime = 0
|
||||
|
||||
local maxTypeIncrementTimer = 0
|
||||
local maxTypeIncrementInterval = 100
|
||||
function love.update(dt)
|
||||
currentMaxPosition = currentMaxPosition + dt
|
||||
|
||||
maxTypeIncrementTimer = maxTypeIncrementTimer + dt
|
||||
while maxTypeIncrementTimer >= maxTypeIncrementInterval do
|
||||
maxTypeIncrementTimer = maxTypeIncrementTimer - maxTypeIncrementInterval
|
||||
currentMaxType = currentMaxType + 1
|
||||
end
|
||||
|
||||
generationTimingCurrentTime = generationTimingCurrentTime + dt
|
||||
while generationTimingCurrentTime >= nextGeneration do
|
||||
generationTimingCurrentTime = generationTimingCurrentTime - nextGeneration
|
||||
nextGeneration = generationTiming:random()
|
||||
table.insert(particles, particular())
|
||||
end
|
||||
|
||||
local deletes = {}
|
||||
--for i=1
|
||||
for k, p in pairs(particles) do
|
||||
p.x = p.vx * dt
|
||||
p.y = p.vy * dt
|
||||
p.lifetime = p.lifetime - dt
|
||||
if p.lifetime <= 0 then
|
||||
table.insert(deletes, k)
|
||||
end
|
||||
end
|
||||
for _, p in ipairs(deletes) do
|
||||
particles[p] = nil
|
||||
end
|
||||
universe:update(dt)
|
||||
end
|
||||
|
||||
--lg.setColor(255, 255, 255, 255)
|
||||
function love.draw()
|
||||
--for i=1,#particles do
|
||||
-- lg.point(particles[i].x, particles[i].y)
|
||||
--end
|
||||
for _, p in pairs(particles) do
|
||||
--lg.point(p.x, p.y)
|
||||
lg.circle("fill", p.x, p.y, 1)
|
||||
end
|
||||
|
||||
lg.circle("line", lg.getWidth()/2, lg.getHeight()/2, currentMaxPosition)
|
||||
universe:draw()
|
||||
end
|
||||
|
||||
function love.keypressed(key)
|
||||
|
Loading…
Reference in New Issue
Block a user