One of the biggest recent indie hits, Balatro, was made in Löve!
I really like it, the developer experience is so smooth for beginners, just drag a zip onto the exe and it starts. And the APIs are simple enough to memorize while allowing pretty cool rendering stuff.
Balatro ships with the entire unobfuscated Lua source by the way.
I once checked if the odds stated on a card were implemented wrong. Turns out no, the code checks out, I'm just that unlucky.
too bad universe doesn't ship with unobfuscated source so that you could see whether you're unlucky, or just skill issue
The source is right there, you just have to grok it.
Good news: the universe is written in LISP. Bad news: with no comments.
> the universe is written in LISP
Ostensibly. Honestly most of it was hacked together with Perl.
I like to imagine perl was bootstrapped from forth and used to build a lisp
You can ask AI to comment an entire code base now in as much detail as you need.
Comments explaining what the code does, which is what an LLM could answer, are basically useless comments. Comments that describes why the code is how it is, is a bit more valuable, but also something LLMs cannot really reliably infer by just looking at the code.
Well, it's kind of a machine code for a self-modifying compiler, so there's that.
The source is not just dna - that's just one type of architecture that exists. There might be others that operate on different instruction sets.
The real source is mathematics. But some might say it's incomplete.
Mathematics is the FORTRAN of the real source. Closer to a real source is probably "real" things like atoms and other universal things.
If I remember correctly, Stargate-SG1 at one point had some ideas about this sort of universal language, that multiple species could use for communication, as any sufficiently intelligent specie probably been able to see atoms and so on, but may have completely other way of doing "math-like" stuff.
I'm still waiting for the slackers at CERN to finish decompiling it.
that's great, could read the source code on how to unify gravity and quantum mechanics for all energy levels? vibeing to a nobel price will be cool...
I don't have to check the source code to know that for me it's a skill issue :/
hahaha, I did the exact same thing after the game came out to see if wheel of fortune was really a 1/4 chance
lol, love seeing that I'm not the only one who did this. Being suspicious of WoF was the first and last time I peeked at the Balatro source.
Game developers sometimes make the “randomness” favor the player, because of how we perceive randomness and chance.
For example in Sid Meier’s Memoir, this is mentioned.
Quoting from a review of said book:
> People hate randomness: To placate people's busted sense of randomness and overdeveloped sense of fairness, Civ Revolutions had to implement some interesting decisions: any 3:1 battle in favor of human became a guaranteed win. Too many randomly bad outcomes in a row were mitigated.
https://smus.com/books/sid-meiers-memoir/
Some threads on randomness and perceived fairness in video games can be found here on HN too, for example https://news.ycombinator.com/item?id=19399044
The original link being discussed in that thread is 404 now, but archived copies of the original link exist such as for example https://archive.is/8eVqt
I used to get so many comments about how the computer opponent in a tile-based board game of mine cheats and got all the high numbers while they always got low numbers, and I'd be like "that's mathematically impossible. I divide the number of spaces on the board in half, generate a deck of tiles to go into a 'bag', and then give a copy of those same tiles to the other player.
So over the course of the game you'll get the exact same tiles, just in a different random order.
Now to be fair, I didn't make that clear to the player that's what was happening, they were just seeing numbers come up, but it was still amazing to see how they perceived themselves as getting lower numbers overall compared to the opponent all the time.
Meanwhile on the base game difficulty I was beating the computer opponent pretty much every game because it had such basic A.I. where it was placing its tiles almost totally at random (basically I built an array of all possible moves where it would increase its score, and it would pick one at random from all those possibilities, not the best possibility out of those).
My Dad used to play a lot of online poker, and he used to complain when other players got lucky with their hands, be like 'I know the chances are like 5% of them getting that! They shouldn't have gotten that!' and it always reminded me of those people.
The better option would be to just increase the flat odds. DQM: The Dark Prince is brutal with it's odds, but fair. A 45% chance is 45%.
In games like Civ/EU/Stellaris/Sins/etc It makes sense that a 3:1 battle wouldn't scale linearly, especially if you have higher morale/tech/etc. Bullets have a miss ratio, 3x as many bullets at the same target narrows that gap and gives the larger side an advantage at more quickly destroying the other side. So just give it an oversized ratio to scale the base (1:1) odds at.
That keeps "losing" realistic...a once in an occasion happenstance of luck/bad tactics/etc but also a generally very favorable and reliable outcome for your side.
I worked on a game where we added a "fairness" factor to randomness. If you were unlucky in one battle, you were lucky in the next, and vice versa. Mathematically you ended up completely fair. (The game designer hated it, though, and it wasn't shipped like that)
Games like Battle for Wesnoth which have it implemented right, you’ll look at a 90-10 scenario with 2 attacks and end up with the 1% scenario. Enough to make a man rage. I have degrees in Mathematics, I am aware of statistics, and all that. And yet when I played that game I would still have an instant “wait what, that’s super unlikely” before I had to mentally control for the fact that so many battles happen in a single map.
Was good because it identified a personal mental flaw.
Dispatch too. If your odds are above a certain threshold, the mission is a gimme.
I think XCOM does this as well.
The 8-ball joker is even more BS. I think I’ve only seen it trigger once ever.
I've read the source a few years back. It's all implemented fairly as it says on the tin.
I've long been suspicious of the RNG/seed implementation.. but not curious enough to automate testing of it, though.
It's been done, it's a valid RNG. It's somewhere on Reddit if you want to try and search for it.
I figured it had been tested by someone more motivated than me, haha, thanks! Will look for it when I'm back at a computer.
Neat example of cognitive bias, the brain perceives the Nope as being much more prevalent than it actually is!
For a small while I've had the idea of a [game engine/fantasy console/Scratch clone?] that comes packed with a bunch of example games. The example games should be good enough that people download it just to play them, but they are also encouraged to peek into their source code. I'd hope for it to be a sneaky gateway into programming.
For that, I'll keep this in mind: "Unlucky players may look at the source code of a chance-based effect to check if the odds are actually as stated."
I didn't know I could check but after losing like 20 times in a row I just stopped taking WoF. Never saw the good outcome.
I’ve 100%’d Balatro and wheel of fortune is quite strong. It’s never worth taking before you’re at max interest though.
I'm sure it's strong if you hit it, I never did so to me it was a waste of chips.
Not on steam does it? I can only see the exe and dlls.
extract the exe like a zip file, that's how love packages itself. last i looked at the source myself it had comments in still from the dev
I'm really curious how they do version control.
The Steam version was created by one guy, but the platform ports have a couple different authors. The Google Play and Xbox PC versions, for instance, have divergences.
I wonder how the ports influence the upstream and each other. How do they keep the codebases in sync, while also accounting for platform differences?
Can't say for sure how Balatro did it, but typically you do one shared core and any platforms basically use that core in their own suitable way. Considering it's lua, would feel very natural and be relatively simple for Balatro to do it this way too. Not much to keep in sync, just ensuring the core remains reusable in the ways the platforms need it.
The Android and Xbox PC versions look more like forks for a shared codebase. Most of the platform-specific code is abstracted to a bridge, but even the bridges aren't consistent across the codebases. (Android's save system uses different methods than Xbox 's.)
yep that works
come on you can blame whatever the program is using for randomness still
I know which card. We were all there. Are the odds wrong? "Nope!"
In case you're curious, here's a Nix derivation to make Balatro for any other system playable on Linux:
https://github.com/NixOS/nixpkgs/tree/master/pkgs/by-name/ba...
I wrote half a blog post when I did the derivation. One day, I should finish it and post it here.
That's awesome!
> One of the biggest recent indie hits, Balatro, was made in Löve!
Moonring[1] is another one that that is written in Löve (apparently by the co-creator of XBox's Fable series). The base game is even available for free. I had lots of fun playing it.
A lot of indie devs actually are fine with decompiling/viewing source. Even the STS2 devs have no issue with this. I think it is great and helps the indie dev community. Seeing this has actually made me excited about game dev to the point where I'm beginning to dig in myself.
Haven't used it in almost 10 years but at least back then one sticky point was that unlike unity and the like, opening the exe didn't open an IDE. Just kind of a dummy window. Also building for Mac from Windows was a nightmare since my end user was not technically literate and it didn't just run on their end. But that's likely just a Mac issue
Anyone who is a fan of the TV Show Community MUST try out the recreation of the 8 bit video game episode(Digital Estate Planning) called Journey to the Center of Hawkthorne.
[1]: https://projecthawkthorne.com/
It is now available to play straight in the browser(I guess using LÖVE Web Builder?).
[1]:https://schellingb.github.io/LoveWebBuilder/
This engine has really come a long way and enabled such a memorable game for me.
The (crucial) arrow keys don’t seem to work in Safari.
I love LÖVE. For me it sits at the perfect intersection between high and low level abstraction. Unfortunately the latest released version is getting pretty long in the tooth now and a lot of devs use the latest HEAD from the repo since it has better performance and compatibility. One day the mythical 12.0 will get released for real…..
It’s been a recurring issue I’ve seen in open source where there is active development but no releases. I don’t get why you’d put all the work in to fixing bugs and building features but not hit the button to build a release.
Been there before, usually because you always feel like there is "one more thing to get into the release" before you consider it "done enough", and that keeps moving. At one point, you've diverged far enough from the previous release, either by time or scope, that now you feel like the next release really should come with major improvements because of other API breakages already, so now you want to fit in more, so the next release after that can skip more breakages.
Rinse and repeat over months, with volunteers, in a game engine no less, and I can easily see many projects being unable to not fall into that trap.
Anyways, I think it's less of an issue for people in practicality, most people who use LÖVE today tends to start with the HEAD source version, which also sets them up to easier contribute back upstream, when they inevitably hit something non-optimal, so maybe it works out in favor for everyone in the end anyways.
The main issue is that distros will only package the latest release. I had a situation where LMMS on their website had download links pointing to the “beta” builds, while the one on all the disto repos was several years behind.
Right now I have a workflow breaking bug in Inkscape which was fixed last year on main but hasn’t made it to a release yet. So my only option is to compile from source.
There being a stigma about a release being “ready” needs to go. Stuff should get only get merged in to main when it’s ready to go live, or behind a feature flag.
You might like MonoGame. Same level of abstraction, but in C#.
Since we've stepped from interpreted language (Lua) to compiled-to-VM language (C#), let's go all the way down to compiled, low-level language (C) with Raylib!
Or use raylib from luajit FFI and blow C# out of the water. Luajit can be faster than C, truly alien tech from Mike Pall.
"long in the tooth"
How? has Lua changed any?
Or all the references are to old versions?
If you liked Love2D, please take a look at Carimbo (my engine).
https://github.com/willtobyte/carimbo
I have a game on Steam made with it, the game is open-source now.
> Carimbo doesn't reinvent the wheel; it uses the best libraries, such as boost, Box2D, EnTT, stb, yyjson, sol2, PhysFS, SDL, and miniaudio.
To me this sounds similar to Love2D. How is Carimbo different, from the perspective of a dev working with it?
Carimbo is more opined.
What does your engine have to do with Love 2D other than also using Lua?
I used LÖVE to build a simple Kodi alternative for my home media center setup. My first attempt was using Electron but rewriting to LÖVE meant much simpler code (turns out manually calculating coordinates is simpler than fighting CSS) and less resource consumption (not a high bar, yes). It works so well I might clean it up and open source it...
What were your (main) problems with Kodi? AFAIK it is written in C++ with Python plugins. Electron would be (on the face) a downgrade yes. But how is a Lua app much smoother?
(My personal pet peeve is that Kodi still doesn't know how to minimize CPU consumption when one is doing nothing on the UI. It should just stop rendering. This means I have to turn Kodi off on my HTPC+server setup to stop it from pushing my CPU in a higher power consumption mode.)
Kodi is super complex. The last straw was me wanting to launch Dolphin games from the UI and not being able to figure it out.
My custom media center is basically just a glorified 10ft-UI file browser. Opens media files in mpv (with some extra GUI to download subtitles and select audio tracks), Wii games in Dolphin, runs shell scripts (I have ones launch Steam Link etc.)
I realize that this might be a case of "simplify by limiting use cases" but I made it for me so it's fine.
I would like you to release this please
I generally very much dislike dynamic languages but for some reason I've always really liked Lua. I'm not exactly sure why to be honest.
Maybe because you can fit the whole language spec on a single sheet of paper and adding more advanced features is pretty easy.
Love looks really cool. I never got into it personally but I still might
The Lua source code is also a masterclass in C, I recommend it to anyone learning that language. It's big enough to be an involved implementation, but small and focused and well-organized enough to (at least roughly) understand what's going on at the various layers. It's a very solidly-written mass of portable C, with only minor exceptions.
Oh I hadn't considered looking at the source but considering how minimal and clean Lua is I should have assumed so :)
Thanks for the tip. That should make for a fun weekend
I know it’s bikeshedding and leads to pointless discussions, but in my opinion Lua would be the perfect scripting language if it had 0-based indexing.
“It makes more sense this way” is not a good enough reason to break convention.
Pardon my ignorance. But in many languages that have alternative ways of iterating you tend to user indexes less and less. Isn't that true in Lua?
Sometimes I feel like I'm the only person in the world who does not care about zero-indexed VS one-indexed. It's just the way Lua is, no big deal. Then again, I don't care about significant whitespace either. Maybe I'm just weird.
There is nothing stopping you from doing someArray[0] = "the first item", you know.
For me, the table is extremely powerful. I like it that it can be used as a sparse array, a hash, a vector, whatever. Of course one must know, at heart, the difference between pairs() and ipairs() and what it means for your data, though ..
> For me, the table is extremely powerful. I like it that it can be used as a sparse array, a hash, a vector, whatever. Of course one must know, at heart, the difference between pairs() and ipairs() and what it means for your data, though ..
So, as someone only very peripherally familiar with Lua, can someone please explain the table thing to me? I've heard Lua fans gush that Lua is tables all the way down, except it seems like there's these tables on the one hand that work like arrays, and those other tables on the other hand that work like objects, and you can't mix them up...
Is that not just an ordinary dynamically typed language with arrays and objects then, except it overloads the word "table" to refer to both?
I'm sure I'm missing something, happy to hear what that is.
It's not really tables all the way down - Lua has datatypes like nil, boolean, number, string, table, userdata + lightuserdata, functions, coroutines. I think that's the entire list, actually.
So a table is a hashtable. Just about anything can be a key to the hash - a number, a string, a boolean, another table, a userdata. I can't recall if functions and coroutines can be keys but I suspect they could. I definitely know that nil can't be an index.
In Lua - all iterators are implemented as a function + state + current key. When you write "for x in (whatever)", that (whatever) is really a function call like func(state,key). Lua calls it repeatedly to traverse the loop.
Lua will take the first returned value and use it as the new key in the next call to func(). Once the function returns nil as the first value (or just returns no values) - the loop stops.
There are two functions - pairs and ipairs - that really just return the built-in next function with a starting key. pairs returns (lua's next(), the table, nil), and ipairs returns (next(), the table, 0).
(there's a bit more to it than that and some under-the-hood changes between Lua versions but we'll just go with that explanation).
Lua repeatedly calls that next() function with the table and previous key.
Say you had an array like table like { [1] = some_value, [2] = another_value }.
When you write something like "for i,v in ipairs(a_table)" that roughly expands to:
* pairs() returns next(), the table, 0.
* Lua calls next(table, 0) and next returns (1, some_value)
* Lua calls next(table, 1) and next returns (2, another_value)
* Lua calls next(table, 2) and next returns nil.
So - when is a table an array?When you can iterate through it with sequential, integer keys.
Note - you don't necessarily need to use ipairs to iterate. Lua also has a numerical "for" loop so you could do that. Or - if you want to start your arrays at 0 instead of one you can write your own ipairs() like function in just a few lines of code. Observe:
local zpair_it = function(table, key)
key = key + 1
if table[key] then
return key, table[key]
end
end
local zpairs = function(table)
return zpair_it, table, -1
end
local tab = { [0] = 'yay', [1] = 'huzzah' }
for i,v in zpairs(tab) do
print(i,v)
end
There - now instead of using ipairs(), you can use zpairs() with zero-based indexes.As far as using like objects, that's getting into metatables and stuff but - basically lua has a syntactical sugar to make object-orientation nice.
If you write "obj:func()" - that's the same as writing "obj.func(obj)" - assuming "obj" is a table, Lua will fetch the "func" key from the table, then call it as a function with "obj" as the first argument (this can be referred to as self within your function definition).
If Lua tries to fetch "func" from your table and it doesn't exist - it will check to see if your table has a metatable defined with an __index metamethod (or table) and pull func from that. So - your table could just have your object's actual state data on it, and functions are referenced in a separate metatable.
Observe:
local dog_methods = {
bark = function(self)
print("bark bark I'm a",self.breed)
end
}
local dog_metatable = {
__index = dog_methods
}
local huskie = setmetatable({
breed = 'huskie'
}, dog_metatable)
local collie = setmetatable({
breed = 'collie'
}, dog_metatable)
huskie:bark()
collie:bark()
huskie:bark() is equivlanet to huskie.bark(huskie). bark doesn't actually exist on huskie, but huskie has a metatable with an __index table where bark is defined. So the function call is really more like dog_methods.bark(huskie).Anyways wow that was a lot. Highly recommend going through the Lua manual. It's not a long read.
Tables are kinda-sorta hashes that can hold anything, not unlike JavaScript objects. The array use case is just a table with automatically assigned numeric keys.
> There is nothing stopping you from doing someArray[0] = "the first item", you know.
Yes, there is:
local l = {[0] = 'a', [1] = 'b', [2] = 'c'}
for i, c in ipairs(l) do
print(i, c)
end
This will only print the last two pairs. Lua is 1-indexed, end of story. You can store values at index zero, but it's no different than storing values at index -1 or index 'lolrofl'. It does not exist in the array-part of the table as far as Lua is concerned.If you're going to use a table as an array, use it as an array:
local l = {[0] = 'a', [1] = 'b', [2] = 'c'}
for i = 0,#l do
print(l[i])
end
.. prints:
a
b
c
Lua haters usually don't get past their misunderstanding of tables, but its really quite unfair on the language and those who have used it quite well to do big things ..I've always assumed that there is some technical reason for Lua being 1 indexed, rather than it being a design choice.
Either way, I think it's a nitpick to complain about. I've written a decent amount of Lua and there's only been a handful of times where 1-indexing was even relevant to me.
It's a design choice. Lua was first intended to be a configuration language for engineers to enter data at an oil company. They were used to the 1st thing being number 1, the 2nd thing being number 2, and so forth. It's just a very natural way of counting.
You don't change something like that because it eventually got picked up by game programmers (never the intent of Lua, something that just happened after it was used by the Grim Fandango team, then it took off in the gaming world).
Lua will forever hold a special place in my heart. It was the first programming language that I actually managed to learn, instead of just attempting to learn it.
It was chosen around 2008 or so to be the scripting language in Multi Theft Auto: San Andreas.
We build entire worlds in Lua, there were many gamemodes, but my favorite was Roleplay.
Good old carefree times.
exactly, the simplicity is its beauty!
A single data structure (tables), no built in OOP (you build it with metatables).
Coroutines instead of threads.
I was curious and explored it in detail here - https://vectree.io/c/lua-language-design-metatables-coroutin...
It has a very lego-like feeling, with simple, orthogonal design that lets you build the language and constructs you need. Very elegant.
Because Lua is simple and elegant — like the moon, isn’t it?
Lua is a scripting language done right.
It doesn’t pretend to be more than it is. Anyone can learn it a couple of sessions. It has all the stuff you need to write a program.
Imagine if we had Lua instead of JS in the browser.
In fact the latter was once closer to Lua, but didn’t have the same philosophy of wanting to stay minimal.
my favorite game in love: mario, with portals
I looove stabyourself. ortho robot was amazing. you know what, let me install again.. here goes my night.
I like the Trosh game
Agreed, mari0 is awesome.
Pity it's not playable in even mildly current versions of love because being backwards compatible takes some slight effort on behalf of framework maintainers.
How have they not been sued by Nintendo yet?
Same reason all the other mario flash games haven't, not a critical enough mass.
Yeah this is amazing. I'd love to see integration with raylib at some point, if possible that is.
Lua's small footprint is it's one big advantage in addition to its pleasent syntax but with tiny cc (which raylib supports when I last checked a few years ago) you can get a compact c runtime as well.
I haven't worked on a project with either of these frameworks but a couple of years back I was researching into some frameworks and was surprised to learn that I can use raylib on my phone with termux!
Tiny CC doesn't have its own runtime, it uses whatever you specify (falling back to system standard), same as GCC or Clang. For low runtime footprint you are probably better off with one of those two compilers as they generate smaller, more optimised code.
Lua is very fast - even without the JIT it makes Python feel like wading through molasses.
Lua is so small and simple (but not simplistic) that you can keep it completely in your head. Even if you only get to work on your project once every weekend you won’t have to relearn half of it every time.
My2c. Fintech tech lead who has only a far memory of hand coding games ages ago. Community makes tech awesome. Love2D discord changed my life. Never met a more awesome and welcoming community in my whole life.
Btw, Love2D is based on SDL2. If you hate Lua but needs the same cross-platform capabilities, you can use an SDL2 binding in other languages or make your own.
It seems to have updated to SDL3 - https://github.com/love2d/love/blob/main/CMakeLists.txt#L178
SDL3 should get more love in general.
The SDL3 GPU API[1] provided a cross-platform GPU API even before WebGPU.
In Rust it's a good alternative for winit/wgpu. For that reason I added it to areweguiyet.com[2] last week, where apparently it wasn't even listed before.
I am currently using it to develop a space game[3] inspired by the original BBC Elite. Using emscripten to get on the web and QUIC/Webtransport for networking.
[1]: https://wiki.libsdl.org/SDL3/CategoryGPU
[2]: https://areweguiyet.com/#ecosystem
[3]: https://git.levitati.ng/LevitatingBusinessMan/elite/src/bran...
SDL3 is something I've been keeping an eye on, but at least one thing that held me back from diving into it was SDL_Mixer (audio library) was not updated to a release version for SDL3 until I think a month ago? I need to get back to it but lately I've been messing with SDL2 + wasm stuff using emscripten.
SDL3 doesn't support bindless resources and the plans to do so in the future are very loose[1].
[1] https://github.com/libsdl-org/SDL/issues/11148#issuecomment-...
There is a lot more that goes into Love2D than just SDL. It uses many other libraries for sound, image loading, etc as well as using luajit so that the lua runs very fast and has a super easy C FFI.
But SDL already provides an API for all the things you listed. So I am assuming the libraries in Love2D still call those underlying SDL APIs right?
Love2D uses openAL for audio, FreeType 2 for fonts, DevIL for image loading and Box2D for physics. It can also use image fonts. It uses luasocket for networking and has a compression API built in.
On top of that there are love2d specific libraries people have written to deal with 2D games like GUIs and tile libraries.
Then there is the ease of debugging, where you can use lua to have runtime access to the table of variables and can print them on screen if you need to, not to mention dynamically loading new update and draw and input functions.
This is all to say that just downloading SDL is not going to get anywhere close to what love2d has included.
Cool stuff!
Now why would you hate lua of all things?
For all the reasons, but the 1-based index alone makes me uncomfortable.
1-based indexing is great. It's just _different_ - from C, where the array index is just sugar for pointer arithmetic, and from other languages which borrowed the practice without reasoning.
There are arguments for why 0-based indexing is _better_, unrelated to pointer arithmetic. https://www.cs.utexas.edu/~EWD/transcriptions/EWD08xx/EWD831...
> we had better regard —after all those centuries!— zero as a most natural number
Of course, a counter argument is that we've already made the mistake of indexing with 1 in natural language (first, second, ...). That decision is not free of annoyances, though: the 19th century are year numbers 18xx, floors below the first have a varying names when they could have been negative numbers, etc.
That EWD is one if my pet peeves. Dijkstra makes an unfair comparison because he lists plenty of examples where 0-based indexing is more convenient but ignores the equally numerous situations where 1-based is more convenient. For example, iterating backwards over an array is much better in an 1-based world.
I like the argument that 1-based is better for indexing and 0-based is better for offsets: https://hisham.hm/2021/01/18/again-on-0-based-vs-1-based-ind...
To be honest, I actually agree that Dijkstra's argument seem a bit one sided. It's also interesting to see the argument in your linked article that offset and index doesn't have to be the same.
If I get the root of the argument in the linked article, it is that zero-based indexing is more of a optimization than anything, but I would disagree; there are reasons beyond that (see the examples in my previous comment).
Also, here's an example of an 1-index based system that has caused me some headaches: In music theory, the first note of the scale is called the "first", etc. It also talks about e.g. "stacking thirds", which means take the third of the scale, than take the third from there. However, the offsets are two. (first=offset 0, second=offset 1, third=offset 2). Which is hard to work with in my opinion.
You have an interesting argument about iterating backwards, although I would say; if we need a tie-breaker between the two, iterating forward should have more weight than backwards.
I appreciate your comment, and while trying as best I can to be convinced of the "other side", I still land on 0-indexing. The only argument I buy, is that it matches our natural language starting at 1. Which, of course, is a strong argument.
The reasoning is to be consistent with C and it's more than enough reasoning for me. I don't know if 1-based indexing is fundamentally better. However, I know the probability that I will need to use other languages in the future is 100%, and they'll use 0-based index.
It's like right-click-to-select.
In many aspects, Lua is more verbose and awkward than other similar languages. Compare
local alive_enemies = {}
for _, enemy in ipairs(enemies) do
if not enemy.dead then
table.insert(alive_enemies, enemy)
end
end
enemies = alive_enemies
with enemies = enemies.filter(enemy => enemy.alive)It's more minimalistic, that's true. But there's nothing stopping you writing or downloading an array library so you can do this:
enemies = array.filter(enemies, function(e) return e.alive end)
Or even setting a metatable so you can do: enemies = enemies.filter(function(e) return e.alive end)Due to the embedded nature of Lua, it’s often impossible or difficult to use libraries. And I don’t want to reimplement basic functionality every time I start a new project.
That seems like a contextual problem, not a Lua problem.
If you're in Love and/or control the environment you're free to bring in whatever libraries you want. Or to build your wrapper to support multiple files from the user.
Like you could suffer from a bad embedded scripting setup with any language. Granted if it was embedded Python or Javascript you would get a bit more for builtin if they embed a full implementation. But also embedding Lua with support for user supplied libraries is less effort than embedding a whole Python/JS runtime
> Due to the embedded nature of Lua, it’s often impossible or difficult to use libraries.
Last time I used LÖVE that wasn't the case, nor does it seem to be the case today, you can require libraries or even use LuaRocks if that is what you prefer, and everything just works.
well, it is true that the second one is more concise.
The only difference is that one of the language is embedded and barely takes any place. it's just a few C files :-D It offers just enough functionality while not making it overly complicated to make basic things.
The other one is way way bigger. and even Array.filter didn't exist from the start
Alright, here is Janet, which is designed to be embeddable just like Lua:
(set enemies (filter |($ :alive) enemies))
Though JavaScript has QuickJS, which is also lightweight.Small stdlib, “implement it yourself” philosophy to even things like classes, diverging language versions and fragmentation (a lot of people don’t like any of the post 5.1 changes), bad tooling and editor support, dynamic duck typed language with no type hints
If it were about making a choice of which web framework to use on the server, obviously you wouldn't want to use Lua.
But if it is about using it as an embedded language. you want just enough language to get you started and be able to tweak controls. so that the embedded language itself doesn't take up unnecessary space, on its own.
It's a design choice to have a language as small as possible while still offering cool tools.
I don't necessarily hate Lua, but I prefer C and Raylib for game dev. Lua is garbage collected, dynamically typed, strays far from standard syntax patterns, and has less existing tooling than C.
I see why people might hate Lua. Especially for game dev!
Luajit is often faster than C. The qualities you described above actually make it great for game dev.
A JIT is a double edged sword, it _can_ make your code faster, i remember in the early days of smartphone gaming, developers often had to manually "warm up" the JIT to prevent stutters during gameplay
It still is an issue nowadays https://discussions.unity.com/t/app-needs-warmup-first-slow-...
Similar story with the GC, it's nice to have, until it causes you problems (wich it will), so you end up having to avoid using it and instead rely on manual techniques
JIT and GC aren't the panacea people make them out to be
True using a JIT without understanding it is not a panacea. Same as a GC. Same as malloc and free (you're often much better off with arena allocators).
Most JITs let you tune when and how they inline. It's also worth knowing how they works and what they can/can't inline.
You linked to monojit. Luajit is a whole other beast. I'd argue it's superior to anything in JS/JAVA/C# land (and I say that as someone with a reasonable understanding of the JVMs C2 JIT).
As an aside with low latency GCs like the JVM's ZGC trading manual memory management for no memory related security vulnerabilities is pretty appealing.
Like everything in programming it's a trade off.
Lua is extremely popular for game dev though?
SDL3
Definitely SDL2.
Author is currently building version 12 which will be using SDL3. But it's been in development for quite some time with no clear end date afaik.
Who is "the author" these days? Is it Slime? I wonder what Rude and Bartbes and vrld are up to these days. Are releases still done on holidays? Are all libraries still named after sex themes? I was active for versions 0.4 - 0.6.
It is easy to get Lua (with LuaJIT) working with SDL3, though.
That obviously isn't a replacement for the framework but it is perfectly doable if someone just wants to write a game in Lua with minimal overhead.
Edit: I mention LuaJIT specifically because it lets you create metaclasses around C objects, which is much easier than messing with the Lua stack from C, and it's easy to make a 2d vector class from an SDL Point or a spritesheet or what have you. There are a few rough edges like dealing with pointers and gc but to me it's the best of both worlds (the speed of C, and some implicit type checking, and the flexibility of Lua.)
Obviously you could do it the hard way and the other way around with normal modern Lua but it's such a pain in the ass.
I stand corrected!
As far as I know only the latest (unstable) version uses SDL3.
If, like me, you have too much "P5 api" muscle memory to really get into LÖVE (not a criticism of that library, tbc), then L5 might be a nice alternative:
I love löve I did some projects in it, lua was one of my fist programming language, i think it's a great fit for game dev.
Also move or die is running on love2d, which is an awesome game.
Also I love that trick that you can just zip your files and binary Comcast them to the love2d binary and it will load it.
Someone should make a framework like this but with static typing and manual memory management. If you want a modable game you really need to have it in a managed language, and I spent enough time fighting with garbage collectors that it's just a non-starter. A shame because Love is really nice to use.
> If you want a modable game you really need to have it in a managed language
... Why is that? Personally, both as a game developer and modder, dynamic languages like Lua and alike tend to be a lot easier to make moddable and also force in mods regardless of how the authors felt about modding in the first place. Isn't it quite the opposite?
It also happens to be one of the better ways to do a GUI in Lua :P
Am I really the first one to mention pico8 in this thread? Anyway, pico8 is another option that has a bit different spin, but you also implement the games in Lua :)
TIC-80 is a nice free as in freedom alternative to PICO-8, and it allows more inputs, which makes for better Tetris games (gotta have that hold piece).
TIC-80 is wonderful to play in. Besides being free/open, another advantage over PICO-8 is TIC-80 has native support for Fennel. i.e. you can code within the system editor in Lua OR Fennel (or half a dozen other languages!) You don't have to edit and transpile to Lua on the desktop as you would with PICO-8. This has some value in debugging with error messages and line numbers.
It's also just plain cool to rock the TIC-80 editor fullscreen with narrow font, coding natively in Lisp and publishing the result to a webpage you can share.
I wish the iOS (app) deployment story was a little smoother for TIC-80.
Wait really? I looked into tic80 a while ago and I know it had native support for moon script, but I had to play with it to get fennel to work
TIC-80 is great indeed, I had even ore fu with it than with PICO-8 and that's a high bar.
But there is one gripe -- when packaging apps into executable, TIC-80 pulls templates from the Internet.
On one hand, it's not that big deal, we are online basically all time nowadays. But on the other hand, I would expect that kind of software to be self-contained.
I found a quite simple (but definitely not frictionless) workaround though - you can build the templates yourself, edit source code to work with localhost instead of TIC website, and host the templates on local webserver.
As I said, it's not a frictionless solution, but I don't know C well enough to make more substantial changes to this behaviour.
I'm planning on doing a TIC-80 implementation as one of the first major pieces of software on an OS I plan on working on (I've already designed the OS on paper, I just need to actually do the hard part (actually implementing it))
Is this about Master of Blocks?
There are a lot of free-as-in-freedom alternatives to (and clones of) PICO-8, but TIC-80 is indeed the most popular one, by far. And popularity is important for any software ecosystem. I really like that it supports other languages, even if that kinda inhibits its ability to be embedded into small hardware.
Apparently the nightly release supports DCPM samples now. Dunno why.
It's just that pico8 has much larger ecosystem. There's a new great game almost every day. It is sort of annoying that it's not FOSS, but on the other hand the team/author has sustainable business.
antirez' LOAD81 never gets enough love in these discussions even though it is simply awesome:
https://github.com/antirez/load81
Anyone looking at Lua/SDL/game engines would learn a lot from antirez' fun little afternoon project ..
People talk about the stuff they use, and there are _a lot_ of fantasy consoles.
As long as we're doing mentions, here's a reminder. If you bought the racial equality bundle in itch.io you already own pico8. You can download the latest version right now on itch.io.
(It is neither open source nor free)
I ported my favorite pre-2000 game into LÖVE -- was easy and fun
Gravity Wars - turn based artillery game in space (planets' gravity affect shot path)
I’m a big fan of Love2D as well. it’s simple, efficient, and really easy to get productive with. After just a short learning period, I was able to ship my first indie game on Steam, a small Chinese‑character puzzle game built entirely with Love2D. https://store.steampowered.com/app/4218330/WordJoy/
Fennel is really cool! And you can write games in it :) https://fennel-lang.org/
they include a LÖVE demo in their documentation: https://dev.fennel-lang.org/wiki/CookbookPong
Was going to post a link to the minimal template for setting up Löve2D with Fennel, that I can really recommend, and found this recent article describing that...
https://itch.io/jam/love2d-jam-2026/topic/6082771/how-to-get...
... posted in the site of the 2026 Löve2D Game Jam, that sounds like something also worth mentioning: https://itch.io/jam/love2d-jam-2026
Too late to enter. Jam was last month. But there are 47 games to check out there, plus many from previous years.
The website might have been better, in the submission https://love2d.org
For anyone looking to code LÖVE2D games directly on an iOS device, I’ve created an app called love2d-studio: https://marknoteapp.com/love2d-studio
As someone that used to write 2D games with things like phaserjs, sdl and even directx7, I always regret I never tried Löve2d. I think Android and iOS packaging was also supported. Is this still the case? What if one wants to integrate IAP?
Pretty sure there is still app packaging documented somewhere. There is also, at least for Android, an official Löve2D Launcher app that can open any love-file saved to the phone and execute it. I use that all the time.
The Launcher is available also for old Android versions, which means that old obsolete Android devices (I have some tablets and phones) can be used for whatever it can be fun to still write some GUI for on some spare touchscreen device.
I use this framework to build prototype applications and it's always a delight. Something about Lua just feels right. Once I'm satisfied with a demo or prototype, I later on port it to native C/C++ implementation.
I love this framework, pun intended. I made a clone of Atari's Missile Command with it many years ago when the Portal / Mario mashup game made with LÖVE was popular. https://github.com/chadpaulson/missile-command
LÖVE seems amazing, I’ve always looked at it with curiosity. There’s also the legendary Harvard CS50’s Introduction to 2D Game Development, which now uses it in its latest version.
But I’m wondering: why do mature tools like this sometimes end up on Hacker News’ front page without any particular news (like new releases or updates)? It’s just a curiosity, not a critique.
Interesting this is at the top of hacker news since this is pretty old, great project though
Could have compiled it to wasm and have an online demo
I've used this for many projects that are still working to this day.
That said, i'm not impressed. A web-based solution is usually better performing, despite all the bloatware necessary. This says a lot about the state of software development unfortunately.
I'm curious as to how you came to that conclusion. Did you run any tests, or is it just a general observation? What's your computer hardware like? This isn't an accusation of anything, I promise I'm genuinely curious.
I've not done proper scientific comparisons, but had to reimplement some games as websites to make them reliably perform on Raspberry Pi's we used embedded.
This is a bit of an apples to oranges scenario, because the algorithm and architecture is not exactly the same, despite the game functioning identical.
The main weak points of LÖVE that we hit were mainly around embedded video playback though, which is probably very well optimized in chromium.
I dunno if this is what you were seeing, but LuaJIT has some serious performance issues on ARM.
https://love2d.org/forums/viewtopic.php?t=94760
It's unfortunate as Love2D is generally VERY snappy on x86. I used it on a 300MHz laptop back in the day.
I don’t usually push LÖVE to its limits because I tend to make simple games as a hobby but I do keep an eye on its framerate and often it‘s in the 100s of frames per second. So it may not be impressive (in sense of winning benchmarks) but it’s rarely perceivably slow.
It isn't web based? It's a set of Lua scripts that run locally
They are saying web based solutions often out perform LÖVE, even though you would expect the opposite because LÖVE doesn't have the bloat of a browser engine.
Browser engines are probably some of the most optimized pieces of software in existence, so it doesn't surprise me at all.
Optimized abstraction layer is still an abstraction layer. The web is like two or three of those.
Love2D uses Luajit and directly calls established game libraries. The CPU usage should be far better for 2D games, luajit is faster than a browser's javascript jit. You can also create single exe games that are a few megabytes and not a few hundred megabytes.
Explain this to electron haters.
step 1 htop
there isnt step 2, explain is over
Browser engines are optimized for displaying web pages, not for applications.
60MB+ for a calculator is not optimal.
explain that to my webgl TypeScript browser game running at 180+ FPS while rendering a large RPG tiled world with infinite procedurally JIT generated biomes, with heavy processing delegated to webworkers.
As you aren't posting code or stats I can't say much, but I'd bet a native app would still be smaller and more efficient, since you have to wrap what you're doing in an entire Chromium instance and deal with a web stack designed for documents, which is definitionally less efficient than a native alternative. Tiles aren't exactly cutting edge technology.
"Heavy processing delegated to webworkers?" That just sounds like threads but worse.
yep, native is faster for sure.
but webgl + web workers is good enough these days.
I can't share code sorry, the project got big and I have commercial plans.
But you can tell Gemini 3.1, Opus 4.6 or GPT 5.4 High to generate a demo and they do a decent job most of the times.
that's how I got started, seeing how it was possible to have good game performance with multi threaded workloads on a browser.
Nobody ever said in the thread that web is the most efficient platform, stop with your “designed for documents” trauma already.
Meanwhile that same computer could probably run Counter Strike at 400 FPS.
Is Love2D a decent option for gamedev compared to Godot? I finished a really simple game using Unity3D and it was fun, but it sucks to use a closed source engine.
Godot will be familiar to you if you then.
Löve on the other hand is 100% just code. You'll not have the gui things and the pletora of different components that go with them. Still gives you freedom. Just too much freedom and not as much helpful preset tools.
For me this is a plus. All the games I've made are small and hobby stuff, and I much prefer writing code to playing around with a UI.
Yeah, Love2d is a great option for gamedev. It doesn't have the same built-in tools as Godot so you'll need something else for putting together maps (use Tiled [1]), and you'll need to write your own main/render loops (these are just two for loops, nothing fancy).
It’s very different, and it depends what you are targeting. I love love2d.
I think love2d is better if what you love is coding, everything is code, love2d just executes Lua.
If what someone wants to do is make (for example) a 2d platformer, or definately for 3d, and the coding is something you need to do to make your game, goody is better, it includes so many batteries, have a built in gui level editor, etc.
One big advantage of love2d (although ironically not loved by many in its audience) is it is the AI friendly engine, as AIs love text and hate GUIs.
Still think Gideros SDK had more potential
I wish lua would be more popular outside of its scripting language bubble, but its tendency to occasionally introduce breaking changes every release doesn't makes it very palatable as a main language for writting software.
I need something like this but for cross platform utilities
I haven't done it myself, using game engines as UI frameworks is not unheard of :)
Interesting. I started playing with Godot this weekend and got something simple to render with some toolbar windows and a statusbar. I’ve always been fascinated by game and graphics programming.
UXN can be interesting for 2D games too.
I love their stuff, but curious if anyone besides them actually use uxn to make stuff
The fantasy computer by 100 rabbits? I love their philosophy, I'm glad Varvara exists, but I'm personally not up to program assembly for a 4-color screen, and I'm sure many others are the same.
I think there's a difference in the want of a game dev. 100r, IMHO, is about code as art rather than using code to make art.
How is it supposed to be pronounced? Is it just gratuitous diacritics? Or should I pronounce it in my native Swedish (where the names makes me think of leaves rather than love)?
(Throwing diacritics on English words look extremely silly to me, since I know how åäö are supposed to be pronounced. It makes something like Motorhead just sound laughable rather than metal.)
The project was started by Norwegians. So I feel like you should apply juuuust the right amount of cheesiness and sort of push that Ø-vowel looong. Not sure if Ruud would agree, though.
I am fairly certain it's a case of https://en.wikipedia.org/wiki/Metal_umlaut
I instinctively pronounce it [løv].
What about the e? If it was Swedish you would definitely not have a silent e, but I don't know if Norwegian might. (On the other hand it is spelled löve, not løve, so arguably Swedish rules should apply.)
I interpret it as English, except with a letter borrowed from other languages.
bluerevolver amazing shmup made with löve.
löve is getting a vulkan backend. I would have prefered löve to be plain and simple C coded instead of this abomination which is c++ (but it seems coding AIs may be very good at assisting mass c++ to plain and simple C port).
Interesting framework :)
I haven't tried Löve, but I somehow enjoyed reading through the README.md, no AI slop, just a natural writing style with tiny indictors showing the authors' enthusiasm in creating software.
The project predates Github, although the first official release came out about a month prior. So, yeah, not a lot of AI slop 20 years ago.