i'm still working on my project to implement a Processing-like API in Lua/Love2d. I have added a majority (?) of the functions, including a number I never use. Because love2d clears the screen between drawing functions I chose to add in persistence using a canvas buffer system that redraws each frame. Here's an example drawing random rectangles with occasional background screen redraw.
ok, i've gotten the API to a draft state and am pretty happy with what i have. of course, i'm aware that i've done 80% of the work in 20% of the time (or however that's stated) so the tiny details will take days/months/years. but i'm already pretty happy with this pre-alpha. i'm ready to start trying to make little programs and put it through its paces.
i'm still going. i got most (?) or at least a lot of the Processing/p5.js API done. I also modified the love.run() function so that the screen isn't cleared between frames but the matrix transformations are, to get it in line with Processing. I added many functions, cleaned up things, and started testing the functions i implemented. still to come: error handling and general bug fixin'

i wrote a crude pong in L5. maybe i still need a better title for this library of Processing API in Lua with Love2d. (any suggestions?)

(music by Hildegard Von Bingen of course)

oops, i left the window open and walked away and now the computer is beating me 115 to 1.

ok, i'm stopping for the night. the next things to do are to add typography functions, full mouse functions, and color modes, then I think that will be most of the API complete. I will still need to do bug testing.

Tonight I ran up against a problem I couldn't quite solve. I am using @Alexjgriffith suggestion to modify love2d's love.run() game loop and modified the default loop to not clear the screen between draw calls. Unfortunately, when drawing graphics from events (such as keyPressed(), keyTyped() ) the screen flickers, I think because of double drawing. I tried half a dozen different solutions but never quite found a satisfactory one unfortunately.

since i am stuck on the flickering background color problem i decided to take a break from that. so this afternoon i implemented a toColor() system so that one can input color names in the same variety of ways that p5.js does: using a html color name - it's glorious to use Rebecca Purple, Lawn Green, Dodger Blue, Mintcream isn't it?, as well as R,G,B, or R,G,B,A or grayness or grayness,A. later i will add in some other modes like HSB
added 3 and 6 digit hex color codes as well.

added frameRate() function.

while working on all this, had a bit of a think. i believe my flickering screen problem is a result of me hacking Love2d to work more like processing/p5. in the processing model, the approach is a synchronous model. draw runs once per frame. if too much processing happens, it slows down/frame rate drops. love2d takes the approach of drawing as many times as needed per game loop. logic is separated out into update(), while drawing is rendered in a separate thread, so game logic doesn't block rendering and realtime logic can be processed. In love2d, the emphasis is on realtime game processes.:

it is 2am and i have at least temporarily nipped this one in the bud. i'm worried there's some edge case i haven't addressed, but i have tried a bunch of tests and so far i'm hoping this sticks. i do not have the jittering/framebuffering issues anymore, all events and setup are able to draw to canvas, with or without any other functions. in the end, i'm worried i made my code a bit hacky - for example, i am running setup code twice , where the second time the graphics are being drawn. i think there's room for improvement and cleanup later, but i'm glad to have gotten through this block.

Don't want to jinx myself but I think I'm nearing completion of what I've set for my first run implementation of Processing API in Lua (via Love2d). I need to add in typography styling, some input/output options, and then probably have some drawing buffer debugging to do (which has been the most difficult thing for me to work through so far).

Today I added in describe() mode from p5.js and decided to try having it output text to the console for CLI screenreaders, but I need to look into more best practices for this.

I also implemented color tables, getting and setting colors, screenshotting (save() ) , smoothing/noSmoothing, strokeCaps, strokeJoins, displayWidth, displayHeight, millis(), mouseWheel() function.

i had temporarily for a day or two jinxed myself but i was able to figure out font loading and textSize, and other typography functions to emulate the processing api / flow (maintaining state).

next i turn to input/output (importing and exporting strings/json/tables?).

completed! loadStrings(), saveStrings(), loadTable(), and saveTable() complete. And current data formats are csv, tsv and lua.
I considered adding in a loadJSON() function, and still could at some point, but didn't think it made sense to DIY build a basic JSON parser or drop in something now. Could always be added later.

And with that, i've pretty much finished most of this first draft of implementing the API. there's a few remaining color modes to add in: HSB, a noise function, some vertex functions, and then lots of debugging and refactoring. notably, i have not tested on a Mac or Windows machine yet, or any computer other than my own! I also need to review how i'm implementing drawing from setup(). my current method is a bit dumb and draws twice. but ultimately, feeling pretty good about the library so far.

I'm building in documentation and example programs as I go. Here's the most complex one so far, a basic implementation of OOP with a robots class via metamethods

fiinished up a heckuva of a lot of the API and have been doing some tests (still need to do some more). I still need to add in colormodes HSB, HSA and a few related functions and then that'll be the first draft of L5. i am ignoring vertex functions for now (I could'nt quite wrap my head around it yet) and need to fix arcs.

I started building out intro documentation yesterday. I saw Casey and Lauren today and told them about the project and will share it with them hopefully soon. Lauren asked me about what if it catches on and I'm working on this for years and years lol.

Now I'm starting to think through documentation and reference sites. I looked at how they build the sites for Processing and p5 and I don't quite want to have to learn JSX and MDX. It's probably not too bad but I'm hoping for something much simpler at first. I can always build it out further later.

Anyone have a suggestion for building a programming language documentation and reference site? particularly that's beginner-friendly, emphasizes the reference, and makes it easy to handle/build a reference page for all of the language's functions? written in markdown, produces static pages, and can be hosted on a git forge and collaboratively built with others.

I am currently looking at:

* hugo documentation themes
* MKDocs
* adapting my own static site generator again - though this may not be robust enough over time
* i keep reading about documentation generators but i don't really grok the idea yet

there's not too much to this sketch, but it's fun trying out rapid code sketching with the language now

code:
require("L5")

function setup()
size(1920,1280)
windowTitle("Flag Thing")

noStroke()
createPage()

frameRate(1)
end

function draw()
createPage()
end

function createPage()
background(random(255),random(255),random(255))
fill(random(255),random(255),random(255))
circle(width/2,height/2,2/3*height)
end

on a whim i decided to port over my Pico-8 quilt generator to my L5 language. took only maybe 15 minutes. the colors are quite ugly on this one!
as much as i love kludgy dynamic programming languages sheesh i really got myself tonight. i was spending 30 minutes trying to debug some wild-ass bug i couldn't make heads or tails of, even when trying to just print it out, and then of course later i realize i had a function and a variable name collision. smh

with a bit of a whimper at the end of a friday night here i have implemented 99% of the API to an unpolished, un-refactored state. I've also assembled a bit of a TODO list so I can go in and start cleaning things up.

Today I added in colorMode() which lets you change between RGB, HSB and HSL. I thought I had it, but since I'm trying to emulate Processing and p5.js I always test against their outcomes and was dismayed to learn that using a html color name in p5.js even in another color mode should always output in RGB. And while this makes complete sense, I kept getting strange color output when rendering "orange" in HSL mode for example. I'm guessing my color juggling is off somewhere because it goes like this:

code:
colormode(HSL)
fill("orange")
square(0,0,100)

behind the scenes:
1. change global color mode state to HSL and max vals for HSLA are 360,100,100,100 default
2. retrieve orange as RGB(A) values. convert that to "orange" in HSL.
3. draw the square in that fill color
..
4. Hmm, yellow appears instead?

The problem exists between 2 and 3 (as well as between my ears).

on the other hand, some other basic tests look great:

just wasting time.

coded a basic chess set with manual placement of pieces, so not a really playable game yet, though maybe hexapawn soon though? (no promises!)

@exquisitecorp * adapting my own static site generator again 💯
@exquisitecorp you are a mad man thank you 👏🏽👏🏽👏🏽
@exquisitecorp badass. glad the canvas method ended up working

@exquisitecorp afaik, unless i’ve misunderstood your post - love2d does not run update and draw on separate threads. in its vanilla configuration, update is run first, draw second. they're both run in the same (blocking) single thread.

i can confirm that via experience - framerate absolutely can tank due to too many update calls. i had some nasty bad code that was checking 100,000,000 coordinates per frame and brought fps to its knees 😅

@vga256 ah ok, thank you for clarifying that.

oh and i've made good progress! fingers crossed, but everything seems to be rendering across draw and events. now i can't seem to get setup to render correctly, but hopefully only a matter of time. need to do more testing but feeling better.

@exquisitecorp woohoo. glad to hear it!

always a drag when progress gets hung up on a single annoying bug

@exquisitecorp is it possible that you could queue up the draw calls in the love.update() loop instead of love.draw()? i believe this would allow everything to be processed in the update before the draw call is ever made, and might prevent the buffer problem.

i'm thinking of love.update, because i *think* keypressed and other events are processed around that same cycle as well

@vga256 i don’t know but will look into this with fresh eyes tomorrow. thanks
@exquisitecorp haha. was hoping you wouldn't read that until tomorrow. just some thinking out loud.

@vga256

here's my present love.run() in case it sparks some brainstorming :)
ok headed to sleep where i'll be murmuring about this

-- Custom love.run() function that doesn't clear screen between frames but does clear matrix transformation
function love.run()
if love.load then love.load(love.arg.parseGameArguments(arg), arg) end

-- We don't want to clear the screen automatically
if love.timer then love.timer.step() end

local dt = 0

-- Main loop
return function()

-- Process events
if love.event then
love.event.pump()
for name, a,b,c,d,e,f in love.event.poll() do
if name == "quit" then
if not love.quit or not love.quit() then
return a or 0
end
end
love.handlers[name](a,b,c,d,e,f)
end
end

-- Update dt
if love.timer then dt = love.timer.step() end

-- Update
if love.update then love.update(dt) end

-- Draw (without clearing!)
if love.graphics and love.graphics.isActive() then
love.graphics.origin()
-- DON'T call love.graphics.clear() here!
if love.draw then love.draw() end
love.graphics.present()
end

if love.timer then love.timer.sleep(0.001) end
end
end

@exquisitecorp so here's what I was wondering: when your Processing functions are called, which loop are they being called from? e.g. update()? draw()?

i can see in the custom love.run() that the event queue is being processed before update() and draw() which might lead to your Processing commands being queued or drawn out-of-order. e.g. hitting a keypress (which love2d treats as an Event) queues a Processing command *before* love2d gets to the ones that exist in update() or draw(). this would create some very unpredictable behaviour. just a hunch.

@vga256 that could be. i tried implementing a drawing queue that would queue up drawing and execute only once in draw() but still had that issue. i also tried blocking drawing outside of drawing queue so only updates once but had same (or at least looked the same) issue. so i'm still a bit stuck on that one. it's not the biggest issue but i'm trying to get feature parity with processing so trying to solve it.

@vga256 i'm bookmarking this forum thread too where i believe this or similar issue is discussed, though it is marked "solved" but i see no solution there
https://www.love2d.org/forums/viewtopic.php?t=86140

i also tried adding a blocker so that when events happen the main draw doesn't run. that didn't solve it either. i've tried so many things that didn't work that i'm feeling better about the idea that i may find something that does for ruling everything else out! lol

@vga256 ohohoho i've figured out something.

ok, so instead of using my events like keyTyped() i instead temporarily just added a flag inside keyTyped and set it to true. Then in my draw if the flag is set to true I draw the elements that were previously inside keyTyped (and i set the flag to off in keyReleased(). ) That worked! Ok, so i'm closer to finding a solution. i need to take a break but will come back at this tonight. i think i'm onto a solution i hope, though i don't want to jinx myself.

my testing file: https://gist.github.com/lee2sman/8ca583a11c79705fd030b3953a157476

screen flickering test file

screen flickering test file. GitHub Gist: instantly share code, notes, and snippets.

Gist

@exquisitecorp ah ha, that really does suggest it that it's because of the order of execution... (keypressed) Events will always be executed first. one option might be something similar to your flag approach, but instead of false/true, having it add each command to a command queue in draw()

update: wrapped each draw function in a closure/anonymous function instead, and clear the queue once per frame:

command_queue = {}

function keyTyped()
if key=='c' then
command_queue[#command_queue + 1] = function() background(0,0,255) end
elseif key == 'p' then
command_queue[#command_queue + 1] = function() background(255,0,255) end
end
end

function draw()
rect(0,0,100,100)

if mouseX>width/2 then
background(255,0,0)
end

-- process the command queue in order
for i, command in ipairs(command_queue) do
command()
end

-- now clear the queue so it doesn't repeat the same commands every frame
command_queue = {}
end

@vga256 i tried it but it failed , so i must have made an error somewhere . i'll try it again later

@exquisitecorp ack the error was mine. table.insert doesn't like inserting functions as a parameter!

function keyTyped()
if key=='c' then
command_queue[#command_queue + 1] = background(0,0,255)
elseif key == 'p' then
command_queue[#command_queue + 1] = background(255,0,255)
end
end

edit: the more i think about this, the less i think it'll work. i suspect lua executes background(0,0,255) the instant it is used as an argument in the keyTyped() function, instead of storing it as a value... it stores the executed value as a value.

i think it needs to be stored as a closure/anonymous function instead:

function keyTyped()
if key=='c' then
command_queue[#command_queue + 1] = function() background(0,0,255) end
elseif key == 'p' then
command_queue[#command_queue + 1] = function() background(255,0,255) end
end
end

@vga256 i tried this and also tried the flags. both times i still had the screen flickering. then i tried deferring drawing the background to the end, only once, and unfortunately same error. i'm out of ideas for the night but going to meet with a friend locally tomorrow so maybe can point out to them and see if they have any ideas.

@vga256 partial-solution! very dumb approach but kinda sorta working:

When drawing a background (which is essentially clearing the screen and drawing a color), i just store the color to a global table holding that background color. I also set a flag to draw the background color. Inside the love.draw() i check for that flag, then clear the screen with whatever the last saved color was. Then i run the rest of the draw() function.
why this isn't a perfect solution: it assumes drawing a background color will always be first before drawing everything else, which isn't a perfect assumption. need to think some more.

@exquisitecorp interesting and yeah - a bit janky haha.

what did you think of the forum post suggesting painting everything to a Canvas instead of the love frame buffer?

@vga256 that will work but i don't love it because i sometimes (not often, but sometimes) use the offscreen buffer to draw to and then apply that to window. but hmmm, maybe it's possible to have a second offscreen canvas, which could solve that issue?
@exquisitecorp yup you can create as many canvases as you’d like and mix them/overlay them in draw()
@vga256 Agh, i tried but it still flickered! Ugh, giving up in defeat for now. Will try again tomorrow.
@exquisitecorp dang. was hoping it was a simple function order problem
@vga256 yeah. on second thought, i'm going to (not now, it's bedtime) look at the canvas approach again tomorrow. i had used the canvas originally to maintain graphics between frames before i had modified love.run(), then stopped when i realized i could remove the clear() from love.run() and i wanted to preserve allowing drawing to an offscreen buffer. so now (at your suggestion), i've looked and see i could have multiple offscreen canvases, so that might be another way to solve the issue. i'll come back and test that tomorrow.
@exquisitecorp very cool approach. looking forward to seeing if that simplifies things
@exquisitecorp @Alexjgriffith i'm down to pair with you
@catilac that would be helpful! what days/times are generally good for you?
@exquisitecorp I am fairly available, but give me a week. Tmrw I'm going to do my first commute on train since having surgery last week
@exquisitecorp really happy seeing a fellow love2d project. it is such an underrated framework
@vga256 thanks, yeah i really love it! this is basically a library that scratches my own particular itch that the processing API is committed to memory and i can do it in my sleep so i figured might as well try this out.
@exquisitecorp awesome. i’m always surprised at the great performance it has despite my monkey quality code.