A Partial Game Written in C
02 February 2021

It was time to revisit C, it is on the list of allowed languages and is the least like a puzzle language of the three. I had the itch to write a game and wanted to see if I get annoyed with the lack features of C. I have experimented with this in the past.

I admit there is a portion of me that wanted to experiment with python and writing a small game/half game. The limiting factor there is with these throw away games it is nice to compile them to something that can be put on this web site. C and C++ allow it using WASM and emcc. If you use SDL2 then porting is fairly painless. It took less then an hour including installing emcc.

Here is the game, well half game and inspired by an old Amiga game but I morphed it into an endless runner. There is no score and no sound effects so you certainly cannot call it complete. I don't really plan on updating it any further.

This game has had about 20hrs work put into it but don't consider me a bad programmer! What you play is only the tip of the iceberg of the dev put in and that is what this post is about.

What did I spend my these 20hrs on?

  1. Make C a little bit more comfortable.
  2. Get back into SDL2
  3. Find some old bitmap text rendering code, fix a ton of bugs in it.
  4. The start of some linear algebra code.
  5. Fully implement Separation of Axis (SAT) collision detection.
  6. Find some graphics (discover AssetForge)
  7. Figure out how to port to WASM.

Oh and I guess actually make a game.

The big learning part was writing the SAT collision detection. I have written this type of thing in the past usually looking at code on the internet. This time I wanted to do a clean room implementation. Weirdly I had not realised how simple the algorithm is until a spent a couple of evenings working on it. I get the feeling a few of the tutorials showing how to implement it don't really have a clear idea on what is going on.

Purchasing is AssetForge was done after I has got the Jeep of off Kenney and thought I have taken a fair amount of graphics from the site over the years and wanting give back in some way. I used AssetForge to create the pyramid, yes I could have created that in Blender but that wasn't really the point. AssetForge seems like a pretty good tool although I have only really spent one evening with it.

Making C comfortable.

C doesn't evolve very fast. C11 was the last set of major changes, c17/18 was a minor bug fix release. C is not due another update for a couple of years. It seems pedestrian compared with other programming languages.

One way to ease this is to decide there are only two decent C compilers. Clang and Gcc, this is not entirely true as MS VC has recently added C11 support! But let's pretend we only have Clang and Gcc, windows builds can be done with either of those compilers after all.

If we pretend this then the world of C compiler extensions opens up to us as Clang and Gcc tend to support the same set.

I instantly missed auto from C++, but can create these macros:

#define let __auto_type const
#define mut __auto_type

// then we can write
let x = 10; // constant value
mut y = 100; // mutable value

The second extension is use of typeof extension and the ability to use code blocks as expressions. This makes macros a little easier to write.

#define clamp(v, min, max)    \
 ({ typeof(v) _v = (v);       \
    typeof(v) _min = (min);   \
    typeof(v) _max = (max);   \
    _v < _min ? _min:         \
    _v > _max ? _max          \
              : v;            \
})

Oh if you are writing C and want to raise your level of abstraction then macros are essential so you may as well lean into them and ignore all the problems the C++ people will tell you about.

That's it at least in this small code base.

C does have some pretty good single header file libraries available. In this game I used stb_image and for anything larger I would probably use the stretchy buffer from the same location. There is also ok_lib if you want a different take on it.

Writing data structures is much easier in C compared to C++ so it doesn't take long to roll you own if needed.

Final thoughts

I actually enjoyed the simplicity of C so will probably do another project in it. Likely another game. One weird plus point is it is easy to stop coding in C. Creating bindings to nearly any language on the planet is easy and so a gradual port to C++/Rust/Zig should be easy if I want to do so.

My willingness to tolerate not great code goes up massively if I can see routes to better places if needed. Along with auto I also missed RAII in a couple of places and std::vector.