Minimalist drawing program

I wrote a very small drawing program, to teach myself Lua and the event loop. Here is the code if it may help others. Any comment on how to make it better is of course highly appreciated!

Main program:

tt = nil

last_touch = nil
touch = nil
moving = false

-- Use this function to perform your initial setup
function setup()
    tt = Touches()
end

-- This function gets called once every frame
function draw()
    background(0, 0, 0, 0)
    
    stroke(255)
    -- default seems to be 0
    strokeWidth(8)
    lineCapMode(ROUND)
    
    touch = vec2(CurrentTouch.x, CurrentTouch.y)
    if CurrentTouch.state == ENDED then
        -- to make sure we don't miss the touch began state
        moving = false
    elseif CurrentTouch.state == BEGAN then
        if touch ~= last_touch then
            moving = true
            last_touch = touch
            tt:add(touch)
        end
    elseif CurrentTouch.state == MOVING then
        if touch ~= last_touch then
            if moving then
                tt:expand(touch)
            else
                -- Did not detect the move
                moving = true
                tt:add(touch)
            end
            last_touch = touch
        end       
    end 
    
    tt:draw()
end

Touches class:

Touches = class()

function Touches:init()
    -- you can accept and set parameters here
    self.touches = {}
end

function Touches:add(t)
    table.insert(self.touches, {t})
end

function Touches:expand(t)
    table.insert(self.touches[#self.touches],t)
end

function Touches:draw()
    local last
    if #self.touches > 0 then
        for i,v in ipairs(self.touches) do
            last = v[1]
            for j,w in ipairs(v) do
                line(last.x,last.y,w.x,w.y)
                last = w
            end
        end
    end
end

Just tried your scripts with my LoveCodify on PC and it works out of the Box :slight_smile:

Great little project, brab! Selectable colors and a screen clearing button would be cool too.

Thanks for the suggestions. I know how to do the colors, but I first want to figure out how to do things more efficiently … which I’ll ask in another post.

Here is an updated version, with color and brush size support. Working with transparency is strange, because of line endings. To clear the screen one can simply do a “reset” :wink:

I still store the whole drawing, to allow to save them when we’ll have local storage.

Main file

tt = nil

last_touch = nil
touch = nil
moving = false

-- clear screen, should not be necessary in future versions of Codea
nb_clear = 3

-- Use this function to perform your initial setup
function setup()
    iparameter("StrokeWidth",1,60,20)
    iparameter("Red",0,255,255)
    iparameter("Green",0,255,255)
    iparameter("Blue",0,255,255)
    iparameter("Alpha",0,255,255)
    tt = Touches()
end

-- This function gets called once every frame
function draw()
    if nb_clear > 0 then
        background(0, 0, 0, 0)
        nb_clear = nb_clear - 1
    end
    
    fill(0)
    rect(700,10,40,20)
    fill(Red,Green,Blue,Alpha)
    rect(700,10,40,20)
    
    touch = vec2(CurrentTouch.x, CurrentTouch.y)
    if CurrentTouch.state == ENDED then
        -- to make sure we don't miss the touch began state
        moving = false
    elseif CurrentTouch.state == BEGAN then
        if touch ~= last_touch then
            moving = true
            last_touch = touch
            tt:add(color(Red,Green,Blue,Alpha),StrokeWidth,touch)
        end
    elseif CurrentTouch.state == MOVING then
        if touch ~= last_touch then
            if moving then
                tt:expand(touch)
            else
                -- Did not detect the move
                moving = true
                tt:add(color(Red,Green,Blue,Alpha),StrokeWidth,touch)
            end
            last_touch = touch
        end       
    end 
    
    tt:draw()
end

Touches class

Touches = class()

function Touches:init()
    self.touches = {}
    self.dr0 = nil
    self.dr1 = nil
    self.dr2 = nil
end

function Touches:add(c,w,t)
    self.dr0 = {type = 0, color = c, width = w, coord = t}
    table.insert(self.touches, {color = c, width = w, tlist = {t}})
end

function Touches:expand(t)
    local tl = self.touches[#self.touches]
    self.dr0 = {type = 1, color = tl.color, width = tl.width,
                old_coord = tl.tlist[#tl.tlist], coord = t}
    table.insert(tl.tlist,t)
end

function Touches:draw_last_stroke()
    self:draw_stroke(self.touches[#self.touches])
end

function Touches:draw_one(d)
    lineCapMode(ROUND)
    if d.type == 0 then
        fill(d.color)
        stroke(d.color)
        ellipse(d.coord.x,d.coord.y,d.width)
    else
        stroke(d.color)
        strokeWidth(d.width)
        line(d.old_coord.x,d.old_coord.y,d.coord.x,d.coord.y)
    end
end

function Touches:draw()
    if self.dr2 ~= nil then
        self:draw_one(self.dr2)
        self.dr2 = nil
    end
    if self.dr1 ~= nil then
        self:draw_one(self.dr1)
        self.dr2 =self.dr1
        self.dr1 = nil
    end
    if self.dr0 ~= nil then
        self:draw_one(self.dr0)
        self.dr1 =self.dr0
        self.dr0 = nil
    end
end

Yeah the line endings are weird. It just naively renders two circles for the caps at the moment, so if you turn down the alpha, you get it double blended. We planned on changing it before release, but were too busy with other stuff. Its still on my “to do” list.

Added to wiki https://bitbucket.org/TwoLivesLeft/codea/wiki/UserContrib