Hacker News new | ask | show | jobs
by seba_dos1 1081 days ago
> Over time, the game’s code became complicated, and I decided to use advanced features such as coroutines and higher order procedures, besides general overly engineered abstractions.

> But then, over time I grew to feel like a lot of those abstractions didn’t really add anything to it, and just made it more complicated (and oftentimes more buggy) than it really needed to be, so a few weeks ago, I made a significant refactoring to it to remove all of those abstractions without removing almost any features from the game.

Abstractions, while incredibly useful, can be overrated.

When I started writing my first C game about a decade ago, I used C89 too. However, after some time I realized that C89's limitations don't make my code cleaner at all and just make it more annoying to write. Since most of those games are game jam projects written under extreme time pressure, it made absolutely no sense for the language to pester me with pointless things like variable declarations outside of for loops or lack of designated initializers, so my toolkit uses C99 now. Initially I also made some use of nested functions, but I disable GNU extensions these days too.

Now I have about 40 games written on top of that codebase, a few of them being bigger projects. I've ended up with an "engine" of sorts that I have never really written - I've been always writing games, not an engine, and only then abstracted things away that actually begged to be abstracted. It did grew some fancy features and abstractions over years of using it, but not every game benefits from using them, so they're completely optional. In its essence it's mostly just a toolbox with handy things I find useful when writing the sort of games I usually write. Writing a game is essentially just filling up functions that update its state based on input and passing time, and that render an image based on that state. The engine can then maintain a state machine between various "stages" implemented that way. For many simple games, that's exactly the abstraction level they need.

I've often seen people making big eyes after being told that I use C to write games in under 48h at game jams - and yet I never really felt disadvantaged when compared to other teams that used big and fancy ready-made engines. Sure, there are kinds of games where I'd use a big engine like Godot too, but... most of those games aren't that kind :) Keeping things simple actually helps, especially where what you need is being able to jump straight into implementation instead of having to think about how to fit your ideas into whatever abstractions you ended up with due to your framework of choice.

(although one thing where using a ready-made engine helps a lot is collaborations with random programmers on your team - however, I usually either work alone or with a single artist, so I can enjoy programming on my own terms :))

2 comments

> I've often seen people making big eyes after being told that I use C to write games in under 48h at game jams - and yet I never really felt disadvantaged

Another comment posted that you would have to be "a madman" to code a game in C, and I was genuinely baffled. Gamedev is one of the realms C truly excels in and is actually relatively easy. Once you're used to it, and know the boilerplate that needs to be hoisted, it's not particularly difficult or time consuming.

It's weird to me that (I assume, at least) professional developers still have this weird mysticism over C as if it's just arcane incantations compared to what they do.

That sounds awesome! This is the most advanced game I have ever made, so I don’t feel like I have as much experience as you. I’m glad you seem to have liked what I came up with in some way or another!

I feel like designated initialisers can be circumvented by simply assigning the fields individually. It’s a bit more verbose, but I feel like it works almost as well, the biggest downside being that the compiler won’t warn you if you miss some.

Regarding loops and variables, I opted for just declaring all variables at the top of each function definiton (only using an initialiser for ‘static’ variables), which I find almost reminds me of how Python handles variables, except with a chunk of declarations at the start of each function.

Of course, this is all subjective, but I find this style looks neat, and I don’t think it gets in my way at all, personally.

But what is the actual point of clinging to C89 for a game like this? Do you expect to port it to obscure DSP platforms?

Note: I freaking love C and often defend/advocate it here and elsewhere. I just don't understand why anyone would choose a more limited version. Artistic expression? Something something limitations something creativity?