aboutsummaryrefslogtreecommitdiff
path: root/src/objs
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-03-30 17:52:23 -0400
committeriamcheeseman <[email protected]>2026-03-30 17:52:23 -0400
commitf52aaaad971d11fa145a391e521e37ea3c3b230e (patch)
treebaf5ae7bd8b284209a2551386fd324b5f57e7d44 /src/objs
parent7859709ac3b1500e3037c5dceacb77bcff778e89 (diff)
parentfeafbd1e1a6a1846ab5fe416ee31e2e14f603edd (diff)
Merge branch 'main' of ssh://codeberg.org/the-gutter/gutshot
Diffstat (limited to 'src/objs')
-rw-r--r--src/objs/speck_entity.lua34
-rw-r--r--src/objs/specks.lua297
2 files changed, 34 insertions, 297 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 16fe021..0000000
--- a/src/objs/specks.lua
+++ /dev/null
@@ -1,297 +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