From 518f5e58b14c6659ef1af0665e61b14fd8f00b56 Mon Sep 17 00:00:00 2001 From: ne_mene Date: Tue, 17 Mar 2026 22:06:18 +0100 Subject: speck bounce and speck reusage --- src/objs/player.lua | 7 +++++ src/objs/specks.lua | 73 +++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 70 insertions(+), 10 deletions(-) (limited to 'src/objs') diff --git a/src/objs/player.lua b/src/objs/player.lua index 4f05c3b..3f1e2aa 100644 --- a/src/objs/player.lua +++ b/src/objs/player.lua @@ -96,6 +96,13 @@ function new_player(x, y) add_comp(ent, "Player") add_comp(ent, "Speck_System") + ent.speck_sys.interval = 0.05 + + ent.speck_sys.lifetime_max = 0.6 + ent.speck_sys.lifetime_min = 0.3 + + ent.speck_sys.forcey = 1000 + ent.speck_sys.bounce = true add_comp(ent, "Body", x, y, 8, 14, { offsetx = -4, diff --git a/src/objs/specks.lua b/src/objs/specks.lua index fdfeb26..d9ed5ea 100644 --- a/src/objs/specks.lua +++ b/src/objs/specks.lua @@ -9,6 +9,7 @@ function Speck_Sys.new() pos = {}, vel = {}, + alive = {}, lifetime = {}, lifetime_max = {}, @@ -16,13 +17,19 @@ function Speck_Sys.new() scale_end = {} } + self.free_ids = {} + self.free_ids_size = 0 + self.scale_curve = lerp - self.scale_start_min = 1 - self.scale_start_max = 1 + 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.lifetime_min = 1 self.lifetime_max = 5 @@ -36,34 +43,80 @@ function Speck_Sys.new() 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:update(dt) local data = self.data + -- particle spawning self.spawn_timer = self.spawn_timer - dt if self.spawn_timer <= 0 then self.spawn_timer = self.interval - data.size = data.size + 1 - data.pos[data.size] = { x = self.x, y = self.y } - data.vel[data.size] = { x = 0, y = 0 } + 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 + + data.pos[id] = { x = self.x, y = self.y } + data.vel[id] = { x = 0, y = 0 } - data.lifetime[data.size] = lmath.random( + data.lifetime[id] = randf_range( self.lifetime_min, self.lifetime_max) - data.lifetime_max[data.size] = data.lifetime[data.size] + data.lifetime_max[id] = data.lifetime[id] - data.scale_start[data.size] = lmath.random( + data.scale_start[id] = randf_range( self.scale_start_min, self.scale_start_max) - data.scale_end[data.size] = lmath.random( + data.scale_end[id] = randf_range( self.scale_end_min, self.scale_end_max) 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 @@ -76,7 +129,7 @@ function Speck_Sys:draw() local data = self.data for i = 1, data.size do - if data.lifetime[i] <= 0 then + if not data.alive[i] then goto next_speck_draw end -- cgit v1.3-2-g0d8e