Splitting a game into several functional binaries? + Nic's Plugin Manager

What do people think about splitting certain parts of a game out into their own executables?

Examples would be intro, credits, options, and of course the main game. Intro would call main game, which would call credits/options, which would exit by calling main game again. All using playdate.file.run(path, [env])

I kind of like the idea of having a self-contained options binary that I can include in a game to instantly get a full featured options screen that reads its layout from one JSON and reads/writes settings to another.

This approach was taken on a lot of 90s games, PS1/PC, judging by those whose filesystem I've seen. I assume they took this approach for memory or clean room reasons?

But I have a niggling feeling that these should all just be states or classes in the main code.

Thoughts appreciated.

1 Like

I believe the main reason games were doing was because it was a nice way to start clean a section of a game. Memory leaks were a common issues so overall it was way more reliable and less error prone to just restart from a fresh start.
It was also a way to reduce the memory footprint of the executable. Instead of have a big executable that would be loaded at the start and take a big part of the RAM, you load only the necessary logic that you need for a section. You can save a lot of precious RAM this way.
I also suspect it was a way for bigger team to collaborate. A team (or even a sub contractor) could work on their part of the game with their own codebase and they would just need to deliver their executable. Much easier that working with a single codebase with crude or non-existent source control.

I don't think it is a helpful pattern nowadays except if you have a game compilation. As you say this is probably better to have a class/state system that allow you to call specific screens or modes of your game. I use that kind of system in my game and I have a debug menu that allow me to jump very easily to any part of the game.

One thing that just cross my mind though, maybe it could be used to have code hot-reloading. You would probably have to do some funky stuff to make it work but maybe it's doable.

Thanks confirming the memory and clean room reasons.

I'd not considered team/codebase silo, but that's a good point.

What do you mean by code hot-reloading in this scenario?

Maybe not "in this scenario" (aka splitting different game section in different game executable) but structuring different part of the code similar to exe and dll. In this case hot reloading mean that you modify your code and compile it and after that the game reload the new code piece while the game is still running.

For your game you could make the physics of the car a system and you could modify it, tweak it while the game is running in the simulator.

It can be difficult sometimes to manage code and data and everything reload automatically but the simplest version is having a table with all your balancing values. You can tweak your values and see the result immediately in game.

1 Like

Out of curiosity I did a quick hot reload test and it works well. Using the same idea we can also easily hot reload assets like bitmaps and sounds. Of course it only works in the simulator but that can be super useful already, especially balancing.

In the following example, the circle is managed by the plugin and I can change it on the fly meanwhile the game is still running (see the frame # keep going)

Screen Recording 2021-02-01 at 18.09.59.2021-02-01 18_20_35

HotReload.zip (54.0 KB)

9 Likes

Got it working!

Will have to get used to using Build rather than Build+Run!

Super work, well done.

You're using playdate.file.run() here, right? I just discovered it can compile and run lua source in the simulator. I had completely forgotten about that! :slight_smile:

@dave yeah I am using playdate.file.run() but to load a pdz file not a lua file.

I just tried to load a vanilla lua file and I get an error in the simulator

main.lua:4: sd_open returned NULL
stack traceback:
	[C]: in field 'run'
	main.lua:4: in main chunk

Anyway I think loading a pdz file is actually better because it has to be compiled and validated by pdc. When I was using hot reloading with love2d, loading lua directly was not ideal. I didn't want necessarily the game to reload everytime the file was saved. Also handling errors is better in the code editor compared to displaying the error in the game or console (or in this case the Simulator console I imagine)

ah! that's what I get for not testing that before opening my mount. file.run/load() would compile .lua files in the pdx folder, but the runtime assumes if you include a lua extension in the file name you're really looking for a compiled pdz file. Oh well. We can make that work if it's useful at any point.

1 Like

Actually I put the vanilla lua file in the save folder and not in the pdx folder. But I guess that doesn’t matter for file.run.load()

So, here I am:

I made a level editor for my game, which runs on desktop (mac/win/linux, made in Love2D)

This saves lua level files and I'd like to play those in the simulator. note that everyone who has the simulator, also has the sdk installed. So I guess I could use pdc for this.

What's the current status on being able to load lua files?

I'm using Nic's plugin Manager from above in a project at the moment. Works just fine in the Simulator! I'm editing Lua code and hot loading using Build (in Nova editor) whilst the game is running.