I Guess I’m Making A Game Engine…

February 25, 2021 ☼ GamesTools

dinghy-wide

Maybe it all comes to this. Any gamedev-focused blog will inevtiably become a game engine development blog, if there wasn’t already a secret engine in the background.

To be clear, I never wanted to do this. I’m still not sure I want to do it, and may drop the project at any moment or put months between any substantial progress.

I’ve got some rough ideas for the engine, and some general thoughts about where I’ll take it, so here’s my general pitch, followed by a manifesto/outline of sorts that goes over the reasoning:

Update: For people interested in follow this project as it moves along, you can subscribe to the newsletter here

The Dream

[ENGINE] will an open-source cross-platform 2D-focused game engine written and scripted in C#, with a focus on immediacy, coziness and magic. [ENGINE] should just work”, with the user not really needing to worry about platform specifics and get all of their benefits for free. [ENGINE], where possible, will have minimal dependencies. [ENGINE] will be code-only, but with easy ways to build your own editors.

For references, I’m really inspired by things like Flixel and Heaps, and would like [ENGINE] to sit somewhere between the two in terms of abstraction.

Why [ENGINE]

I have a game idea. I want to work that out or prototype it quickly, using my favorite language (C#). I don’t want to use Unity, it reeks too much of my day job and wants me to really make Something Substantial. I don’t want to learn Monogame or learn all of the XNA framework becuase I don’t have that nostalgia. I don’t want to learn Godot, because again it feels too big”. I want the ability to put together a game in a way that feels as simple as drawing on paper, and something I can discard at any moment and start over from scratch. I don’t need a scene editor (at least at this stage). I don’t want updates, an asset store, anything. I want to use a single C# file and in a few lines have something meaningful. I’d like something like this:

//game.cs
using ENGINE;
Engine.Init();
var obj = new Object2D(Resources.MySprite);
Engine.Update += () => {obj.Rotate(45)};

There’s a lot implied in those few lines. Real ENGINE-HEADS may be pulling their hair out. But to them I say: there’s a million different options for you. In <5 lines I want to be able to get something on screen, doing stuff. I think it’s more than possible. Looking at those above lines I think you can also see how they philosophically align with the ideas of immediacy, coziness, and magic.

Immediacy

Hand waving away other C# engine options has largely to do with their demanded cognitive load. Most game engines have the capactiy to allow you to make something BIG. However, even if you want to make something small or a simple sketch, you’re still presented with all the tooling to make something BIG. [ENGINE] should get out of your way. It should feel invisible and intuitive. I don’t want to have to think about the engine I’m using when I’m using it, and I don’t want you to have to think about [ENGINE] when you’re using it. It should just work, with next to no flaff.

In the above example, I make a sprite appear in less than five lines. And those lines themselves are also meaningful, it’s not abbreviated garbage. It’s easy to reason about and read plainly. Monogame requires 10x the number of lines, and doesn’t even get a sprite loading.

[ENGINE] should be immediate, and out of your way.

Coziness

Can a game engine be cozy”? I think so! We’re just overly accostomed to not cozy engines, such that the notion of engines themselves don’t seem cozy. Some notable games people sat down a few years ago to give the idea of coziness in games A Big Think. Here’s what they came up with:

Coziness in Maslow’s Hierarchy Coziness Defined in Covey’s Time Management Grid
img img

They talk about aesthetics of coziness and bring up the ideas of Protection, Support, Focus. They also bring up some things that are anathema to cozy” and mention Danger, Fear, Threat, Responsibility, Pretentiousness, Fanciness”. Let’s make another table.

Cozy Not Cozy
Not Urgent & Important Reponsibility
Self-reflection Pretentiousness
Connectedness Fanciness”
Protection Danger
Support Threat
Focus Fear

Typing this up, a word and idea I’m circling is symbiotic. You feel like you’re working with something, and are sharing with each other as you uncover goals and ideas.

Looking at the not cozy side really echoes my experiences with most game engines. They stare you down, wielding all their features in your face and demanding that YOU make something worthy of the tool. If you don’t shame on you for not using the engine to its fullest. A game can be too small for Unity” — nothing should be too small for [ENGINE].

It’s weird to write this and realize how much more philosophical my want for [ENGINE] is, but I’m imaginging the engine almost cheering you on as you go. In the linked report above they also talk about how a sense of welcome-ness” to a space is a big indicator of cozy”. I don’t feel welcomed in Unity. I feel like it’s annoyed that I’ve arrived. I want [ENGINE] to be there for you.

A Note: It’s worth saying too that, especially in games that would be defined as cozy, the scale you operate at often expands over time. [ENGINE] should be similar. It should be able to effectively scale with you. It won’t demand you need to keep your game as small as possible, and if you want to make something bigger for you can definitely do that, and [ENGINE] can handle it.

Magic

Magic in software is usually seen as a bad thing. The closet non-taboo way we get to socially-acceptable magic in software” is the concept of just works”. Maybe Magic is even anathema to cozy, as there’s some unknowing and fear involved.

For [ENGINE], I’m hoping that things feel like magic due to things that both just work,” but also lean on the symobiosis mentioned in the previous section. In the sample code, this line is the kind of magic I want:

var obj = new Object2D(Resources.MySprite);

The outcome of this line is that MySprite.png appears on the screen. Let’s talk about what it doesn’t require, and then talk about what it does.

  1. It doesn’t require you to know the string name of the sprite you want to load.
  2. You don’t need to add it to a scene
  3. You don’t need to work with generics.

In every other C# language, you need to do at least two of those above things explicitly. Here’s what [ENGINE] does (obviously considering this isn’t yet working code):

  1. A predefined Resources folder is searched for files on Engine.Init
  2. Using Source Generators, [ENGINE] builds a dynamic class called Resources with properties the name of all those assets, that, on being accessed, load themselves via the asset loading system.
  3. Inside the Object2D constructor, create a new Object2D and attach this sprite to it.
  4. We add that new Object to a default scene.
  5. Once added to that scene the object renders as part of that Scene.

Each of those steps can also be invoked directly, overriden, and managed, but the key here is that you don’t need to worry about that. If you’re making a game jam game you may only need a single scene. A prototype may only need a single scene. If you’re loading a tilesheet instead of a single sprite you’ll need to do some other stuff, but again, this just works.

I’m really recalling here the concept of a casual creator” by Kate Compton and her idea of no invisible holes”/“sensible defaults”. These imply a baseline working functionality with no additional config. Actually reviewing the zine now I think I’ve just been subconciously recalling a lot of what she discusses as the goals of a Casual Creator”:

[Casual Creators] encourage a user to feel safe and creative exploring a possibility space, while not striving for total control.

Additionally she lists major concepts of Casual Creators:

  1. Trading control for power
  2. Surprise and Emergence
  3. Explorability, with assistance and guidance so a user doesn’t feel lost of stuck
  4. Ownership

And lastly she also talks about unfolding control and the time between executing something and evaluating what was executed (a grokloop”). This really hits for where I see [ENGINE] fitting, and touching more on that magic. Something like magic is born and reinforced through discovery — small ah ha” moments that build up a sense of ownership and knowing-ness, as [ENGINE] reveals itself to you over time.


Other assorted thoughts

Outside of those general goals of immediacy, coziness, and magic, I’ve got a few other bones to pick, software to praise, and thoughts to type out as I embark on this journey that I wanted to have laid out here. Some of the stuff below goes into the general tech stack I’m looking at as well, so if you’re interested in technical stuff you may find more to love below than above.

  1. I love C#/Dotnet. I want to write everything in C#. What I don’t like is engines taking forever to get the latest C# stuff as soon as it hits. Dotnet 5 especially is a milestone release, as it has moved everything to a unified framework and has a pretty good baseline for performance and is a standardized cross-platform runtime that will only continue to get better.

    Similarily, C# continues to get better, with things like their advanced pattern matching and expressions, and now Records, Source Generators, and Top-line programs (teased above in my code example) continue to push the boundary on what the language can do. I want [ENGINE] then to always leverage the most bleeding edge versions of C# as soon as possible.

  2. BLAZOR. The Dotnet 6 release introduced a Blazor desktop target, which seems huge. Being able to natively author data driven UI frames and panels with C# and throw in some JS where necessary feels like a huge boon for the constant woe of UI in game development. I want to jump onto that as soon as possible, and [ENGINE] should support it.

  3. Speaking of Blazor — I don’t really want [ENGINE] to have any sort of canonical editor”. You should be able to easily tie in Blazor to your games made with [ENGINE] and make you own editor — again channeling the idea of cozy” here. Maybe there will be a terminal built just so things are easy.

  4. Beyond XNA/FNA — nearly every code-centric C# framework uses some fork of XNA. Maybe I’m being crazy but I want to move past that. If you want to use those frameworks you still definitely can, but as someone who doesn’t hold a ton of nostalgia for that era of C# development I want to try and pave a new way forward using a more modern stack.

  5. Platforms: All of them? Dotnet 5 runs everywhere, and I want to run everywhere that runs, including mobile. I think mobile development isn’t cozy due to having to go through XCode or Android Studio, but ideally, towards the point of not having to think about it”, my hope is that [ENGINE] just works” wherever you want it to.

  6. Minimal dependencies, but not interested in trying to be clever. [ENGINE] should just work out of the box, but having hooks for things like FMOD would definitly be nice. I don’t have a desire to redeisgn the wheel (in some places). In a way I’m sort of against doing work, and more about doing as little work as possible to make it happen.

  7. Let’s talk about frameworks then. I’ve been really interested in Kinc recently as a modern C backend for games. It handles most everything, and does it well enough to support a game coming out on PS5, so that seems good enough for me. Additionally, it makes me not have to worry about graphics libraries, platform APIs, etc. Kinc handles that in native C. I get access to stuff like Compute Shaders, Metal, Vulkan, etc. if I ever want them, and don’t need to worry about their implementaion. In a way Kinc is its own magic.

  8. This also means that the engine” is two seperate things. First, and what I’ve been mostly working on, is a set of bindings for Kinc functions in C#. For now I’m writing these by hand, because it seems easier than trying to learn the programs that generate bindings for you. The second part of the engine is [ENGINE] itself, built in C# using those bindings. I’m also hoping people use those bindings for other things as well, and I don’t want them to be too attached to [ENGINE].

    It’s worth bringing up Foster now as well, because it’s operating in a similar space with what seems like a similar philosophy. However we’re going about the problem” in slightly different ways:

    Screen Shot 2021-02-24 at 10.12.23 PM

    Foster itself acts as a collection of platform specifics in that it brings together bindings of multiple APIs together at the C# level and provides an abstracted way to reference those libraries. This is totally fine and great!

    For [ENGINE], I’m skipping all that hard work and letting Kinc (aka not me) manage it all. Kinc acts like Foster for me, but at the C level. If Kinc collapses, I could also just make [ENGINE] on top of Foster! Kinc also has minimal dependencies, and itself acts as SDL/GLFW. It already works on mobile, works with Metal, etc.

  9. This probably brings up some questions of performance. I don’t really care about performance. I’m assuming that any modern hardware can pretty effectively run almost any 2D game. If it ever becomes an issue I’ll look into it, but I’m in the camp of Performance? I’m sure we’ve got it.” Also, caring about performance isn’t cozy. Similarily, the graphics will be… fine! The target is 2D for now, and I’m fine with that. If you really care about graphics and performance, this probably won’t be for you. Maybe it’s heckin fast though who knows.

  10. I mentioned it earlier above, but I’m really looking at things like Flixel and Heaps as API targets. Heaps actually gives me some similar vibes to what I’m describing wanting here, but I’d much prefer to be in C# land than Haxe land. Haxe is definitiely a fun and cool language, but being able to offer something in C# as a refuge from Unity will, I think, be well recieved.

  11. Routes not taken — I already mentioned Foster, but it’s worth talking about stuff like Veldrid too. I think Veldrid is totally great at what it’s doing (and imo Foster should look at it), but using it means faffing with the internals of what it’s wrapping a bit. I don’t really want to worry about that. If you do want that, Veldrid is there for you.

  12. Technical challenges: not really interested! I’m more interested in the API design, but am happy to tackle the challenges along the way. I’m already learning a lot, but the goals of [ENGINE] are not meant to be a personal learning exercise, but something that other people can use and find value in.

  13. DOCUMENTATION! There are a ton of I’m sure great engines out there, but similarily great documenation is nearly impossible to find. Documentation will be a first priority for [ENGINE], and allow other people to easily get up and running with it.

  14. Other tools — I’m obviously interested in tying in Depot to the engine if possible. I’ve also been tracking Eno and think, in the spirit of cozy, it could be a good data file format to support. Which is also to say…

  15. [ENGINE] should be data-driven where possible. I want it to feel open so if it’s doing something you know how/why. In the spirit of sensible defaults, maybe it has a basline configuration file, but if you provide an additional engine.eno file you can configure your settings. Engine data should be easily readable and editable.

  16. THE NAME — [ENGINE] will have a real name. The bindings I’ve given the name Karp, for Kinc in CSharp, but for [ENGINE], here’s what I’m thinking. It’s primarily a Dotnet Game Engine, or DNGE. Saying these letters together gets you… Dinghy,” which actually feels like an apt description.

    Dinghys are small boats that are often used to take people to bigger boats. They’re solid themselves, but more importantly they often do only one job and do that single job pretty well. They support the people using them on the journey to their destination. So let’s see where this boat goes.

    Update: For people interested in follow this project as it moves along, you can subscribe to the newsletter here

dinghy-wide


Back To Index