Hey, so here's a couple functions!

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Nicholas Scott
Prole
Posts: 49
Joined: Sun Jun 07, 2015 9:12 am

Hey, so here's a couple functions!

Post by Nicholas Scott »

I take no credit for creating the concepts or the formulas, I only wrote the code :D, obviously xD I'm not a genius, but I did the tedious work of putting the functions together. I don't think there is any practical use for them, but I still found them interesting to play with :D

This is a Super Ellipse function, not much to explain here haha :D
Pretty basic, xOff and yOff are the positions of the center of the Ellipse, a, b, and n are variables to play with at your leisure(A and B are w and h, n is the gud stuff, detail is line segments :D

Code: Select all

function love.graphics.superEllipse(xOff, yOff, a, b, n, detail)
  local function sgn(x) --Function for stuff :3
    return x > 0 and 1 or x < 0 and -1 or 0
  end
  xOff, yOff, a, b, n, na, detail = xOff or 0, yOff or 0, a or 100, b or 100, n or 2, n/2, detail or 0.1
  local PointTable = {}
  for i=0, math.pi*2, (math.pi*2) / detail or 0.1 do
    table.insert(PointTable, {x=math.pow(math.abs(math.cos(i)), na) * a * sgn(math.cos(i)),y=math.pow(math.abs(math.sin(i)), na) * b * sgn(math.sin(i))})
  end
  for k,v in pairs(PointTable) do
    local thisVec = v
    local nextVec = PointTable[k+1] or PointTable[1]
    love.graphics.line(v.x + xOff, v.y + yOff, nextVec.x + xOff, nextVec.y + yOff)
  end
end
Now here comes the fun stuff! SuperShapes Mwahahhahahaa, if you have no idea what it is, or what you can go do with it, go check out this page http://paulbourke.net/geometry/supershape/. It even goes over some variables you can input to have various different shapes. I'm not gonna go into super detail cuz it's allot haha. But it's cool nonetheless :D
Once again, xOff and yOff are positions, n1, n2, n3, m, a, and b are your children.. Don't abuse them... Naw, jk do what you want fam, it's just a letter. Detail is segments, and radius is.. well radius :D

Code: Select all

function love.graphics.superShape(xOff, yOff, n1, n2, n3, m, a, b, detail, radius)
  --[[ Default values ]]--
  n1, n2, n3, m, a, b, detail, radius, xOff, yOff = n1 or 1, n2 or 1, n3 or 1, m or 0, a or 1, b or 1, detail or 500, radius or 100, xOff or 0, yOff or 0
  --[[ Function for stuff :3 ]]--
  local function spshpe(theta)
    local formula = math.pow((math.pow(math.abs((1 / a) * math.cos(theta * m / 4)), n2)) + (math.pow(math.abs((1 / b) * math.sin(theta * m / 4)), n3)), 1 / n1)
    
    return formula == 0 and 0 or 1 / formula
  end
  
  local PointTable = {}
  for i=0, math.pi * 2, (math.pi*2) / detail do
    table.insert(PointTable, {x=radius * spshpe(i) * math.cos(i),y=radius * spshpe(i) * math.sin(i)})
  end
  for k,v in pairs(PointTable) do
    local thisVec = v
    local nextVec = PointTable[k+1] or PointTable[1]
    love.graphics.line(v.x + xOff, v.y + yOff, nextVec.x + xOff, nextVec.y + yOff)
  end
end
Have fun guys, It's fun to tinker with :P

EDIT:
Here's the more optimized and ability to use outside of LOVE2D with credit from the all mighty Positive07 :D
Positive07 wrote:Okey I had a go with the first function, trying to optimize and making it nicre, Also with lot's of comments so you can understand why I changed what I changed

Code: Select all

--Declare variables that are gonna be used EVERY time the function is called outside of it
--This is so that Lua doesn't calculate them every single time
local tau = math.pi*2
local func = { math.cos, math.sin }

function superEllipse(x, y, a, b, n, detail)
  -- I used tables here because I'm actually cheating later
  local offset = { x or 0, y or 0 }
  local v = { a or 100, b or 100 }
  --It didn't look like you needed n after all
  local na = (n or 2)/2
  --I declared all variables in different lines because it's easier to know which one gets which value
  local detail = detail or 0.1

  --ranamed for consistency
  local points = {}

  for i=0, tau, tau / detail do
    --x and y are calculated the same so we can do it in a loop
    for j=1, 2 do
      --This are only used here so they must be locals
      --we don't want to pollute the global scope
      local f = func[j](i)
      local abs = math.abs(f)
      --I removed the sign function and used this which ivan suggested
      local sgn = math.floor(f/abs + 0.5)
    
      --We apply the offset directly to the points
      local result = (math.pow(abs, na) * v[j] * sgn) + offset[j]
      --All points are in a single list, odd enrties are x values, even are y values
      --table.insert is slow in common Lua (Not that it matters with LuaJIT though)
      points[#points + 1] = result
    end
  end

  --Return the list of points
  return points
end

--LÖVE specific function, the other is just math
function superEllipseDraw (...)
  --love.graphics.polygon has a line mode which do the same job as your second loop
  love.graphics.polygon("line", supperEllipse(...))
end
No comments version

Code: Select all

local tau = math.pi*2
local func = { math.cos, math.sin }

function superEllipse(x, y, a, b, n, detail)
  local offset = { x or 0, y or 0 }
  local v = { a or 100, b or 100 }
  local na = (n or 2)/2
  local detail = detail or 0.1

  local points = {}

  for i=0, tau, tau / detail do
    for j=1, 2 do
      local f = func[j](i)
      local abs = math.abs(f)
      local sgn = math.floor(f/abs + 0.5)
    
      local result = (math.pow(abs, na) * v[j] * sgn) + offset[j]
      points[#points + 1] = result
    end
  end

  return points
end

function superEllipseDraw (...)
  love.graphics.polygon("line", supperEllipse(...))
end
Last edited by Nicholas Scott on Wed Dec 14, 2016 1:00 am, edited 4 times in total.
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Hey, so here's a couple functions!

Post by Jasoco »

The first function (math.sgn) can be replaced with a much more compact version:

Code: Select all

function math.sgn(x)
  return x > 0 and 1 or x < 0 and -1 or 0
end
And the if formula/return lines could be replaced too...

Code: Select all

return formula == 0 and 0 or 1 / formula
Sorry, I've just been obsessed with this trick lately. Probably an unhealthy obsession. No idea if they'd even make things faster or slower. Just more compact and neat looking. (As long as you understand what they do)
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Hey, so here's a couple functions!

Post by ivan »

In this case, since you already know the absolute value you can simply write:

Code: Select all

local absValue = math.abs(value) -- already known
assert(absValue > 0)
local sign = value/absValue
Also, make sure to store intermediate stuff in locals since Lua is a dynamic language (and cannot optimize 'constant' operations):

Code: Select all

    local a = a or 100
    local b = b or 100
    local n = n or 2
    local na = n/2
    local co = math.cos(i)
    local si = math.sin(i)
    local aco = math.abs(co)
    local asi = math.abs(si)
    local x = math.pow(aco, na) * a * co/aco
    local y = math.pow(asi, na) * b * si/asi
    table.insert(PointTable, Vector(x, y))
Note: You'll need an extra check if aco==0 or asi==0 to avoid a division by 0
or better yet, if your math code is robust enough, that shouldn't happen at all.

PS. and move "local a = a or 100" outside of the loop, you don't need that check in every iteration.
Nicholas Scott
Prole
Posts: 49
Joined: Sun Jun 07, 2015 9:12 am

Re: Hey, so here's a couple functions!

Post by Nicholas Scott »

ivan wrote:
Jasoco wrote:
Credit to you two :D, I worked stuff out and just did some general changes, so there ya go :D
Also I can't get over that trick either Jasoco haha, I love it but don't use it for when I'm lettin others see the code cuz well.. It's kind of a hard concept for new people to understand but ye :P
User avatar
Jasoco
Inner party member
Posts: 3725
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

Re: Hey, so here's a couple functions!

Post by Jasoco »

Haha, yeah. It can be confusing to newbies, but when you get used to it, it saves a lot of code typing.
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Hey, so here's a couple functions!

Post by Positive07 »

Okey I had a go with the first function, trying to optimize and making it nicre, Also with lot's of comments so you can understand why I changed what I changed

Code: Select all

--Declare variables that are gonna be used EVERY time the function is called outside of it
--This is so that Lua doesn't calculate them every single time
local tau = math.pi*2
local func = { math.cos, math.sin }

function superEllipse(x, y, a, b, n, detail)
  -- I used tables here because I'm actually cheating later
  local offset = { x or 0, y or 0 }
  local v = { a or 100, b or 100 }
  --It didn't look like you needed n after all
  local na = (n or 2)/2
  --I declared all variables in different lines because it's easier to know which one gets which value
  local detail = detail or 0.1

  --ranamed for consistency
  local points = {}

  for i=0, tau, tau / detail do
    --x and y are calculated the same so we can do it in a loop
    for j=1, 2 do
      --This are only used here so they must be locals
      --we don't want to pollute the global scope
      local f = func[j](i)
      local abs = math.abs(f)
      --I removed the sign function and used this which ivan suggested
      local sgn = math.floor(f/abs + 0.5)
    
      --We apply the offset directly to the points
      local result = (math.pow(abs, na) * v[j] * sgn) + offset[j]
      --All points are in a single list, odd enrties are x values, even are y values
      --table.insert is slow in common Lua (Not that it matters with LuaJIT though)
      points[#points + 1] = result
    end
  end

  --Return the list of points
  return points
end

--LÖVE specific function, the other is just math
function superEllipseDraw (...)
  --love.graphics.polygon has a line mode which do the same job as your second loop
  love.graphics.polygon("line", supperEllipse(...))
end
No comments version

Code: Select all

local tau = math.pi*2
local func = { math.cos, math.sin }

function superEllipse(x, y, a, b, n, detail)
  local offset = { x or 0, y or 0 }
  local v = { a or 100, b or 100 }
  local na = (n or 2)/2
  local detail = detail or 0.1

  local points = {}

  for i=0, tau, tau / detail do
    for j=1, 2 do
      local f = func[j](i)
      local abs = math.abs(f)
      local sgn = math.floor(f/abs + 0.5)
    
      local result = (math.pow(abs, na) * v[j] * sgn) + offset[j]
      points[#points + 1] = result
    end
  end

  return points
end

function superEllipseDraw (...)
  love.graphics.polygon("line", supperEllipse(...))
end
Last edited by Positive07 on Mon Dec 12, 2016 10:38 pm, edited 1 time in total.
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: Hey, so here's a couple functions!

Post by zorg »

Just to nitpick a bit, 2pi is commonly called "tau".
Me and my stuff :3True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
User avatar
ivan
Party member
Posts: 1911
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Hey, so here's a couple functions!

Post by ivan »

Good job, Positive, your revisions look much cleaner than the original.
Of course, I would even remove "table.insert" and "love.graphics" too
so the code would be pure Lua math (each function could return a list of points).
User avatar
Ref
Party member
Posts: 702
Joined: Wed May 02, 2012 11:05 pm

Re: Hey, so here's a couple functions!

Post by Ref »

For those just curious what super ellipses look like, see attached Love.
Definitely not an example of great code - just wanted to see what this was all about.
Key control for 'm' and 'n' parameters.
love.math.triangulate definitely doesn't like certain parameter combinations.
Have fun.
Attachments
Super.love
No credit taken
(1.18 KiB) Downloaded 137 times
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Hey, so here's a couple functions!

Post by Positive07 »

ivan wrote:Good job, Positive, your revisions look much cleaner than the original.
Of course, I would even remove "table.insert" and "love.graphics" too
so the code would be pure Lua math (each function could return a list of points).
Okay I fixed this things, [manual]table.insert[/manual] is not slower than points[#points + 1] in LuaJIT though, because LuaJIT optimizes it
I added a superEllipseDraw function which is LÖVE specific but the supperEllipse one is just math
zorg wrote:Just to nitpick a bit, 2pi is commonly called "tau".
I fixed this too because there was actually a bug and instead of writing "pi2", I wrote "p12"... so "tau" is better
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
Post Reply

Who is online

Users browsing this forum: No registered users and 54 guests