was encouraged by @dantescanline to keep going on the quasi-broughlike roguelike i started yesterday while watching the Roguelike Celebration @roguelike_con
i added a bit more functionality, but this is still far from a fun/playable game
was encouraged by @dantescanline to keep going on the quasi-broughlike roguelike i started yesterday while watching the Roguelike Celebration @roguelike_con
i added a bit more functionality, but this is still far from a fun/playable game
Nice studio visit with @computersandblues today, checking out the inkblot library and showing my progress on L5 and jamming with PureData/PlugData.
In the evening, I wanted to make a Captcha font writer type program and it took me a surprisingly long time. I added applyMatrix() functionality to L5. Each key press currently redraws a scrambled matrix so the writing gets re-funkified with each keypress and mousepress.
I solved a huge bug that I have been trying to solve for months, and that moves me much closer to getting ready to put out a pre-alpha version of L5. It relates to what I've been calling the "double setup problem."
Basically, I was calling a user's setup() function twice even though it's only supposed to run once. I did it once to grab sizing defaults, for example from the size() function or fullscreen. Then again inside the love.draw() once in order to draw graphics the first time.
By default, the underlying love2d framework only allows drawing in love.draw() but I am attempting to clone Processing's ability to display graphics in setup as well as in events like mousePressed and keyPressed. Basically what I had to do was majorly modify the love.run() underlying love2d, as well as love.load() and love.draw() and some other things. Finally, I have a solution, by handling canvas states at the correct place and buffer recreation.
Okay, then I found another bug. I could not get fullscreen() to correctly draw graphics to the screen any longer as a result of those changes to the underlying way that love2d functions.It's a testament to its incredible documentation that it didn't dawn on me til now that I should have perhaps studied Love2d's underlying functions for setting the mode because I was getting really stuck on why graphics rendering no longer worked. It turns out that I needed not just to declare setFullscreen but also setMode, so I needed to write this:
love.window.setFullscreen(true, "desktop")
local w, h = love.graphics.getDimensions(display)
love.window.setMode(w, h, {fullscreen = true, fullscreentype = "desktop"})
This to me looks bizarre, like I'm redoing the same thing multiple times, and it's likely a result of my monkeying with the underlying love.run but in any case, all 3 of these lines are needed to be able to draw graphics in setup with fullscreen on. Anyway...
I also made a change from p5.js style implementation of fullscreen(true) to Processing's cleaner/easier: fullscreen() or fullscreen(display_number) which will send to whichever specified monitor (by number of display).
lastly, i tried to figure out a way to allow a user to write code without a setup function but i couldn't figure out how to do that. Beyond this, I think I just want to finish the basic documentation reference site and get it up and then start doing a pre-alpha test with friends. Hopefully can wrap this in the next week or two. Maybe 2 - 10 hours more effort? (though by saying that, it guarantees i'll need double that time!)
In L5 Studies tonight I implemented a first version of a webcam library!
I'm not targetting finishing this by the time I release a pre-alpha of L5 but it is important to me that there is a useful audio library and a camera library that can be used with L5. I have already set up a test of a audio library a month ago and it went ok. Tonight I tried to take on accessing the webcam, which wasn't obvious what to do. I implemented a little webcam library using libjpeg-turbo in C wrapped in a little webcam.lua library that can be used with L5.
still goin'. have been working on the documentation site for the past couple days. i am cleaning up the reference and reviewing missing functions. i kind of wanted to freeze where i'm at and do a little pre-alpha release but i am still trying to pick up and implement more bits of functionality.
tonight i added a few helper conversion functions from p5/processing: boolean(), byte(), char(), float(), hex(), str(), unchar(), unhex().
more on the way.
Ok, from my git log I also added fract, log, norm, pow, sq, sqrt, asin, acos, atan, atan2, randomGaussian, randomSeed.
I experimented with a headless noWindow() mode but basically it just closes the window. It's not really a headless mode for rendering graphics/sketches, so I removed the functionality and will rethink it again in the future if it's possible to implement differently (maybe not).
I also spent a great deal of time tonight cleaning up the L5 documentation site to get it ready for a soft launch. It still feels a bit basic in terms of design, but good to get something up and then build from there. I have 186 reference pages now! But in a fit of reorganization I realize I broke the reference page image paths tonight before bed when I fixed a different path issue. So tomorrow I'll have to write one hell of a regex to fix all of them in their various sub-directories! But overall, things are in a good shape.
I have Openhaus open studios at ZK/U Thursday the 20th and would like to be at a point where I can tell friends about the site/language and have them start playing around and testing and giving feedback then.
spent much of the weekend plugged into my laptop trying to grind through the damn reference pages and fixin' little bugs. Fixed some of the color modes like HSB and HSL which I think should be working.
So now you should be able to work with colors in all of the following ways:
fill(grayscale)
fill(grayscale, alpha)
fill(R, G, B)
fill(R, G, B, alpha)
fill(HSB)
fill(HSL)
fill('HTML color name') or
fill('#3-digit hex code') or
fill('#6-digit hex code') or
fill(color-object-table) or
wow, that's a lot. and that's why debugging took me some time. i had to build in some sanity checks and make sure things worked correctly for:
color(), fill(), background() - which also takes an image file input, and fixed lerp(), lerpColor(), brightness(), lightness(), hue(), alpha(), red(), green(), blue().
In addition, I had to fix all of the documentation pages for each of these, plus many others, test all of the code and produce screenshots to add to the documentation pages. It's a lot.
Still a lot left but i'm on a roll. Will keep grinding through it this week.
oh i am so deep in this hole. i am hand-checking every one of the 200+ reference pages, which can take me 3 to 15 minutes a page or so. For each page, I check my automatically converted p5.js to L5 reference code examples (i have a bash script that built these!). then i alter the description if needed, run all example code and screenshot, and then usually have to hand alter the parameters section as my conversion script didn't successfully build those. Also, for a sizeable minority of these reference pages I realize I left out a parameter or add in an extra error checking code or something. So that expands the time considerably.
Yesterday I checked and edited maybe 20 or so pages and fixed textAlign(), textWrap(), text() (added BASELINE positioning correctly this time), added in error correction to rectMode(), imageMode(), ellipseMode().
With each reference page i generally compare to both p5.js's reference as well as Processing's reference. Well, Cloudflare is down today so I can't check p5.js's site which relies on it. A good reminder to myself NOT to use services like that, I think, as it feels very un-resilient.
Right now I'm testing the L5 website to run without Javascript. I loaded it up in Links and w3 in the terminal, w3 with the img extension actually, and then with @dillo
Looks good.
I am using mkdocs with Material (a static site generator) for rendering the site. It makes many things easier and organized well for a documentation reference site for an API, but it has one big drawback: while the site works without JS, I think the site is larger because of it, 6MB page load, which I'd really like to get down to under 500k but not sure it's possible with this framework! I tried to use Firefox's built-in memory profiler and read its documentation so that I can learn how to cut things down but (argh!) the documentation site for Firefox is down due to a Cloudflare outage.
In the meantime, here's 4 views of the documentation site so far:
1. with w3 in the command line,
2. with netSurf
3. with Dillo (landing page)
4. with Dillo (an example reference page)
One other issue: I've been using webp images to make everything render out in small file sizes, but that doesn't worth on everything! I guess I'll have to have jpg fallback files? I anticipate another bash script to make that happen...
ah, i think i fundamentally misunderstood how the memory profiler and network tools work and what they mean.
i removed loading 2 custom fonts, but that's it. might slim the fonts and put em back.
in the meantime, locally testing the site is about 650kb and i think that when deployed based on gzip compression it might go down a few hundred k more. hopefully i'm understanding this correctly.
fixed a ton of smaller functions and built maybe 60 reference pages total now. there are still 140 page to do! lol. one accomplishment: i fixed multi display support and tested on windows and linux so you can correctly specify which display to run a sketch fullscreen in.
here's my multi monitor installation coded in L5 with the updated library.
the last week was a bit of a blur as it was my last week in my art residency and then some international travel.
On my flight I got back to L5 studies and built "Photocrapier", a photocopy machine emulator with various features like rescanning, jiggling the paper, glitching the paper (i guess jiggling it a ton while scanning?), sliding the paper around, rotation, etc.
I wonder if i should package these things up as little binary files and make them available for download. or at least make my whole L5-studies code in a git repo.
Staying with my parents is a bit like a mini residency. This weekend I worked quite a bit on the reference pages website for L5 and performed a variety of smaller bugfixes to the lang.
* max() and min() can now accept tables
* added exp() function
* deltaTime global var now outputs millis() to match Processing/p5 output
* added resetMatrix() and fixed addMatrix() (and used these to complete the L5 studies project photocrapier)
only 60 of the reference pages (out of about 200ish total) left to do.
I did 10 more pages of the reference and deployed to the (not-so-secret) website. Basically, the reason it takes so long for each reference page is that I use writing the page as a chance to go through and bug fix the actual function I'm referencing. loadTable() and saveTable() were my time stealers today, among other things. for example, I modified saveTable() to deal with both a single table as well as a table of tables. That added...dozens of lines of code, plus debugging.
I also kicked off #DecemberAdventure today after forgetting about this annual tradition and then seeing it pop off on Mastodon here. I participated in the last 2 years and basically liked it so much I continued doing it year round on my log page, so I made an anchor tag to jump to my December Adventure 2025 posts here:
Today was spent working on reference pages and debugging the L5 language library, getting ready for the pre-alpha release. What I worked on today: save() can take an optional filename. I added an alternate data structure for single element tables to saveTable. I updated text() to deal with non-strings. Lots of fixes to events: key detection majorly mproved, fixing delete and function keys, etc reporting. Surgical fix so that keyTyped() reports true at the correct spot. Cleaned up mouseWheel() (no need to report x-value since wheel only scrolls vertically). The biggest update/fix was debugging and correcting the order of mouse handling events. mousePressed() runs as soon as the user clicks the mouse. mouseReleased() runs as soon as the user releases the mouse click. mouseClicked() runs immediately after mouseReleased(). Phew. Worked through a ton of reference pages and it looks like I have a bit under 30 left to do now. At the rate of 10 a day I seem to be on now maybe there are 2 - 3 days left.
churned through a bunch more reference pages, updated the p5.js to L5 conversion script too to help me with that. Thinking I will likely finish the remaining reference pages tomorrow.
A BIG DAY FOR ME: I HAVE AN INITIAL ALPHA RELEASE OF L5, which I have been working on for 4 months so far. I also have a nice website up for it with 200 documentation pages!
My next step is to try to get the word out to friends to try out L5, give initial feedback, and see if folks find it useful, want to contribute, etc.
I then need to concentrate on getting some more tutorials done, more/better error() message reporting, just general bug-fixing/refactoring, and add a L5 mode to the Processing IDE application.
I've slowly been adding tutorials and examples pages, ported from p5.js and Processing (and thanks to a CC-BY-NC-SA license), but adapted for L5.
It'll take me some time but I plan on adding many more.
I'm looking for some suggestions about the https://L5lua.org documentation site for L5.
At first I tried to optimize the site for small page load, focusing on making all images webp files.
Question 1: Is there some html or css only option that allows "falling back" from webp to loading jpg instead if needed for browsers that can't load webp?
Question 2: For example code that shows interaction or animation i'm showing animated gifs. These gifs can be quite large! I want L5 and the website to be able to work on lower-powered and lower-bandwidth computers, even ones without JS. Could my use of gifs be improved?
I'm currently recording the window with SimpleScreenRecorder at low fps as a mp4, then using imagemagick to convert to gif. On a tip, I found ezgif.com converts even smaller. Anyone know their 'recipe'? I would love to automate the process in the command line.
Question 3: Any other tips for how I can make the site work better, particularly for low bandwidth and offline browsing?
Boosts ok! Politely written responses appreciated!
I just added downloadable offline documentation for L5. You can download the entire L5 website for offline use, easily, with or without images. Added to the download page.
I've been adding lots of examples to the L5 documentation site, including implementations of 10print and Conway's Game of Life written in L5. I also adapted some tutorials and examples from p5.js (thanks to Creative Commons licensing!).
https://l5lua.org/examples/conways-life/
I still need to add more tutorials and to build some better "getting started" materials that show exactly how to get a Mac and Windows machine set up specifically for a cozy coding environment with L5.
It took me two days. After a comprehensive review of my own intro coding notes for p5.js and reviewing many other creative commons licensed sources I selected and then very liberally adapted and built off the Happy Coding Tutorials to create an 11 part comprehensive:
A complete introduction to programming with L5
I am still interested in developing a few more useful tutorials on setting up for various systems (Mac, Windows particularly) for a variety of code editors. Open to suggestions and contributions!
Also want to clean up and build out the working with video tutorial and create a new one on breaking out to the wider system with Lua's os.execute()
In the process of working on the tutorials I found minor inconsistencies between L5 and p5.js in key and mouse handling, so I patched it so they have parity.
I'm wondering where the right place to set up "discussions" should be for L5. There is a robust Discord and Discourse forum for Processing and p5.js, and yet I'm not on those things. There is also a subreddit, but again I'm not on that.
Maybe I could add a github discussions 'forum' since the repos are already there? But do i want to enable capture within the Microsoft system there? Alternatively, maybe join the Discourse forum and have a L5 forum heading? But I don't know. I do think these things matter and help spread the word about the library and {code, documentation} contribution. I'm just not keen on getting deeper into other "social media" and related.
Separately: I added @oppen 's Walking Lines example to the examples page. I'd love to have more community-contributed examples and tutorials by the way!
I made a little Cadavre Exquis code sketch for breakfast today, implemented in L5. The original images from 1926 - 27 should be public domain in the US.
after installing a new hard drive (and having to reinstall my Void Linux distro on the new drive), i decided to re-install the OS on my parents' unused 2014 macbook. i thought about putting linux on there but the goal is to have an old Mac to test L5 programs on. I installed Love2d and L5, tested a bug I had found on iOS and also found it on the Mac. It's a minor bug that when going to fullscreen, if you had set up a background color in setup() it doesn't persist when going to fullscreen. Somehow the Mac side it clears/resets the drawing buffers. Not present on Linux. Need a Windows machine to test and see if it persists. I noted the bug here, in case anyone wants to test on other eras of macOS or on Windows until I get my own old windows machine.
https://github.com/L5lua/L5/issues/3
I also tested to see if it had the same shader error reported earlier from the 2009 Windows machine but it didn't. It worked fine for shader code.
Thanks to a contributed code suggestion from the community, patched the save() function in L5 so that if the current directory is not writeable then it will save to the default directory and print a warning and location of the save.
Day 3 of #Genuary2026 and I'm using #L5
prompt: Fibonacci sequence
Day 4 of #Genuary2026
prompt: Lowres. An image or graphic with low resolution, where details are simplified or pixelated.
This one feels in my wheelhouse much more than the previous ones. So I started having some fun and made something I'm excited about. I think I will use it as a 'filter' to create a music video for some no-input mixing board mixes I want to put online.
Little test here. I was having too much fun so this is a larger video file with my own music recorded with my collaborator ZZZelin. I'll upload some screenshots too.
and here's the code for that one:
```
--genuary 2026 day 4
require "L5"
function setup()
fullscreen()
img = {}
for i = 1, 9 do
img[i] = loadImage('assets/graff/'..i..'.jpg')
end
mouseDragged() --pick an image to start
end
function draw()
buffer_w = map(mouseX, 0, width, 15, 200)
buffer_h = map(mouseY, 0, height, 15, 200)
pg = createGraphics(buffer_w, buffer_h)
pg:beginDraw()
image(current_img, 0, 0, buffer_w, buffer_h)
pg:endDraw()
translate(width, height)
rotate(PI)
image(pg:getCanvas(), 0, 0, width, height)
end
function mouseDragged()
current_img = random(img)
end
```
Day5 of #Genuary2026 in #L5. The prompt is to write Genuary in some way without a font. I made this little drawing thing and drew the title, using an offscreen buffer that continuously repeats my drawing
--genuary 2026 day 5
require("L5")
function setup()
background(255)
blocksize = 250
-- Create offscreen canvas
offscreenCanvas = createGraphics(800, 600)
end
function mouseDragged()
background(frameCount % 255)
offscreenCanvas:beginDraw()
strokeWeight(random(7))
stroke(random(255))
line(mouseX,mouseY,pmouseX,pmouseY)
offscreenCanvas:endDraw()
end
function mouseReleased()
for y=1,height,blocksize/4 do
push()
translate(0, y)
image(offscreenCanvas:getCanvas(), 0, 0)
pop()
end
end
Day7 of #Genuary2026 and today's prompt was something related to booleans. Programmed in #L5
(Hmm, on upload, i see the video gets upscaled! it should only be 100 pixels wide! that's why this looks so pixelated).
Also, on reflection, this doesn't look like generative art as such, but it was still fun to program and i'm ready for bed! :)
--genuary 2026 day 7
require("L5")
function setup()
windowTitle('Genuary day 7: Boolean play')
total = 0
val = {
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0},
}
size(110,200)
textAlign(CENTER, CENTER)
describe('a grid of values that can be toggled between 0 and 1 when clicked.')
end
function draw()
background(0)
textSize(80)
fill(255,0,0)
text(total,width/2,height-50)
fill(255)
textSize(10)
total = 0
for y = 1,#val do
for x = 1,#val[1] do
text(val[y][x], x* 10 , y * 10)
if val[y][x] == 1 then
total = total + 1
end
end
end
end
function mouseDragged()
local _x = floor(mouseX/10)
local _y = floor(mouseY/10)
local total = 0
if val[_y][_x] == 1 then
val[_y][_x] = 0
else
val[_y][_x] = 1
end
end
I added a web-based survey for L5 (there is the option to fill it out, then send it via email). I had tried to do it with just HTML and CSS but the mailto link didn't copy the info correctly so there is now a minimal javascript to send the info correctly. There is also a link to a google form, as well as a <noscript>-wrapped text that explains what to copy an paste and send in an email. I tested on Netsurf, Dillo, Brave, Firefox, w3m and offpunk.
I also tightened up some info on the L5 landing page.
The biggest recent site change I made was that I added a downloadable zip folder as the recommended L5 Starter project, based on feedback from Gottfried, who filled out the survey! This should make it easier for folks to begin using L5.
I put out a local call in my network in NYC to meet up to work on L5 next week as a group to document installation and test on old Macs and PCs and more than 10 folks responded! I'm now looking for a room for us all to meet next Tuesday afternoon and wrote to a couple friends looking for space suggestions.
Although Genuary is still going on I felt drawn to work on something without the prompts today. I started working on something with scrolling marquee text, but printing out an excerpt from my daily journal entry. Obvious references are the works of Barbara Kruger and Jon Rubin, but I wasn't thinking of that at the time, and this is much simpler, made in about 20 minutes. Just came out of me. Coded in #L5.
CW: mentions violence, political news
require("L5")
function setup()
windowTitle("Thinking out loud")
textSize(100)
fill(0)
noStroke()
fullscreen()
describe("scrolling text from top to bottom, alternating direction, vaguely reminiscent of a flag, with thoughts on today.")
messages = loadStrings('thoughts.txt')
--print(messagePos[1])
--print(#messagePos)
--messagePos = {
messagePos = {}
for i=1,#messages do
messagePos[#messagePos + 1]=
{x = random(width), y = 100 * i - 50, delta = 1, bg = 'red', c = 'white'}
--even or odd?
if (i % 2 == 0) then
messagePos[#messagePos].bg = 'white'
messagePos[#messagePos].c = 'red'
else
end
end
fill(0)
end
function draw()
background(255)
for i=1,#messagePos do
fill(messagePos[i].bg)
rect(0, messagePos[i].y - 100, width, 100)
fill(messagePos[i].c)
text(messages[i], messagePos[i].x,messagePos[i].y)
messagePos[i].x = messagePos[i].x + messagePos[i].delta
-- check offscreen
if messagePos[i].x > width or messagePos[i].x < -width then
messagePos[i].delta = messagePos[i].delta * -1
end
end
end
I switched from Genuary projects back to working on #L5. I am doing testing of alternative implementations of filter() with fallbacks for older machines that can't handle some aspects of shader code. My research shows me that some GPU stuff is needed for Love2d to work at all, so i tried to match the minimum requirements. Will be doing testing this month on a variety of older machines and OSes.
The L5 community survey I put out has only gotten a few responses so far but they've been extremely helpful and led to some fixes and better documentation and starter. From one person's survey I learned of some more synthesis options in Love2d, so I am feeling much more confident we could match most of the functionality of Processing's Sound Library or p5.sound. I've mapped out the Processing Sound API and ways to replicate with Love2d native and adding in a lightweight lovefft library. I have other stuff to work on for the next few months but will definitely put time into this in the spring.
A report on the first L5 Contributors Meetup, held today in Brooklyn.