commit db930b13fb8ef54fcbd5d276872451d73d059415 Author: Rokas Puzonas Date: Tue Jun 1 19:08:10 2021 +0300 feat: Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..f01c405 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Lissajous table + +![Preview](example.gif) + +I was inspired by this video "[Making a physical Lissajous curve](https://www.youtube.com/watch?v=4CbPksEl51Q)" +and thought "That looks pretty cool and easy to code". So here it is a program +which draws a resizable lissajous table. The wider or higher your window is +the more circles will be drawn. + +## Starting + +To run this project you need to install [Love2D](https://love2d.org) yourself. +There is a great tutorial on how to do all of this [here](https://love2d.org/wiki/Getting_Started). + diff --git a/conf.lua b/conf.lua new file mode 100644 index 0000000..7868d2b --- /dev/null +++ b/conf.lua @@ -0,0 +1,4 @@ +function love.conf(t) + t.window.title = "Lissajous tables" + t.window.resizable = true +end diff --git a/example.gif b/example.gif new file mode 100644 index 0000000..787398a Binary files /dev/null and b/example.gif differ diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..506838c --- /dev/null +++ b/main.lua @@ -0,0 +1,214 @@ +-- NEEDS OPTIMIZATIONS +local angle = 0 +local relativeGap = 0.5 +local relativeMarker = 0.1 +local relativeWidth = 0.08 +local rows, cols, circles, curves, markerSize, gap +local opacity = 0.3 +local constants = { + circleRadius = 20, + speed = 1, + drawLines = false, + colors = true, + drawMarkers = true, + drawCircles = true, + drawTable = true +} + +function HSV(h, s, v, a) + if s <= 0 then return v,v,v end + h, s, v = h/256*6, s/255, v/255 + local c = v*s + local x = (1-math.abs((h%2)-1))*c + local m,r,g,b = (v-c), 0,0,0 + 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 or 1 +end + +function addColors(h1, h2) + local r1, g1, b1, a1 = HSV(h2, 255, 255) + local r2, g2, b2, a2 = HSV(h1, 255, 255) + return (r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2 +end + +local function distance(x1,y1,x2,y2) + return ((x1-x2)^2 + (y1-y2)^2)^0.5 +end + +function Curve() + local self = {} + self._points = {} + self.draw = function(self) + if #self._points >= 4 then + love.graphics.line(self._points) + end + end + self.addPoint = function(self, x, y) + table.insert(self._points, x) + table.insert(self._points, y) + end + self.clear = function(self) + self._points = {} + end + return self +end + +function genTable(default, N) + local t = {} + for i=0, N-1 do + if type(default) == "function" then + t[i] = default() + else + t[i] = default + end + end + return t +end + +function roundDown(X) + return X - (X / 10) +end + +function recalc(w, h) + local realSize = (relativeGap + 1) * constants.circleRadius + local rows = roundDown(w / realSize) + local cols = roundDown(h / realSize) + circles = genTable(angle, math.max(rows, cols)) + curves = {} + for i=0, rows-1 do + curves[i] = genTable(Curve, cols) + end +end + +function love.load(args, unfilteredArgs) + for i=1,#args do + for name in pairs(constants) do + if "-"..name == args[i] then + if type(constants[name]) == "boolean" then + constants[name] = args[i+1] == "true" + elseif type(constants[name]) == "number" then + constants[name] = tonumber(args[i+1]) + end + i = i + 1 + break + end + end + end + + markerSize = constants.circleRadius*relativeMarker + gap = constants.circleRadius*(1+relativeGap) + + recalc(love.graphics.getDimensions()) +end + +function love.update(dt) + angle = angle + constants.speed * dt + for i in pairs(circles) do + circles[i] = angle * (i+1) + end + if angle > math.pi*2 then + angle = angle % math.pi*2 + for _, j in pairs(curves) do + for _, curve in pairs(j) do + curve:clear() + end + end + end +end + +function setColor(r,g,b,a) + if constants.colors then + love.graphics.setColor(r,g,b,a) + else + love.graphics.setColor(1, 1, 1, a) + end +end + +function drawMarker(x, y) + if constants.drawMarkers then + love.graphics.circle("fill", x, y, markerSize) + end +end + +function drawCircle(x, y) + if constants.drawCircles then + love.graphics.circle("line", x, y, constants.circleRadius) + end +end + +function love.draw() + local w,h = love.graphics.getDimensions() + + love.graphics.setLineJoin("none") + love.graphics.setLineStyle("smooth") + -- Circles and lines + for i, circleAngle in pairs(circles) do + local dist = constants.circleRadius + (i+1) * gap*2 + local p = i/#circles + + -- X-axis + if dist+gap < w then + local x = dist + constants.circleRadius * math.cos(circleAngle-math.pi/2) + local y = gap + constants.circleRadius * math.sin(circleAngle-math.pi/2) + setColor(HSV(p*511, 255, 255)) + love.graphics.setLineWidth(constants.circleRadius * relativeWidth) + drawMarker(x, y) + drawCircle(dist, gap) + + if constants.drawLines then + setColor(HSV(p*511, 255, 255, opacity)) + love.graphics.line(x, 0, x, h) + end + end + -- Y-axis + if dist+gap < h then + local x = gap + constants.circleRadius * math.cos(circleAngle-math.pi/2) + local y = dist + constants.circleRadius * math.sin(circleAngle-math.pi/2) + setColor(HSV(p*511, 255, 255)) + love.graphics.setLineWidth(constants.circleRadius * relativeWidth) + drawMarker(x, y) + drawCircle(gap, dist) + + if constants.drawLines then + setColor(HSV(p*511, 255, 255, opacity)) + love.graphics.line(0, y, w, y) + end + end + end + + -- Draw intersection point + for i, circleAngle1 in pairs(circles) do + for j, circleAngle2 in pairs(circles) do + local distX = (constants.circleRadius + (i+1) * gap*2) + local distY = (constants.circleRadius + (j+1) * gap*2) + if distX+gap < w and distY+gap < h then + local x = constants.circleRadius * math.cos(circleAngle1-math.pi/2) + distX + local y = constants.circleRadius * math.sin(circleAngle2-math.pi/2) + distY + + setColor(addColors(i/#circles*511, j/#circles*511)) + drawMarker(x, y) + curves[i][j]:addPoint(x, y) + end + end + end + + -- Draw curves + if constants.drawTable then + for n1, j in pairs(curves) do + for n2, curve in pairs(j) do + setColor(addColors(n1/#circles*511, n2/#circles*511)) + curve:draw() + end + end + end +end + +function love.resize(w, h) + angle = 0 + recalc(w,h) +end