Freeze-frame
commit
cd16117b83
|
@ -0,0 +1,47 @@
|
|||
read_globals = {
|
||||
"DIR_DELIM", "INIT",
|
||||
|
||||
"minetest", "core",
|
||||
"dump", "dump2",
|
||||
|
||||
"Raycast",
|
||||
"Settings",
|
||||
"PseudoRandom",
|
||||
"PerlinNoise",
|
||||
"VoxelManip",
|
||||
"SecureRandom",
|
||||
"VoxelArea",
|
||||
"PerlinNoiseMap",
|
||||
"PcgRandom",
|
||||
"ItemStack",
|
||||
"AreaStore",
|
||||
|
||||
"vector",
|
||||
|
||||
table = {
|
||||
fields = {
|
||||
"copy",
|
||||
"indexof",
|
||||
"insert_all",
|
||||
"key_value_swap",
|
||||
"shuffle",
|
||||
}
|
||||
},
|
||||
|
||||
string = {
|
||||
fields = {
|
||||
"split",
|
||||
"trim",
|
||||
}
|
||||
},
|
||||
|
||||
math = {
|
||||
fields = {
|
||||
"hypot",
|
||||
"sign",
|
||||
"factorial"
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
ignore = "513"
|
|
@ -0,0 +1,18 @@
|
|||
MIT Copyright 2021 GreenXenith
|
||||
|
||||
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.
|
|
@ -0,0 +1,23 @@
|
|||
# Animated Entity Textures
|
||||
Created as an exercise in entity and texture handling for a Discord challenge.
|
||||
|
||||
The `_tiles` key should be a table of [tiles](https://github.com/minetest/minetest/blob/5.4.1/doc/lua_api.txt#L7124-L7144). Animated tiles should use the [tile animation definition](https://github.com/minetest/minetest/blob/5.4.1/doc/lua_api.txt#L7146-L7173) (optional).
|
||||
|
||||
### Minimum Example
|
||||
```lua
|
||||
minetest.register_entity("modname:verticalframes", {
|
||||
_tiles = {{
|
||||
name = "vertical_frames.png",
|
||||
animation = {type = "vertical_frames", aspect_w = 16, aspect_h = 16, length = 1}
|
||||
}},
|
||||
})
|
||||
|
||||
minetest.register_entity("modname:sheet2d", {
|
||||
_tiles = {{
|
||||
name = "sheet_2d.png",
|
||||
animation = {type = "sheet_2d", frames_w = 4, frames_h = 2, frame_length = 0.25}
|
||||
}},
|
||||
})
|
||||
```
|
||||
|
||||
Set `TEST` to `true` in `init.lua` to register these testing entities.
|
|
@ -0,0 +1,106 @@
|
|||
local TEST = false
|
||||
|
||||
local function get_file_dimensions(path)
|
||||
local f = io.open(path, "rb")
|
||||
f:seek("set", 1)
|
||||
if f:read(3) == "PNG" then
|
||||
f:seek("set", 16)
|
||||
return {
|
||||
w = tonumber(string.format("0x%x%x%x%x", f:read(4):byte(1, 4))),
|
||||
h = tonumber(string.format("0x%x%x%x%x", f:read(4):byte(1, 4))),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function find_textures(path, files)
|
||||
files = files or {}
|
||||
for _, filename in pairs(minetest.get_dir_list(path, false)) do
|
||||
if filename:sub(-4) == ".png" then
|
||||
files[filename] = get_file_dimensions(path .. "/" .. filename)
|
||||
end
|
||||
end
|
||||
|
||||
for _, dir in pairs(minetest.get_dir_list(path, true)) do
|
||||
files = find_textures(path .. "/" .. dir, files)
|
||||
end
|
||||
|
||||
return files
|
||||
end
|
||||
|
||||
-- List of dimensions for all textures
|
||||
local texturelist = {}
|
||||
for _, modname in pairs(minetest.get_modnames()) do
|
||||
texturelist = find_textures(minetest.get_modpath(modname), texturelist)
|
||||
end
|
||||
|
||||
local old_dynamic_add = minetest.dynamic_add_media
|
||||
minetest.dynamic_add_media = function(filepath, ...)
|
||||
local success = old_dynamic_add(filepath, ...)
|
||||
if success then texturelist[filepath:match("[^/\\]+$")] = get_file_dimensions(filepath) end
|
||||
return success
|
||||
end
|
||||
|
||||
-- Animation handler
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _, ent in pairs(minetest.luaentities) do
|
||||
-- _tiles and properties must exist
|
||||
if ent._tiles and ent.object:get_properties() then
|
||||
local textures = ent.object:get_properties().textures
|
||||
local tiles = table.copy(ent._tiles)
|
||||
|
||||
for i, tile in pairs(tiles) do
|
||||
if type(tile) == "table" then
|
||||
if tile.animation then
|
||||
local anim = tile.animation
|
||||
assert(anim.type and (anim.type == "vertical_frames" or anim.type == "sheet_2d"), ("Invalid animated tile type in entity '%s'."):format(ent.name))
|
||||
|
||||
tiles[i]._timer = (tile._timer or 0) + dtime
|
||||
tiles[i]._frame = tile._frame or 0
|
||||
|
||||
local size = texturelist[tile.name] or {w = 16, h = 16}
|
||||
|
||||
if anim.type == "vertical_frames" then
|
||||
assert(anim.aspect_w and anim.aspect_h and anim.length, ("Invalid vertical_frames animation definition in entity '%s'."):format(ent.name))
|
||||
-- height / frame height (width / aspect ratio)
|
||||
local total_frames = size.h / (size.w * (anim.aspect_h / anim.aspect_w))
|
||||
|
||||
-- floor(timer / seconds per frame)
|
||||
tile._frame = math.floor(tile._timer / (anim.length / total_frames)) % total_frames
|
||||
tile._timer = tile._timer % anim.length
|
||||
|
||||
textures[i] = ("%s^[verticalframe:%s:%s"):format(tile.name, total_frames, tile._frame)
|
||||
else -- type == "sheet_2d"
|
||||
assert(anim.frames_w and anim.frames_h and anim.frame_length, ("Invalid sheet_2d animation definition in entity '%s'."):format(ent.name))
|
||||
local total_frames = anim.frames_w * anim.frames_h
|
||||
local tile_w, tile_h = size.w / anim.frames_w, size.h / anim.frames_h
|
||||
|
||||
tile._frame = math.floor((tile._timer / anim.frame_length)) % total_frames
|
||||
tile._timer = tile._timer % (total_frames * anim.frame_length)
|
||||
|
||||
textures[i] = ("[combine:%sx%s:%s,%s=%s"):format(tile_w, tile_h, -(tile._frame % anim.frames_w) * tile_h, -math.floor(tile._frame / anim.frames_w) * tile_w, tile.name)
|
||||
end
|
||||
else
|
||||
textures[i] = tile.name
|
||||
end
|
||||
else
|
||||
textures[i] = tile
|
||||
end
|
||||
end
|
||||
|
||||
ent._tiles = tiles
|
||||
ent.object:set_properties({textures = textures})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- Test
|
||||
if TEST then
|
||||
local speed = 1
|
||||
minetest.register_entity("entity_anim:verticalframes", {
|
||||
_tiles = {{name = "entity_anim_test_verticalframes.png", animation = {type = "vertical_frames", aspect_w = 1, aspect_h = 1, length = speed}}}
|
||||
})
|
||||
|
||||
minetest.register_entity("entity_anim:sheet2d", {
|
||||
_tiles = {{name = "entity_anim_test_sheet2d.png", animation = {type = "sheet_2d", frames_w = 2, frames_h = 2, frame_length = speed / 4}}}
|
||||
})
|
||||
end
|
|
@ -0,0 +1,2 @@
|
|||
name = entity_anim
|
||||
description = Animated texture support for entities.
|
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.2 KiB |
Loading…
Reference in New Issue