Skip to content

Instantly share code, notes, and snippets.

@akkartik
Last active June 11, 2022 21:18

Revisions

  1. akkartik revised this gist Jun 11, 2022. 1 changed file with 47 additions and 4 deletions.
    51 changes: 47 additions & 4 deletions love-paint.lua
    Original file line number Diff line number Diff line change
    @@ -82,6 +82,8 @@ function love.mousepressed(x,y,button)
    pending = {shape='line', x1=x,y1=y, Vermelho=R,Verde=G,Azul=B}
    elseif current_shape == 'horvert' then
    pending = {shape='horvert', x1=x,y1=y, Vermelho=R,Verde=G,Azul=B}
    elseif current_shape == 'freehand' then
    pending = {shape='freehand', points={{x=x,y=y}}, Vermelho=R,Verde=G,Azul=B}
    elseif current_shape == 'circle' then
    pending = {shape='circle', cx=x,cy=y, Vermelho=R,Verde=G,Azul=B}
    end
    @@ -106,6 +108,9 @@ function love.mousereleased(x,y,button)
    end
    love.mouse.setPosition(pending.x2, pending.y2) -- make mouse position intuitive
    table.insert(shapes_committed, pending)
    elseif pending.shape == 'freehand' then
    table.insert(pending.points, {x=x,y=y})
    table.insert(shapes_committed, pending)
    elseif pending.shape == 'circle' then
    pending.r = math.dist(pending.cx, pending.cy, x, y)
    table.insert(shapes_committed, pending)
    @@ -126,10 +131,8 @@ function love.update()
    if current_shape == 'dot' then
    table.insert(shapes_committed,{shape='dot', x=love.mouse.getX(),y=love.mouse.getY(),Vermelho=R,Verde=G,Azul=B})
    elseif current_shape == 'freehand' then
    if pending.x1 then
    table.insert(shapes_committed,{shape='line', x1=pending.x1, y1=pending.y1, x2=mouse.x,y2=mouse.y, Vermelho=R,Verde=G,Azul=B})
    end
    pending = {shape='freehand', x1=mouse.x,y1=mouse.y, Vermelho=R,Verde=G,Azul=B}
    --? generate_freehand(mouse)
    table.insert(pending.points, {x=love.mouse.getX(), y=love.mouse.getY()})
    elseif current_shape == 'line' then
    elseif current_shape == 'circle' then
    end
    @@ -254,7 +257,31 @@ function draw_menu()
    love.graphics.draw(img,down,UI.downbx,UI.downby)
    end

    function draw_freehand_bounds()
    color(0,0,0)
    love.graphics.rectangle("line",200,200,300,300)
    end

    pending_freehand = {}
    function generate_freehand(mouse)
    local iconside = 20
    local function g(a) return math.floor((a-200)/(300/iconside)) end
    local function f(a) return tostring(g(a)) end
    local function far_enough(a, b) return math.abs(g(a)-g(b)) > 1 end
    if mouse.x > 200 and mouse.y > 200 and mouse.x < 500 and mouse.y < 500 then
    if pending_freehand.x == nil then
    -- initialize
    pending_freehand = {x=mouse.x, y=mouse.y}
    end
    if far_enough(mouse.x, pending_freehand.x) or far_enough(mouse.y, pending_freehand.y) then
    print('love.graphics.line(x+'..f(pending_freehand.x)..',y+'..f(pending_freehand.y)..',x+'..f(mouse.x)..',y+'..f(mouse.y)..')')
    pending_freehand = {x=mouse.x, y=mouse.y}
    end
    end
    end

    function freehand_icon(x, y)
    -- generated by generate_freehand
    love.graphics.line(x+4,y+7,x+5,y+5)
    love.graphics.line(x+5,y+5,x+7,y+4)
    love.graphics.line(x+7,y+4,x+9,y+3)
    @@ -283,11 +310,14 @@ function draw_shapes()
    love.graphics.circle("fill", v.x,v.y, 4)
    elseif v.shape == 'line' then
    love.graphics.line(v.x1, v.y1, v.x2, v.y2)
    elseif v.shape == 'freehand' then
    draw_freehand(v)
    elseif v.shape == 'circle' then
    love.graphics.circle('line', v.cx, v.cy, v.r)
    end
    end

    --? draw_freehand_bounds()
    if love.mouse.isDown("1") then
    if pending.shape == 'line' then
    color(pending.Vermelho, pending.Verde, pending.Azul)
    @@ -299,13 +329,26 @@ function draw_shapes()
    else
    love.graphics.line(pending.x1, pending.y1, pending.x1, mouse.y)
    end
    elseif pending.shape == 'freehand' then
    color(pending.Vermelho, pending.Verde, pending.Azul)
    draw_freehand(pending)
    elseif pending.shape == 'circle' then
    color(pending.Vermelho, pending.Verde, pending.Azul)
    love.graphics.circle('line', pending.cx, pending.cy, math.dist(pending.cx, pending.cy, mouse.x, mouse.y))
    end
    end
    end

    function draw_freehand(v)
    local prev
    for _,p in ipairs(v.points) do
    if prev then
    love.graphics.line(prev.x,prev.y, p.x,p.y)
    end
    prev = p
    end
    end

    function color(r, g, b)
    -- "In versions prior to 11.0, color component values were within the range of 0 to 255 instead of 0 to 1."
    -- https://love2d.org/wiki/love.graphics.setColor
  2. akkartik revised this gist May 10, 2022. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions love-paint.lua
    Original file line number Diff line number Diff line change
    @@ -4,6 +4,8 @@
    -- Run the program from that directory.
    -- * on Linux (using the appimage binary): `chmod +x path/to/love-11.4-x86_64.AppImage; path/to/love-11.4-x86_64.AppImage .`
    -- * on Mac: `path/to/love.app/Contents/MacOS/love .`
    --
    -- Based on https://love2d.org/forums/viewtopic.php?t=87469

    function love.load()
    img=love.graphics.newImage("pointers.png")
  3. akkartik revised this gist May 10, 2022. No changes.
  4. akkartik created this gist May 9, 2022.
    313 changes: 313 additions & 0 deletions love-paint.lua
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,313 @@
    -- To run:
    -- Download LÖVE from https://love2d.org
    -- Download this file to a directory and rename it to `main.lua`
    -- Run the program from that directory.
    -- * on Linux (using the appimage binary): `chmod +x path/to/love-11.4-x86_64.AppImage; path/to/love-11.4-x86_64.AppImage .`
    -- * on Mac: `path/to/love.app/Contents/MacOS/love .`

    function love.load()
    img=love.graphics.newImage("pointers.png")
    up=love.graphics.newQuad(0,0,19,10,img:getDimensions())
    down=love.graphics.newQuad(19,0,19,10,img:getDimensions())
    ex=love.graphics.newQuad(38,0,13,12,img:getDimensions())
    -- maximize window
    love.window.setMode(0,0)
    local width, height, flags = love.window.getMode()
    -- shrink slightly to account for window decoration
    width = width-100
    height = height-100
    love.window.setMode(width, height)
    love.window.setTitle("Love Paint")
    local status_height = 20
    UI={
    x=5,y=5,w=width-10,h=100, -- menu area
    status_height=status_height,
    x2=5,y2=110,w2=width-10,h2=height-status_height-115, -- shapes area
    -- top-left coords for lots of widgets on screen
    -- shapes
    dotx=145,doty=30,
    freehandx=125,freehandy=30,
    linex=145,liney=50,
    horvertx=125,horverty=50,
    circlex=145,circley=70,
    -- large square for the selected color
    colorx=165,colory=30,
    -- colors
    px=235,py=30, -- black
    bx=235,by=65, -- white
    vx=265,vy=30, -- red
    vex=265,vey=65, -- green
    ax=295,ay=30, -- blue
    amx=295,amy=65, -- yellow
    lx=325,ly=30, -- orange
    rx=325,ry=65, -- pink
    acx=355,acy=30, -- cyan
    rox=355,roy=65, -- purple
    -- color arrows
    uprx=400,upry=65,
    downrx=400,downry=80,
    upgx=440,upgy=65,
    downgx=440,downgy=80,
    upbx=485,upby=65,
    downbx=485,downby=80,
    }
    mouse={x=0,y=0}
    R=255; G=0; B=0;
    shapes_committed={}
    current_shape='dot'
    pending={}
    end

    function love.mousepressed(x,y,button)
    if button==1 then
    if x>UI.px and x<UI.px+25 and y>UI.py and y<UI.py+25 then R=0; G=0; B=0 end
    if x>UI.bx and x<UI.bx+25 and y>UI.by and y<UI.by+25 then R=255; G=255; B=255 end
    if x>UI.vx and x<UI.vx+25 and y>UI.vy and y<UI.vy+25 then R=255; G=0; B=0; end
    if x>UI.vex and x<UI.vex+25 and y>UI.vey and y<UI.vey+25 then R=0; G=255; B=0 end
    if x>UI.ax and x<UI.ax+25 and y>UI.ay and y<UI.ay+25 then R=0; G=0; B=255 end
    if x>UI.amx and x<UI.amx+25 and y>UI.amy and y<UI.amy+25 then R=255; G=255; B=0 end
    if x>UI.lx and x<UI.lx+25 and y>UI.ly and y<UI.ly+25 then R=255; G=128; B=0 end
    if x>UI.rx and x<UI.rx+25 and y>UI.ry and y<UI.ry+25 then R=255; G=128; B=255 end
    if x>UI.acx and x<UI.acx+25 and y>UI.acy and y<UI.acy+25 then R=0; G=125; B=192 end
    if x>UI.rox and x<UI.rox+25 and y>UI.roy and y<UI.roy+25 then R=163; G=73; B=164 end
    if x>UI.dotx and x<UI.dotx+20 and y>UI.doty and y<UI.doty+20 then current_shape='dot' end
    if x>UI.freehandx and x<UI.freehandx+20 and y>UI.freehandy and y<UI.freehandy+20 then current_shape='freehand' end
    if x>UI.horvertx and x<UI.horvertx+20 and y>UI.horverty and y<UI.horverty+20 then current_shape='horvert' end
    if x>UI.linex and x<UI.linex+20 and y>UI.liney and y<UI.liney+20 then current_shape='line' end
    if x>UI.circlex and x<UI.circlex+20 and y>UI.circley and y<UI.circley+20 then current_shape='circle' end
    if x>UI.x2 and x<UI.x2+UI.w2 and y>UI.y2 and y<UI.y2+UI.h2 then
    if current_shape == 'line' then
    pending = {shape='line', x1=x,y1=y, Vermelho=R,Verde=G,Azul=B}
    elseif current_shape == 'horvert' then
    pending = {shape='horvert', x1=x,y1=y, Vermelho=R,Verde=G,Azul=B}
    elseif current_shape == 'circle' then
    pending = {shape='circle', cx=x,cy=y, Vermelho=R,Verde=G,Azul=B}
    end
    end
    end
    end

    function love.mousereleased(x,y,button)
    if x>UI.x2 and x<UI.x2+UI.w2 and y>UI.y2 and y<UI.y2+UI.h2 then
    if pending.shape == 'line' then
    pending.x2 = x
    pending.y2 = y
    table.insert(shapes_committed, pending)
    elseif pending.shape == 'horvert' then
    pending.shape = 'line'
    if math.abs(x-pending.x1) > math.abs(y-pending.y1) then
    pending.x2 = x
    pending.y2 = pending.y1
    else
    pending.x2 = pending.x1
    pending.y2 = y
    end
    love.mouse.setPosition(pending.x2, pending.y2) -- make mouse position intuitive
    table.insert(shapes_committed, pending)
    elseif pending.shape == 'circle' then
    pending.r = math.dist(pending.cx, pending.cy, x, y)
    table.insert(shapes_committed, pending)
    end
    pending = {}
    end
    end

    function love.update()
    if R>255 then R=255 end if R<0 then R=0 end
    if G>255 then G=255 end if G<0 then G=0 end
    if B>255 then B=255 end if B<0 then B=0 end
    mouse.x=love.mouse.getX()
    mouse.y=love.mouse.getY()
    if love.mouse.isDown("1") then
    -- updates that can depend on dragging
    if mouse.x>UI.x2 and mouse.x<UI.x2+UI.w2 and mouse.y>UI.y2 and mouse.y<UI.y2+UI.h2 then
    if current_shape == 'dot' then
    table.insert(shapes_committed,{shape='dot', x=love.mouse.getX(),y=love.mouse.getY(),Vermelho=R,Verde=G,Azul=B})
    elseif current_shape == 'freehand' then
    if pending.x1 then
    table.insert(shapes_committed,{shape='line', x1=pending.x1, y1=pending.y1, x2=mouse.x,y2=mouse.y, Vermelho=R,Verde=G,Azul=B})
    end
    pending = {shape='freehand', x1=mouse.x,y1=mouse.y, Vermelho=R,Verde=G,Azul=B}
    elseif current_shape == 'line' then
    elseif current_shape == 'circle' then
    end
    end
    if mouse.x>UI.uprx and mouse.x<UI.uprx+19 and mouse.y>UI.upry and mouse.y<UI.upry+10 then R=R+1 end
    if mouse.x>UI.downrx and mouse.x<UI.downrx+19 and mouse.y>UI.downry and mouse.y<UI.downry+10 then R=R-1 end
    if mouse.x>UI.upgx and mouse.x<UI.upgx+19 and mouse.y>UI.upgy and mouse.y<UI.upgy+10 then G=G+1 end
    if mouse.x>UI.downgx and mouse.x<UI.downgx+19 and mouse.y>UI.downgy and mouse.y<UI.downgy+10 then G=G-1 end
    if mouse.x>UI.upbx and mouse.x<UI.upbx+19 and mouse.y>UI.upby and mouse.y<UI.upby+10 then B=B+1 end
    if mouse.x>UI.downbx and mouse.x<UI.downbx+19 and mouse.y>UI.downby and mouse.y<UI.downby+10 then B=B-1 end
    end
    end

    function love.draw()
    draw_shapes()
    draw_menu()
    end

    function draw_menu()
    color(50,50,50)
    love.graphics.rectangle("fill",UI.x,UI.y,UI.w,UI.h)
    color(255,255,255)
    local width, height, flags = love.window.getMode()
    love.graphics.print(mouse.x,5,height-UI.status_height)
    love.graphics.print("|",35,height-UI.status_height)
    love.graphics.print(mouse.y,45,height-UI.status_height)
    color(R,G,B)
    love.graphics.rectangle("fill",UI.colorx,UI.colory,60,60)
    color(0,0,0)
    love.graphics.rectangle("fill",UI.px,UI.py,25,25)
    color(255,255,255)
    love.graphics.rectangle("fill",UI.bx,UI.by,25,25)
    color(255,0,0)
    love.graphics.rectangle("fill",UI.vx,UI.vy,25,25)
    color(0,255,0)
    love.graphics.rectangle("fill",UI.vex,UI.vey,25,25)
    color(0,0,255)
    love.graphics.rectangle("fill",UI.ax,UI.ay,25,25)
    color(255,255,0)
    love.graphics.rectangle("fill",UI.amx,UI.amy,25,25)
    color(255,128,0)
    love.graphics.rectangle("fill",UI.lx,UI.ly,25,25)
    color(255,128,255)
    love.graphics.rectangle("fill",UI.rx,UI.ry,25,25)
    color(0,128,192)
    love.graphics.rectangle("fill",UI.acx,UI.acy,25,25)
    color(163,73,164)
    love.graphics.rectangle("fill",UI.rox,UI.roy,25,25)

    if current_shape == 'dot' then
    color(255,255,255)
    love.graphics.rectangle('fill',UI.dotx,UI.doty,20,20)
    color(R,G,B)
    love.graphics.circle('fill', UI.dotx+10,UI.doty+10, 4)
    else
    color(192,192,192)
    love.graphics.rectangle('fill',UI.dotx,UI.doty,20,20)
    color(0,0,0)
    love.graphics.circle('fill', UI.dotx+10,UI.doty+10, 4)
    end

    if current_shape == 'freehand' then
    color(255,255,255)
    love.graphics.rectangle('fill',UI.freehandx,UI.freehandy,20,20)
    color(R,G,B)
    freehand_icon(UI.freehandx, UI.freehandy)
    else
    color(192,192,192)
    love.graphics.rectangle('fill',UI.freehandx,UI.freehandy,20,20)
    color(0,0,0)
    freehand_icon(UI.freehandx, UI.freehandy)
    end

    if current_shape == 'line' then
    color(255,255,255)
    love.graphics.rectangle('fill',UI.linex,UI.liney,20,20)
    color(R,G,B)
    love.graphics.line(UI.linex+4,UI.liney+2, UI.linex+16,UI.liney+18)
    else
    color(192,192,192)
    love.graphics.rectangle('fill',UI.linex,UI.liney,20,20)
    color(0,0,0)
    love.graphics.line(UI.linex+4,UI.liney+2, UI.linex+16,UI.liney+18)
    end

    if current_shape == 'horvert' then
    color(255,255,255)
    love.graphics.rectangle('fill',UI.horvertx,UI.horverty,20,20)
    color(R,G,B)
    horvert_icon(UI.horvertx, UI.horverty)
    else
    color(192,192,192)
    love.graphics.rectangle('fill',UI.horvertx,UI.horverty,20,20)
    color(0,0,0)
    horvert_icon(UI.horvertx, UI.horverty)
    end

    if current_shape == 'circle' then
    color(255,255,255)
    love.graphics.rectangle('fill',UI.circlex,UI.circley,20,20)
    color(R,G,B)
    love.graphics.circle('line', UI.circlex+10,UI.circley+10, 8)
    else
    color(192,192,192)
    love.graphics.rectangle('fill',UI.circlex,UI.circley,20,20)
    color(0,0,0)
    love.graphics.circle('line', UI.circlex+10,UI.circley+10, 8)
    end

    color(255,255,255)
    love.graphics.print("Red",400,25)
    love.graphics.print(R,400,45)
    love.graphics.draw(img,up,UI.uprx,UI.upry)
    love.graphics.draw(img,down,UI.downrx,UI.downry)
    love.graphics.print("Green",440,25)
    love.graphics.print(G,440,45)
    love.graphics.draw(img,up,UI.upgx,UI.upgy)
    love.graphics.draw(img,down,UI.downgx,UI.downgy)
    love.graphics.print("Blue",485,25)
    love.graphics.print(B,485,45)
    love.graphics.draw(img,up,UI.upbx,UI.upby)
    love.graphics.draw(img,down,UI.downbx,UI.downby)
    end

    function freehand_icon(x, y)
    love.graphics.line(x+4,y+7,x+5,y+5)
    love.graphics.line(x+5,y+5,x+7,y+4)
    love.graphics.line(x+7,y+4,x+9,y+3)
    love.graphics.line(x+9,y+3,x+10,y+5)
    love.graphics.line(x+10,y+5,x+12,y+6)
    love.graphics.line(x+12,y+6,x+13,y+8)
    love.graphics.line(x+13,y+8,x+13,y+10)
    love.graphics.line(x+13,y+10,x+14,y+12)
    love.graphics.line(x+14,y+12,x+15,y+14)
    love.graphics.line(x+15,y+14,x+15,y+16)
    end

    function horvert_icon(x, y)
    love.graphics.line(x+2,y+4,x+6,y+4)
    love.graphics.line(x+6,y+4,x+6,y+14)
    love.graphics.line(x+6,y+14,x+14,y+14)
    end

    function draw_shapes()
    color(255,255,255)
    love.graphics.rectangle("fill",UI.x2,UI.y2,UI.w2,UI.h2)
    local r = 4
    for i, v in ipairs(shapes_committed) do
    color(v.Vermelho,v.Verde,v.Azul)
    if v.shape == 'dot' then
    love.graphics.circle("fill", v.x,v.y, 4)
    elseif v.shape == 'line' then
    love.graphics.line(v.x1, v.y1, v.x2, v.y2)
    elseif v.shape == 'circle' then
    love.graphics.circle('line', v.cx, v.cy, v.r)
    end
    end

    if love.mouse.isDown("1") then
    if pending.shape == 'line' then
    color(pending.Vermelho, pending.Verde, pending.Azul)
    love.graphics.line(pending.x1, pending.y1, mouse.x, mouse.y)
    elseif pending.shape == 'horvert' then
    color(pending.Vermelho, pending.Verde, pending.Azul)
    if math.abs(mouse.x-pending.x1) > math.abs(mouse.y-pending.y1) then
    love.graphics.line(pending.x1, pending.y1, mouse.x, pending.y1)
    else
    love.graphics.line(pending.x1, pending.y1, pending.x1, mouse.y)
    end
    elseif pending.shape == 'circle' then
    color(pending.Vermelho, pending.Verde, pending.Azul)
    love.graphics.circle('line', pending.cx, pending.cy, math.dist(pending.cx, pending.cy, mouse.x, mouse.y))
    end
    end
    end

    function color(r, g, b)
    -- "In versions prior to 11.0, color component values were within the range of 0 to 255 instead of 0 to 1."
    -- https://love2d.org/wiki/love.graphics.setColor
    love.graphics.setColor(r/255,g/255,b/255)
    end

    function math.dist(x1,y1, x2,y2) return ((x2-x1)^2+(y2-y1)^2)^0.5 end