Fun line drawing

I dug up some code @Tnology made a while back, found it interesting, and so put a little more into it to make it a pretty drawing thing. I thought it was fun, so I shared it here.

displayMode(OVERLAY)
supportedOrientations(LANDSCAPE_ANY)
function setup()
    q=Linedrawer()
end
function draw()
    background(0)
    q:draw()
end
function touched(t)
    q:touched(t)
end

Linedrawer=class()
function Linedrawer:init()
    self.m, self.ps = mesh(), {}
    grzzzzzzxyfmblpooootqrssszvgrwbgfw = self
    parameter.action("newdraw", function() grzzzzzzxyfmblpooootqrssszvgrwbgfw.i=1 end)
    parameter.action("Eliminate_Leftovers", function() for x=self.i,#self.ps do 
            tween(.5, self.ps[x], {d=0}, tween.easing.quadInOut)
        end end)
    parameter.color("colors",color(255))
    self.i=1
    for b=0,1000 do 
        self:addline(vec2(b^2%WIDTH,HEIGHT+10),vec2(b^2%WIDTH+1,HEIGHT+5))
    end
    self.i=1
    local xnorp = math.random(WIDTH)
    self:addline(vec2(xnorp,HEIGHT+10),vec2(xnorp,HEIGHT+5),.1)
    self.i=1
end
function Linedrawer:draw()
    self.m:clear()
    for i,v in ipairs(self.ps) do
        self.m:addRect(v.x, v.y, v.d, 2, v.a)
        for b=0,5 do
        self.m:color(i*6-b,v.r,v.g,v.b)
        end
    end
    self.m:draw()
end
function Linedrawer:touched(touch)
    self.p = vec2(touch.x, touch.y)
    if touch.state == BEGAN then
        self.sp= self.p
    elseif touch.state == ENDED or (self.sp-self.p):len() > 10 then
        self:addline(self.sp, self.p)
        self.sp = self.p
    end
    if touch.state == ENDED then
        --for x=self.i,#self.ps do 
        --    tween(.5, self.ps[x], {d=0}, tween.easing.quadInOut)
        --end
    end
end
function Linedrawer:addline(a,b,twtime)
    local time = twtime or 3
    local v = b - a
    local p = a + v*.5
    p = {x=p.x, y=p.y,d=v:len(),a=-v:angleBetween(vec2(1,0)),r=colors.r,g=colors.g,b=colors.b}
    if self.ps[self.i] then
        tween(time, self.ps[self.i], p, tween.easing.quadInOut)
    else
        table.insert(self.ps, p)
    end
    self.i = self.i + 1
end

Added some features to it. When a drawing is done click “save temp” and it will save that drawing (until you close the app). Clicking “loadtemp” will cycle through saved images. The scroll Boolean disallows you to draw and automates cycling through the saved images.

displayMode(OVERLAY)
supportedOrientations(LANDSCAPE_ANY)
function setup()
    q=Linedrawer()
    parameter.color("bgcol")
end
function draw()
    background(bgcol)
    q:draw()
end
function touched(t)
    q:touched(t)
end

Linedrawer=class()
function Linedrawer:init()
    self.num=1
    self.tm=0
    self.tables={}
    self.m, self.ps = mesh(), {}
    parameter.action("newdraw",function() self.i,self.tab=1,{} end)
    parameter.action("Eliminate_Leftovers", function() for x=self.i,#self.ps do 
            tween(.5, self.ps[x], {d=0}, tween.easing.quadInOut)
        end end)
    parameter.color("colors",color(255))
    parameter.action("temporarysave",function() self.tables[#self.tables+1]=self.tab end)
    parameter.boolean("scroll",false,function() self.tm=0; if scroll then self:load(self.num) end end)
    parameter.action("loadtemp",function() self:load(self.num) end)
    self.tab={}
    self.i=1
    for b=0,2000 do 
        local xnorp = math.random(WIDTH)
        self:addline(vec2((b*xnorp)%WIDTH,HEIGHT+10),vec2((b*xnorp)%WIDTH+1,HEIGHT+5))
    end
    self.i=1
    self.tab={}
    local xnorp = math.random(WIDTH)
    self:addline(vec2(xnorp,HEIGHT+10),vec2(xnorp,HEIGHT+5),.1)
    self.i=1
    self.tab={}
end
function Linedrawer:draw()
    if scroll then
        self.tm = self.tm + DeltaTime
        if self.tm > 5 then
            self.tm = 0
            self:load(self.num)
        end
    end
    self.m:clear()
    for i,v in ipairs(self.ps) do
        self.m:addRect(v.x, v.y, v.d, 2, v.a)
        for b=0,5 do
        self.m:color(i*6-b,v.r,v.g,v.b)
        end
    end
    self.m:draw()
end
function Linedrawer:load(q)
    if self.tables[1] then
    if self.num>#self.tables then self.num=1 end
    if q>#self.tables then q=1 end
    self.i=1
    self.tab={}
    for a=1,#self.tables[q] do
        self:addline(self.tables[q][a][1],self.tables[q][a][2],nil,self.tables[q][a][3])
    end
    for x=self.i,#self.ps do 
        tween(.5, self.ps[x], {d=0}, tween.easing.quadInOut)
    end
    self.num = self.num + 1
    end
end
function Linedrawer:touched(touch)
    if not scroll then
    self.p = vec2(touch.x, touch.y)
    if touch.state == BEGAN then
        self.sp= self.p
    elseif touch.state == ENDED or (self.sp-self.p):len() > 10 then
        self:addline(self.sp, self.p)
        self.sp = self.p
    end
    end
end
function Linedrawer:addline(a,b,twtime,cor)
    table.insert(self.tab,{a,b,colors})
    local time = twtime or math.random(100,300)/100
    local v = b - a
    local p = a + v*.5
    if cor then
        p = {x=p.x, y=p.y,d=v:len(),a=-v:angleBetween(vec2(1,0)),r=cor.r,g=cor.g,b=cor.b}
    else
    p = {x=p.x, y=p.y,d=v:len(),a=-v:angleBetween(vec2(1,0)),r=colors.r,g=colors.g,b=colors.b}
    end
    if self.ps[self.i] then
        tween(time, self.ps[self.i], p, tween.easing.quadInOut)
    else
        table.insert(self.ps, p)
    end
    self.i = self.i + 1
end

Really cool drawing app! Very unique. I suggest you keep working on it!

I will keep working on it if @tnology approves. He came up with the concept and the core code.
That said, thanks! For the both of us!

Added some functionality, made it so that it never runs out of line transitions (there used to be a point when it had no more lines to send in so they just drew directly). Added better color support, more control over transitions, and, of course, made some minor, mostly invisible, adjustments. Oh! Also made starting a new draw in the middle of tweeting not break the whole thing, so, that’s a major plus! Want to make this into a real thing, as it’s probably the most fun I’ve had improving and modifying something, but since tnology disappeared it complicates matters…

displayMode(OVERLAY)
supportedOrientations(LANDSCAPE_ANY)
function setup()
    q=Linedrawer()
    parameter.color("bgcol")
end
function draw()
    background(bgcol)
    q:draw()
end
function touched(t)
    q:touched(t)
end

Linedrawer=class()
function Linedrawer:init()
    self.num=1
    self.tm=0
    self.tables={}
    self.m, self.ps = mesh(), {}
    parameter.action("newdraw",function() self.i,self.tab=1,{}; tween:stopAll() end)
    parameter.action("Eliminate_Leftovers", function() self:elim() end)
    parameter.color("colors",color(255))
    parameter.action("temporarysave",function() self.tables[#self.tables+1]=self.tab end)
    parameter.boolean("scroll",false,function() self.tm=0; if scroll then self:load(self.num) end end)
    parameter.action("loadtemp",function() self:load(self.num) end)
    parameter.number("scrolltime",0,10,2)
    parameter.integer("mtranstime",1,100,3)
    parameter.action("killall :(", function() self.ps,self.i,self.tab,self.tables = {},1,{},{} end)
    self.tab={}
    self.i=1
end
function Linedrawer:draw()
    if scroll then
        self.tm = self.tm + DeltaTime
        if self.tm > scrolltime+mtranstime then
            self.tm = 0
            self:load(self.num)
        end
    end
    self.m:clear()
    for i,v in ipairs(self.ps) do
        self.m:addRect(v.x, v.y, v.d, 2, v.a)
        for b=0,5 do
        self.m:color(i*6-b,v.r,v.g,v.b)
        end
    end
    self.m:draw()
end
function Linedrawer:load(q)
    if self.tables[1] then
    tween:stopAll()
    if self.num>#self.tables then self.num=1 end
    if q>#self.tables then q=1 end
    self.i=1
    self.tab={}
    for a=1,#self.tables[q] do
        self:addline(self.tables[q][a][1],self.tables[q][a][2],nil,self.tables[q][a][3])
    end
    self:elim()
    self.num = self.num + 1
    end
end
function Linedrawer:touched(touch)
    if not scroll then
    self.p = vec2(touch.x, touch.y)
    if touch.state == BEGAN then
        self.sp= self.p
    elseif touch.state == ENDED or (self.sp-self.p):len() > 10 then
        self:addline(self.sp, self.p)
        self.sp = self.p
    end
    end
end
function Linedrawer:addline(a,b,twtime,cor)
    table.insert(self.tab,{a,b,colors})
    local time = twtime or mtranstime--math.random(100,300)/100
    local v = b - a
    local p = a + v*.5
    if cor then
        p = {x=p.x, y=p.y,d=v:len(),a=-v:angleBetween(vec2(1,0)),r=cor.r,g=cor.g,b=cor.b}
    else
    p = {x=p.x, y=p.y,d=v:len(),a=-v:angleBetween(vec2(1,0)),r=colors.r,g=colors.g,b=colors.b}
    end
    if self.ps[self.i] then
        tween(time, self.ps[self.i], p, tween.easing.quadInOut)
    else
        local xnorp = math.random(WIDTH)
        self.ps[self.i] = {x=xnorp, y=HEIGHT+2, d=10,a = 0,r=0,g=0,b=0}--255,g=255,b=255}
        tween(time, self.ps[self.i], p, tween.easing.quadInOut)
        --table.insert(self.ps, p)
    end
    self.i = self.i + 1
end
function Linedrawer:elim()
    for x=self.i,#self.ps do
        local xnorp = math.random(WIDTH)
        tween(math.random(50,100)/100, self.ps[x], {x=xnorp, y=HEIGHT+2, d=10,a = 0}, tween.easing.quadInOut) --,r=255,g=255,b=255
        end
end

I’m pushing to speed-optimize this program (as it is remaking the rects EVERY FRAME), so I was wondering: is there a faster alternative to mesh:addRect()? Perhaps I could calculate the four vertices in the addline function instead? But then would I have to manually set the colors or could I still do mesh:setRectColor() (which is faster than a for loop to manually set the vert colors)? I experimented with a custom very-fast line drawing shader as a replacement for the rects but it was about 30% slower once the line count got above 1000 (Though it was about 10% faster on average before that threshhold)
So far I have increased the framerate about twofold by making slight modifications here and there, but it’s still not at a desirable level.