2019-04-08 02:46:07

Hey, thought I'd share this with folks looking for a great, easy way to build audio games that can run on every mainstream desktop and mobile platform:

https://www.love2d.org is a Lua-based 2-D game engine that runs on Linux, Windows, MacOS, iOS, Android, and the browser via Web Assembly. It's essentially a Lua interpreter with audio, networking, physics, graphics, input, and more libraries linked into a single binary. Distribution is as easy as zipping up your game and assets into a single file and either distributing that file as is, or concatenating it onto the platform-specific executable and packaging that however you like. It ships the LuaJIT interpreter by default, meaning you can access C libraries via Lua's FFI. I used that to put together a simple Speech Dispatcher TTS binding under Linux in about half an hour, and imagine it wouldn't be too difficult to do the same for Tolk/SAPI, which I'll be working on early next week.

Anyhow, I'm not the biggest Lua fan. I'm still tripping over 1-based array indices and a few additional gotchas. But I've been having lots of luck building an audio game in it for the last week or so. I've pulled in a few libraries for math operations, an entity component system, and a GUI. But other than those, I've managed to stick with the APIs Love ships out of the box. It's only 2-D of course, but most of our games are 2-D anyway, and the biggest obstacles to 3-D use are graphical. If you don't mind handling the math and physics yourself, there's no reason you can't represent game objects in 3-D and turn off the physics. Physics uses Box2D, so 3-D realistic physics would require something else.

Anyhow, I thought I'd share this for anyone struggling to put a bunch of pieces together to build a good audio game engine. I'm not going to hand-hold anyone through getting it installed or learning Lua, but I'll probably put together a series of blog posts on how to build a simple audio game with it, and will almost certainly open source at least whatever TTS module I get going. If I or someone else can get it working on MacOS, I don't see why folks couldn't port their Love games to the Mac, though you'd almost certainly want to at least have access to a Mac for testing.

Enjoy.

Thumbs up +4

2019-04-08 04:41:22 (edited by Ethin 2019-04-08 04:41:58)

Speaking of game engines I've been trying to find a good game engine for Rust. I've unfortunately had (literally) no luck in that department in regards to audio libraries; Alto doesn't seem very intuitive and I couldn't figure out how to generate *readable* and *usable* bindings for FMOD. Graphics I already got, but input handling also stumpped me. The same applies to go, as well, which is sad.
Haven't written in Lua in some time. Should probably crack open that book on programming Lua again...

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-08 07:59:46

Hi.
Interesting. Thanks for sharing. I look forward to see your blog posts about the engine.

Best regards SLJ.
If you like the post, then please give it a thumps up.
Feel free to contact me privately if you have something in mind. If you do so, then please send me a mail instead of using the private message on the forum, since I don't check those very often.
Happy gaming... :D

2019-04-08 09:21:39

when i open the thing, there are no buttons to speak of, pressing ctrl n to make a new thing simply doesn't work, or am i missing something like everything's in the alt menus

one day, i will host a road to rage server...
one day, i will have a website with games i learned to code

Thumbs up

2019-04-08 12:38:39

@4 There isn't an interface that I know of. I think launching love without a script just produces a blank screen. Put your game code in a main.lua file, navigate to the directory from a command prompt and run "love .". This will run your game. Alternatively, I think they have a VSCode addon that does this for you, or you can create a task.

Thumbs up

2019-04-08 14:34:55 (edited by CAE_Jones 2019-04-08 14:37:21)

There are some tricks one can do with Box2d to simulate limited 3d, especially if you make the XY plane be the ground and implement your own gravity. Still, it's not so trivial, if that's important.
[edit]Ex, I remember something about collision masks for 2d objects. These use bit-checks, so you can probably puzzle out a way to make these represent z position and size. I think treating the bits as tiles would work, but it's been a long time since I read that section.[/edit]

Some of my games
Keep up to date by following @Jeqofire on twitter!
Ear Ninja?

Thumbs up

2019-04-09 01:45:44

@2 Not sure what you found unintuitive about Alto. I used it to build the audio subsystem for the engine I was originally working with and it was probably the most straight-forward part. smile The most complicated bit was integrating third-party libraries for loading Vorbis, MP3 and wave files, then integrating all of that into Amethyst's asset pipeline.

As for Rust game engines, Amethyst and GGEZ seem to be where most development is happening right now. I was working with Amethyst before I decided last week to invest a week in Love2D, and I was pretty happy with it, but it's an Entity Component System all the way down. So if ECSs aren't your thing, then stay clear of Amethyst.

I personally like the ECS pattern, but Amethyst's implementation was starting to get a bit hairy for me. I had some functions with 14-parameter call signatures so some systems got all the data they needed, and that was just for a simple Asteroids shooter. But Amethyst seems to be where lots of momentum is gathering, and they were much more receptive to game accessibility than the Godot folks were, so if I ever need a Rust engine for whatever reason then I'm likely back to Amethyst.

Thumbs up

2019-04-09 01:56:36

@7, I think its the lack of the documentation, really. Like, the creator gives an overview of how to load it but not how to play sounds, use OpenAL EFX presets, and so on. I'm poking through it, I might have missed something crucial. I haven't heard about GGEZ, though I've checked out Amethyst. It might be me -- I'm a bit rusty on my rust (ha!), and rust can get on your nerves (the borrow checker mainly) but it is an excellent programming language. I have a prototype project (I have a lot of those...) that's written in C++. Its game loop is interesting. I'd be happy to PM you the details -- I'm derailing this topic with my commentaries on my difficulty of rust, so should probably stop with that... heh. Feel free to PM me (or we can get connected on Skype, Signal, etc. and chat about things).

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-09 05:45:09

@nolan, sent you a PM.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-09 07:28:29

This engine sounds really interesting. Let's see how much of the stuff we need will support. Its audio engine seems robust enough, though I can't find a source stereo pan method.

Thumbs up

2019-04-09 14:31:16

@10 Just move the source in 3-D space as if it were stereo (I.e. source.setPosition(1, 0, 0) for right, (-1, 0, 0) for left. Use source.setRelative(true) to make that relative to the listener, which I think by default is at the origin. The audio engine is a thin wrapper over OpenAL.

Over the last week I've ported most of my soon-to-be-released Asteroids shooter over from Rust, so it definitely has what we'd need.

Thumbs up

2019-04-09 17:02:17

@9 Responded. Does this thing not tell you when you get PMs? Insanity. tongue

Thumbs up

2019-04-09 17:54:31

@12, nope, it doesn't. Insanity is what I think all the time too. Rofl

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-09 18:06:25

@12, replied.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-10 06:47:58 (edited by Ethin 2019-04-10 07:16:46)

*NOTE*: this post is subjective. But my point of this post? Don't use LOVE for commercial products! smile Old post is below.

Um... so looking at the way you distribute game executables with Love... are we sure that antivirus programs don't identify this is malicious? Apparently you supposedly create an executable by just appending a .love file (which is just a zip archive) onto the end of love.exe. That's all wonderful and all, but I see two major problems right off the bat:
1. as zip is well-known, its not hard for someone to retrieve the header of a zip file. Knowing that, this makes it possible for someone to, say, extract the .love file from the executable file and then extract the .love file and get the code for the game. This is bad for commercial uses or for storing sensitive information (encryption keys, much?).
2. Is this safe to transport? Do AV programs identify it as malicious? If so, then its pretty much BGT all over again.
Update: Just scanned it with virus total. No engines found it malicious. (Source of analysis: https://www.virustotal.com/#/file-analy … MDg4OQ==). So that's good. But what about the zip extraction? (I'll use Aeternum Blammo for the below demonstration. As noted on the forum post where you can download it, the original developer has no interest (or no time) in maintaining it, and it doesn't even load in LOVE any longer, so it was a good experimental base.) The zip file format has four magic numbers: none, PK\x03\x04, PK\x05\x06 (empty), and PK\x07\x08 (spanned). Using PK\x03\x04, I found the possible location of the .love file at offset 0x5e400. Knowing that offset, all I need do is...
Yep, it worked. So, here's exactly what I did:

d:\>file Aeternum-Blammo_v1.0.exe
Aeternum-Blammo_v1.0.exe; PE32+ executable for MS Windows (GUI) Mono/.Net assembly

d:\>python
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> file=open("Aeternum-Blammo_v1.0.exe", "rb")
>>> data=file.read()
>>> data.find(b"PK\x03\x04")
386048
>>> out=open("out.love", "wb")
>>> out.write(data[0x5e400::])
5780386
>>> out.close()
>>> exit()

d:\>file out.love
out.love; Zip archive data, at least v2.0 to extract

d:\>

And there you go; I have the original source code of the game, all its assets and so on. if there's a way to compile the love lua code into native code, I don't know of it -- please let me know! smile
Some notes about this:
* The file offset is [not] constant. That is, each "executable"-ized game will have a different offset.
* The security for this is sad. Its sadder that you can't compile this to native code. I don't really understand why they couldn't have just used luajit and embedded luac... Maybe that's what lovec is for?
I get the spirit behind LOVE -- to make open-source better (or at least that what it seems to be). But there are much better ways of making an executable for a game than just appending data onto the end of an executable and then saying "hey, its an executable!" because, at the end of the day, its really not. As a poster on this reddit thread says, "LÖVE makes it extremely easy to get started on a project and make rapid progress, which is what makes it so good for game jams and prototyping. But there's a tradeoff: the time you save at the start will come back with a vengeance later." Keep using it if you like, I won't stop you. Hell, I couldn't even if I wanted to. Just pointing out things I think are important (or relevant...)

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-10 07:29:20 (edited by magurp244 2019-04-10 07:31:23)

@15
There's a few posts around [here] that suggest its even easier than that, such as by renaming the *.exe to *.zip and just straight extracting it, unless they patched it since then. There's also some info [here] that mentions compiling into bytecode with luajit, source obfusticators, and compiling into the exe. Its not much more secure than most interpreted languages, or ultimately any source stored locally on the client. Generally though unless networking and or trolling is involved most people skilled enough won't care, and for anything else get a lawyer.

-BrushTone v1.3.3: Accessible Paint Tool
-AudiMesh3D v1.0.0: Accessible 3D Model Viewer

Thumbs up

2019-04-10 07:45:23

@11 you do realize that moving the sound position like x -1 0 0 1 0 0 is not real stereo pan right? this engine uuses 3d positioning, so it's going to use other filters to compensate for y and z position as well. this isn't real stereo pan.

anyway yeah, the security doesn't sound very good for this engine.

Thumbs up

2019-04-10 14:01:23

Fair enough. My attitude is, if that's what folks want to do to save $10 or so, I don't like it but that says more about them than it does me. I'm in my late 30s, and I think about my time differently than I did when I was younger.

Use what works for you. If that's a natively compiled C/C++/Rust engine, great. If that's Love, great. If that's Python and some Python scheme for shipping your code with your game, great. That Python interpreter is going to have to extract your code from somewhere to run it. On Linux, I can probably kill the running game binary and find that Python code in the coredump, or attach GDB to a running process and poke around until I find it. The important thing is that you're spending the time you have in a way commensurate with what you're doing. If using Love means I can sell a game for $10 because I spend less time on it, then I think that's worth it. At the end of the day, I'd rather have *written* a cool game and spend time with others or doing other things, not be writing that game because it takes longer to get it right in native code. And the kind of person who's going to steal something is going to steal something. I live in an apartment that is trivial to break into--hell, I've seen my neighbor pop doors open when someone is locked out and we can't find someone with a keybox key. I just get insurance and try not to worry about it. There's not much else you can do, short of fortifying the building and getting a big dog.

And I *AM* bytecode-compiling the code as well. Not that it's much more of a barrier, but it's something.

And there's one protection scheme I *don't* see people using on these forums to deal with stolen code. Lawyers. If someone decompiles my code just to say they can and save $10, fair enough and to hell with them. If someone recompiles it into a new game and starts distributing it as their own, as I have seen done here, I will get a lawyer to protect my IP, and that lawyer can work with forum administrators if needed to obtain the thief's email address and track that back as far as needed. This would actually not be as challenging for me as one might think--my girlfriend is a paralegal at a law firm with a sliding scale small enterprise legal aid clinic. If someone's piracy is a legitimate threat to my business, and they're blatantly stealing my code and packaging it as their own, they will at least get a C&D, and that's only the first step in the process. How are they distributing it? Let's alert their website provider and cancel their account, or let's shut down their account here so it's harder for them to brag. The letters calling for that won't come from me, but from my lawyer. Sure, it'll cost money, but so is their theft, and having done this for longer means I am not without certain resources.

So, yeah, in short it's about how you value your time. It's also about how you protect your assets if someone's activities represent a legitimate threat. The person who will steal your game will ultimately do so, regardless of what steps you take to protect it. The question is, how much of your time on this earth is that worth guarding against? On my deathbed, I likely *won't* regret not spending more time crafting stronger copy-protection schemes--I suspect not, at least. smile

Thumbs up

2019-04-10 14:37:38 (edited by Ethin 2019-04-10 14:56:15)

@18, fair enough. I just thought I'd point it out since that seemed important for people to know. Ultimately though, your right -- it depends on what time your willing to put into it. I also think it depends on what your planning to do with it in the future, but that's just me.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-10 15:11:18

I also want to release lots of this as open source. Right now I have loosely coupled components for:

* Positioning, rotating, and moving with either simple or physics-based motion.
* Sound system integrated with the above, including setting velocity/rotation/position in sync with the physics engine for entities with a physics-based component attached.
* Relative pitch adjustment based on whether an entity is ahead or behind, settable per entity.
* Raycast-based radar system with physics integration. Cast rays ahead, behind, left and right at a set distance. Get callbacks whenever those rays hit a physics object, and play sounds or perform other actions to alert the player.
* UI system with keyboard control. At the moment it only supports desktops, but I'd like to add touchscreen support and explore-by-touch on mobile devices.

Pretty soon I'll probably have a physics-based tile tracer for taking a map of open/blocked tiles and generating either chain shapes or physics bodies for wall colliders. Hopefully you can just plug that into either your own simple tile-based loader, or use it in tandem with the existing procedural map generators for Lua. With that, the physics-based motion, and the radar system, prototyping new game ideas on desktop and mobile platforms becomes vastly simpler.

So after releasing all that, people may still want to steal my games. But my hope is that they'll make more, and I'll have something other than my own games to play on Linux, and folks on MacOS might have the same. I'm still on the fence, but another aspect of getting older and trying/working in various business contexts is that I've started thinking about the entire process differently. We're such a niche market that working solo and keeping everything to one's self may be easier in some ways, but in others it really doesn't make much sense. If I could see then I could just write a game in Unity or work with some big studio and have access to a pile of plugins, community support, and assets. What do we have in the audio games community? Bunches of people working alone. Even most of the "larger" studios in this space are doing their own thing. And that's fine, but a rising tide lifts all boats. If I can contribute something like the next gen BGT in a modern language with better platform support and a community larger than audio games, I'd call that a win. If that code is on GitLab, and others can help improve it, then that's even better. And if I'm making it easier for folks to make whatever games they like, then maybe they won't rip off my own ideas and game code to do it.

Anyhow, enough of my perspective. tongue

Thumbs up

2019-04-10 15:50:29

@20, I like your perspective, actually. I've never done much with RayCasting (I don't know much about it) but the package you've got so far is pretty damn awesome as is.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-10 16:00:00

That's kind of part of my attitude about this. I literally started on this Love2d-based implementation a week ago Tuesday and already have all of these things written. That's not because I'm particularly smart, but because the engine makes it so damned easy to put these pieces together. The raycasting is just a Box2D call. I just create start and endpoints based on the player's position and direction, call into Box2D, then map its callbacks to something a bit closer to the ECS. I'm as far as I am because I stood on the shoulders of giants--the Love2D makers, the developers who wrote my ECS and UI, folks on this forum who did all the work of sorting through Freesounds and giving me nice soundpacks to work with, an old game called Golgotha that went bust in the late 90s and open sourced a bunch of music and SFX...to say nothing of the open source technologies I'm using to build my website, set up an authentication system for licensing and game distribution, etc. If me contributing some of this back gets me more fun games to play that I don't have to write myself, then bring it. smile

Thumbs up

2019-04-10 16:18:11 (edited by Ethin 2019-04-10 16:20:57)

@22, fair enough. I wonder if I should start contributing to LOVE. I wonder if upgrading it to Lua 5.3 would impact it at all? It would make the transition to 64-bit LOVE much simpler.
What I've been trying to peace together either way is, with LOVE, you have specific callbacks you must implement. So, how would I implement, say, a loading screen, a menu, and so on? Would I need to implement a form of an FSM? Would I need to have a central update() loop that does something similar to the following (which was my update loop in C++, I thought it was quite a nice design though I don't know anything about its safety or security):
* Game loop redraws black screen, updates contexts, polls for events and swaps buffer.
* State changes to menu. The menu instance is set as the currently (active) state object. (This can be stored in a stack, which makes going back one state simple.)
* Game update loop detects the change on the next frame, determines if the game state has user data associated with it, and if so, attains a pointer (or the equivalent in Lua) to that state object and sets up appropriate handlers for input. This repeats each frame. (An LRU cache might make this a lot faster; the way it is in C++ there is almost no overhead.)
* Game loop then calculates sleep times to ensure as close to a constant FPS loop as achievable.
* Game loop then sleeps.
* Operation repeats.
Whenever I see something like what most games do I always puzzle over how I'll implement such a thing while making it maintainable. Perhaps my way is way over-complicated. I designed my game loop off of this article.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-04-11 02:58:49

So essentially what I'm doing is:

* I use Lovetoys as an ECS. You get some great library names with this, I'll say that. I was briefly evaluating the Gspot GUI library.
* Lovetoys handles my actual game objects. If Lovetoys isn't updating, the game isn't updating.
* I use Luigi for my GUI. Luigi uses a Layout to store all widgets associated with the currently-displayed GUI.
* If there's a `gui` variable set to a non-nil value, love.update() doesn't run engine:update() (I.e. the ECS update procedure) so the game is effectively paused.
* I thought about using a menu stack, but realistically I don't really need it. I just need a single previous layout. My nested layout screens just check for the presence of that. If it's set, display it and then set it to nil.

So in short, love.load() displays my start menu and sets the `gui` variable to that layout. Clicking Start clears that, initializes the ECS engine instance, at which point love.update() starts updating the ECS on each game tick. Pressing escape creates the in-game menu GUI, sets gui to that layout, and stops calling the ECS update procedures. It also dispatches a Pause event, which pauses any playing sounds on any entities marked with the Pausable component.

You really don't need a complex state-tracking system--at least, not initially. You also really don't need every ounce of performance for an audio game--at least, not initially. I remember playing GMA Tank Commander and Shades of Doom on an old referbished low-end Pentium laptop running Windows XP. But if you ever *do* need that, Love lets you rewrite hot code paths in LuaJIT's FFI module to call directly into C. There are also a few game state systems which I might adopt if I ever find I need them. But for now, everything is in cleanly-defined functions that are all just a few lines long and easy to follow. It's about shipping product, not creating an architectural marvel. smile

Thumbs up

2019-04-11 05:04:46

@24, nice. I use game states. Its a primitive form of a finite state machine. The only thing this state machine is missing is transitions. (I've tried modeling a game loop with a full FSM; it doesn't work. At least, I could never get it to make sense.) So, te primitive FSM can switch out two states, cleaning up the state your switching from and allowing the state your switching to to take control, or you can push and pop states, which is like a stack: if you push a state, it pauses the previous state and lets the state take control, and when you pop that state off of the stack, the old state resumes. Its pretty much Amethyst's ECS state manager without the transitions. And itsvery fun to use (my menu class uses the switch from/to to tell you what option the user selected in it). Its pretty clever, IMO. Definitely isn't original though.
I couldn't find a GUI library that I was contented with. Not for LOVE, anyway. I checked out Gspot (certainly didn't hit the spot, if you catch my drift), And CatUI certainly wasn't purring contentedly either. Is there any way I can tie in the libraris your using to complete a GUI that lets me capture all the events I need (focus, highlighted, selected, clicked, ...)?

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up