tech

Type safe Game Development, is it possible?

My struggle with game development and type safety continues. It all hinges on a simple question: is it possible for a single indie developer to implement a complex game in less time with the help of types?


Sandro Maglione

Sandro Maglione

Games

"I have a simple idea for a game" 🤔

That's how all games start. How hard could it be to create a Pokémon clone after all?

And then you get smashed by complexity on your first step 🫠

This is what you are facing 👇


Why things need to be mutable?

My conflict with game development is all around mutability (or maintainability in a broader sense).

I know for a fact that code complexity originates from unpredictable/dynamic logic. In fact, for standard apps you can get close to 100% type safety and sail safe 🚣

But not game development. Games are the wild west of mutable and scattered code. Deceptively not indie-friendly (despite so many indie games out there).

That's (part of) the origin of years and years of development for even simple games when you go solo 🤯

The complexity of an object moving on the screen

A game starts with getting something moving on the screen.

Even at this step you are flooded by complexity:

  • Game loop: in sync with the platform, synchronous, working on any machine
  • Collisions: good luck manually dealing with physics
  • Assets: asynchronous loading and performance optimization
  • Animations: state machines and sync them with frame rate and game loop

My context is mostly the web, therefore Promise, requestAnimationFrame, and static assets 🏗️

All of these get you a player moving on the screen, with a decent walking animation, stopping when hitting a wall. Not much 🫠

Adding features

This is how your future looks like:

  1. Sprite rendering
  2. Player movement and animation
  3. Tile map loading and rendering
  4. Collision detection with map
  5. Basic camera following player
  6. NPCs placed on map (static, non-moving)
  7. Simple interaction (press button to start dialogue)
  8. Basic event system (trigger dialogue, get items)

Can you spot the trick?

Each of these systems is related/dependent to each other 🔗

Some innocuous examples:

  • What if an NPC is moving but you want to interact with it?
  • What if you start moving on an empty tile but at the same time an NPC is moving there as well?
  • Should you be able to move behind a building (tile map layers)?

And when everything can depend on everything else, complexity spreads to the whole system 🤯

Tame complexity with types

Outside of game dev, libraries like effect tame complexity with types.

Dependencies and errors are tracked on a type level. You control their spread, and deal with it 🫡

Can this be done as well with games? I am in the process of finding out 🤔

First step was building an ECS library (@typeonce/ecs). It solves some problems, but not others:

  • Values are still mutable
  • Async code is not "expected"
  • Dependencies are mostly implicit (not typed)

The more I ventures into these flaws, the more it all started to resemble effect 🙌

export class SnakeGrowSystem extends SystemFactory<{}>("SnakeGrow", {
  dependencies: ["Collision"], // 👈 Dependency, but not on the type
  execute: ({ poll }) => {
    // ...
  },
}) {}

Alas, I started a possible implementation of a game loop with effect (and more).

My initial goal would be to have a playable website, with type safe and maintainable game code, with effect 🫡

At the moment I am still struggling with the main game loop (requestAnimationFrame), I will keep you posted 🔜


Published a new article on my personal blog: Creative Constraints.

The next (big) event of the year is approaching: localfirstconf. See you in Berlin at the end of May if you plan to join 🔜

See you next 👋

Start here.

Every week I dive headfirst into a topic, uncovering every hidden nook and shadow, to deliver you the most interesting insights

Not convinced? Well, let me tell you more about it