The "WAVE" Engine | Devlog - 000


Why even bother creating a new game engine from scratch? Why engines like Ren’Py and the like are not for me.

Introduction

I love a good story. Reading books is fine and everything, but for my ADHD brain definitely not enough. Staring at a white page with nothing but black words printed on it, and that for hours, is way to boring for my taste. The solution? Probably comics or managas, however, you could’t get the content of a thousand page book into a single comic. I assume that is, I don’t really know much about comics.

Anyway, as an IT person, you get around the internet a lot. A few months ago I stumbled across Itch.io. To put it briefly, it’s nothing more than an online platform and marketplace designed for independent creators to share, distribute, and sell their digital works. It’s not a small platform too.

On Itch.io I found a lot of so called “visual novels”.

Not going into detail here what visual novels are, but here’s a quick summary:

A visual novel is an interactive storytelling medium that combines text, visuals, and audio to deliver a narrative-driven experience. It is a popular format in video games, particularly in Japan, and often focuses on character development, branching storylines, and player choices.

Thinking about it, that’s exactly what I need. Basically a book with visuals and audio. No more staring at a boring book!

Two months later, I’ve read through a lot of the VNs found on Itch.io and never really got bored. Most of them had a really good (and sometimes wholesome) story that I really enjoyed.

The Ren’Py visual novel engine

The Ren’Py engine is a game engine written in Python specifically made for visual novels. It does exactly what you expect it to do, run visual novels. It’s relatively easy to use too, but being written in a high-level language like Python, it’s a pretty slow and bloated engine. A simple game with barely any text and textures that are mere kilobytes in size, can reach around ~70MB in file size and consume a staggering 180MB of memory. The game assets alone (textures and text) are only 1.7MB in size.

Ren’Py assets and libraries: Ren'Py assets size totalling 70.0MB

Game only assets (text and textures): Ren'Py game only assets size totalling 1.4MB

Memory usage: Ren'Py game memory usage around 180MB

As mentioned, this is not necessarily bad and with modern hardware not an issue. However, it leaves a lot of head for improvement.

The good, the bad and the ugly

Now let us take a look at everything that Ren’Py does good, bad and what’s just ugly about it.

The good:

Easy to use

Ren’Py is fairly easy to use and to get started with. Most game engines make it unnecessarily complicated to get started with and to setup the engine itself. With Ren’Py you just have to download the SDK (as .zip or tarball), extract the SDK and execute the launcher. It’s as simple as that. Generally speaking, the launcher is really intuitive and does a lot of stuff for you. In my opinion it offers a bit too much functionality so it becomes confusing fast, but most developers are likely going to enjoy the large amount of functionality.

Cross-platform support

Ren’Py makes it exceptionally easy to port your game to all major platforms such as Windows, MacOS, Linux and Android. Mind you’ll need a Mac if you want to build your game for iOS, but that was to be expected. Building for Android requires the Java Development Kit as well as the Android SDK to be downloaded seperately.

Customizability

Ren’Py gives developers a broad set of tools and capabilities to customize a Ren’Py game to the bones. Using custom Python code you can integrate complex logic in your games.

Moddability

Ren’Py does not encrypt or obfuscate any part of the code. This allows games to be modified without restrictions and eliminates the need for a seperate modding API.

The bad:

Performance

Being written in Python and the interpreted nature of Python results in slower execution speeds compared to other game engines written in low-level languages such as C++. Typically this is not an issue considering Ren’Py is made for 2D story games, however, very complex logic and a high count of high resolution assets can lead to significant performance issues.

Lack of compression

Instead of compressing game files such as images, sprites or audio files at build time, it completely skips that step and leaves compression to the developers. This is very bad practise and causes some games to be unnecessarily big in size. I had a case where a game had sprites that were really high resolution but were barely compressed. This caused the game to be over one gigabyte in size. Some developers are really efficient with asset management and can keep the size of the game reasonably low while still having a lot of assets.

Memory management

Because Ren’Py uses Python as its scripting language, and Python has a garbage collector that handles memory management. Objects (like images or text) that are no longer needed are eventually removed from memory. For the most part, Ren’Py will manage memory for you, but large amounts of high-resolution assets or continuous animations can lead to memory bloat if no managed properly. Ren’Py loads images into memory as they’re used, but it doesn’t automatically release them after they’re no longer needed unless you manually instruct it to do so. Ren’Py provides functions like renpy.dispose() to manually dispose of unused images, sounds, or videos. This means, for larger projects, you’ll need to actively manage memory by unloading assets at appropriate times.

The ugly:

The Ren’Py language

Please take this with a grain of salt. As a rust developer I’m kind of biased when it comes to judging other languages. Python itself is a totally fine language especially for something as simple as a visual novel, however, instead of consistenly using Python throughout the entire Ren’Py development environment, they decided to use a custom domain-specific language (DSL) that is built on top of Python. It offers no formal code structure and has very inconsistent formatting. Writing dialogue, story events, and conditional choices can make the script messy, especially if the story has many branches and complex conditions. For instance, you might write if and else statements to control different outcomes based on player choices, which can create deeply nested blocks and make the script harder to follow visually. While Ren’Py is based on Python, it abstracts away much of the actual Python code, so it looks very different. You can use Python within Ren’Py scripts, but when you’re doing so, you’re working in two worlds: the easy-to-read visual novel syntax for dialogue and a more typical programming language (Python) for logic.

Not compiling to single binary

Ren’Py does not compile the game to a single binary. This is not always bad, but can cause confusion for non tech-savvy people who just want to download an .exe and enjoy the game. There are no game engines (that I am aware of), that compile a game to a single binary, but considering the simplicity of visual novels, that shouldn’t be an issue here. Even worse is the fact that renpy compiles a binary only for windows and relies on shell scripts to execute Python code on Linux and Mac. This leaves a lot of head for errors and opens a shell when executing the shell script (obviously), which can confuse people and is just ugly to work with and look at.

Inconsistent project structure

Ren’py works with a very weird and ugly project structure, which can quickly cause confusion. For example, why are the GUI, images and audio files stored in three different directories instead of a unified assets folder and using logical subdirectories instead? I suppose with the amount of customizability Ren’Py offers, it should be possible to manually change that, but it’s just ugly to look at out of the box.

About the WAVE Engine

The goal of the Wave engine is to solve all the issues Ren’Py has while offering even more capabilities. Leveraging the power and speed of the Rust programming language allows Wave games to run at incredible speed and efficiency. 🦀⚡

Features:

Stupidly simple syntax

Use Markdown like syntax to create games without any code and in a really short time. Wave focuses on a story-first approach.

// write comments using two slashes
# define scene: horse
## background: house_table

## group family: lois, peter, meg, chris, stewie, brian
## show character: family

- [Lois] "Peter, the horse is here."

## show character: horse slide-in left 1s

### await input: click // wait for mouse/touch click
## character peter property: lookingDirection left
Optimized for speed and efficiency

Thanks to Rust’s incredible performance and low execution time, your games will run blazingly fast and with low overhead. Rust’s compiler can be customized to allow for different settings. This way you can tell the compiler what to focus on.

[profile.release]
panic = "abort" # Strip expensive panic clean-up logic
codegen-units = 1 # Compile crates one after another so the compiler can optimize better
lto = true # Enables link to optimizations
opt-level = "3" # Optimize for runtime performance
strip = true # Remove debug symbols

For more information, refer to the Cargo books Profiles section.

Additionally, Wave features a dynamic memory management system. This means, your game will dynamically offload resources to memory. Often used assets will be loaded into memory for quick access (eager-loading), while rarely used or unimportant assets will remain on disk and will only be loaded to memory shortly before being required (lazy-loading). Once a lazy-loaded asset has been used, it will be released to preserve memory. Android builds will feature a much more aggresive memory management due to typically smaller memory. The game will detect the amount of available memory and will manage resources appropriately. This way we can avoid memory bloat.

No dependency-hell during building

You can configure Wave to use GitHub Actions to build your game using GitHub Actions or if you prefer to build your game locally, you can use Wave’s dependency free building system using docker containers. Wave will pull docker containers specifically designed for use with the Wave engine building system. These containers contain all required software and libraries, so your environment can stay clutter free. This is the recommended way to build your game.

Use Rust code for complex logic

You can accomplish almost everything without using Rust, but for deep integration with Wave, you can use Rust code. This allows you to integrate functionality not found in the Wave engine by default.

Hot Reloading system

Wave will come with a hot reloading system so you can view your changes in near real time without restarting or recompiling your game.

Compilation to single binary

All games made with Wave will eventually compile to a single binary (Android as an exception). This ensures a worry-free and easy-to-use experience. Official support for AppImages and Flatpaks, as well as setup binaries will be available once Wave reaches some sort of maturity as a game engine.

Compression

Wave will compress all assets that have not yet been compressed. If you’re using a format, such as AVIF, which is already heavily compressed, Wave will only package that asset and skip compression. This will make sure you don’t have to worry too much about game size. Early testing showed Wave’s compression can cut game size almost in half, going from 15MB without compression, to a staggering 8MB.

Easy to use Modding-API

The Wave engine will provide an extensive and intuitive modding API to allow anyone to modify a games source code. You can use the Wave builder to interact with a games modding API.

Developers will be able to enable or disable Modding support for their games. It is enabled by default.

Note: Modding is a feature that has yet be decided if it’s going to be implemented.

Free and Open Source

Wave will be 100% free. Forever and always

It will be available under the MIT license

No costs, contracts or fees ever and ever

Note: The Wave engine is not at a point in development where its source code can be made public!

You’ll be able to follow its development through blog posts on my Website.

Wave Logo Gif

Cheers and happy new year by the way! :D
- Lurish