lua utils

Showcase your libraries, tools and other projects that help your fellow love users.
User avatar
ivan
Party member
Posts: 1524
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

lua utils

Post by ivan » Mon Aug 04, 2014 3:15 pm

Just wanted to show off a small library for working with tables.
The basic idea is using concatenated string keys.
Accessing tables (table.get):

Code: Select all

a = { b = { c = 'foo' } }
-- old style
if a.b then
  foo = a.b.c
end
-- new style:
foo = table.get(a, 'b.c')
The lib works with numeric values too.

Assignment (table.set):

Code: Select all

table.set(_G, "love.game.window.resolution", 800)
assert(love.game.window.resolution == 800)
Assignment creates nested tables on the fly.

Iteration:

Code: Select all

planets = 
{
  Mercury = {},
  Venus = {},
  Earth = { 'Moon' },
  Mars = { 'Deimos', 'Phobos' }
}

for k, v in table.ckeys(planets) do
  print(k .. ' = ' .. tostring(v))
end
Outputs:

Code: Select all

Earth = table: 00DA45D0
Earth.1 = Moon
Mars = table: 00DA4980
Mars.1 = Deimos
Mars.2 = Phobos
Mercury = table: 00DA3EC0
Venus = table: 00DA4438
Limitations:
Supported key types are strings and numbers.
Keys containing the dot character (.) are accessed through (%.) so:

Code: Select all

a['these.are.dots'] = 5 -- table.set(a, "these%.are%.dots", 5)
Implementation is not great but fast enough for storing your game options and such.

Repository: https://bitbucket.org/itraykov/utils/src/
Attachments
table.lua
bug fix
(6.3 KiB) Downloaded 206 times
Last edited by ivan on Sun Aug 10, 2014 8:47 am, edited 6 times in total.

User avatar
Roland_Yonaba
Inner party member
Posts: 1562
Joined: Tue Jun 21, 2011 6:08 pm
Location: Ouagadougou (Burkina Faso)
Contact:

Re: ckeys: a new table library

Post by Roland_Yonaba » Tue Aug 05, 2014 11:54 am

Great! And implemented nicely.
Lua 5.3 will provide a table.copy function. :)

User avatar
ivan
Party member
Posts: 1524
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: ckeys: a new table library

Post by ivan » Fri Aug 08, 2014 4:21 pm

Thanks Roland!
Roland_Yonaba wrote:Lua 5.3 will provide a table.copy function. :)
Cool :)

User avatar
ivan
Party member
Posts: 1524
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: lua utils

Post by ivan » Sun Aug 10, 2014 8:52 am

I don't want to start another thread, but here is another util for packing RGB colors into a single number:

Code: Select all

local colors = {}

function colors.hex_to_rgb(rgb)
  -- clamp between 0x000000 and 0xffffff
  rgb = rgb%0x1000000 -- 0xffffff + 1

  -- extract each color
  local b = rgb%0x100 -- 0xff + 1 or 256
  local g = (rgb - b)%0x10000 -- 0xffff + 1
  local r = (rgb - g - b)
  -- shift right
  g = g/0x100 -- 0xff + 1 or 256
  r = r/0x10000 -- 0xffff + 1

  return r, g, b
end

function colors.shex_to_rgb(sz)
  local n = tonumber(sz)
  return colors.hex_to_rgb(n)
end

function colors.rgb_to_hex(r, g, b)
  return r*0x10000 + g*0x100 + b
end
Repository: same as above
Pros:
All maths, does not create temporary strings.
Cons:
Does not store alpha information.
Yes, it is possible to pack alpha information in a number too as long as your lua distribution treats numbers as doubles not floats.

User avatar
ivan
Party member
Posts: 1524
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: lua utils

Post by ivan » Sat Aug 30, 2014 8:03 am

Don't want to start another thread but here are a few Lua tutorials:

Tiling (how to use bitwise operations to draw tiled maps):
http://2dengine.com/doc_1_3_10/gs_tiling.html

Itersections (collision detection)
http://2dengine.com/doc_1_3_10/gs_intersection.html

Collisions (collision response)
http://2dengine.com/doc_1_3_10/gs_collision.html

Waveforms (how to use waveforms in games)
http://2dengine.com/doc_1_3_10/gs_wave.html

Vector math
http://2dengine.com/doc_1_3_10/gs_vector.html

User avatar
undef
Party member
Posts: 438
Joined: Mon Jun 10, 2013 3:09 pm
Location: Berlin
Contact:

Re: lua utils

Post by undef » Sat Aug 30, 2014 10:58 am

I think for the tutorials a new thread or maybe this one: viewtopic.php?f=3&t=12, might be better.
But thanks anyway.
twitter | steam | indieDB

Check out quadrant on Steam!

User avatar
ivan
Party member
Posts: 1524
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: lua utils

Post by ivan » Fri Sep 12, 2014 9:17 am

Now with illustrations and even more examples:
http://2dengine.com/doc_1_3_10/gs_intersection.html

User avatar
ivan
Party member
Posts: 1524
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: lua utils

Post by ivan » Wed Sep 24, 2014 9:57 am

The next util I want to share calculates the aspect ratio given a width and a height.
Super hacky and ugly but gets the job done:

Code: Select all

aspect = {}
aspect.ratios = { '5:4', '4:3', '3:2', '8:5', '5:3', '16:9', '17:9' }

aspect.gdc = function(a, b)
  if b == 0 then
    return a
  end
  return aspect.gdc(b, a%b)
end

--- Returns the aspect ratio and percentage error
-- thanks to Petrucio from StackOverflow and the Steam Hardware survey page
aspect.ratio = function(w, h)
  local gdc = aspect.gdc(w, h)
  local rx, ry = w/gdc, h/gdc
  local r = rx/ry
  
  local li = -1
  local le = 999
  local sz = string.format("%d:%d", rx, ry)
  for i, v in ipairs(aspect.ratios) do
    if v == sz then
      li = i
      le = 0
      break
    end
    local _rx, _ry = string.match(v, "([%d]+):([%d]+)")
    _rx, _ry = tonumber(_rx), tonumber(_ry)
    local _r = _rx/_ry
    local d = math.abs(r - _r)
    if d < le then
      li = i
      le = d
    end
  end
  rx, ry = string.match(aspect.ratios[li], "([%d]+):([%d]+)")
  rx, ry = tonumber(rx), tonumber(ry)
  -- hack to fix 8:5, more known as 16:10
  if rx == 8 and ry == 5 then
    rx, ry = 16, 10
  end
  return rx, ry, le
end
Thanks to Petrucio from StackOverflow and the Steam Hardware survey page

User avatar
ivan
Party member
Posts: 1524
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: lua utils

Post by ivan » Tue Oct 14, 2014 4:59 am

If you have used the Love2D physics module you might be familiar with some of these questions:

What will be the future position/angle of body A?

Code: Select all

--- Returns the future position assuming no external forces are acting on the body
-- @x, @y Current position at the beginning of the time step
-- @lvx, lvy Current linear velocity at the beginning of the time step
-- @damping Linear damping
-- @gx, gy Gravity
-- @dt Time step
-- @return Future position at the end of the time step
function steering.futurePos(x, y, lvx, lvy, damping, gx, gy, dt)
  -- integrate gravity
  local fpx = lvx + gx*dt
  local fpy = lvy + gy*dt
  -- apply damping
  local d = 1 - dt*damping
  if d < 0 then
    d = 0
  elseif d > 1 then
    d = 1
  end
  return fpx*d + x, fpy*d + y
end

--- Returns the future angle assuming no external forces are acting on the body
-- @x, @y Current angle at the beginning of the time step
-- @lvx, lvy Current angular velocity at the beginning of the time step
-- @damping Angular damping
-- @dt Time step
-- @return Future angle at the end of the time step
function steering.futureAng(a, av, damping, dt)
  -- apply damping
  local d = 1 - dt*damping
  if d < 0 then
    d = 0
  elseif d > 1 then
    d = 1
  end
  return av*d + a
end
What velocity should I set so that body A is not affected by damping/gravity?

Code: Select all

--- Compensates for the effects of gravity
-- @lvx, lvy Desired linear velocity at the end of the time step
-- @gx, gy Gravity
-- @dt Time step
-- @return Target linear velocity at the beginning of the time step
function steering.compG(lvx, lvy, gx, gy, dt)
  return lvx - gx*dt, lvy - gy*dt
end

--- Compensates for the effects of linear damping
-- @lvx, lvy Desired linear velocity at the end of the time step
-- @damping Linear damping
-- @maxLV Maximum linear velocity
-- @dt Time step
-- @return Target linear velocity at the beginning of the time step
function steering.compLD(lvx, lvy, damping, maxLV, dt)
  local d = 1 - dt*damping
  if d <= 0 then
    local lv = math.sqrt(lvx*lvx + lvy*lvy)
    local nx, ny = lvx/lv, lvy/lv
    return nx*maxLV, ny*maxLV
  elseif d > 1 then
    d = 1
  end
  return lvx/d, lvy/d
end

--- Compensates for the effects of angular damping
-- @av Desired angular velocity at the end of the time step
-- @damping Linear damping
-- @maxAV Maximum angular velocity
-- @dt Time step
-- @return Target angular velocity at the beginning of the time step
function steering.compAD(av, damping, maxAV, dt)
  local d = 1 - dt*damping
  if d <= 0 then
    if av < 0 then
      return -maxAV
    else
      return maxAV
    end
  elseif d > 1 then
    d = 1
  end
  return av/d
end
How much force/torque do I need to apply so that body A can reach a given velocity?

Code: Select all

--- Returns the force required to reach a given linear velocity
--- force = ( change in velocity / time ) * mass
-- @ivx, @ivy Initial linear velocity at the beginning of the time step
-- @fvx, @fvy Final linear velocity at the end of the time step
-- @mass Mass
-- @dt Time step
-- @return Force
function steering.force(ivx, ivy, fvx, fvy, mass, dt)
  return (fvx - ivx)/dt*mass, (fvy - ivy)/dt*mass
end

--- Returns the torque required to reach a given angular velocity
--- inertia = mass * initial velocity
--- torque = ( change in velocity / time ) * inertia
-- @iv Initial angular velocity at the beginning of the time step
-- @fv Final angular velocity at the end of the time step
-- @mass Mass
-- @dt Time step
-- @return Torque
function steering.torque(iv, fv, mass, dt)
  local inertia = mass*iv
  return (fv - iv)/dt*inertia
end
How long does it take to accelerate to a given velocity?

Code: Select all

--- Returns the time required to accelerate to a given linear velocity
--- time = change in velocity * mass / force
-- @ivx, @ivy Initial linear velocity
-- @fvx, @fvy Final linear velocity
-- @mass Mass
-- @force Maximum force
-- @return Time
function steering.atime(ivx, ivy, fvx, fvy, mass, force)
  -- change in velocity
  local dx, dy = fvx - ivx, fvy - ivy
  local d = math.sqrt(dx*dx + dy*dy)
  return d*mass/force
end

--- Returns the time required to accelerate to a given angular velocity
--- inertia = mass * initial velocity
--- time = change in velocity * inertia / torque
-- @iv Initial angular velocity
-- @fv Final angular velocity
-- @mass Mass
-- @force Maximum torque
-- @return Time
function steering.aatime(iv, fv, mass, torque)
  local inertia = mass*iv
  return (fv - iv)*inertia/torque
end
example use:

Code: Select all

-- current linear velocity
local cvx, cvy = body:GetLinearVelocity()

-- target linear velocity required to counteract the effects of gravity and linear damping:
local lvx, lvy = steering.compG(0, 0, gx, gy, interval)
lvx, lvy = steering.compLD(lvx, lvy, damping, maxLV, interval)

-- force required to reach the target linear velocity
local fx, fy = steering.force(cvx, cvy, lvx, lvy, mass, interval)

-- keep the body aloft using only forces
body:ApplyForce(fx, fy)

-- update simulation(interval)

User avatar
Snuux
Prole
Posts: 49
Joined: Sun Dec 15, 2013 10:43 am
Location: Russia, Moskow
Contact:

Re: lua utils

Post by Snuux » Tue Oct 14, 2014 11:36 am

Perfect! Thanks for this functions.
But, help me please, how use function, that calculate aspect ratio?
My library for easy saving Slib! Try this! Now you can encrypt your save!
- Drop of light LD#30
- OUTRANGE LD#31
(Sorry for my english. I learn it myself, and I don't have enough experience)

Post Reply

Who is online

Users browsing this forum: No registered users and 4 guests