Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Grid – A Lua Game Engine (planimeter.org)
177 points by Bambo on June 7, 2020 | hide | past | favorite | 77 comments


Thank you for posting this, Bambo! I was curious why we were seeing 10s of new stars all of a sudden and trying to figure out where the GitHubbers were coming from.

Grid Engine 9 is now the largest pure-Lua game engine on GitHub. As s_y_n_t_a_x has mentioned in this thread, I built the Grid Engine on top of LÖVE.

I came from the hlcoders world, having used the Source Engine for several years, and was upset the 2D world didn't have sophisticated game engine technology like the 3D solutions in the field.

There's tons of great game software out there! But to me, a game engine isn't just a load, update, draw framework. There's a lot of hard work involved past binding libraries together.

A game engine needs an architecture, it needs to do multiplayer serialization for you, and give you a meaningful way to load maps out-of-the-box, and so much more.

Too many hobbyists are rolling this themselves, and I hope to continue to bring rich game development features OOTB to other hobbyists like myself.

If you're interested in Grid, but don't find something quite right with it, could you tell me? I've worked on this project for at least the past 6 years from what my logs tell me, but it only continues to get better thanks to people like you all reading posts like this and giving me feedback over the years.

Thanks again, Andrew


I also saw this on your repo [1], I was wondering if you are planning to move from Love to it, or what is it about? (just curious :-)

1: https://github.com/Planimeter/lgf


A few casual notes, though I could continue to expand on this:

lgameframework is a project I took on some time ago to provide a LuaJIT FFI alternative to LÖVE. It helped educate me on what was necessary to interact directly with the OpenGL layer, and understand what challenges the LÖVE developers will have in the distant future with OpenGL being deprecated on macOS. (Will they move to bgfx? Or Vulkan/MoltenVK? Who knows. Ask Alex, I suppose.)

As an interesting side note, it does things LÖVE doesn't, which may or may not be interesting depending on whether or not you think first-party 3D features, PBR, VR (See also LÖVR) are desirable in a pure Lua project.

It also serves as a hatch door project I hope I never have to use. Valve broke Source for modders somewhere between the 2007 and 2013 engine branches with SteamPipe, and the idea that you could spend literal years on a project and have some developer break your work in Bellevue was scary to me. They don't have the same respect for the modding community today that they did maybe 15 or so years back. I don't think that's going to change, unfortunately, but I'm digressing.

I trust the LÖVE team, and appreciate that it's FOSS software, but I need full control over the stack I present to developers using the Grid Engine, and I need to respect users by not breaking things.

In the event LÖVE breaks things, the Grid Engine needs to be patched to account for those changes, and Grid has been around long enough to see this happen a small number of times. I think the changes have been reasonable so far, but mature projects will inevitably end up with deprecation notices and backwards compat patches, and that's where we are now.

lgameframework is defensive software, but I'd rather continue to promote LÖVE. The only issue I see with this, and cannot condone however, are the libraries that have come out of the community with inappropriate names.

Edit: I apologize that all of this sounds a bit dark, that's not my intention, but a lot of people's hard work can be at stake. Implementors of such software need to defend their users. The LÖVE developers have created something wonderful, and I must reiterate this.

I plan on Grid being around for years to come, which means you have to start thinking about protecting that mote. Planimeter projects have been in the works since 2010. I work in a narrow subset of the gamedev space, and don't plan on stopping any time soon. It will be my life's work.


Thanks for the extensive answer! It is very commendable that you want to provide such level of stability for your users.

On a side note, your comment made me check: hard to believe Love2d was released 12 years ago now!


Thank you for browsing my work, I greatly appreciate it!


Hey I know you mentioned it here and it is shown on the getting started tutorial, but may be useful to mention it on the front page too: the engine is built upon Love 2D.


Thank you for your comment. I will make sure that I emphasize this in newer marketing collateral.


Would you happen to know of any games that use Grid?

If so, it would be nice to list them on the homepage.


Unfortunately not. I'm always looking to feature game developers on Grid's site, though!


I love the idea of a game engine with multiplayer built in from the start. It reminds me a bit of MUD engines for text-based games back in the day. Interested to see where this goes!


Thank you. I think it's particularly important that features like this come standard these days. In the last two decades a lot of work in client-side prediction has taken place, but not a lot of it has been working itself back to hobbyists.


Would love to get your thoughts on Mun-lang: https://mun-lang.org/


Quite an impressive project! I'm curious how the authors went about their strategy for hot reloading in particular.

In Grid, I extend the package library, and utilize the implementation details of `module` which allow one to override or set new keys on subsequent loads of the same file.

It's one of the reasons I don't think I can use the newer module patterns beyond Lua 5.1.5, because as far as I understand, they require one to completely replace what's stored in `package.loaded` versus merging to any existing table.

I had also not given much thought to static typing with Lua until the last year or so working with Lua only because it makes generating documentation harder. Otherwise, I tend to share Roberto Ierusalimschy's opinions of dynamic typing.

I would read his most recent interview from Moscow in 2019. I think he's a very interesting person.


Why Lua and not say Haxe? Because of LÖVE?


Yes, primarily. But the real answer is because of Lua from Garry's Mod, and the design of the engine is heavily inspired by Source and QuakeWorld. Even today, I still believe Quake is one of the most elegantly designed game codebases in existence.

Planimeter was formerly called Team Sandbox, and we were a group of developers working on a game called Half-Life 2: Sandbox, which was a FOSS alternative to Garry's Mod that stayed Half-Life themed.

The team is comprised of mostly different volunteers now.


Of course it is you!

Astounding work as always. Thanks!


Thank you for the kind words, voppe. :)


Lua is a little confusing language for me because you need to throw out most of the things you know because it has its own way of doing things, it is not necessarily a bad thing but it is confusing. Luckily, it is a very small language so it wouldn't take that long to grasp it all. The most confusing thing was the fact that (almost) everything seems like a hashtable.


Ignoring metatable weirdness, I think "you need to throw out most of what you know" is quite wrong.

The main thing you need to know is that Lua's table type can be numerically iterated between index 1 and the first gap where numeric index has nil value using the ipairs iterator in addition to the non-exclusively-numeric unordered pairs iterator. A common pitfall with sparse tables is that the length shortcut # returns seemingly the wrong result if you aren't aware of that first part.

Most of the difficulty writing in Lua comes from the fact that there's no first class support for OO-style Classes, so you have to fake them, and there's no standard library so you end up reinventing a lot.

But other than that, it's a dead simple language with few features.


Lua's lack of integer support caused me some issues. Using floor() around everything wasn't really an ideal solution and I ended up changing languages for that project.

Metatables are cool, but have some weirdness to them. For OOP i ended up using metatables to make a simple prototype(rather than class) based system, but it was hacky at best.

Tables themselves are pretty awesome and powerful, but I have to admit, working with them gets a bit tiresome in ways working with dedicated arrays and hash maps don't. You have to remember exactly what kind of data is in your tables and looping through them can be a pain.

Overall though, I still love lua, it's the language that helped me 'get' programming and I wouldn't actually appreciate dedicated data structures and typed variables so much if I hadn't had the experience of starting with a more free, loose and simple language like lua. Also, its ability to easily interface with C and be easily embedded has made it appear in so many different and sometimes strange and just downright cool applications.

I've been playing with the solarus engine lately, it uses lua for its scripting, it's the first time I've written any lua in a while, but i've been enjoying it as I rediscover all the little cool things I like about it and i still think it makes a good first or second language for people.

Having the reinvent the wheel isn't necessarily a bad thing when you're learning. That hacky prototype system I made helped me understand OOP far better than just using classes in other languages had. Even if it didn't really work all that well in the end. It really made me appreciate what a built in class system actually gives you.


Integer support was added in Lua 5.3 (released in January 2015). It also added binary operators, rendering the bitop module obsolete.

One thing I never understood is the mania for OO programming---I regularly see people announce Yet Another OO Module for Lua on the mailing list, and I have to ask myself, "Why?" Is OO the only thing taught these days in school? There are other ways of organizing code than OO.


Serious question: How do you organize your data in a semantically meaningful way without something like an object/struct (in a strong type system preferably). I get functional programming and all, but structs just seem like a natural way to organize data.


Structs are a natural way to organize data, but that doesn't necessarily make it "OO". In Lua, a module is typically a table (associative array really) of functions. All of the standard modules that come with Lua are just collections of functions that don't have a concept of "this" (like math or os).

Now, an object in Lua can have functions that assume a "this" parameter (Lua calls it "self") and thus, it can be viewed as an object qua OO, for example, an open file:

    file = io.open("foo.txt","r")
    file:setvbuf('no') -- no buffering
    file:seek('set',10) -- seek to byte 10 in file
    data = file:read(8) -- read 8 bytes
    file:close()        -- close file
but Lua lacks typical OO features like inheritance, a "class" function or method, which are what the OO modules in Lua always add. It's this mentality, that OO is missing if you don't have inheritance.


> Lua can have functions that assume a "this" parameter (Lua calls it "self")

Even Lua's assumed "self" via the thing:funcname(...) call is just a charade and is secretly just thing.funcname(thing, ...). The split between . and : calling, IME as an informal Lua teacher, is confusing to programming newbies when they first encounter it and I kinda wish the language hadn't chosen _that_ as the thing to spend time implementing.


The same is true in C++ and Java, only the "self" argument is completely hidden in that case.


To second the use of structs, mostly this. Typically i use structs for most numeric types or anything that doesn't need a method and classes for any reference type with methods. Though, i'll stick to structs/stack allocated data as much as possible.

I try to make a clear distinction between stack and heap stuff and use one or the other where appropriate.

From lua i moved to D for a lot of my heavier projects. I like the way D separates types and uses appropriate reference and copy semantics. Being able to specifically separate heap and stack data and essentially use structs and classes as either copy or reference data just seems fairly straightforward to me.

A struct is just a bunch of stuff of different types grouped up in memory, while a class is essentially a pointer that can be moved to some places in memory and can point to data or functions, use each appropriately and where necessary.


Object orientation is not really about making use of structs - many (most?) functional languages also use structs; it's just a grouping of related data.

Object-orientation is about grouping together functionality and data. I.e., an object consists of both a struct, and the functions that act on that struct, known as methods.

In OO, your type additionally refers to the functions called on the data, not just on the data. E.g. you might have a car and a boat and they both only have a position and velocity as data, but the boat has a "sink" method the car doesn't.

There are also debates on what qualifies as "true" object orientation. https://stackoverflow.com/questions/250062/what-is-meant-by-...

For games programming in particular, there is a paradigm known as ECS or Entity Component System. (Depending on your view you might call this a sub-paradigm of object orientation, but I think it's much more accurately described as an alternative.) As the Wikipedia article states:

> An entity only consists of an ID and a container of components. The idea is to have no game methods embedded in the entity.

https://en.wikipedia.org/wiki/Entity_component_system

EDIT: There's also the very interesting paradigm that e.g. Julia uses known as "Multiple Dispatch". This is kind of like defining methods on objects, except that the method is defined on a collection of objects instead of a single one.

E.g., in traditional OO, you might have a vehicle#crash method. And it might take another vehicle as argument, e.g. car.crash(truck). But in multiple dispatch you define a function crash that takes in two vehicles, and then depending on the type of the vehicles given, it changes its behaviour so that crash(car, truck) is different from crash(car, car).

In a sense, the function is not thought of as belonging to either the car or the truck, but as belonging to the pair of them, so conceptually this is different to OO.

I'm not particularly familiar with the paradigm so I'm sure I'm not doing it justice, but you can read further on Wikipedia and in the Julia docs, or the given video:

https://en.wikipedia.org/wiki/Multiple_dispatch

https://docs.julialang.org/en/v1/manual/methods/index.html#M...

https://www.youtube.com/watch?v=kc9HwsxE1OY


You talking about Solarus Engine rang a bell for me as I wondered if it had anything to do with Zelda Solarus, a fan game I played fifteen years ago and what introduced me to RPG Maker. And it does ! It's really heart warming to see people follow through with their own projects for so long, Thanks for the throwback !


Solarus is such an interesting engine in that it's almost certainly more powerful than Defold, but its focus on making a Zelda-like game engine probably makes it harder for users to see how it can be reused for other works.


Even the OO shortcomings of Lua aren't very different from the Javascript of the recent past. The two languages are quite similar, save that Lua indices are 1-based and JS comparators are nightmare fuel.

My pet peeve is that it's somewhat verbose in using keywords rather than single-character punctuation to mark blocks and clauses.


This looks interesting but the documentation needs more information.

I dont want to "mess around" for a few days to learn what this thing is good at. I want to read the docs and be ready to make stuff.

eg)

https://www.planimeter.org/grid-sdk/api/networkvar

https://www.planimeter.org/grid-sdk/tutorials/Getting_Starte...


I will prioritize this immediately. I believe one should be able to understand all of the concepts the engine offers within short order, and clearly I need documentation to back that belief.

Everything is there to get started in just minutes, reducing any installation friction typically found with larger game engines, but I agree that documentation should be able to reduce the cognitive friction such that one can get started faster.

Thank you for pointing this out. If you're so inclined, sample game code comes with the engine for the time being to understand how it works. I realize this isn't completely ideal, but feedback like this is critical to the direction I take.


If you're looking for inspiration on how to organize your docs, I found this resource really valuable: https://documentation.divio.com

You can see the documentation system in action in this project: https://www.brachiograph.art

Regarding Grid, personally I always like to look at example applications built with framework/library/engine so seeing a list of projects that utilize Grid would be nice.


Thank you, mmlkrx. I'm focusing on this today and I appreciate your help! I will keep this feedback in mind and emphasize the points you have made.


Thanks for taking my feedback.

I suggest for the Tutorial sectiona that you walk the reader through making the type of game that you think this engine excels at making.

Would also like to know more about the networking capabilities.


I would appreciate more examples on the web site - it seems like there are very, very few details on e.g. capabilities, etc.


I will prioritize this based on your feedback.


That would be awesome, going to tinker with this tomorrow!


Thank you for saying so! I will be available if you need anything at all.


Apparently the developers are reading this thread, so I have a request: Please reduce your website's dependence on javascript. Doesn't leave a great impression when I need to fiddle with noscript before seeing static text.


I would do more of this if I had a simpler way of pulling documentation from the GitHub Wiki repo.

I’m sorry the experience was poor, and I’ll consider this feedback as I make improvements to our documentation and marketing collateral to make it nicer to use. My apologies. I work hard to win over developers, many times one at a time, and so your feedback isn’t lost on me.


any examples of games made with this?


I'm making a mobile mmorpg using this engine.

We're currently in the early spriting & game mechanic planning phases but Grid has been a perfect starting point.

It's the sweet spot in-between LÖVE (Grid extends LÖVE) and a heavier engine like Defold, the multiplayer features are killer.

If you're wanting to make a tile-based multiplayer game, I highly recommend it.


Are you posting anything on GitHub publicly? I'd be interested in seeing some sample code!


Unfortunately, not. Parts of the game I may open-source, but it won't be fully open and it's nowhere near ready.


Url changed from https://github.com/Planimeter/grid-sdk, which points to this.


Why do people use Lua in a world where we have Python?


IMO, these are the main reasons;

1. Embeddability. You can create a game engine in a performant systems language like c++ and embed lua in it for the scripting.

2. Speed. The lua interpreter is much faster than python in general. When you throw luajit into the fix, they are not really comparable at all.

3. simplicity: lua is tiny. and one of the easier languages for non coders (game designers, artists) to get started with.

4. Effortless C interop. You can make lua bindings for anything written in c with minimal effort.

Now to this specific engine. lua has one of the simplest and most beloved game frameworks out there - Love2d. its almost a foundational game framework for so many people (like pygame in python, XNA etc), including yours truly. Its been a beginners choice for over a decade now. Grid is built on top of Love2d.

btw, just in case you are interested in a python game engine, you should try out Arcade. Its pretty feature rich and aimed at beginners.


To be clear: Python does have embeddability, but it is orders of magnitude more complicated to integrate.


Hehe, hence the word "embeddability" instead of "embeddable".


Oh yes. I used that word very precisely :D


I was half asleep when typing that comment, sorry. Too late do edit now. I meant to write:

"I believe that word was used very precisely"


To add to this, Lua has a thread-safe interpreter, which allows running multiple Lua threads in the same process. This contrasts with Python's GIL.


You could make the same 4 points about Pawn, I don't know why nobody uses it. Pawn has all of lua's strengths without any of its quirks and weaknesses.


Some reasons I might not use Pawn:

The only benchmarks I could find claims that it is significantly slower than Luajit. The official docs claim that the fastest implementation is available on fewer platforms than Luajit.

Regarding the lack of structs, the official docs say "pawn has no "struct"s, but it extends arrays so that it can mimic light-weight structures with arrays; as an example of those extensions, pawn supports array assignment and array indices can be assigned an individual "identify" (or "purpose") and even form a sub-array." but the manual's mentions of array assignment make it seem like that's just memcpy. One could imagine having bullet objects and declaring BULLET_X=0, BULLET_Y=1, BULLET_SPRITE_IDX=2, and so on, just so that when one has a bullet object and they would like to draw it at the right location they could avoid writing draw(b[2], b[0], b[1]). Having an array of untyped cells and memcpy isn't really the same as having a struct with named members. Please correct me if I'm wrong.

A lot of useful patterns become less possible when one does not have a map or set type and when one does not have coroutines. It seems like instead of coroutines Pawn includes a syntactic sugar for a switch statement that depends on a single global state variable, in which the cases can be declared like functions. This is interesting but not particularly helpful. Why can one not have multiple different state machines, multiple instances of a state machine, and so on?


Because Lua is much simpler than Python, but not in a way that makes it less powerful. You can grasp the entirety of Lua in your head, with all its semantics and behaviour, which is less easily done with Python (in my opinion).


LuaJIT is much faster than Python, directly interfaces with C, incredibly small,and the language itself is very simple. This is also built on top of LOVE2D which is written in Lua and is arguably one of the best game frameworks out there.


just a minor nitpick: LOVE2D is written in C++ :-)


Seriously asking or just trolling? This statement could be made for almost any language. Why did we start with Python when there was Perl? Why did we start with Perl when we could use shell and awk? Why did we start writing something like awk when we could just have dedicated C programs? Why C when we had BCPL/Algol? Why Algol when we had... okay, granted, there's a limit.

Regarding the specifics: Lua is very simple, you can keep the whole language in your head easily, the table mechanism is very powerful, and the whole thing is easy to embed. Which is why it was used in commercial games and thus is industry/genre-relevant.


Does Python have any good game engines? PyGame project is a nightmare.

Lua's https://love2d.org/ is amazing.


Grid appears to be based on LOVE: https://www.planimeter.org/grid-sdk/api/Game_Loop


They are not comparable with Pygame, but easier for beginners:

https://pygame-zero.readthedocs.io

https://github.com/mjbrusso/game2dboard

Disclosure: I am the author of game2dboard


I recently found https://arcade.academy/ Haven't used it myself but it looks feature rich and has an active community.


Arcade is pretty nice. It's what pygame should be, at least in terms of installability.

https://arcade.academy/


I'm curious as to what you found nightmareish about Pygame... It's SDL.


Years of being extremely difficult to run on a Mac (no pip install), horrible website update (the old one was bad, but at least it was cool & functional), and on-going issues like this: https://github.com/pygame/pygame/issues/555

There's not even a note on the website that it's entirely broken in Mojave. It's just _always_ something.

Compared to LOVE and numerous other projects which just worked right out of the box. I'm a total Python guy, but Pygame has always been frustrating.


Fair enough. Though I have similar complaints about other packages on mac (Python and Ruby MySQL packages being good examples.)


Lua has significantly better performance than Python, but the big reason is that Lua has a very nice C/C++ API that makes it easy to integrate with other programs. Combined with a 20k LoC source code, and you have a programming language that is cheap and easy to embed, fast, and simple. Batteries are not included, so it’s very light weight.


I'm constantly asking a similar question: Why do people use Python in a world in which we have Lua.

Never gotten a satisfactory answer.


Ease of embedding has been pointed out.

Another reason for using Lua in games is that its garbage collection strategy is well-suited for the task.

Python uses reference counting (which has a predictable performance profile but can lead to long pauses if a large object graph is deallocated at once) and stop-the-world GC for reference cycles.


Have you ever tried to embed a python interpreter?

Lua is both easier to embed and allows you to have a strict interface. Look up the history of bastion/rexec in Python - with python there's no possibility of controlling untrusted code.


I liked the speed and the power of tables. It's also an incredibly simple language. I learned the ins and outs in a couple of days and was able to get right to work on making a game. Almost never did I have to reference documentation after that--it all fit in my head without even really trying to memorize it. Python, on the other hand, has loads of features, but that results in me often looking up the right way to do something since there are so many layers to it. What Lua provides is rather bare, yet powerful and incredibly easy to jump right into.


Lua is very easy to parse fast in a way python isn’t. It makes it adaptable to embedding, JIT and other optimizations.

The cost is a less elegant syntax. I understand a lot of folks hate working with Lua, but it fits a certain niche.


Hi Kataphract,

Much like many people turn to Python for scientific scripting, for example, Lua has gained a reputation for being easy to use in the game development world.


I am not sure this is not a trolling attempt.


I like how that comment has more responses than the OP


For the record, Grid is also a racing game https://www.codemasters.com/game/grid/




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: