Added several convenience features.
Including allowing specifying number of tiles for each dimension, if for example it is known that the image will contain 16x16 sprites, but the size of the individual sprite is unknown.
This commit is contained in:
parent
69f0d85100
commit
bc3752da1b
|
@ -1,5 +1,14 @@
|
|||
|
||||
local error = require 'errors' 'SpriteSheet2'
|
||||
local error_orig = error
|
||||
local error, error_internal do
|
||||
error, error_internal = error_orig, error_orig
|
||||
error_orig = nil
|
||||
local success, errorlib = pcall(require,'errors')
|
||||
if success then
|
||||
error = errorlib 'spritesheet'
|
||||
error_internal = error.internal
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Util
|
||||
|
@ -102,7 +111,7 @@ function Animation:generateImage ()
|
|||
|
||||
if self.wrap then t = t % self.duration end
|
||||
local quad = get_quad_based_on_time(self, t)
|
||||
if not quad then error.internal('Could not determine quad when drawing animation. Time was %f.', t) end
|
||||
if not quad then error_internal('Could not determine quad when drawing animation. Time was %f.', t) end
|
||||
love.graphics.draw(self.imagesheet.image, quad, x, y, 0, 1, 1, self.imagesheet.origin_x, self.imagesheet.origin_y)
|
||||
end
|
||||
end
|
||||
|
@ -165,8 +174,8 @@ local function load_quads (image, quad_data, imagesheet)
|
|||
|
||||
local image_width, image_height = image:getDimensions()
|
||||
local tile_width, tile_height = quad_data.tile_width, quad_data.tile_height
|
||||
local tiles_pr_row = image_width/tile_width
|
||||
local max_quad_id = tiles_pr_row * (image_height/tile_height) - 1
|
||||
local tiles_per_row = image_width/tile_width
|
||||
local max_quad_id = tiles_per_row * (image_height/tile_height) - 1
|
||||
local quad_cache = {}
|
||||
|
||||
local function quad_from_id (id)
|
||||
|
@ -177,7 +186,7 @@ local function load_quads (image, quad_data, imagesheet)
|
|||
|
||||
-- Calculate
|
||||
if not quad_cache[id] then
|
||||
quad_cache[id] = love.graphics.newQuad((id%tiles_pr_row)*tile_width, math.floor(id/tiles_pr_row)*tile_height, tile_width, tile_height, image_width, image_height)
|
||||
quad_cache[id] = love.graphics.newQuad((id%tiles_per_row)*tile_width, math.floor(id/tiles_per_row)*tile_height, tile_width, tile_height, image_width, image_height)
|
||||
end
|
||||
return quad_cache[id]
|
||||
end
|
||||
|
@ -226,15 +235,40 @@ local function load_quad_data (filename)
|
|||
local chunk, error_msg = love.filesystem.load(filename..'.lua')
|
||||
if chunk then
|
||||
local data = setfenv(chunk, SPRITESHEET_ENV)()
|
||||
|
||||
-- Error check
|
||||
if type(data) ~= 'table' then error('Bad spritesheet "%s". Must return a table, but returned %s (%s)', filename, data, type(data)) end
|
||||
if type(data.tile_width) ~= 'number' then error('Bad spritesheet "%s". The root table must contain key "tile_width", with integer value, but it was %s (%s)', filename, data.tile_width, type(data.tile_width)) end
|
||||
if data.tile_width ~= math.floor(data.tile_width) then error('Bad spritesheet "%s". The root table must contain key "tile_width", with integer value, but it was %f (float)', filename, data.tile_width) end
|
||||
if type(data.tile_height) ~= 'number' then error('Bad spritesheet "%s". The root table must contain key "tile_height", with integer value, but it was %s (%s)', filename, data.tile_height, type(data.tile_height)) end
|
||||
if data.tile_height ~= math.floor(data.tile_height) then error('Bad spritesheet "%s". The root table must contain key "tile_height", with integer value, but it was %f (float)', filename, data.tile_height) end
|
||||
if not (type(data.tile_names) == 'table' or type(data.tile_names) == 'number') then error('Bad spritesheet "%s". The root table must contain key "tile_names", with either a table or a number value, but it was %s (%s)', filename, data.tile_names, type(data.tile_names)) end
|
||||
if data.tile_origin and type(data.tile_origin) ~= 'table' then error('Bad spritesheet "%s". If the root table contains key "tile_origin", it must be a table value, but it was %s (%s)', filename, data.tile_origin, type(data.tile_origin)) end
|
||||
--
|
||||
if type(data) ~= 'table' then
|
||||
error('Bad spritesheet "%s". Must return a table, but returned %s (%s)', filename, data, type(data))
|
||||
end
|
||||
local l = {'Bad spritesheet "'.. filename.. '"'}
|
||||
if data.tiles_per_row ~= nil and data.tile_width ~= nil then
|
||||
l[#l+1] = 'Root table must not contain both keys "tiles_per_row" and "tile_width"'
|
||||
elseif data.tiles_per_row == nil and data.tile_width == nil then
|
||||
l[#l+1] = 'Root table must contain either keys "tiles_per_row" or "tile_width"'
|
||||
end
|
||||
if data.tiles_per_column ~= nil and data.tile_height ~= nil then
|
||||
l[#l+1] = 'Root table must not contain both keys "tiles_per_column" and "tile_height"'
|
||||
elseif data.tiles_per_column == nil and data.tile_height == nil then
|
||||
l[#l+1] = 'Root table must contain either keys "tiles_per_column" or "tile_height"'
|
||||
end
|
||||
local INTEGER_TILESET_KEYS = {'tile_width', 'tile_height', 'tiles_per_row', 'tiles_per_column'}
|
||||
for _, integer_key in ipairs(INTEGER_TILESET_KEYS) do
|
||||
local v = data[integer_key]
|
||||
if v and (type(v) ~= 'number' or v % 1 ~= 0) then
|
||||
l[#l+1] = string.format('Key "%s" in root table must map to integer value, but it was %s (%s)', integer_key, v, type(v))
|
||||
end
|
||||
end
|
||||
if not (type(data.tile_names) == 'table' or type(data.tile_names) == 'number') then
|
||||
l[#l+1] = string.format('Root table must contain key "tile_names", with either a table or a number value, but it was %s (%s)', data.tile_names, type(data.tile_names))
|
||||
end
|
||||
if data.tile_origin and type(data.tile_origin) ~= 'table' then
|
||||
l[#l+1] = string.format('Key "%s" in root table must map to a table value, but it was %s (%s)', 'tile_origin', data.tile_origin, type(data.tile_origin))
|
||||
end
|
||||
|
||||
-- Throw error or return
|
||||
if #l > 1 then
|
||||
error(table.concat(l, '\n '))
|
||||
end
|
||||
return data
|
||||
end
|
||||
print(error_msg)
|
||||
|
@ -253,18 +287,38 @@ local SpriteSheet = {}
|
|||
function SpriteSheet.new (filename)
|
||||
local quad_data = load_quad_data(filename)
|
||||
|
||||
-- NOTE: `force_uneven_tile_size` in quad_data can be used to
|
||||
-- ignore the image size-tile size divisibility check. Edit the
|
||||
-- spriteimage itself if you can, as it will silently ignore
|
||||
-- several errors.
|
||||
|
||||
-- Set info
|
||||
local self = setmetatable({}, SpriteSheet)
|
||||
self.filename = filename
|
||||
self.image = love.graphics.newImage(filename..'.png')
|
||||
self.origin_x = 0
|
||||
self.origin_y = 0
|
||||
self.tile_width = quad_data.tile_width
|
||||
self.tile_height = quad_data.tile_height
|
||||
|
||||
-- TODO: Give warning/error due to rounding down.
|
||||
quad_data.tile_width = quad_data.tile_width or math.floor(self.image:getWidth() / quad_data.tiles_per_row)
|
||||
quad_data.tile_height = quad_data.tile_height or math.floor(self.image:getHeight() / quad_data.tiles_per_column)
|
||||
print(self.tile_width, self.tile_height)
|
||||
|
||||
self.tile_width = quad_data.tile_width
|
||||
self.tile_height = quad_data.tile_height
|
||||
|
||||
-- Error checking
|
||||
if self.image:getWidth() % self.tile_width ~= 0 then error('Bad spritesheet "%s". Image size (%i, %i) must be dividable by tile size (%i, %i), but width leaves a remainder of %i.', filename, self.image:getWidth(), self.image:getHeight(), self.tile_width, self.tile_height, self.image:getWidth() % self.tile_width) end
|
||||
if self.image:getHeight() % self.tile_height ~= 0 then error('Bad spritesheet "%s". Image size (%i, %i) must be dividable by tile size (%i, %i), but height leaves a remainder of %i.', filename, self.image:getWidth(), self.image:getHeight(), self.tile_width, self.tile_height, self.image:getHeight() % self.tile_height) end
|
||||
do
|
||||
local rem_width = self.image:getWidth() % self.tile_width
|
||||
local rem_height = self.image:getHeight() % self.tile_height
|
||||
if not quad_data.force_uneven_tile_size and (rem_width ~= 0 or rem_height ~= 0) then
|
||||
local s = ('Bad spritesheet "%s". Image size (%i, %i) must be dividable by tile size (%i, %i)')
|
||||
:format(filename, self.image:getWidth(), self.image:getHeight(), self.tile_width, self.tile_height)
|
||||
if rem_width ~= 0 then s = s..('\n Width leaves a remainder of %i.'):format(rem_width) end
|
||||
if rem_height ~= 0 then s = s..('\n Height leaves a remainder of %i.'):format(rem_height) end
|
||||
error(s)
|
||||
end
|
||||
end
|
||||
|
||||
-- Set origin
|
||||
if quad_data.tile_origin then
|
||||
|
|
Loading…
Reference in New Issue
Block a user