Add global smoke spawning API

This commit is contained in:
Elias Fleckenstein 2021-04-14 18:14:21 +02:00 committed by kay27
parent 989acf889e
commit b7c68e776c
3 changed files with 91 additions and 134 deletions

View file

@ -66,3 +66,58 @@ function mcl_particles.delete_node_particlespawners(pos)
end end
return false return false
end end
-- 3 exptime variants because the animation is not tied to particle expiration time.
-- 3 colorized variants to imitate minecraft's
local smoke_pdef_cached = {}
function mcl_particles.spawn_smoke(pos, name, smoke_pdef_base)
local min = math.min
local new_minpos = vector.add(pos, smoke_pdef_base.minrelpos)
local new_maxpos = vector.add(pos, smoke_pdef_base.maxrelpos)
-- populate the cache
if smoke_pdef_cached[name] then
for i, smoke_pdef in ipairs(smoke_pdef_cached[name]) do
smoke_pdef.minpos = new_minpos
smoke_pdef.maxpos = new_maxpos
mcl_particles.add_node_particlespawner(pos, smoke_pdef, "high")
end
-- cache already populated
else
smoke_pdef_cached[name] = {}
local smoke_pdef = table.copy(smoke_pdef_base)
smoke_pdef.amount = smoke_pdef_base.amount / 9
smoke_pdef.time = 0
smoke_pdef.animation = {
type = "vertical_frames",
aspect_w = 8,
aspect_h = 8,
-- length = 3 exptime variants
}
smoke_pdef.collisiondetection = true
smoke_pdef.minpos = new_minpos
smoke_pdef.maxpos = new_maxpos
-- the last frame plays for 1/8 * N seconds, so we can take advantage of it
-- to have varying exptime for each variant.
local exptimes = { 0.175, 0.375, 1.0 }
local colorizes = { "199", "209", "243" } -- round(78%, 82%, 90% of 256) - 1
for _,exptime in ipairs(exptimes) do
for _,colorize in ipairs(colorizes) do
smoke_pdef.maxexptime = exptime * smoke_pdef_base.maxexptime
smoke_pdef.animation.length = exptime + 0.1
-- minexptime must be set such that the last frame is actully rendered,
-- even if its very short. Larger exptime -> larger range
smoke_pdef.minexptime = min(exptime, (7.0/8.0 * (exptime + 0.1) + 0.1))
smoke_pdef.texture = "mcl_particles_smoke_anim.png^[colorize:#000000:" ..colorize
mcl_particles.add_node_particlespawner(pos, smoke_pdef, "high")
table.insert(smoke_pdef_cached[name], table.copy(smoke_pdef))
end
end
end
end

View file

@ -47,94 +47,16 @@ local alldirs=
{ x = 0, y = 0, z = 1} { x = 0, y = 0, z = 1}
} }
-- 3 exptime variants because the animation is not tied to particle expiration time. local smoke_pdef = {
-- 3 colorized variants to imitate minecraft's amount = 0.009,
local smoke_pdef_base = { maxexptime = 4.0,
amount = 0.001,
time = 0,
-- minpos = vector.add(pos, { x = -0.45, y = -0.45, z = -0.45 }),
-- maxpos = vector.add(pos, { x = 0.45, y = 0.45, z = 0.45 }),
minvel = { x = -0.1, y = 0.3, z = -0.1 }, minvel = { x = -0.1, y = 0.3, z = -0.1 },
maxvel = { x = 0.1, y = 1.6, z = 0.1 }, maxvel = { x = 0.1, y = 1.6, z = 0.1 },
-- minexptime = 3 exptime variants,
-- maxexptime = 3 exptime variants
minsize = 4.0, minsize = 4.0,
maxsize = 4.5, maxsize = 4.5,
-- texture = "mcl_particles_smoke_anim.png^[colorize:#000000:(3 colourize variants)", minrelpos = { x = -0.45, y = -0.45, z = -0.45 },
animation = { maxrelpos = { x = 0.45, y = 0.45, z = 0.45 },
type = "vertical_frames",
aspect_w = 8,
aspect_h = 8,
-- length = 3 exptime variants
},
collisiondetection = true,
} }
local smoke_pdef_cached = {}
local spawn_smoke = function(pos)
local min = math.min
local new_minpos = vector.add(pos, { x = -0.45, y = -0.45, z = -0.45 })
local new_maxpos = vector.add(pos, { x = 0.45, y = 0.45, z = 0.45 })
-- populate the cache
if not next(smoke_pdef_cached) then
-- the last frame plays for 1/8 * N seconds, so we can take advantage of it
-- to have varying exptime for each variant.
local exptimes = { 0.75, 1.5, 4.0 }
local colorizes = { "199", "209", "243" } -- round(78%, 82%, 90% of 256) - 1
local id = 1
for _,exptime in ipairs(exptimes) do
for _,colorize in ipairs(colorizes) do
smoke_pdef_base.minpos = new_minpos
smoke_pdef_base.maxpos = new_maxpos
smoke_pdef_base.maxexptime = exptime
smoke_pdef_base.animation.length = exptime + 0.1
-- minexptime must be set such that the last frame is actully rendered,
-- even if its very short. Larger exptime -> larger range
smoke_pdef_base.minexptime = min(exptime, (7.0/8.0 * (exptime + 0.1) + 0.1))
smoke_pdef_base.texture = "mcl_particles_smoke_anim.png^[colorize:#000000:" ..colorize
smoke_pdef_cached[id] = table.copy(smoke_pdef_base)
mcl_particles.add_node_particlespawner(pos, smoke_pdef_cached[id], "high")
id = id + 1
end
end
-- cache already populated
else
for i, smoke_pdef in ipairs(smoke_pdef_cached) do
smoke_pdef.minpos = new_minpos
smoke_pdef.maxpos = new_maxpos
mcl_particles.add_node_particlespawner(pos, smoke_pdef, "high")
end
end
--[[ Old smoke pdef
local spawn_smoke = function(pos)
mcl_particles.add_node_particlespawner(pos, {
amount = 0.1,
time = 0,
minpos = vector.add(pos, { x = -0.45, y = -0.45, z = -0.45 }),
maxpos = vector.add(pos, { x = 0.45, y = 0.45, z = 0.45 }),
minvel = { x = 0, y = 0.5, z = 0 },
maxvel = { x = 0, y = 0.6, z = 0 },
minexptime = 2.0,
maxexptime = 2.0,
minsize = 3.0,
maxsize = 4.0,
texture = "mcl_particles_smoke_anim.png^[colorize:#000000:127",
animation = {
type = "vertical_frames",
aspect_w = 8,
aspect_h = 8,
length = 2.1,
},
}, "high")
-- ]]
end
-- --
-- Items -- Items
@ -303,7 +225,7 @@ minetest.register_node("mcl_fire:fire", {
end end
fire_timer(pos) fire_timer(pos)
spawn_smoke(pos) mcl_particles.spawn_smoke(pos, "fire", smoke_pdef)
end, end,
on_destruct = function(pos) on_destruct = function(pos)
mcl_particles.delete_node_particlespawners(pos) mcl_particles.delete_node_particlespawners(pos)
@ -367,7 +289,7 @@ minetest.register_node("mcl_fire:eternal_fire", {
if has_mcl_portals then --Calling directly minetest.get_modpath consumes 4x more compute time if has_mcl_portals then --Calling directly minetest.get_modpath consumes 4x more compute time
mcl_portals.light_nether_portal(pos) mcl_portals.light_nether_portal(pos)
end end
spawn_smoke(pos) mcl_particles.spawn_smoke(pos, "fire", smoke_pdef)
end, end,
on_destruct = function(pos) on_destruct = function(pos)
mcl_particles.delete_node_particlespawners(pos) mcl_particles.delete_node_particlespawners(pos)
@ -627,7 +549,7 @@ minetest.register_lbm({
nodenames = {"group:fire"}, nodenames = {"group:fire"},
run_at_every_load = true, run_at_every_load = true,
action = function(pos, node) action = function(pos, node)
spawn_smoke(pos) mcl_particles.spawn_smoke(pos, "fire", smoke_pdef)
end, end,
}) })

View file

@ -1,3 +1,14 @@
local smoke_pdef = {
amount = 0.5,
maxexptime = 2.0,
minvel = { x = 0.0, y = 0.5, z = 0.0 },
maxvel = { x = 0.0, y = 0.6, z = 0.0 },
minsize = 1.5,
maxsize = 1.5,
minrelpos = { x = -1/16, y = 0.04, z = -1/16 },
maxrelpos = { x = 1/16, y = 0.06, z = 1/16 },
}
local spawn_flames_floor = function(pos) local spawn_flames_floor = function(pos)
-- Flames -- Flames
mcl_particles.add_node_particlespawner(pos, { mcl_particles.add_node_particlespawner(pos, {
@ -15,52 +26,39 @@ local spawn_flames_floor = function(pos)
glow = minetest.registered_nodes[minetest.get_node(pos).name].light_source, glow = minetest.registered_nodes[minetest.get_node(pos).name].light_source,
}, "low") }, "low")
-- Smoke -- Smoke
mcl_particles.add_node_particlespawner(pos, { mcl_particles.spawn_smoke(pos, "torch", smoke_pdef)
amount = 0.5,
time = 0,
minpos = vector.add(pos, { x = -1/16, y = 0.04, z = -1/16 }),
maxpos = vector.add(pos, { x = -1/16, y = 0.06, z = -1/16 }),
minvel = { x = 0, y = 0.5, z = 0 },
maxvel = { x = 0, y = 0.6, z = 0 },
minexptime = 2.0,
maxexptime = 2.0,
minsize = 1.5,
maxsize = 1.5,
texture = "mcl_particles_smoke_anim.png",
animation = {
type = "vertical_frames",
aspect_w = 8,
aspect_h = 8,
length = 2.05,
},
}, "medium")
end end
local spawn_flames_wall = function(pos) local spawn_flames_wall = function(pos)
local minrelpos, maxrelpos local minrelpos, maxrelpos
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local dir = minetest.wallmounted_to_dir(node.param2) local dir = minetest.wallmounted_to_dir(node.param2)
local smoke_pdef = table.copy(smoke_pdef)
if dir.x < 0 then if dir.x < 0 then
minrelpos = { x = -0.38, y = 0.04, z = -0.1 } smoke_pdef.minrelpos = { x = -0.38, y = 0.04, z = -0.1 }
maxrelpos = { x = -0.2, y = 0.14, z = 0.1 } smoke_pdef.maxrelpos = { x = -0.2, y = 0.14, z = 0.1 }
elseif dir.x > 0 then elseif dir.x > 0 then
minrelpos = { x = 0.2, y = 0.04, z = -0.1 } smoke_pdef.minrelpos = { x = 0.2, y = 0.04, z = -0.1 }
maxrelpos = { x = 0.38, y = 0.14, z = 0.1 } smoke_pdef.maxrelpos = { x = 0.38, y = 0.14, z = 0.1 }
elseif dir.z < 0 then elseif dir.z < 0 then
minrelpos = { x = -0.1, y = 0.04, z = -0.38 } smoke_pdef.minrelpos = { x = -0.1, y = 0.04, z = -0.38 }
maxrelpos = { x = 0.1, y = 0.14, z = -0.2 } smoke_pdef.maxrelpos = { x = 0.1, y = 0.14, z = -0.2 }
elseif dir.z > 0 then elseif dir.z > 0 then
minrelpos = { x = -0.1, y = 0.04, z = 0.2 } smoke_pdef.minrelpos = { x = -0.1, y = 0.04, z = 0.2 }
maxrelpos = { x = 0.1, y = 0.14, z = 0.38 } smoke_pdef.maxrelpos = { x = 0.1, y = 0.14, z = 0.38 }
else else
return return
end end
-- Flames -- Flames
mcl_particles.add_node_particlespawner(pos, { mcl_particles.add_node_particlespawner(pos, {
amount = 8, amount = 8,
time = 0, time = 0,
minpos = vector.add(pos, minrelpos), minpos = vector.add(pos, smoke_pdef.minrelpos),
maxpos = vector.add(pos, maxrelpos), maxpos = vector.add(pos, smoke_pdef.maxrelpos),
minvel = { x = -0.01, y = 0, z = -0.01 }, minvel = { x = -0.01, y = 0, z = -0.01 },
maxvel = { x = 0.01, y = 0.1, z = 0.01 }, maxvel = { x = 0.01, y = 0.1, z = 0.01 },
minexptime = 0.3, minexptime = 0.3,
@ -71,25 +69,7 @@ local spawn_flames_wall = function(pos)
glow = minetest.registered_nodes[node.name].light_source, glow = minetest.registered_nodes[node.name].light_source,
}, "low") }, "low")
-- Smoke -- Smoke
mcl_particles.add_node_particlespawner(pos, { mcl_particles.spawn_smoke(pos, "torch", smoke_pdef)
amount = 0.5,
time = 0,
minpos = vector.add(pos, minrelpos),
maxpos = vector.add(pos, maxrelpos),
minvel = { x = 0, y = 0.5, z = 0 },
maxvel = { x = 0, y = 0.6, z = 0 },
minexptime = 2.0,
maxexptime = 2.0,
minsize = 1.5,
maxsize = 1.5,
texture = "mcl_particles_smoke_anim.png",
animation = {
type = "vertical_frames",
aspect_w = 8,
aspect_h = 8,
length = 2.05,
},
}, "medium")
end end
local remove_flames = function(pos) local remove_flames = function(pos)