
Why I Write Games in C - ingve
http://jonathanwhiting.com/writing/blog/games_in_c/
======
petke
You don't really get rid of complexity by using a simple language. You just
move the complexity into your own code.

Say if your language doesn't have dynamically sized containers, you will end
up writing your own. You hack it so you can store different types in it. You
have reinvented polymorphism. And then you need sort functions, and everything
else that is missing from the language.

And it wont be simple any more. Probably slow and buggy too. But you are not
alone. Everyone has their own private code framework that is too complicated
for anyone else to make use of. If only there was some way to avoid this mess
...

~~~
fennecfoxen
> their own private code framework that is too complicated for anyone else to
> make use of

Well, to be fair, games are one place where code reuse and maintenance by
third parties is less likely to be needed. The real sadness is when you get
corporate websites, technology platforms, and the like that decide they need
their own framework to make their own set of tradeoffs, and do a mediocre job
of it, and end up with a slow buggy bastardization with 15% of the
capabilities of a common well-understood framework. If I had a dollar for
every minute I wasted on something like that... it'd be an accurate
description of a nontrivial portion of my career :b

Bonus points for making this framework to optimize performance, without
actually measuring the performance or setting explicit goals.

~~~
chii
> Well, to be fair, games are one place where code reuse and maintenance by
> third parties is less likely to be needed.

i feel like this is somehow perpetuated like folklore, but there shouldn't be
any reason why game code should be inherently less reusable than other areas
of software development. For example, code that deal with geometry data
shouldn't really be any different for games, or code that deal with setting up
a rendering environment ought to be the same for most, if not all games (i
can't imagine initializing directx or opengl would be different for different
games).

Game logic is one area that is going to change a lot between games. However,
if you partitioned your game logic well, wouldn't it make the next game easier
since you're "just" swapping game logic?

~~~
loup-vaillant
> _code that deal with geometry data shouldn 't really be any different for
> games_

Counter-example:
[http://jonathanwhiting.com/games/knossu/](http://jonathanwhiting.com/games/knossu/)
(Highly recommended if you have 20 minutes to spare.) The geometry of this
game is unlike _any_ I have seen so far. There is common logic with that of a
Doom-like ray caster, but I'd argue not much. The time spent rewriting the
generic parts of a ray caster probably pales in comparison to the specific
parts of his graphics engine.

(Of course, your point stands in general. But for Jonathan Whiting in
particular, I have the feeling that it may not.)

~~~
Ace17
Great game, thank you!

------
hellofunk
>Even more than that I care about the speed of the compiler. I am not a zen
master of focus, and waiting 10+ seconds is wasteful, yes, but more
importantly it breaks my flow. I flick over to Twitter and suddenly 5+ minutes
are gone.

Quick suggestion, has really helped me: take that 10 or 20 seconds waiting for
compilation, and stare out a window. This gives your eyes much needed break
from focusing on a computer monitor, allows the muscles to refocus and
breathe, and doing this regularly during a coding session can have important
long-term benefits for your vision.

~~~
stinos
_10 or 20 seconds waiting for compilation .. but more importantly it breaks my
flow_

Luckliy the OP doesn't build for microprocessors etc. There you wait for
compilation (of C, for instance) but than the damn thing has yet to be
flashed.. Thing is, it actually learns you how to not let it break your flow.
Which is a valuable skill.

~~~
ajdlinux
My day job regularly involves git bisecting the Linux kernel and testing it on
a hardware platform that can take up to 10 minutes to reboot. If I find a new
bug introduced in an -rc1, that can be the better part of my afternoon gone
just in bisection...

------
raverbashing
I understand the want for simplicity in C (and Go gets closer, but has its
issues), however, it seems in the end it drags you down.

Just having the C++ ability to have objects doing things is very helpful. But
yeah, C++ has the ability to get very complicated

But it's your choice to have "complicated C++". Limit yourself to some
functionalities and it's much more manageable.

Use basic STL and keep it simple (also C++11 at least) and it's a very
pleasant experience (or less worse experience, depending on your point of
view).

~~~
crafn
There are some arguments to stick with C instead of a very C-like subset of
C++. Off the top of my head:

\- Recompiling and reloading parts of your game at run-time is quite easy in
C. In C++ you have to make sure (at least) that nobody has pointers to vtables
of the dll at the time of reload. This can be a bit tricky if you're using
things like std::function in your dll code. Yes, you could be using a
scripting language, but thinking how to match the semantics of a scripting
language with your engine, where to draw the line, and then write the glue
code is a lot more work than just reloading some plain C functions. And if you
later decide this was a bad/worthless idea, reverting from dynamic C code to
static is almost a no-op, whereas reverting back from scripts is dreadful.

\- A quick & dirty reflection is easy when you don't have to deal with name
mangling, templates, and overloading. Just some script scanning through your
code and outputting elementary type info to .c file may be enough for things
like real-time memory browser-editor for your whole engine. This can be very
valuable when developing new engine features, as you can view and edit, and
maybe draw even graphs of members you just added to some struct. Also useful
for modifying game object data on the fly when debugging/creating levels.

(I too do my game programming in C)

~~~
hellofunk
>Recompiling and reloading parts of your game at run-time is quite easy in C.

This is cool to hear. I've never done anything like this, but it almost sounds
like REPL-driven development is a possibility in C?

~~~
adrusi
Check out the first few episodes of Casey Muratori's Handmade Hero series
where he implements an extremely simple hot code reloading system in C
(actually C++, but he doesn't use almost any C++ features, certainly not
vtables).

~~~
chii
if you don't want to watch the video, here is a basic overview tldw; of the
technique:

on every run of the game loop(usually every frame), reload a dynamically
linked module (dll for windows, .so for linux), which contains the actual code
you want to run every frame. The function you then invoke from the module must
be passed the entire block of memory allocated for the game state. You then
just recompile the dll/so module when you make a change, and the game would
execute the new code on the next frame. Adding new data structures is OK as
long as you don't mangle an existing data structure...but because a game can
expect to work with a constant block of pre-allocated memory, this actually
works fine most of the time...

~~~
hellofunk
I assume you'd be using techniques discussed here?

[http://stackoverflow.com/questions/384121/creating-a-
module-...](http://stackoverflow.com/questions/384121/creating-a-module-
system-dynamic-loading-in-c)

~~~
chii
yes - but different OS have different ways to load dynamically linked modules,
and the casey video only showed the windows method. But it's basically the
same, just library calls differently named.

------
dom96
How about Nim? [1] [2]

To me it is in many ways a "nicer and safer C". Sure it's not as mature as C,
but what is? What it does have going for it is portability (it compiles to C
so it shares C's portability), a soft real-time GC which can be manually
controlled [3], generics, AST macros and much more.

1: [http://nim-lang.org](http://nim-lang.org)

2: [https://github.com/nim-lang/nim](https://github.com/nim-lang/nim)

3: [http://nim-lang.org/docs/gc.html#realtime-support](http://nim-
lang.org/docs/gc.html#realtime-support)

~~~
vidarh
I can't speak for the article writer of course, but the Python-like syntax /
significant indentation would be a deal-breaker for me. I'd suffer through a
lot to avoid that. And back when I used C a lot myself, I found that even more
objectionable. I often care more about syntax than many other language
features - with a good syntax you can sugar over a lot of other deficiencies,
but a syntax you dislike will stare you in the face every moment you use the
language.

~~~
dom96
I am in some ways the same, but the other way around. I like Python-like
syntax more than C-like syntax. But not to the same extreme as you, I wouldn't
mind using a language with a C-like syntax.

What are your reasons for disliking Python-like syntax?

~~~
vidarh
I want strong visual cues for the end of blocks most importantly. And I want
the freedom to adjust indentation in ways that to me improve readability
without consideration of whether or not it matches language expectations.

But also because I've yet to work in any environment where broken indentation
due to tools with different ideas about how to handle it has not been a
regular occurrence - indentation is brittle.

~~~
lobster_johnson
I think Haskell gets whitespace-sensitive indentation right. It is a lot less
strict than Python, and if you didn't know it was whitespace-based you
wouldn't necessarily realize it. Thanks to the functional nature of the
language, the "hanging block" problem you have in Python (where the lack of an
explicit end construct has blocks indent but never "close") doesn't really
exist.

~~~
vidarh
I wouldn't know - I gave up on Haskell because of the cryptic syntax long
before I got to the stage of hating on smaller syntactic details... I love a
lot of concepts from functional programming, but I wish I could get them in a
language with a syntax more like Ruby and very much less than Haskell.

------
AndyKelley
The thing I miss most in C when I don't cheat and use a couple C++ features is
templates. Specifically, a dynamically sized List implementation that is type-
generic.

If you do this in pure C, you have to pick your poison:

1\. preprocessor abuse

2\. void *

3\. multiple redundant implementations of the data structure

Dynamically sized lists are used so often, that this tends to be a problem in
almost every C project. I wonder what the author's solution is to this
dilemma.

~~~
abcd_f
BAH!

4\. The "intrusive" containers, but of course.

The one true way to do it in C.

For one, you can keep items in multiple containers, all being on equal
footing. None of that typical C++ mess, when _this list_ is a primary storage
for items, and _those maps_ are secondary indexes, all sprinkled evenly with
iterators. Intrusive containers don't _own_ items, they merely _organize_
them, which is exactly the right way to go about it.

For two, the actual code for container operations is as abstract and on-point
as it gets as it focuses solely on "weaving" items into and out of a container
rather than on other things, like de/allocating supporting structures.

For three, you get no heap activity when adding/removing items to/from a
container. This means that if you already have the items, you can always
arrange them into a collection. This also eliminates a lot of error handling
code, leading to a simpler code.

Obviously, this is not limited to just linked lists.

[1]
[http://www.makelinux.net/ldd3/chp-11-sect-5](http://www.makelinux.net/ldd3/chp-11-sect-5)
(

~~~
zodiac
What is an intrusive container?

~~~
exDM69
A technique commonly used in C, for example in the Linux kernel. You embed
"links" to other nodes in your structs, and find the struct from the link
based on offsetof. Linux kernel uses linked lists and red-black trees this
way. Probably other data structures too.

Intrusive containers are cache friendly and typically require no dynamic
allocations (in addition to allocating the data itself).

See the link in the post above for more about linked lists in the linux
kernel.

~~~
charlieflowers
Interesting. At first I thought you were claiming this technique made linked
lists cache friendly. After looking at it, I have concluded you meant merely
that the next and prev pointers are near your data. Am I understanding you
correctly?

~~~
krakensden
That's my understanding too. Instead of going to your data structure, and then
dereferencing a pointer to your data, after going to your data structure,
you're already there.

------
cies
Because he claims that reducing the possibility for bug is a main concern I
feel two languages, in his nicely written write-up, are left out:

Rust -- low-level like C, fast like C, more modern than C, specific ways to
reduce categories of bugs (borrow checker), promotes a more functional way for
programming

Haskell -- not as low-level as C, but pretty fast (best possible performance
was not his main concern), many ways to reduce categories of bugs that can
arise

For game dev't you'll find both have maintained bindings to SDL2.

~~~
ksk
Do you have any examples of AAA games (or even major indie ones) that use Rust
or Haskell?

Often I find that when people recommend a technology for game development, no
professional game studios ever seem to use them. I'd love to be proven wrong
though...

~~~
pjmlp
Professional game studios only change when forced to do so.

It was straight Assembly until console and OS SDK became mostly C.

Then it was straigh C until the said SDKs became C++.

Nowadays it will be C++ until they get forced to change again.

~~~
ksk
In your mind who is forcing them and why?

~~~
pjmlp
I said it on my comment already, OS and console vendors SDKs.

Contrary to common belief among current generation of young developers, C
compilers did not always generated good code.

In the 8 and 16 bit days, proper games were done in Assembly. Any language you
can think of, were the managed languages of the day.

At the end of the 16bit days, C had widespread enough outside UNIX, that OS
vendors started adopting it. So SDKs were then in C.

So many were forced to use C, even if their code was mainly composed of C
functions wrapping inline Assembly.

Similarly, around the PS3 time, SDKs started to move to C++. So many didn't
had other options than moving along to C++ compilers. But, just like the
Assembly generation, many still use mainly C code compiled by a C++ compiler.

So when an OS or console vendor says the language X is the platform's
language, they either adopt it, even if only partially, or ignore the platform
until they cannot avoid it anymore.

------
Tistel
C++ compile and link time. I once worked on a PS3 game that had a 50 minute
turnaround time (change code -> compile -> link -> load). No scripting either.
The horror. It was because the company had home brewed a bunch of
"optimizations" into the build process.

On the up side it will force you to learn to live edit the game with the
debugger to tweak and adjust.

If its C++ and the programmers know the engineering KISS adage it can be ok. I
have seen so much horrible needlessly complex C++. So bad you are pleasantly
surprised it runs at all. C++ so bad and unpleasant to work on it makes you
question why you are a programmer at all.

 _sigh_

Then you write some python, C, ruby or lisp (or scheme, or clojure) and your
like: "oh, now I remember why i do this again, this is so much fun!"

I like the simplicity of C too. You can have a good mental model right down
the CPU of what is going on. But these days given how fast CPUs are and how
much more productive you can be in a high level language (python is 10x more
productive than C++, apparently) I think a garbage collected high level
language is the way to go.

If I accept their offer, my next job will be using Golang.

~~~
pcwalton
> I like the simplicity of C too. You can have a good mental model right down
> the CPU of what is going on.

Not really, with compilers as sophisticated as they are and the spec as
liberal with undefined behavior as it is. The C virtual machine that the spec
defines is every bit as complex as any other virtual machine.

> But these days given how fast CPUs are and how much more productive you can
> be in a high level language (python is 10x more productive than C++,
> apparently) I think a garbage collected high level language is the way to
> go.

I totally agree. In fact, I wouldn't use C even for projects where a GC isn't
suitable, just because we have alternatives now and it's so difficult to write
programs free of basic memory management mistakes we've been making since the
80s.

~~~
bluecalm
>>Not really, with compilers as sophisticated as they are and the spec as
liberal with undefined behavior as it is. The C virtual machine that the spec
defines is every bit as complex as any other virtual machine.

Having some undefined behavior in your code is just a bug, it has nothing to
do with being complicated or compiling to machine code. It's not nearly as
complex, in fact there are many people who understand quite well what the code
compiles to. You can read the assembly as well and understand it for big parts
of the code (oh, it compiled it to that, vectorized this but didn't vectorized
that etc.). Try guessing what Java compiles to. It's not even close to the
same level of complexity.

>>I totally agree. In fact, I wouldn't use C even for projects where a GC
isn't suitable, just because we have alternatives

The only serious alternative as of today is C++. Rust is a new untested
language which no one wrote anything quite serious in yet and which offers a
lot of trade-offs in exchange for being safer, everything else is slow as
hell.

~~~
pcwalton
> Having some undefined behavior in your code is just a bug, it has nothing to
> do with being complicated or compiling to machine code.

In theory, yes. In practice, all C/C++ programs have undefined behavior in
them, so you have to understand what compilers do to _really_ understand your
code.

> It's not nearly as complex, in fact there are many people who understand
> quite well what the code compiles to.

Not true in my experience. The only people who really understand it are, by
and large, compiler developers. There are very few compiler developers.

> Try guessing what Java compiles to.

I know what Java compiles to more or less as well as I know what C++ compiles
to. The only real difference is in GC (which is quite simple--inline a nursery
bump and fall back to a malloc-like slow path if it fails) and ICs, which are
a lot less complicated than things like alias-analysis-sensitive load
forwarding.

~~~
fanf2
Re. undefined behaviour, this fairly definitive paper agrees that it has gone
too far: [http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n1637.pdf](http://www.open-
std.org/jtc1/sc22/wg14/www/docs/n1637.pdf)

------
djur
> I would like to use [Go], but there are big roadblocks that prevent me. The
> stop-the-world garbage collection is a big pain for games, stopping the
> world is something you can't really afford to do.

GC pauses in Go should not be a serious issue for games like the ones featured
on the OP's site. The same general techniques used for high-performance manual
memory management work fine in garbage-collected languages -- allocate on the
stack if possible, allocate the heap you're going to need up front and reuse
it (with object pools or the like).

> The library support for games is quite poor

I would say the same for C, honestly. Last time I was looking for game
libraries to write a binding to (from OCaml) I found more C++ and Java options
than C.

~~~
jeremyjh
>I would say the same for C, honestly.

Really? SDL is quite poor??? It has bindings in pretty much every language and
I would guess is the most popular game library in existence, written in pure
C. It is not a game engine but is an excellent library to build one with. It
is so popular for this purpose that it has its own COLUMN in the Wikipdia
table of game engines:

[https://en.wikipedia.org/wiki/List_of_game_engines](https://en.wikipedia.org/wiki/List_of_game_engines)

~~~
strangecasts
Another nice library is SFML[1], which has bindings for C and several other
languages (including OCaml).

[1]: [http://www.sfml-dev.org/](http://www.sfml-dev.org/)

~~~
seba_dos1
There's also Allegro[1]. While its popularity peak was on older versions,
Allegro 5 has been completely redesigned and it's a pretty great modern C
library now.

[1]: [http://liballeg.org/](http://liballeg.org/)

------
jaked89
"C# ... does a lot to railroad a programmer into a strongly OOP style that I
am opposed to".

C# has functional capabilities as well. People write in it nowadays in a whole
lot of different styles, including procedural, OO, functional, reactive.

Yes, the average developer uses it in an OO style, but it can do a lot more.

~~~
gregmac
His argument against OOP makes it sound to me more like he's using OOP design
patterns he doesn't like:

> I've spent most of my professional life working with classes and objects,
> but the more time I spend, the less I understand why you'd want to combine
> code and data so rigidly. I want to handle data as data and write the code
> that best fits a particular situation.

To put it simply, I find when using DTOs to store data, and following SOLID
principles to write the rest of the code, I end up with quite clean code that
provides a very nice separation of code and data, and that the right level of
abstraction and loose coupling is exactly what allows me to write the code
that best fits a particular situation. Granted, I don't write games, but I do
write high-performance, highly-distributed multi-threaded applications where
clean and fast connectivity between components is very important, and the
ability to unit test basically everything is essential.

I guess to characterize OOP as 'combining code and data rigidly' is just so
far off base from my style of OOP and my experience that I really can't
identify with this as a reason to drop to C.

~~~
mobiuscog
Exactly - After all, you don't put all your code in a single C file.

Using classes as simple modules - encapsulating a set of functionality - can
still lead to a very procedural style without all of the extras.

------
_ph_
The article mixes up the virtues of a programming language with the quality of
the environment. C might very well be the best language in our current
environment, which says little about the language itself. One major point
certainly is, that it is that good compilers are available everywhere and
almost any library can be used from C. There are a lot of historic reasons for
that.

If he wants strict typing, C is actually much worse than many languages of its
time. But it is certainly stricter than Javascript.

GCs and gaming are of course a challenge, but with the new GC of Go1.5 and
hopefully futher improvements, it might actually become a very good language
for gaming, especially if there is a better support with libraries. But if one
wants good type checking, a simple language model and fast compilation times,
it checks all the boxes.

~~~
dottrap
The Google Go team lives in a completely different environment. Their
perspective of performance is not the same as a game dev. Go 1.5 stated their
goal was 10ms GC latency. A game loop is 16ms for a 60fps game. 10ms is not
close to acceptable. Fast for a web server backend, but not fast for a game.

~~~
_ph_
I have not experimented with the Go GC under heavy loads yet, but the
important points of 1.5 are, that the GC pauses have an upper limit of about
10ms for multi-gigabyte heaps - previously they could be up to a second, and
often are much faster (in a game environment with smaller heaps, they might
actually as low as 1ms, which would be acceptable). I wrote, that there might
be further tweaks required, i.e. having an API to call the GC for a set number
of milliseconds. If your code isn't 100% using the time slice for each frame,
it could use the remaining part of each time slice for garbage collection,
eliminating the need for blocking stops. So, whether Go is acceptable now
entirely would depend on some measurements. And if not, could be possibly
tweaked. As I wrote, I would rather count this under "environment" where C
might still win.

------
bproctor
The language wars get exhausting. Several years ago Ruby was the coolest thing
ever, now I guess people think it's just boring. Also, PHP got really
unpopular and all you heard about was how it would kill your dog and sacrifice
it to satan. Now days it's still cool to look down on those who use it, but
you shouldn't talk about it. Don't know know all "real" devs program in
Python? Go was short lived, a year or two ago it was the greatest thing ever
and now all you hear about is how much it sucks. The latest trendy thing is
Rust. Rust is our new savior. I wonder how long that will last before
something else comes along as the coolest thing ever. Maybe Brainfuck for it's
simple syntax?

~~~
cdelsolar
who says Go sucks?

------
hellofunk
Since game development often requires interfacing with robust C++ libraries in
graphics or physics (i.e. Bullet), I'm curious how you do that... are you
either not using physics or writing your own basics physics engine? Or, are
you writing parts of your app in c++ just to wrap the interface in a way you
can do the rest of the work in C?

~~~
rhodysurf
Its trivial to expose a C interface from C++ and I would guess most game
libraries have an api

~~~
hellofunk
It's not as trivial as you would think. I'm reading through the long
discussions from the Bullet developers, and clearly it's not just a short
project.

------
shurcooL
> The library support [in Go] for games is quite poor,

I'd like to know the author's familiarity of Go libraries. Perhaps he's
unaware of what does exist and makes false claims, or perhaps he's saying
accurate statements and just has really high standards.

I help maintain many of the Go libraries/wrappers for games, so I might be
biased, but I'm happy with what is available. Almost more so than when I was
using C++, because Go packages can be made go-gettable and very easy to
include and distribute, unlike with C++.

I've also not hit GC problems so far, but arguably my games are just not
demanding enough yet.

~~~
synthmeat
I'd like to pick your brain in real-time, but, in a nutshell, how far do you
think Go game ecosystem is from something like Corona, LibGDX, Haxe? Have SDL,
OpenGL wrappers stabilized, are there native ports? Any frameworks that might
be considered close to production-ready?

~~~
shurcooL
OpenGL libraries have definitely stabilized and have been that way for
multiple years now. GLFW 3 wrapper is go-gettable (some years ago, it required
manual installation of the C library separately, now you just go get it). I
don't use SDL so I don't know much about it.

I don't know if there are complete frameworks or engines that are finished,
but there are some works in process.

[https://github.com/avelino/awesome-
go#opengl](https://github.com/avelino/awesome-go#opengl)

[https://github.com/avelino/awesome-go#game-
development](https://github.com/avelino/awesome-go#game-development)

------
mpdehaan2
I've had this thought quite a few times.

Basically, if you want your software to last and work on lots of platforms
(particularly if it is a game you put a lot of love into), using a lot of
dependencies you worry about it.

I know I've written some things - not even games, that would be a major chore
to port.

But C and OpenGL APIs are still going to be there, and there's a nice feeling
of quietness when it's just you, libraries you know are going to be stable,
and the code, and not having to wonder "is this fully baked?" or "which one of
these libs is the best".

You can almost get paralyzed in finding the ideal tools and libs to use and
keeping up with all of them. Whereas if you limit yourself to just what comes
with the language (and maybe a few small things) a side project can be a lot
more fun.

A side project is also often about the journey, not the destination, and
people can get a lot of mileage out of building incredibly complicated weird
things that not many people will know are even there (I don't really know how
to play Dwarf Fortress and don't play it, but the idea of the history
generator, terrain generator, and so on... all that runs before you play the
game strike me as great examples - the kind of thought that this is incredibly
impractical and therefore must have been a ton of fun to write)>

------
antaviana
Delphi compiles extremely fast, is strongly typed, no GC, has templates,
objects. Too bad Embarcadero positioning towards Enterprise with its
relatively high pricing effectively derailed it as a mainstream language and
killed its community.

~~~
egonelbre
And doesn't have console support (AFAIK).

~~~
clouddrover
If iOS and Android devices count as consoles (and I think some of them do)
then Delphi has console support. :)

Free Pascal ([http://www.freepascal.org/](http://www.freepascal.org/)) says it
supports the Nintendo GBA, Nintendo DS and the Nintendo Wii (to what extent
and how well I don't know, never tried it). It also supports Win32, Win64 and
FreeBSD so I suppose it could be made to work on the PS4 and XBox One without
too much trouble.

A real strength of Object Pascal is that it can be as low level (inline
assembly, manual memory management, etc) or as high level (OOP, generics, etc)
as you like. It satisfies most of the article's wishlist items.

Today I happened to find a simple but still interesting programming language
feature matrix on Ian Hixie's website:
[http://ian.hixie.ch/programming/](http://ian.hixie.ch/programming/)

He'll have to update the Execution column for Free Pascal to be both "Native"
and "VM" since Free Pascal 3.0 can now also compile to JVM byte code:
[http://wiki.freepascal.org/FPC_JVM](http://wiki.freepascal.org/FPC_JVM)

------
Mikeb85
He mentioned a bunch of languages, and I'm not sure why he doesn't look into
something like Kotlin. It's the JVM so you get maturity and it's fast as hell
(ran a few economics-related benchmarks on my machine, OpenJDK 8 beat both C++
and Fortran!), has great IDE support (Intellij IDEA - which will actually
translate Java into Kotlin if you want to translate snippets), and it doesn't
strong-arm you into an OO style. And of course Lwjgl 3 is written mostly in
Kotlin.

If he liked Flash, I'm also surprised he didn't go with Haxe. It's fairly
mature, is a very nice language (Swift looks like it was mostly ripped from
Haxe), with OpenFL he gets the Flash API (but can also compile to native or
JS), and of course Haxe also has other frameworks available, or can even be
used with native frameworks quite easily.

Anyhow, as far as C goes, it's a decent enough choice. It's simple enough, if
you don't mind writing helpers for various tasks and building your own
libraries then why the hell not. I definitely prefer the typical C style of
programming to the prevailing C++ style.

~~~
ZoFreX
Making games on the JVM is a lot of fun, but the garbage collector does limit
what you can do (the OP mentions this as one of the drawbacks of Go).

~~~
Mikeb85
Does it though? Java's garbage collector is very mature and can be tuned any
which way. It's definitely more mature than Go's (although Go's is getting
better all the time).

Not to mention, Unity uses a garbage collector (for all the C# bits, which is
a very significant part), as does Unreal (their own written in C++), and even
game-oriented languages like Flash and Haxe have garbage collectors. I'm not
sure it's as big a problem as popular wisdom would state.

Edit - here's some documentation from Oracle about tuning the GC:
[https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gc...](https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/ergonomics.html#sthref12)

~~~
ZoFreX
It's entirely possible I'm behind the times, I haven't attempted game
programming on the JVM in a long time.

------
johnydepp
I write games as well (Written more than 10 games, though they are not very
large at scale) and I write them in C++. Reasons being writing networking code
(TCP/UDP) is much easier & efficient in C/C++ than any other language IMHO.
And most of the code works across platforms.

~~~
seba_dos1
Just my 5 cents: Although there's nothing wrong with it in the context of your
comment alone, C and C++ are so distinct languages it's weird to see them
aggregated as "C/C++" given that the article is about C and it explicitly
recognizes C++ as a bad alternative.

~~~
johnydepp
The article doesn't say C++ is a bad alternative. Just that he did not use it
to avoid complexity.

And yes C and C++ are distinct. But the simple modules can be written in C,
but the bigger ones need OOPS, so generally written in C++.

------
drawkbox
> _I can 't afford to spend my time dealing with bugs I didn't cause myself_

It is very frustrating to deal with bugs introduced by others, a product or
engine changes that you aren't aware of. But you have to balance that with how
much you can get done in your own engine/tech with the time wasted from bugs,
and how much time you want to spend on tech vs games.

For 2D games, building your engine is probably doable with lots of small kits
like physics libs (box2D, bullet, etc), libgdx, sdl etc but for 3D games and
certain titles, a single person working on an engine is difficult, tons of
work on the tech side. So the balance is key, whatever makes you able to ship
more often is probably the best choice.

Unity is used by many people and does have very frustrating releases that
aren't solid many times. Recently 5.3, 5.3.1 [1] all have issues. For a long
time in 2015 the IL2CPP iOS versions were broken. But doing it alone you get
caught in a tech swamp instead of making games if you aren't careful and
limiting. There will be times where your engine product or team or yourself is
wading tech changes that are needed and take time away from game making.
During the period of IL2CPP and Unity bugs, games could still be developed in
parallel and for other platforms, so this is a benefit even though there are
bugs.

Even when we do engine or platform based games it is a good idea to keep it as
platform agnostic as possible. In Unity this might be keeping all source
assets, using less MonoBehaviours, storing/loading data in JSON/web formats
rather than in serialize prefabs. Anything that locks your game into one
engine too much one should be careful of to limit your surface area of
exposure to bugs by the engine. For a long time other UI libraries ruled Unity
before they made their new UI, it is still a bit buggy but better. For a long
time Mecanim was not very solid and many still use legacy animation. The newer
Shuriken particle systems are awesome but not as accessible in code and had
scale limitations for a long time. You just have to see where areas are solid
and not venture into areas prone to bugs in your own engines or existing
engine platforms for shipping games like Unity/Unreal etc.

[1] [http://forum.unity3d.com/threads/unity-5-3-1f1-particle-
syst...](http://forum.unity3d.com/threads/unity-5-3-1f1-particle-system-
errors-invalid-aabb-result-isfinite-d.374926/#post-2432662)

------
jokoon
To me lambdas justifies using C++ while still coding in a C style.

Although my wet dream would a C language with map, vector and other
containers, a simpler build system (no more headers), more nice syntactic
sugar, and an interactive mode... I'd gladly see a language that break C
compatibility for this.

~~~
dottrap
Swift might hit all your bullet points there. It breaks from C compatibility,
but it has really impressive C bridging/interop.

------
swah
This is exactly what Casey talks about on handmade hero.

------
RaitoBezarius
What about Rust?

~~~
AndyKelley
I like Rust, but sometimes it is pretty difficult to convince the compiler
that one's code is safe. And this does not mean that the compiler is
preventing unsafety; there are many safe programs that the compiler rejects.

Also, the OP said that compile time was a priority, and compiling Rust code is
closer to C++ speed than C.

~~~
pcwalton
> And this does not mean that the compiler is preventing unsafety; there are
> many safe programs that the compiler rejects.

Two nits:

1\. The compiler _does_ prevent safety problems. It just happens to rule out
some safe programs while doing so. (Although I think this is a bit of a
misconception, because with the aliasing rules being used for optimization
many things that the Rust compiler rejects that people think are safe are
actually not.)

2\. You can describe any type system this way. That doesn't mean we don't like
type systems.

~~~
Jach
I think game programmers don't like type systems -- or rather, they prefer the
minimal typing necessary for speed improvements and their ability to simplify
basic static analysis (with tools or in their heads). I don't blame them,
games are a lot of work even for relatively simple things, and to get anything
done at a reasonable pace you just need to be able to churn out lots of code
that compiles on the first try, and when it doesn't the mistakes should be
easy to fix and minimize the time you're spending fighting with the type
system (C++ templates come to mind as they're often avoided in games no small
reason being the cryptic error messages they can produce). There might be an
argument of familiarity, that eventually if they used Rust or Haskell enough
it would all come to them as easy as C, but then well known Haskell promoters
say things like "if you're using the type system right your code will never
compile on the first time."

~~~
tome
> the mistakes should be easy to fix and minimize the time you're spending
> fighting with the type system

In Haskell you don't fight the type system. It fights your bugs.

[Yes, yes, this isn't an absolute truth, but it is a relative truth when the
point of reference is C++'s, or even Java's, type system.]

------
SunShiranui
I don't share some of the needs the author has, however, for game development,
I like to use Haxe. Mainly because it allows for very easy crossplatform
development (to both PC and mobile OSes)

------
weavejester
Are GC pauses really significant? I can understand there being problems if you
have to churn through gigabytes of world data, but the author's games don't
appear to be on that scale.

~~~
0xcde4c3db
They often are if specific care is not taken to minimize garbage in the game
loop, particularly in resource-constrained environments like some console and
mobile platforms [1]. In GC languages, this often means deliberately avoiding
common idioms that perform allocation under the hood.

The threshold for a noticeable pause is much lower for action games than it is
for general applications. 100ms is often used as a rule-of-thumb
"instantaneous reaction" threshold for general UX [2], but that's a lot of
time to a highly competitive player (e.g. this guy playing Super Punch-Out
blindfolded [3]).

In fact, in high-reliability real-time software, even non-GC heap allocation
is often avoided (or done once at startup and then left alone). Heap
allocation is not a very predictable operation beyond "probably fast enough".

[1] [https://stackoverflow.com/questions/5063190/game-jitters-
on-...](https://stackoverflow.com/questions/5063190/game-jitters-on-xbox360)

[2] [https://www.nngroup.com/articles/response-
times-3-important-...](https://www.nngroup.com/articles/response-
times-3-important-limits/)

[3] [https://youtu.be/vSr3aXd4XuQ?t=358](https://youtu.be/vSr3aXd4XuQ?t=358)

~~~
weavejester
I can see that you'd probably have to take care on mobile and older platforms,
and with resource-heavy games. But I have difficulty imaging that there'd be
much issue with anything else, as long as the code wasn't overly terrible.

Do you happen to know of any benchmarks, or non-anecdotal evidence?

------
moron4hire
Incidentally, all of his reasons that don't misrepresent C are all the same
reasons I write games in JavaScript. Mostly, it's about speed of development,
understanding, and platform compatability. Performance is good enough and
almost always my fault when it isn't.

I wish for a strictly typed language, but OP isn't using one, either. I've
tried several of the transpilers and have generally found the workflow lacking
in one way or another.

~~~
seanwilson
Did you try Typescript? I'm curious what you thought of it for games if you
tried it. I enjoyed using Cocos2D JavaScript bindings for cross-platform game
development.

~~~
moron4hire
Found it difficult to integrate with existing JS, such as THREE.js. Also found
it difficult to create libraries (I make a RAD workflow for VR apps) that
could be used in arbitrary JS projects; I want people to be able to drop my
concatenated script into their page with a script tag and not have to worry
sbout anything else. Also, early on I ran into quality issues with the 3rd
party type mappings for popular libraries, and eventually decided it wasn't
worth the hassle.

Generally speaking, gradual typing doesn't get me excited. I don't think there
is a payoff to having some of your code statically typed and others not. The
mismatch between the two causes problems. So TypeScript, et al are an all-or-
nothing proposition, and there were big chunks in my workflow that prevented
it from being "all".

If you choose to embrace dynamic code, you can write less of it and minimize
your surface area to bugs. I'd prefer static checking and more code because of
stricter typing, but dynamic can be done well in its own right if you approach
it at a much higher, metaprogramming level. Don't half-ass two programming
styles. Whole-ass one.

I also missed the fast-reload workflow of native JS. I sometimes live-edit
code in the browser, and being able to go back and forth between the two with
no hiccups is nice.

So while a lib layout e.g. THREE.js is "old", it at least works without major
machinations on the most systems for the most implementing developers.

I might start using more ES6 features, as I could use native browser support
in my browser of choice for development and a transpiler to pack up packages
for deployment. But I won't be going to a language that gets between me and
the browser.

Contemporary webdev workflow is designed for either A) automated setup and
execution of scripts in remote, headless environments or B) getting beginners
gluing libraries together quickly. These are frequently not the same thing as
a great developer experience.

~~~
xixixao
You should give Flow a try, seems it would fit your requirements from typing
point of view. You'll see whether it'll be fast enough for you.

~~~
moron4hire
You will have to provide a link, because Googling revealed only a long-dead
project with a Chinese website and an empty GitHub repo.

~~~
kenOfYugen
flowtype.org

------
je42
no auto in C. no standardized data structures. no lambda. no exceptions. and
C++ still compiles actually fast. at least on my machine.

~~~
lmedinas
For years developers used C++ without most of these features and built great
code. So this is not the problem of C. There are still lot's of great code
done in C.

~~~
je42
Really ? Look at this code:
[https://github.com/danfis/libccd/blob/master/src/ccd.c](https://github.com/danfis/libccd/blob/master/src/ccd.c)
Looks like great C code doesn't it?

Still you see lots of plumbing: 1\. call of init functions 2\. unsafe
array/pointer usage 3\. goto

I rather use C++'s functional constructs rather than the imperative ones. It
is less code, that directly self-explains the business logic; instead of being
littered with (unsafe) plumbing code.

And IF I find a performance bottleneck - I can still opt to use/develop an
unsafe lowlevel version.

------
hjek
Absolutely amazing games on the webpage, especially Knossu, a "A non-euclidean
horror game." Crisp and trippy graphics and sounds. Good gameplay, no
"installation" required.

But running a closed-source binary can be a bit sketchy; whereas you don't
have to trust a publisher to the same degree running a game in the browser.

------
BatFastard
Flash is not dead. It's the ONLY plugin left that works in all desktop
browsers, and works on Mobile phone. Facebook supports it, more and more who
have started in HTML5 have lived to regret the day. For many years I was a C++
snob who totally dismissed Flash, but now I really enjoy actionscript

I am working with a client who is write a phone app in Flash because of the
low level cross platform abilities and it is awesome! It also lets me build
web based admin tools for the backend really quickly. Only negative thing I
can say about it is the garbage collection is slow...

~~~
mikeash
Flash doesn't work in most installations of desktop Safari, nor does it work
on iPhones. Many others are fleeing it because of massive ongoing security
problems with it. If you're content with the audience that remains then great,
but it's far from "all."

~~~
BatFastard
Flash has many colors now, on mobile phones its called Adobe AIR. And it just
won the mobile tech of the year award as CES.

------
lugus35
I thought Lua was great for games development, the author does not mention it.

[http://www.lua.org](http://www.lua.org)

~~~
cookiecaper
Lua is widely used as a scripting layer on top of a game engine. The intense
calculations needed to generate a high-fidelity simulation like graphics and
physics are usually implemented in the engine in C++, and then the game
logic/item behavior/etc. is defined in Lua. I haven't heard of anyone using
pure Lua for a whole game, including the engine. It'd be really interesting to
see what it looked like if someone did so.

~~~
nunodonato
there are plenty of games using pure Lua. www.love2d.org :)

~~~
lbenes
No, Only the scripting is Lua. The engine is all in C++.[1]

[1]
[https://bitbucket.org/rude/love/src/tip/src/](https://bitbucket.org/rude/love/src/tip/src/)

~~~
krylon
After all, that's kind of the point of Lua. Write all of the performance-
critical / low-level stuff in C or C++, expose it to Lua, then orchestrate it
from a Lua script. Lua's C API is very pleasant to use.

As a standalone scripting language, I found it rather awkward to use when
compared to, say, Python or Perl. It was only when using it as an embedded
scripting language (not on a game, though) that I could really see it shine.

------
Ace17
Simplicity of a programming language, and simplicity of programs written in it
are two very different beasts.

I understand funny things happening under the hood (garbage collection) might
not look attractive ; However you can't require everything to be explicit and,
at the same time, keep your programs simple/small.

The more you want your code to be small, the more you're gonna need a
programming environment (language/API/runtime/framework) doing things for you
under the hood. And there's nothing wrong about it!

~~~
sebcat
> The more you want your code to be small, the more you're gonna need a
> programming environment (language/API/runtime/framework) doing things for
> you under the hood. And there's nothing wrong about it!

Or have your code do one thing and only one thing, a single purpose, with
clear, well defined interfaces and then compose things doing only one thing to
a bigger thing that you can reason about more easily because the interfaces
and processes are well-defined.

One thing I've seen too much of in my professional life is complex projects
trying to do too much, with ill-defined roles and implicit, poorly documented
interfaces.

Simplicity of a language works well as long as your projects are kept simple.
You can build fairly complex solutions by composing multiple simple projects
with well defined interfaces.

I think we agree that simplicity of a language works less well when the scope
of a single project is too large and too arbitrarily defined.

------
oilywater
Static typing and C.

C is very simple and it's missing a Hindley-Milner type system.

If that was a part of it, I'd use it.

C++ wins now, every time. Type safety in C is a pain.

------
rootw0rm
Just mix C and C++ like a regular horrible person would do. An entire game in
C sounds....tedious.

------
cLeEOGPw
I see one of the core reasons C is chosen over C++ is the speed of
compilation. My question would be, to what extent is compilation speed
relevant? What time differences are we talking about? I agree that every
second counts, and I understand that fast compilation just feels good to work
with for a hobby project, but what serious relevancy it has? At least the way
I do it is divide program (a game for example) into several projects and
compile them into dll's, this way compilation time is drastically reduced and
with a side benefit of clear separation of different parts of the program.

~~~
loup-vaillant
Most C++ projects I have worked with, regardless of their size, had re-
compilation times that routinely exceeded 20, sometimes 30 seconds. There are
various reasons for this, among which uncontrolled use of templates and nested
header inclusions where a forward declaration would have sufficed.

C, with its simpler grammar and the absence of template, tend to re-compile
under 5seconds even for sizeable projects.

~~~
cLeEOGPw
So, roughly speaking, you can expect for a difference in the order of tens of
seconds. But my question was, how relevant is this? At least in my experience,
and I have worked with projects that took up to 50 minutes to fully recompile
(before we moved to newer ms compiler) when taking all dlls, the full
recompilation is rarely required. Sometimes you have to recompile project,
which can take minute or so, but most often you do incremental compilations
that barely takes a second. So for me it's hard to imagine compile time having
considerable impact on delivery. Most of the time is used while reading the
code and thinking how to solve a problem, not typing the keyboard and waiting
for compilation to finish. And I would argue that properly written C++ can
greatly improve the biggest part of work - reading and understanding the code.
I admit that properly written code is not a given etc., but for personal
project you can write however you want. In the end it's probably more personal
prefference and how confortable you feel rather than strict rational choice. I
think both C and C++ are very close calls, especially considering all the
other choices there are.

~~~
dottrap
As for understandability, I used to work with a lot of EE people building
various equipment that required both hardware/software. Everybody was smart,
but not necessarily an expert in programming. We also used various programming
languages. The rule was keep all code at an "8th grade level" and write
everything like C. Everybody regardless of language background can read C. C
has become the universal pseudo-code.

Nobody agrees on what "properly written C++" is. A colleague with a C++98
background told me C++11 looks like a completely foreign language to him.

------
Kenji
I wanted to program my game in C but then I took notice of how incredibly
comfortable things like Vector and Map are. I never look back again. C is for
plain libraries and OS where compatibility and performance are of utmost
importance.

------
sklogic
Well into C++14, but yet this outdated myth of an unbearable "complexity".
This is not the language you knew.

~~~
Rusky
C++11 and 14 make it possible to avoid or ignore much of the complexity of
old-style C++, but they also introduce plenty of complexity of their own and
they don't deprecate any of the old stuff. It's not a myth.

~~~
sklogic
Yes, but now you can safely use a nice and clean subset without ever touching
any dark corners.

~~~
hellofunk
There are a few new dark corners in modern c++ ... Enough to inspire Scott
Meyers to fill a new book of advice just for the new idioms. C++ is powerful
but complex no matter how you look at it.

------
smegel
Did anyone break it to him that when he writes C, he is writing C++?

~~~
leksak
C is not a true subset of C++ so no, when he is writing C he is writing C.

~~~
moron4hire
Given he is calling C a strictly typed language, I'm not sure the OP really
knows C _that_ well. Sure, it's strictee than, say, PHP. But in the pantheon
of languages, it's not objectively strict.

~~~
leksak
I mentioned this in another comment, as has many others.

------
kilon
C is super slow when it comes to compiling, if you really want fast compiling
take a look at Pascal, around 10 times faster the last time I checked. There
is Free Pascal that is open source and also has a great IDE called Lazarus.
Both much better as a language compared to C and C++ and still close to their
speed.

------
holografix
tl;dr overly comfortable, old school C developer is still worrying about the
death of flash and hanging on to what he knows. Finds reason why he shouldn't
step out of his comfortable zone.

~~~
fsloth
Um, "fast compilation", "hotloading dll:s", "future proof" are all to me valid
and non-trivial technical requirements. Also - there are better languages than
c for lots of things but there is a class of problems (like efficient and
correct numerial code) where c is as good as any language "in the same
category" (unless one counts fortran)

------
leksak
If by "strict typing" you mean strongly typed then you are factually
incorrect. By virtue of casting C is weakly typed, as is Java, C++ et al.

If your understanding of strict typing is statically typed, i.e. that types
are checked at compile time then C still has some flaws as you could write a
whole slew of C that is "typeless" using void * although that would be
terribly misguided.

I understand your intent, but I dislike the ambiguity of the phrasing.

~~~
masklinn
> By virtue of casting C is weakly typed, as is Java, C++ et al.

Java's casts are dynamically checked, memory-safe and only work through the
inheritance hierarchy, if you try to cast to an invalid type you'll get an
error. Putting it in the same class as a C-style cast makes your usage of
"weakly typed" as meaningless as it ever is.

For C++ — ignoring C-style casts — it depends which cast you use, dynamic_cast
requires RTTI but IIRC it offers the same guarantees as Java's cast;
static_cast should check that the types are related and the conversion is
valid at compile-time, reinterpret_cast is the "weakly typed" one (essentially
a simpler version of a C-style cast).

> I understand your intent, but I dislike the ambiguity of the phrasing.

Yet you use the expressions "strongly typed" and "weakly typed"?

~~~
Rusky
There's also a valid distinction to be made between weak typing through
implicit conversions and weak typing through reinterpret_cast. C++ has both
unfortunately, but the second one is often necessary for a low-level language.

------
ivanca
TL;DR Many people is making money doing Unity games, so I ignore it exists -
for $1500 - and I go the hipster way and create my own hundreds of memory
corruption bugs myself.

~~~
scrollaway
If you're going to write a TL;DR for others, you should at least read the
article yourself, don't you think?

~~~
ivanca
I did, it is so abstract to pretend you can do better that there is no way to
discern. He didn't even mention "unity" in his post, thats just ridiculous in
2016, but yeah, keep down voting, your implementation of 2d graphics, sound,
collision, physics, plugins, marketing, sprites, menus is gonna be so much
better than hundreds of engineers at unity withing 10 years straight.

~~~
loup-vaillant
Try and implement
[http://jonathanwhiting.com/games/knossu/](http://jonathanwhiting.com/games/knossu/)
with Unity.

My guess is, the author would have taken more time learning Unity than
implementing this game.

~~~
Jach
I'm looking forward to playing that next time I boot into Windows (couldn't
get it to even create a window on my Linux machine after satisfying its
dynamic dependencies (really old libpng for one), or even the Windows exe via
Wine -- one of the perils of custom engine development) but I know Antichamber
([http://www.antichamber-game.com/](http://www.antichamber-game.com/)), which
has the similar concept of a non-Euclidean world, was built in Unreal. Unreal
is pretty different from Unity, and I know neither of them well, but I think
it shouldn't be all that difficult once you know Unity. And a lot of what I
briefly looked at on Youtube for Knossu looks like shader heavy lifting,
rather independent of the core engine.

~~~
loup-vaillant
From the author of Knossu himself here
[http://jonathanwhiting.com/games/knossu/press.html](http://jonathanwhiting.com/games/knossu/press.html)

> _[Knossu is] an answer to the question: What can you do with a Doom style
> raycasting engine if you 're tired of realism and shooting things?_

So it's a Ray caster. Which you can confirm by playing the game and looking up
and down: the distortions are typical of a ray-caster.

Too bad you're using an old GNU/Linux distribution. For the record, it worked
out of the box for me (Debian Testing, 32bits).

~~~
Jach
My distro is current (Gentoo), I meant that the game required libpng 1.2 when
libpng current is on the 1.6 branch. (Though apparently the 1.2 branch still
receives security updates so maybe it's not as old as I thought.) On a whim I
tried again by just copying a 32-bit libpng1.2 so from Penumbra, that actually
made it work, but no sound plays. Ah well.

~~~
loup-vaillant
Crap. Why does it even work on my system?

