The initial idea came from an entry in the previous Jam. I liked the concept, but immediately after playing it, I started thinking of ways I would have approached it differently. This was my second Jam, so I was more prepared this time.
Once Pawel announced the wavedash element, I began looking at its API. I took a previous project and started figuring out how to implement leaderboards and achievements. Eventually, I neatly wrapped most of the functionality into a convenient Lua module. I had also been learning druid (which is so useful).
My first decision was how to run the game. Initially, I started using game objects to form the puzzle grid, but after rethinking, I switched to tilemaps. Once a rudimentary version was working, I realized the best way forward was to build a level editor. I split the project into two—one for the editor and one for the game—while keeping as much core logic as possible in modules. This made it easy to switch between the two projects.
With the help from Druid, a basic (and ugly) level editor was running. The level editor was the perfect testing ground. At this point there was no electrons. just debug numbers at every entry and exit to check the logic was working correctly. By now most of the operation nodes where added and everything seemed to work.
The next stage was implementing the electrons. These are pre-calculated. The solver module receives a starting grid reference and computes a path to the next processing node. This produces a list of points with go.easings for curved segments. The electron script converts into a chain of go.animate segments. Initially, this was passed as a property in the factory create function, but I began hitting the message size limit. Since the solver module already maintained a list of active electrons, I attached the path to it and let the electron script read it directly from the module instead.
Finally, electrons were firing from the source, creating a chain reaction as they moved around the circuit. The levels are stored in a table and then serialized to a file. The level editor uses straightforward file I/O routines, while the game loads them using the sys.load_resource function.
Then the focus shifted to the game. Once the level loads, it removes all non-fixed tiles and creates a tile list. I used a Fisher-Yates shuffle algorithm combined with a predictable random number generator to ensure the shuffle and rotations are the same across all platforms. Each level has its own seed, so the order is different for every level.
Since a lot of the code was shared, the game development progressed quickly. I enhanced the tracing electron code to handle breaks and additions that weren’t present when the path was first created.
The level selector collection was next, followed by the main collection, which loads either the level selector or the level play collections via proxy collections.
The next stage was adapting to Wavedash. and I ran into two main issues: the async nature of Wavedash and the cloud save load function.
The first problem was loading the cloud save. The Wavedash docs include an example for saving, but not for loading. At first, I tried using a similar method to saving, but it kept failing during deserialization. After rereading the docs in more detail, I found that the load function returns a table of bytes, which you need to convert into string/data before it can deserialized properly.
The second issue was with async behaviour. The cloud save manages storing and loading player progession data, so it has to be in memory before the level_selector proxy collection loads. But you can’t access the cloud data until the backend is connected.
So the html5 normal version:
- calls the level_selector proxy load message from its main collection’s init() function
The wave dash version
- calls the wavedash.init() from its main collection’s init() function
- catches the backend connected event
- from this it runs a coroutine function to load the cloud save with a callback function
- the callback function calls the level_selector proxy load message.
As I type this out and read it back, I think I may have overcomplicated the process. It works, so for now, that’s my method. Now the data is in place ready for level selector
The itch.io version only displays your total score. The wavedash.com version, features cloud saves for player progress, a global leaderboard, and achievements (though you might need a proper Wavedash account to unlock those achievements).
I think the leader board display might need some adjustments, but right now I don’t have enough entries to see how the current setup works.
Finally, I’d like to thank everyone who posts on this site. Many parts of this project were streamlined thanks to the questions and solutions shared here. For example, the level load mechanism was inspired by a topic from Ben James.
itch.io = https://afowleer77776.itch.io/ohms-law
wavedash.com = Play Ohm's Flaw for Free on Wavedash
Please note: These will probably be adjusted before the entry period ends. I know there are a few spots where I can optimize the code, but this time I focused on getting it running and uploaded first, giving myself some breathing room instead of scrambling to fix issues and panicking with only hours left before the game jam deadline—like last time.
