u/Dry-Huckleberry8284

The Web is the best platform for 2D games, and why, and why it’s likely the best for 3D too

The Web is the best platform for 2D games, and why, and why it’s likely the best for 3D too

I recently made a game, primarily using Svelte js + Pixi js.
First, let me explain the background I had while developing this game:

  • I have game development experience, mainly with Godot + C#
  • I released a game on Steam, but it was made with Compose Multiplatform (if you don’t know it, Compose is basically a UI library for Kotlin)
  • I had zero web experience and only knew a little TypeScript
  • My new game uses Svelte js + Pixi js

Why I chose this tech stack

Godot is great software, but—every game engine, note, every single one—lacks a truly good UI solution.

My first game was an Idle game that was basically all UI. I didn’t need complex physics simulations, particle systems, animation systems, or any of those “general game development” solutions.

When I made that game, I ended up picking Compose Multiplatform instead of web technologies, simply because I didn’t really like frontend; the ecosystem is chaotic, and HTML and CSS are genuinely painful to write.

Compose offers a top-tier UI development experience. It’s reactive (just like Svelte, you directly modify variables without needing any advanced special syntax—interestingly, Compose also heavily depends on the Kotlin compiler; specifically, Compose code literally lives inside the Kotlin compiler’s source code, so Compose isn’t a very pure library. However, the Kotlin compiler’s role isn’t quite the same as Svelte’s. I won’t dive into details here). It has a layout model that is better than CSS, an officially recommended best practice, and everything feels comfortable.

That is, until I needed to make a new game that required some things closer to a traditional game engine, like sprites. At that point, sticking with Compose became unwise. After some research, I ultimately chose Svelte + Pixi js.

(PS. Before this, I had already made a small demo using Solid js.)

Ultimately, it comes down to one thing: I want a genuinely good UI solution.

Svelte is that ultimate solution

To be honest—and I love telling the truth—Svelte is the most comfortable UI framework in the web world. I know that sounds a bit radical, but when I entered this field, I tried:

  • Solid js
  • Vue
  • React

All of them have their own shortcomings:

  • Solid js is nice, and JSX felt familiar because of my Compose background, but really, syntax like setStore/setXXX just feels incredibly annoying, super annoying. Once your objects start getting complex, you’re forced to bring in libraries like mutative, otherwise it’s genuinely painful.

  • Vue feels like it was designed for true “web developers.” SFC is awful (and this is different from Svelte—in Vue you can’t write local snippets and have to put them in a separate file). Template directives like v-for aren’t great either, kind of tricky to write. And it offers two APIs simultaneously. This might seem picky, but I really dislike it; it just leads to everyone’s code looking different.

  • React is basically a worse Solid js. (I know, I should actually say Solid js is a better React, sorry!)

Svelte is great; it solves all these problems:

  • You can have snippets inside SFCs
  • $state lets you directly mutate plain JavaScript objects while keeping reactivity
  • It’s wonderful

I believe Svelte will become the new de facto standard.

Pixi js is exactly the game engine I was looking for

Yes, Pixi js is just a rendering library, but isn’t that even better! It removes unnecessary abstractions for you, yet keeps useful ones like the Scene Graph! And it’s very fast, more than enough for making games! 99% of 2D games won’t hit a rendering bottleneck. If you do, don’t blame Pixi js—it just means your code is too messy.

All game engines share this problem: too many poorly designed abstractions, because they’re general-purpose game engines after all.

I’m totally fine with pulling in other libraries as I need them.

For instance, in my new game, I use Tone js as my audio library because I want a great reactive audio experience, and Tone js is incredibly comfortable for that.

You might think, “Ahhh, without the high-level abstractions of a game engine, how will we write game logic?? You’re lying blah blah blah.” The answer is simple: bun add bitecs.

Pixi js’s own UI solution is also terrible—writing a UI library is hard—but we already have Svelte!

The only downside is that since I’m using Svelte, my UI must be drawn in the DOM, which means it can’t benefit from post-processing on the Canvas.

No big deal, I don’t need that feature right now. I’ve also seen some in-progress Canvas HTML libraries, so the future looks promising.

UI

Time to talk about the elephant in the room—UI.

To be honest, the developer experience for UI in the web world isn’t exactly superb—

  • HTML wasn’t designed for describing UI. If you don’t care about accessibility and search engines (which happens to be the case for my game-making scenario), you can ignore all semantic tags and just use div.
  • CSS is especially awful. It has a chaotic layout model, and vanilla CSS is basically unusable.

Yes, we have Tailwind CSS, which significantly alleviates the problem of CSS itself being terrible, but it doesn’t completely solve it—you still have to think about CSS’s messy layout model...

But either way, the UI experience still surpasses 100% of game engines, simply because it lets you describe UI with text and provides reactivity.

Oh, and also very importantly, we have a ton of component libraries. (daisyUI, absolutely amazing!)

The best distribution

I barely need to elaborate here. You just log into Vercel, push your repository, and you can share a link!

Local distribution is also easy: you can use Tauri and even write native code in Rust.

The best DX

No other field’s developer experience compares to the web world, I’m serious.

On my Compose journey, I had to painfully wrestle with Gradle. In the end, I even wrote my tasks.ts in TypeScript because Gradle is truly baffling, and it’s super slow, extremely slow, incredibly slow. The Kotlin compiler itself is also very slow.

Vite is fast, Bun is fast, hot reload is fast—change one line of code and you instantly see the result. That is pure fantasy in Compose.

TypeScript is top-tier

TypeScript is wonderfully designed. It has everything I need; I think I don’t need to say much more. Compared to Kotlin, though, it’s still a little behind. I think the only downsides are the lack of an enum class and a relatively small standard library.

Speaking of enum class, I feel most people underestimate its use cases. Specifically, Kotlin’s enum class is a set of constants with associated data, which is incredibly handy. Consider:

enum class Rarity(val label: string, val color: Color) {
    Epic("Epic Equipment", RED),
    Common("Common Equipment", BLACK),
}

In UI you can do:

Rarity.entries.forEach { Text(it.label, color = it.color) }

In TypeScript you have to:

const Rarity = [
    { label: "Epic Equipment", color: RED }
    { label: "Common Equipment", color: BLACK }
] as const

{#each Rarity as rarity}
    <p>{rarity.label}</p>
{/each}

And you lose the ability to do things like:

const epic = Rarity.Epic; // ???

Also, the standard library is small, so I ended up implementing many commonly used utility functions myself (like mapOrPut and similar).

The NPM ecosystem is top-tier

I have to say, you really rarely need to reinvent the wheel—NPM basically has every library you need!

What about 3D?

We have Babylon js. I haven’t used it deeply yet, but it is indeed a real game engine.

Summary

I think more game developers should try to break free from all-in-one game engines. You certainly don’t use every single feature of an engine, right? Plus, experimenting with new technology is inherently fun.

If you want to see an actual product: https://store.steampowered.com/app/4646350

u/Dry-Huckleberry8284 — 1 day ago

Hello! I'm developing an active incremental game about network expansion. It's in the early stages, but I'm struggling to make the loop feel "fun" or engaging. I’m committed to the project and would love to hear your thoughts, ideas, or critiques.

If you have a moment to playtest it, that would be amazing. Thanks!

GameLink

u/Dry-Huckleberry8284 — 15 days ago