Skip to content

Instantly share code, notes, and snippets.

@akkartik
Last active June 11, 2022 21:18
Show Gist options
  • Save akkartik/b141370fbb2bb5ae6f8b47de36a121d1 to your computer and use it in GitHub Desktop.
Save akkartik/b141370fbb2bb5ae6f8b47de36a121d1 to your computer and use it in GitHub Desktop.
Little drawing program
-- 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 .`
--
-- Based on https://love2d.org/forums/viewtopic.php?t=87469
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 == '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
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 == '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)
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
--? 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
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 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)
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 == '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)
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 == '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
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment