Page 4 of 13
Re: Small extra functions
Posted: Tue May 06, 2014 10:28 am
by foo0
Code: Select all
function round(n, r)
local r = r or 0
return math.floor(n*10^r)/10^r
end
More appropriate name for that function would be roundDown, because it returns values like this:
1.5 -> 1
-1.5 -> -2
The "classic round" rounds values away from zero when the decimal part is greater than or equal to 0.5, and towards zero when less than 0.5. That's how C++'s
std::round does this. It returns values like this:
1.5 -> 2
-1.5 -> -2
Here's a snippet of most common round variations:
Code: Select all
-- "Classic round", rounds away from zero in halfway cases.
function round(num, idp)
local shift = idp and 10 ^ idp or 1
if num < 0 then
return math.ceil(num * shift - 0.5) / shift
end
return math.floor(num * shift + 0.5) / shift
end
function roundDown(num, idp)
local shift = idp and 10 ^ idp or 1
return math.floor(num * shift) / shift
end
function roundUp(num, idp)
local shift = idp and 10 ^ idp or 1
return math.ceil(num * shift) / shift
end
-- Truncates decimal part, leaving the rest of the number unchanged.
function trunc(num, idp)
local shift = idp and 10 ^ idp or 1
if num > 0 then
return math.floor(num * shift) / shift
end
return math.ceil(num * shift) / shift
end
function roundAwayFromZero(num, idp)
local shift = idp and 10 ^ idp or 1
if num > 0 then
return math.ceil(num * shift) / shift
end
return math.floor(num * shift) / shift
end
Re: Small extra functions
Posted: Tue May 06, 2014 2:24 pm
by WetDesertRock
Forgive me, but why can't 'trunc' be replaced by math.floor?
Re: Small extra functions
Posted: Tue May 06, 2014 3:42 pm
by foo0
Because they're not equal. They return the same values if x >= 0, but different when x < 0. Know how each function work and choose one that fits the purpose. If you know that x will always be >= 0, it doesn't matter if you use math.floor or trunc, but for negative x they work differently, e.g.:
Code: Select all
trunc(4.2) == 4
math.floor(4.2) == 4
trunc(-4.2) == -4
math.floor(-4.2) == -5
Re: Small extra functions
Posted: Thu May 08, 2014 4:32 am
by HugoBDesigner
A code I wrote to convert frames to quads (a new image in quad format)! It saves me infinite minutes of doing it by hand
Code: Select all
local folder = "glow"
local newfile = "glow"
local files = love.filesystem.enumerate(folder)
local newwidth = 0
local newheight = 0
local imagestable = {}
local n = 0
for i, v in pairs(files) do
if string.sub(files[i], -4, -1) == ".png" then
n = n + 1
table.insert(imagestable, love.image.newImageData(folder .. "/" .. files[i]))
newwidth = newwidth + imagestable[n]:getWidth()
if imagestable[n]:getHeight() > newheight then
newheight = imagestable[n]:getHeight()
end
end
end
local newimage = love.image.newImageData(newwidth, newheight)
for i = 1, #imagestable do
for x = 1, imagestable[i]:getWidth() do
for y = 1, imagestable[i]:getHeight() do
local pixeltoset = {(i-1)*imagestable[i]:getWidth()+(x-1), y-1}
local r, g, b, a = imagestable[i]:getPixel(x-1, y-1)
newimage:setPixel(pixeltoset[1], pixeltoset[2], r, g, b, a)
end
end
end
newimage:encode(newfile .. ".png")
For LÖVE 0.8.0. To use in LÖVE 0.9.0, just replace the "love.filesystem.enumerate" by "love.filesystem.getDirectoryItems"
Re: Small extra functions
Posted: Sun May 11, 2014 9:13 pm
by HugoBDesigner
Two more codes. One to load quads from an image:
The
mode can be "size" (you specify the quads' size - the default mode) or "amount" (number of quads horizontally and vertically)
Code: Select all
function love.getQuads(image, width, height, mode)
local width = width
local height = height
local mode = mode or "size"
if mode == "amount" then
width = math.floor(image:getWidth()/width)
height = math.floor(image:getHeight()/height)
end
local horizontalquads = math.floor(image:getWidth()/width)
local verticalquads = math.floor(image:getHeight()/height)
local returner = {}
for y = 1, verticalquads do
for x = 1, horizontalquads do
table.insert(returner, {image = image, quad = love.graphics.newQuad((x-1)*width, (y-1)*height, width, height)})
end
end
return returner
end
It returns a table. Each item of the table is a table too, with the image (table
["image"]) and the quad (table["quad"]). To draw, you can just do love.graphics.draw(table["image"], table["quad"], ...)
Also a function to merge two tables. Not the most practical function, but saves time and keeps your code clean:
Code: Select all
function table.merge(t1, t2)
local ret = {}
for i, v in pairs(t1) do
table.insert(ret, v)
end
for i, v in pairs(t2) do
table.insert(ret, v)
end
return ret
end
Re: Small extra functions
Posted: Sun May 11, 2014 10:28 pm
by foo0
Merge t1 and t2 into t1:
Code: Select all
function table.merge(t1, t2)
for k, v in pairs(t2) do
t1[k] = v
end
return t1
end
Re: Small extra functions
Posted: Sun May 11, 2014 10:45 pm
by HugoBDesigner
At first I was going to do this, but then came the question: does it automatically changes the original table?
Because if yes, then I'd still prefer mine, because you can make a completely different table with the data of both merged functions...
Re: Small extra functions
Posted: Mon May 12, 2014 11:37 am
by Robin
HugoBDesigner wrote:At first I was going to do this, but then came the question: does it automatically changes the original table?
Yes.
Your version probably doesn't do what you want, though, because it merges {x = 1} and {y = 2} into {1, 2}.
What you'd probably want is closer to foo0's version:
Code: Select all
function mergetables(...)
local ret = {}
for i, tbl in ipairs {...} do
for k, v in pairs(tbl) do
ret[k] = v
end
end
return ret
end
Notes:
- I renamed it to mergetables. Modifying the standard library is bad, don't do it.
- This one handles an arbitrary number of tables, not just two. Passing one makes a shallow copy of it.
- In the case of conflicting keys, the last one wins, like in foo0's version.
Re: Small extra functions
Posted: Mon May 12, 2014 12:47 pm
by HugoBDesigner
Your version is WAAAAY better, thank you! But won't it replace values? Like:
Code: Select all
t1 = {"first value", a = 2}
t2 = {"another first value", b = 3}
mergetables(t1, t2)
--returns {"another first value", a = 2, b = 3}
EDIT: Nevermind. It's written in your post this...
Also, for what I needed my function worked. It was something like this (about the love.loadQuads function):
Code: Select all
local img = love.graphics.newImage("something.png")
local img2 = love.graphics.newImage("something2.png")
local img3 = love.graphics.newImage("something3.png")
local quads = {}
table.merge(quads, love.loadQuads(img, quadWidth, quadHeight)
table.merge(quads, love.loadQuads(img2, quadWidth, quadHeight)
table.merge(quads, love.loadQuads(img3, quadWidth, quadHeight)
It was for a game with an image with quads that didn't fit the 512x512 size. We had to split it in 2 images, and to make things easier I made this function to load and draw both with a single draw:
Code: Select all
love.graphics.draw(quads[frame]["image"], quads[frame]["quad"], ...)
EDIT 2: Can't we make this to solve the problem:
Code: Select all
function mergetables(...)
local ret = {}
local val = 0
for i, tbl in ipairs {...} do
for k, v in pairs(tbl) do
if type(k) == "number" then
val = val + 1
ret[val] = v
else
ret[k] = v
end
end
end
return ret
end
Re: Small extra functions
Posted: Mon May 12, 2014 2:27 pm
by foo0
You can use table.insert like in your first version:
Code: Select all
function mergetables(...)
local ret = {}
for i, tbl in ipairs {...} do
for k, v in pairs(tbl) do
if type(k) == "number" then
table.insert(ret, v)
else
ret[k] = v
end
end
end
return ret
end