diff options
Diffstat (limited to 'src/objs')
| -rw-r--r-- | src/objs/speck_entity.lua | 34 | ||||
| -rw-r--r-- | src/objs/specks.lua | 296 |
2 files changed, 34 insertions, 296 deletions
diff --git a/src/objs/speck_entity.lua b/src/objs/speck_entity.lua new file mode 100644 index 0000000..cf81130 --- /dev/null +++ b/src/objs/speck_entity.lua @@ -0,0 +1,34 @@ + +register_comp("Speck_System", function(ent) + ent.speck_sys = Speck_Sys.new() +end) + +function speck_update_sys(ent, dt) + ent.speck_sys.x = ent.x + ent.speck_sys.y = ent.y + + ent.speck_sys:update(dt) +end + +function speck_draw_sys(ent) + ent.speck_sys:draw() +end + +function new_speck_entity(x, y, filepath) + local ent = new_entity() + add_comp(ent, "Position", x, y) + add_comp(ent, "Speck_System") + ent.speck_sys = load_speck_sys(filepath) + ent.speck_sys.oneshot = true + + add_comp(ent, "Speck_Entity") +end + +register_comp("Speck_Entity", TAGCOMP) + +function speck_entity_system(ent, dt) + local sys = ent.speck_sys + if not sys.emitting and sys:is_empty() then + queue_entity_kill(ent) + end +end diff --git a/src/objs/specks.lua b/src/objs/specks.lua deleted file mode 100644 index baa9a14..0000000 --- a/src/objs/specks.lua +++ /dev/null @@ -1,296 +0,0 @@ -Speck_Sys = {} -Speck_Sys.__index = Speck_Sys - -local SPAWN_FUNCTIONS = { - Rectangle = function (speck_sys) - local w = (speck_sys.spawn_width or 0) / 2 - local h = (speck_sys.spawn_height or 0) / 2 - - return randf_range(-w, w), randf_range(-h, h) - end, - - Circle = function (speck_sys) - local angle = randf_range(0, math.pi * 2) - local r = speck_sys.spawn_radius or 0 - r = r * lmath.random() - return r*math.cos(angle), r*math.sin(angle) - end, - - Point = function (speck_sys) - return 0, 0 - end -} - -function Speck_Sys.new() - local self = setmetatable({}, Speck_Sys) - - self.data = { - size = 0, - pos = {}, - vel = {}, - - alive = {}, - lifetime = {}, - lifetime_max = {}, - - scale_start = {}, - scale_end = {} - } - - self.free_ids = {} - self.free_ids_size = 0 - - self.bounce = false - self.gradient = "res/img/test_gradient.png" - - self.spawn_shape = "Point" - - self.spawn_amount_min = 1 - self.spawn_amount_max = 1 - - self.scale_curve = "Lerp" - self.scale_start_min = 0.8 - self.scale_start_max = 1.25 - - self.scale_end_min = 0 - self.scale_end_max = 0 - - self.forcex = 0 - self.forcey = 0 - - self.initial_velx = 0 - self.initial_vely = 0 - self.spread = 0 - - self.lifetime_min = 1 - self.lifetime_max = 5 - - self.interval = 0.1 - - self.texture_path = "res/img/speck.png" - - self.x = 0 - self.y = 0 - self.spawn_timer = self.interval - - self.oneshot = false - self.emitting = true - return self -end - -function Speck_Sys:check_bounce(i) - if not self.bounce then - return false - end - - local scn = get_current_scene() - assert(scn, "No scene set.") - - return has_tile( - scn.tilemap, - to_tile_coords(self.data.pos[i].x, self.data.pos[i].y)) -end - -function Speck_Sys:spawn_particles() - local data = self.data - local amt = lmath.random(self.spawn_amount_min, self.spawn_amount_max) - - local shape_func = SPAWN_FUNCTIONS[self.spawn_shape] - for i = 1, amt do - local id - if self.free_ids_size > 0 then - id = self.free_ids[self.free_ids_size] - self.free_ids_size = self.free_ids_size - 1 - else - self.data.size = self.data.size + 1 - id = self.data.size - end - - data.alive[id] = true - - local offx, offy = shape_func(self) - data.pos[id] = { x = self.x + offx, y = self.y + offy } - data.vel[id] = { x = self.initial_velx, y = self.initial_vely } - - local beta = self.spread * math.pi / 180 - beta = beta / 2 - beta = randf_range(-beta, beta) - - local rvx = (data.vel[id].x * math.cos(beta)) - - (data.vel[id].y * math.sin(beta)) - local rvy = (data.vel[id].x * math.sin(beta)) - + (data.vel[id].y * math.cos(beta)) - data.vel[id].x = rvx - data.vel[id].y = rvy - - data.lifetime[id] = randf_range( - self.lifetime_min, self.lifetime_max) - data.lifetime_max[id] = data.lifetime[id] - - data.scale_start[id] = randf_range( - self.scale_start_min, self.scale_start_max) - data.scale_end[id] = randf_range( - self.scale_end_min, self.scale_end_max) - end -end - -function Speck_Sys:update(dt) - local data = self.data - - -- particle spawning - self.spawn_timer = self.spawn_timer - dt - if self.spawn_timer <= 0 and self.emitting then - self.spawn_timer = self.interval - - self:spawn_particles() - if self.oneshot then - self.emitting = false - end - end - - -- particles processing - for i = 1, data.size do - if not data.alive[i] then - goto next_speck_update - end - - if data.lifetime[i] <= 0 then - data.alive[i] = false - - self.free_ids_size = self.free_ids_size + 1 - self.free_ids[self.free_ids_size] = i - goto next_speck_update - end - - data.vel[i].x = data.vel[i].x + self.forcex * dt - data.vel[i].y = data.vel[i].y + self.forcey * dt - - -- move and bounce - data.pos[i].x = data.pos[i].x + data.vel[i].x * dt - if self:check_bounce(i) then - data.vel[i].x = -data.vel[i].x - data.pos[i].x = data.pos[i].x + data.vel[i].x * dt - end - - data.pos[i].y = data.pos[i].y + data.vel[i].y * dt - if self:check_bounce(i) then - data.vel[i].y = -data.vel[i].y - data.pos[i].y = data.pos[i].y + data.vel[i].y * dt - end - - data.lifetime[i] = data.lifetime[i] - dt - - ::next_speck_update:: - end -end - -function Speck_Sys:is_empty() - if self.data.size == 0 then - return true - end - return self.free_ids_size == self.data.size -end - -function Speck_Sys:draw() - local scale_curve = EASING_FUNCTIONS[self.scale_curve] - local data = self.data - local tex = get_tex(self.texture_path) - - for i = 1, data.size do - if not data.alive[i] then - goto next_speck_draw - end - - local anim = 1 - data.lifetime[i] / data.lifetime_max[i] - local scale = scale_curve(data.scale_start[i], data.scale_end[i], anim) - - local w, h = tex:getDimensions() - - local gradient = get_tex_data(self.gradient) - local sample_pos = math.floor((gradient:getWidth() - 1) * anim) - lg.setColor(gradient:getPixel(sample_pos, 0.5)) - - lg.draw( - tex, data.pos[i].x, data.pos[i].y, 0, scale, scale, w / 2, h / 2 - ) - lg.setColor(1, 1, 1, 1) - ::next_speck_draw:: - end -end - -register_comp("Speck_System", function(ent) - ent.speck_sys = Speck_Sys.new() -end) - -function speck_update_sys(ent, dt) - ent.speck_sys.x = ent.x - ent.speck_sys.y = ent.y - - ent.speck_sys:update(dt) -end - -function speck_draw_sys(ent) - ent.speck_sys:draw() -end - -function export_speck_sys(sys, filename) - local EXPORTED_ARGS = { - "spawn_shape", - "spawn_amount_min", - "spawn_amount_max", - "spawn_width", - "spawn_height", - "spawn_radius", - "scale_curve", - "scale_start_min", - "scale_start_max", - "scale_end_min", - "scale_end_max", - "forcex", - "forcey", - "initial_velx", - "initial_vely", - "spread", - "lifetime_min", - "lifetime_max", - "interval", - "texture_path", - "gradient", - "oneshot", - "bounce", - } - local exp = {} - - for i, arg in ipairs(EXPORTED_ARGS) do - exp[arg] = sys[arg] - end - export_to_source(exp, filename) -end - -function load_speck_sys(filename) - local sys = Speck_Sys.new() - local loaded = lf.load(filename)() - for key, data in pairs(loaded) do - sys[key] = data - end - return sys -end - -function new_speck_entity(x, y, filepath) - local ent = new_entity() - add_comp(ent, "Position", x, y) - add_comp(ent, "Speck_System") - ent.speck_sys = load_speck_sys(filepath) - ent.speck_sys.oneshot = true - - add_comp(ent, "Speck_Entity") -end - -register_comp("Speck_Entity", TAGCOMP) - -function speck_entity_system(ent, dt) - local sys = ent.speck_sys - if not sys.emitting and sys:is_empty() then - queue_entity_kill(ent) - end -end |
