Page 2 of 4

Re: lua utils

Posted: Tue Oct 14, 2014 12:05 pm
by ivan

Code: Select all

local x, y = aspect.ratio(800, 600)
print("aspect ratio is: " .. x .. " : " .. y)

Re: lua utils

Posted: Tue Oct 14, 2014 12:16 pm
by Snuux
))

Oh, sorry. I mean this question: how can I use information about aspect ratio, to properly zoom game (for different screens)?

Re: lua utils

Posted: Wed Oct 15, 2014 6:37 am
by ivan
The aspect ratio function simply rounds the resolution to the nearest aspect ratio format.

I'm not 100% sure how the transformations work in Love2D but take a look at "Coordinate System" on this wiki page:
http://love2d.org/wiki/love.graphics#co ... e%20system

Re: lua utils

Posted: Mon Dec 08, 2014 12:55 pm
by ivan
Tutorial on platformers and finite state machines:
http://2dengine.com/doc_1_3_10/gs_fsm.html

Attached is a love2d version of the tutorial.

Image

line/ray/segment casting

Posted: Wed Jan 21, 2015 2:16 pm
by ivan
I was inspired by Taehl and davisdude to write a small raycasting lib:

Code: Select all

--
-- Segment, ray and line casts
-- ===========================
-- Based on "Real-Time Collision Detection" by Christer Ericson
--

-- Definitions
-- ===========
-- This module works with three different types:
-- "segment" has two endpoints
-- "ray" has one endpoint
-- "line" has no endpoints

-- Results
-- =======
-- Each test, returns either one or two points.
-- The order of returned points is determined by
-- the direction of the segment, ray or line (a-b).
--
-- After each returned intersection point,
-- the module also returns the "intersection value".
-- The "intersection value" can be defined as the ratio:
-- R = |a-q|/|a-b|
-- if a-b is a segment: R is from 0 to 1
-- if a-b is a rays: R is 0 or greater
-- if a-b is a line: R could be any number

-- Example
-- =======
-- -- one intersection point:
-- qx,qy,q = line.segment(-1,0,1,0, 0,-1,0,1, "segment", "segment")
-- assert(qx == 0 and qy == 0 and q == 0.5)
--
-- -- two intersection points:
-- qx,qy,q, qx2,qy2,q2 = line.circle(-1,0,1,0, 0,0,0.5, "segment")
-- assert(qx == -0.5 and qy == 0 and q == 0.25)
-- assert(qx2 == 0.5 and qy2 == 0 and q2 == 0.75)

-- Limitations
-- ===========
-- "line.segment" does not work with "collinear" segments, rays or lines
-- None of the functions work with "degenerate" segments, rays or lines
-- Triangles are not supported :(

-- License
-- =======
-- MIT License

local sqrt = math.sqrt

local line = {}

function line.is_degenerate(ax, ay, bx, by)
  --return dist2(ax, ay, bx, by) == 0
  local dx, dy = ax - bx, ay - by
  return dx*dx + dy*dy == 0
end


--  (a)
--    \  (b2)
--     \ / 
--     (q)
--     / \
--   (a2) \
--        (b)

--- Segment
-- @param ax,ay,bx,by segment, ray or line
-- @param ax2,ay2,bx2,by2 segment, ray or line
-- @param lt defines a-b as either: "segment", "ray" or "line" (optional)
-- @param lt2 defines a2-b2 as either: "segment", "ray" or "line" (optional)
-- @return intersection point and ratio or nil
function line.segment(x1, y1, x2, y2, x3, y3, x4, y4, lt1, lt2)
  lt1 = lt1 or "segment"
  lt2 = lt2 or "segment"
  local dx1, dy1 = x2 - x1, y2 - y1
  local dx2, dy2 = x4 - x3, y4 - y3

  local d = dx1*dy2 - dy1*dx2
  if d == 0 then
    return -- collinear
  end
  local dx3, dy3 = x1 - x3, y1 - y3
  local t1 = (dx2*dy3 - dy2*dx3)/d
  if (lt1 ~= "line" and t1 < 0) or (lt1 == "segment" and t1 > 1) then
    return -- non-intersecting segment or ray
  end
  local t2 = (dx1*dy3 - dy1*dx3)/d
  if (lt2 ~= "line" and t2 < 0) or (lt2 == "segment" and t2 > 1) then
    return -- non-intersecting segment or ray
  end
  return x1 + t1*dx1, y1 + t1*dy1, t1, t2
end

-- (a)
--   \ .-'''-.
--   (q)      \
--   | \ (c)   |
--    \ \     /
--     `(q2)-'
--        \   
--        (b)  

--- Circle
-- @param ax,ay,bx,by segment, ray or line
-- @param cx,cy circle center
-- @param cr circle radius
-- @param lt defines a-b as either: "segment", "ray" or "line" (optional)
-- @return intersection point(s) and ratio(s) or nil
function line.circle(ax, ay, bx, by, cx, cy, cr, lt)
  lt = lt or "segment"
  local dx, dy = bx - ax, by - ay
  local d = sqrt(dx*dx + dy*dy) -- len(dx, dy)
  if d == 0 then
    return -- degenerate
  end
  local nx, ny = dx/d, dy/d
  local mx, my = ax - cx, ay - cy
  local b = mx*nx + my*ny -- dot(mx, my, nx, ny)
  local c = mx*mx + my*my - cr*cr -- dot(mx, my, mx, my) - cr*cr
  if lt ~= "line" and c > 0 and b > 0 then
    return -- non-intersecting
  end
  local discr = b*b - c
  if discr < 0 then
    return -- non-intersecting
  end
  discr = sqrt(discr)
  local tmin = -b - discr
  if lt ~= "line" and tmin < 0 then
    tmin = 0
  end
  if lt == "segment" and tmin > d then
    return -- non-intersecting
  end
  local tmax = discr - b
  if lt == "segment" and tmax > d then
    tmax = d
  end
  local qx, qy = ax + tmin*nx, ay + tmin*ny, tmin
  if tmax == tmin then
    return qx, qy, tmin/d
  end
  return qx, qy, tmin/d, ax + tmax*nx, ay + tmax*ny, tmax/d
end

-- (a)
--   \ --------
--    \|      |
--    (q)     |
--     |\     |
--     -(q2)---
--        \   
--        (b)

--- Axis-aligned rectangle (l,t,r,b)
-- @param ax,ay,bx,by segment, ray or line
-- @param l,t left/top corner of the rectangle
-- @param r,b right/bottom corner of the rectangle
-- @param lt defines a-b as either: "segment", "ray" or "line" (optional)
-- @return intersection point(s) and ratio(s) or nil
function line.aabb(ax, ay, bx, by, l, t, r, b, lt)
  lt = lt or "segment"
  -- misaligned aabb?
  if l > r then
    l, r = r, l
  end
  if t > b then
    t, b = b, t
  end
  local dx, dy = bx - ax, by - ay
  local d = sqrt(dx*dx + dy*dy) -- len(dx, dy)
  if d == 0 then
    return -- degenerate
  end
  local nx, ny = dx/d, dy/d
  local tmin, tmax
  if lt == "segment" then
    tmin = 0
    tmax = d
  elseif lt == "ray" then
    tmin = 0
  end
  --if abs(dx) < EPSILON then
  if dx == 0 then
    if ax < l or ax > r then
      return -- non-intersecting
    end
  else
    local ood = 1/nx
    local t1, t2 = (l - ax)*ood, (r - ax)*ood
    if t1 > t2 then
      t1, t2 = t2, t1
    end
    if tmin == nil or tmin < t1 then
      tmin = t1
    end
    if tmax == nil or tmax > t2 then
      tmax = t2
    end
    if tmin > tmax then
      return -- non-intersecting
    end
  end
  --if abs(dy) < EPSILON then
  if dy == 0 then
    if ay < t or ay > b then
      return -- non-intersectings
    end
  else
    local ood = 1/ny
    local t1, t2 = (t - ay)*ood, (b - ay)*ood
    if t1 > t2 then
      t1, t2 = t2, t1
    end
    if tmin == nil or tmin < t1 then
      tmin = t1
    end
    if tmax == nil or tmax > t2 then
      tmax = t2
    end
    if tmin > tmax then
      return -- non-intersecting
    end
  end
  local qx, qy = ax + nx*tmin, ay + ny*tmin, tmin
  if tmin == tmax then
    return qx, qy, tmin
  end
  return qx, qy, tmin/d, ax + nx*tmax, ay + ny*tmax, tmax/d
end

--- Axis-aligned rectangle (second representation)
-- @param ax,ay,bx,by segment, ray or line
-- @param l,t left/top corner of the rectangle
-- @param w,h width and height of the rectangle
-- @param lt defines a-b as either: "segment", "ray" or "line" (optional)
-- @return intersection point(s) and ratio(s) or nil
function line.rect(ax, ay, bx, by, l, t, w, h, lt)
  return line.aabb(ax, ay, bx, by, l, t, l + w, t + h, lt)
end

--- Axis-aligned rectangle (third representation)
-- @param ax,ay,bx,by segment, ray or line
-- @param x,y center point of the rectangle
-- @param hw,hh half-width and half-height extents of the rectangle
-- @param lt defines a-b as either: "segment", "ray" or "line" (optional)
-- @return intersection point(s) and ratio(s) or nil
function line.box(ax, ay, bx, by, x, y, hw, hh, lt)
  return line.aabb(ax, ay, bx, by, x - hw, y - hh, x + hw, y + hh, lt)
end

return line
It's still WIP and some things could be refactored/improved.
A lot of the code is based on Christer Ericson's book.

For the latest code I would advise to visit this repository under math/line.lua

Edit: improved segment vs segment, getting closer to a solution for collinear segments

Re: lua utils

Posted: Wed Jan 21, 2015 5:45 pm
by Ref
FYI Ivan!
Following does not function as advertised:

Code: Select all

--- Splits a path into directory, filename and extension
--- Assumes the path is a filename, if it does not end with a slash
--- Adapted from Paul Kulchenko
-- @param fn Filename
-- @return Directory path, filename and extension
function io.split(fn)
  return string.match(fn, "(.-)([^\\/]-%.?([^%.\\/]*))$")
end
Returns the filename with extension.

Re: lua utils

Posted: Thu Jan 22, 2015 6:05 am
by ivan
Hey Ref, thanks for taking a look. :)
Yep, I agree - that lib needs some revisions too.
You're right - "split" is not the right word in this case.
Can you please give some example input that doesn't work.
Seems to return three captures:

Code: Select all

function io.split(fn)
  return string.match(fn, "(.-)([^\\/]-%.?([^%.\\/]*))$")
end
a,b,c = io.split("c:/dev/games/oops.lua")
print("path:".. (a or "nil"))
print("file:".. (b or "nil"))
print("ext:".. (c or "nil"))
Output:

Code: Select all

path:c:/dev/games/
file:oops.lua
ext:lua

Re: lua utils

Posted: Thu Jan 22, 2015 2:43 pm
by Ref
I have a warped sense of what 'filename' means.
Expected 'filename' would be the name without extension.
Your function returns path, filename.ext and ext.
Lot of neat stuff in your library.

SVG

Posted: Sat Mar 07, 2015 9:24 am
by ivan
I noticed a few people asking if SVG files can be used/loaded in Love2D/Lua.
After a lot of testing with the AGen engine I have to say, yes, it's possible but it's slow and not very practical.
Check out the attached SVG demo.
It's only a demo though so don't treat this as a complete library.
All done in Lua, no external libs. Love2D is used purely for rendering.

What "utils.svg" supports:
-parses svg files (parses xml using "utils.io.table")
-filled paths with holes (triangulates using "utils.math.poly")
-bezier curves (level of detail is defined in "utils.math.curves")
-filled shapes
-elliptic arcs

What's not supported:
-stroke (requires polygon offsetting)
-self-intersecting paths, fill-rules, etc (requires polygon difference/union)
-textures/images
-gradients
-type and fonts
-styles

How to use:
Use the left/right arrow keys to change examples.
So ya, don't expect this to work for every type of SVG file, but as long as it doesn't use "stroke" it would probably work.
Extract svg.love and drop your SVG files into "svg/tests/" to try it out.

Re: lua utils

Posted: Sat Mar 07, 2015 9:48 am
by arampl
Check my post in the "What's everyone working on? (tigsource inspired)" section (page 110).
May be you find this interesting. Self-intersecting beziers (it's only the beginning of full paths support).
SVG import is planned. I'm thinking about full-scale vector editor and new lua+vector graphics file format.

About slowliness: vector graphics can be prepared beforehand using canvases, and drawn as plain images in love.draw() later. Something like precaching svgs' in Qt.

Vector graphics can be extremely useful for procedural content generation. Just invaluable tool for that. Plus different shaders for amazing effects.