Compare commits

...

5 Commits

6 changed files with 220 additions and 42 deletions

View File

@ -5,25 +5,10 @@
-- @author Lorenzo Cogotti
local floor = math.floor
local min, max = math.min, math.max
local algo = {}
--- Clamp x within range [a,b] (where b >= a).
--
-- @number x value to clamp.
-- @number a interval lower bound (inclusive).
-- @number b interval upper bound (inclusive).
-- @treturn number clamped value.
function algo.clamp(x, a, b) return min(max(x, a), b) end
--- Sign function.
--
-- @number x value whose sign should be returned.
-- @treturn number sign of x, -1 if negative, 1 if positive, 0 otherwise.
function algo.sign(x) return x > 0 and 1 or x < 0 and -1 or 0 end
--- Fast remove from array.
--
-- Replace 'array[i]' with last array's element and

View File

@ -38,6 +38,50 @@ function Color.lighten(r, g, b, amount)
return r, g, b
end
function Color.hsl(h, s, l, a)
a = a or 1
if s <= 0 then return 1, 1, 1, a end
h = h * 6
local abs = math.abs
local c = (1 - abs(l*2 - 1))*s
local x = (1 - abs(h%2 - 1))*c
local m = l - c*0.5
local r, g, b
if h < 1 then r, g, b = c, x, 0
elseif h < 2 then r, g, b = x, c, 0
elseif h < 3 then r, g, b = 0, c, x
elseif h < 4 then r, g, b = 0, x, c
elseif h < 5 then r, g, b = x, 0, c
else r, g, b = c, 0, x
end
return r+m, g+m, b+m, a
end
function Color.hsv(h, s, v, a)
a = a or 1
if s <= 0 then return v, v, v, a end
h = h * 6
local c = v * s
local x = (1 - math.abs(h%2 - 1))*c
local m = v - c
local r, g, b
if h < 1 then r, g, b = c, x, 0
elseif h < 2 then r, g, b = x, c, 0
elseif h < 3 then r, g, b = 0, c, x
elseif h < 4 then r, g, b = 0, x, c
elseif h < 5 then r, g, b = x, 0, c
else r, g, b = c, 0, x
end
return r+m, g+m, b+m, a
end
--- Given two RGB colors, calculate fade by the specified amount.
--
-- @number cr first color, red channel

View File

@ -14,6 +14,7 @@ local BASE = (...)..'.'
return {
algo = require(BASE..'algo'),
mathx = require(BASE..'mathx'),
meta = require(BASE..'meta'),
rect = require(BASE..'rect'),
shadowtext = require(BASE..'shadowtext'),

142
mathx.lua Normal file
View File

@ -0,0 +1,142 @@
--- Extended math functions
--
-- @module gear.mathx
-- @copyright 2022 The 1414 Code Forge
-- @author Lorenzo Cogotti
local floor = math.floor
local min, max = math.min, math.max
local cos, pi = math.cos, math.pi
local random = love and love.math.random or math.random
local mathx = setmetatable({}, math)
--- Clamp x within range [a,b] (where b >= a).
--
-- @number x value to clamp.
-- @number a interval lower bound (inclusive).
-- @number b interval upper bound (inclusive).
-- @treturn number clamped value.
function mathx.clamp(x, a, b) return min(max(x, a), b) end
--- Sign function.
--
-- @number x value whose sign should be returned.
-- @treturn number sign of x, -1 if negative, 1 if positive, 0 otherwise.
function mathx.sign(x) return x > 0 and 1 or x < 0 and -1 or 0 end
--- sign() variant returning 1 if x is non-negative.
--
-- @number x value whose sign should be returned.
-- @treturn number sign of x, -1 if negative, 1 if non-negative.
function mathx.sign2(x) return x >= 0 and 1 or -1 end
--- Linear interpolation between a and b.
--
-- @number a first interpolation point.
-- @number b second interpolation point.
-- @number t the interpolation factor, a real number within [0,1].
-- @treturn number the interpolated value.
function mathx.lerp(a, b, t) return a*(1 - t) + b*t end
--- Less accurate, but slightly faster, variant of lerp().
function mathx.lerp2(a, b, t) return a + (b - a)*t end
--- Cosine interpolation between a and b.
--
-- @number a first interpolation point.
-- @number b second interpolation point.
-- @number t the interpolation factor, a real number within [0,1].
-- @treturn number interpolated value.
function mathx.cerp(a, b, t)
local tt = (1 - cos(t * pi)) * 0.5
return a*(1 - tt) + b*tt
end
--- Cubic interpolation between a, b, c and d.
--
-- @number a first interpolation point.
-- @number b second interpolation point.
-- @number c third interpolation point.
-- @number d fourth interpolation point.
-- @number t the interpolation factor, a real number within [0,1].
-- @treturn number the interpolated value.
function mathx.cberp(a, b, c, d, t)
local tt = t * t
local a0 = d - c - a + b
return a0*t*tt + (a - b - a0)*tt + (c - a)*t + b
end
--- Catmull-Rom spline interpolation between a, b, c and d.
--
-- @number a first interpolation point.
-- @number b second interpolation point.
-- @number c third interpolation point.
-- @number d fourth interpolation point.
-- @number t the interpolation factor, a real number within [0,1].
-- @treturn number the interpolated value.
function mathx.catmullrom(a, b, c, d, t)
local tt = t * t
local mha = -a * 0.5
local hd = d * 0.5
return (mha + 1.5*b - 1.5*c + hd)*t*tt + (a - 2.5*b + 2*c - hd)*tt + (mha + 0.5*c)*t + b
end
--- Hermite interpolation between a, b, c and d.
--
-- @number a first interpolation point.
-- @number b second interpolation point.
-- @number c third interpolation point.
-- @number d fourth interpolation point.
-- @number t the interpolation factor, a real number within [0,1].
-- @number tension the tension factor, 1 is high, 0 normal (default), -1 is low.
-- @number bias the bias factor, 0 is even (default), positive is towards the first segment, negative towards the other.
-- @treturn number the interpolated value.
function mathx.herp(a, b, c, d, t, tension, bias)
tension = tension or 0
bias = bias or 0
local b0 = 1 + bias
local b1 = 1 - bias
local ht = (1 - tension) * 0.5
local s0 = b0 * ht
local s1 = b1 * ht
local tt = t * t
local ttt = tt * t
local ttt2 = ttt * 2
local tt3 = tt * 3
local m0 = (b - a)*s0 + (c - b)*s1
local m1 = (c - b)*s0 + (d - c)*s1
local a0 = ttt2 - tt3 + 1
local a1 = ttt - tt*2 + t
local a2 = ttt - tt
local a3 = tt3 - ttt2
return a0*b + a1*m0 + a2*m1 + a3*c
end
--- Pseudo-random sign value.
--
-- @treturn number the pseudo-random sign value, either -1, 0, or 1.
function mathx.rsign() return random(-1, 1) end
--- rsign() variant returning -1 or 1.
--
-- @treturn number the pseudo-random sign value, either -1 or 1.
function mathx.rsign2() return random(2) == 2 and 1 or -1 end
--- Precise pseudo-random number within [min,max] (where max >= min).
--
-- @number min interval lower bound (inclusive).
-- @number max interval upper bound (inclusive).
-- @treturn number the pseudo-random real number within [a,b].
function mathx.prandom(min, max)
local t = random()
return min * (1 - t) + max * t
end
return mathx

View File

@ -74,7 +74,7 @@ function Timer:after(delay, func)
end
function Timer:every(delay, after, count)
local count = count or math.huge -- exploit below: math.huge - 1 = math.huge
count = count or math.huge -- exploit below: math.huge - 1 = math.huge
local handle = {
time = 0,
during = _nothing_,

58
vec.lua
View File

@ -206,66 +206,72 @@ function vec.angleto(x1,y1, x2,y2) return atan2(y1,x1) - atan2(y2,x2) end
--- Transform world coordinates to screen coordinates.
--
-- @param x (number) World coordinate X.
-- @param y (number) World coordinate Y.
-- @param vx (number|nil) Point of view X coordinate, defaults to w/2.
-- @param vy (number|nil) Point of view Y coordinate, defaults to h/2.
-- @param rot (number|nil) View rotation in radians, defaults to 0.
-- @param scale (number|nil) View scale (zoom), defaults to 1.
-- @param left (number|nil) Viewport left corner, defaults to 0.
-- @param top (number|nil) Viewport top corner, defaults to 0.
-- @param w (number|nil) Viewport width, defaults to love.graphics.getWidth().
-- @param h (number|nil) Viewport height, defaults to love.graphics.getHeight().
-- @number x World coordinate X.
-- @number y World coordinate Y.
-- @number xview Point of view X coordinate, defaults to w/2.
-- @number yview Point of view Y coordinate, defaults to h/2.
-- @number rot View rotation in radians, defaults to 0.
-- @number scale View scale (zoom), defaults to 1.
-- @number left Viewport left corner, defaults to 0.
-- @number top Viewport top corner, defaults to 0.
-- @number w Viewport width, defaults to love.graphics.getWidth().
-- @number h Viewport height, defaults to love.graphics.getHeight().
-- @number xparallax Parallax factor over X, defaults to 1.
-- @number yparallax Parallax factor over Y, defaults to 1.
--
-- @return (x,y) Transformed to screen coordinates according to
-- viewport and offset.
function vec.toscreencoords(x,y, vx,vy, rot, scale, left,top, w,h)
function vec.toscreencoords(x,y, xview,yview, rot, scale, left,top,w,h, xparallax,yparallax)
left,top = left or 0, top or 0
w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight()
local halfw,halfh = w/2, h/2
vx,vy = vx or halfw, vy or halfh
xview,yview = xview or halfw, yview or halfh
rot = rot or 0
scale = scale or 1
xparallax,yparallax = xparallax or 1, yparallax or 1
local sina,cosa = sin(rot),cos(rot)
x,y = x - vx, y - vy
x,y = x - xview*xparallax, y - yview*yparallax
x,y = cosa*x - sina*y, sina*x + cosa*y
return x*scale + halfw + left, y*scale + halfh + top
end
--- Transform screen coordinates to world coordinates.
--
-- @param x (number) Screen coordinate X.
-- @param y (number) Screen coordinate Y.
-- @param vx (number|nil) Point of view X coordinate, defaults to w/2.
-- @param vy (number|nil) Point of view Y coordinate, defaults to h/2.
-- @param rot (number|nil) View rotation in radians, defaults to 0.
-- @param scale (number|nil) View scale (zoom), defaults to 1.
-- @param left (number|nil) Viewport left corner, defaults to 0.
-- @param top (number|nil) Viewport top corner, defaults to 0.
-- @param w (number|nil) Viewport width, defaults to love.graphics.getWidth().
-- @param h (number|nil) Viewport height, defaults to love.graphics.getHeight().
-- @number x Screen coordinate X.
-- @number y Screen coordinate Y.
-- @number xview Point of view X coordinate, defaults to w/2.
-- @number yview Point of view Y coordinate, defaults to h/2.
-- @number rot View rotation in radians, defaults to 0.
-- @number scale View scale (zoom), defaults to 1.
-- @number left Viewport left corner, defaults to 0.
-- @number top Viewport top corner, defaults to 0.
-- @number w Viewport width, defaults to love.graphics.getWidth().
-- @number h Viewport height, defaults to love.graphics.getHeight().
-- @number xparallax Parallax factor over X, defaults to 1.
-- @number yparallax Parallax factor over Y, defaults to 1.
--
-- @return (x,y) Transformed to world coordinates according to
-- viewport and offset.
function vec.toworldcoords(x,y, vx,vy, rot, scale, left,top,w,h)
function vec.toworldcoords(x,y, xview,yview, rot, scale, left,top,w,h, xparallax,yparallax)
left, top = left or 0, top or 0
w,h = w or love.graphics.getWidth(), h or love.graphics.getHeight()
local halfw,halfh = w/2, h/2
vx,vy = vx or halfw, vy or halfh
xview,yview = xview or halfw, yview or halfh
rot = rot or 0
scale = scale or 1
xparallax,yparallax = xparallax or 1, yparallax or 1
local sina,cosa = sin(-rot),cos(-rot)
x,y = (x - halfw - left) / scale, (y - halfh - top) / scale
x,y = cosa*x - sina*y, sina*x + cosa*y
return x+vx, y+vy
return x + xview*xparallax, y + yview*yparallax
end
return vec