back
120 comments
Author here. I'm positively surprised, constructive discussion on internet!

There's been some discussion about using Rust.

Rust is an interesting language, and has definitely potential substituting C and C++ in some domains. The main reason I'm not so interested in using it is for game development, is because it's more complicated than C (like C++), and the complications are a bit off from what I'd want (like in C++). Just a quick googling reveals that rust mangles names by default, and doesn't have reflection, so I'd probably be in for a lot of negative surprises. Add that with being indifferent about the absolute security, and soon my code is mostly inside unsafe blocks so that I don't have to spend time convincing the compiler my pointers are safe. Maybe. I haven't done much programming in Rust. There are some nice convenience features though, when comparing to C, but they seem to be rather minor things.

It comes down to choosing between two non-ideal solutions. I value simplicity more than some, so favoring the simpler one feels more natural to me. Sure, when you need the safety then Rust seems like a decent choice.

Only responding to one element of your comment -- but I think that Rust's safety features are over-marketed in my experience. The safety Rust offers is only part of a package that provides high-performance high-level abstractions over functionality that is normally very bit-twiddly in C. So far, my favorite thing about Rust is not its safety, but how easy it is to write good performance software using abstractions that are as convenient as Python (or another high-level language). The safety is just icing on the cake at that point (for me at least).

EDIT: Re: pointers -- Rust is a lot easier to write if you just ignore pointers. Really. Either pass small structs by value or pass references (either immutable or mutable), and let the compiler handle the actual pointer manipulation.

FYI, if you care as much about compilation speed as your post suggests, today's Rust is right out: rustc is considerably slower than C++ compilers for typical workloads in large part because it doesn't have proper incremental rebuilds. That could change in a matter of months, which I'm looking forward to, but it still probably won't be at C level.* And without optimizations, rustc produces considerably worse object code than even C++.

* I could be pleasantly surprised, though. In theory, for incremental builds, based on the general design planned [1], rustc should be able to do better even than C in a lot of cases because only changed functions need to be recompiled rather than entire files; but I'm a pessimist and expect there will be something to make it slow in practice. I could be wrong though.

[1] https://github.com/rust-lang/rfcs/blob/master/text/1298-incr...

I was positively surprised by the constructiveness of the article itself. You'd usually get Linus' style rant about how C++ sucks so bad and C is the epitome of simplicity and design. I wholeheartedly agree with you that both languages are lacking, and I'm also waiting until Rust or another language grows mature enough to replace both of them in most cases.

But I think most of the main points you describe as impossible in C++ are actually completely possible. It means moving away from the 90's paradigm of using C++ to implement deep class hierarchies with design pattern, but after all C++ is a multi-paradigm language. If you can do data-oriented design in C, you could most certainly do it in C++, and the abstractions C++ provides actually make it easier.

In essence, I would separate game objects to a logic instance and state objects (pure structs) and use smart pointers with a generation-counter to point the logic instance, which in turn would have smart a pointer to the state struct. The smart pointer would overload the dereference operator and transparently update the logic instance to get the new vtable if needed.

This decoupling of state and logic could do many nice things, such as serializing the entire game state in a very clean way, and pure state structs would not be harder to parse than C structs (they would essentially be C structs), so you can still have your memory editor.

The main difference between C and C++ here would be the cost abstractions, both cognitive and performance-wise. I have to admit I've never ran into standard abstractions significantly slowing optimized debug code, except for standard library containers. I'm not a game programmer though, so YMMV. I get the cognitive cost argument, but for me the cognitive cost of C (namely having boilerplate noise scattered all over hiding the interesting code and having to be super-extra-careful with memory management) is higher than than the cognitive cost of internalizing all the layers of abstraction in C++.

If you're programming a network game, I still think you'd do your users a better service if you don't dismiss safety offhand. There's a whole class of memory-safety bugs which would never surface during normal play, but could still be exploited with specially crafted packets. Of course, C++ wouldn't give you perfect protection either.

This is a nice talk from Jonathan Blow (Braid's author) about the necessity of a new language for game programming as an alternative to C++, and why new languages like Go or Rust are not apt to the task:

https://www.youtube.com/watch?v=TH9VCN6UkyQ

I doubt you'd have the sort of trouble with pointers and unsafe blocks that you suggest. Most typical pointer patterns don't even require lifetime annotations, let alone bypassing the borrow checker.

I also think the "convenience features" are a pretty big deal. Generics with traits are a pretty big value add for their complexity, and to me affine types take away a lot of the complexity of C.

I can sense the pitchforks coming out already! A quick disclaimer first of all: I LOVE C. Love love love it. I'm a reverser so it's my native tongue. I get as much joy from the actual creative process of coding and playing with pointers as I do from having a reliable working finished project.

No offense, but I think you suffer from the same problem. You're in love with coding, so being forced to micro-manage things the 'C' way isn't a problem for you.

But at some point in time you have to look back and justify the hours spent. You -will- be more productive by having the majority of your code in C++ 11. Things -will- be easier to maintain for yourself and others.

I have written absolutely brilliant C code that I'm very proud of, but if it's been a while since I looked at the project I have to sit down for an hour and re-familiarize myself with how things work....and I'm the one who wrote it.

Based on what you've written I can tell that you don't have the experience to justify writing the bulk of your code in C. Guys who inline ASM all day long can have a hard time doing that. I know it's harsh, but it's meant as helpful criticism.

One other thing: You don't have to pick just C or just C++. If you have engines in your project that are clearly better in C and you enjoy doing it, more power to you....I encourage you to do that. However, it's very easy to get hung up on C and lost in your own C world of imagined optimizations.

My advice: Start off with solid C++, move parts to C later on when testing justifies it and your amount of free time justifies it.

I don't think you're addressing the concerns which made him choose C. In his case: debugging is complex, compilation is slow, name mangling is unreliable, global state is abound.

He makes no mention of inline assembler, nor does he encourage premature optimization. He talks instead about a concrete problem he had: the typical performance of operations was not good enough, thus no single optimization would help much. He also mentions that the abstractions encouraged by C++ do not help you build data-oriented applications (e.g. games); using them properly actually hurts performance.

You speak about perfomance a lot, but do you actually have it as an important requirement, or is it just fun problem to tackle as programmer? In modern game development, it's usually the latter — most hobby game projects don't have art assets detailed enough to be slow on platforms where your end-users actually will play your game.

I make games in Unity/C#, and yes, of course it's slower than a custom C solution. But instead of spending time on writing my own containers and memory allocation, I spend time writing game logic. Instead of optimizing game to run from 100 to 150 FPS on my computer, I'd rather spend this productive time making 5 variants of the same game mechanic to find out which is more fun. Even if the game runs in just 30 FPS.

Of course, I sometimes try to research low-level stuff, write my own renderer, or do a small experimental project in pure C, but then my goal is to research, not to write a game. I can hardly imagine a project, where the goal would be to develop a game, and not to research, where using C and having to spend so much time on this matters would be a good trade-off compared to working on actual game mechanics in higher-level language.

Unity is written in C. That the game logic is written in C# is hardly relevant as you explain. In fact this guy might still embed C# at some point if he wishes for his logic to be less painful to write.

The author states at the beginning that his goal is writing an engine and only after that write a game. You are right on all other points though, most people working on game engines simply never get to the making a game part. There's simply too much to do.

I spent a couple years' working together with a friend every now and then on a game+game engine in C#. We did get past the game engine phase because it was kept simple (ECS + box2d and simple monogame 3d renderer) but we eventually gave up because even though game logic was progressing swiftly assets were just a pain in the ass.

Most low level engineers (as we are/were) underestimate the work it requires to get a proper asset pipeline set up. You're never going to build a 3d game if you can't load cheap 3rd party assets with their animations and materials. And then the level designer which is basically just another game in your game.

We went with UE4 as a change of pace and man is it librating not to have to worry about the limitations of your homebrew engine anymore. In UE4 literally anything is possible (you have the full source after all) and its always less work.

The need for high performance meets with my creative interests. (But I also have technical interest in making the engine). I also value the ability of being able to implement extraordinary features to the engine in a whim, which is hard with large general use engines.

I agree that there is a class of games that can be easily implemented with a prebuilt engine, but this is not one of them.

I don't personally think it matters all that much even on AAA games. Unreal has GC. Take a look at the games made in Unity. Plenty of AAA or close to AAA games. Cities Skylines, Firewatch, Ori and the Blind Forest, Pollen, Endless Legend.

I've written several game engines in the past. I hope to never do it again.

> I have to choose between writing duplicated code, writing a code generator, or tedious macro stuff for generic code.

Code-generation all the way. Use an expressive language like python/lua/tcl/lisp/scheme to work on a higher layer than C.

Two-language programming (one GC scripting, the other C) beats the heck out of C++, in terms of best of both worlds: expressivity in higher layer, performance in lower layer.

C++ has a dirty secret no one likes to talk about. Stroustrup himself was a two-language programmer. C++ was C with classes where the classes were built with unhygienic C macros. When he decided to show his work to "average joe programmers" of the world, he turned it into one language (it turned out he was not a very good language designer so the world has to live with it).

If you're working with C++ you are Stroustrup's average-joe customer.

If you're working with two-language programming you're Stroustrup himself (even better cz you're using a higher language way better than the C macro system)!

Other than that. You want superpowers? give your text-editor your C parser (something similar to this [1]). Structured-editing can do amazing productivity gains in C. This is something I'm still looking into (using some vi/vi-clone, or emacs/emacs-clone, and pycparser) but I very excited about the possibilities.

[1] https://www.jetbrains.com/mps/

Where's your proof that a mix of e.g Python and C is a particularly productive way of working? This is not the first time you make this unsubstantiated claim.

The opposite of what you say is easy to argue for: two languages, twice the headaches.

* first of all, you need to know TWO different languages. C is completely different from a language like Ruby or Lisp.

* even if you manage to do that, you still have two build systems, two things to package and deploy, you need two libraries of everything (e.g: unit testing)

* you need to constantly pass information between the two worlds, which can be both performance costly and challenging from a design perspective.

* normally it's not as easy as "rewriting the slow parts in C". What if your problem is overall memory usage? What if there is no one function to rewrite?

* if you make a mistake in C (super easy), your whole app crashes.

I don't think this is the magical solution you're presenting it to be at all.

I generally support this approach. I have liked working with C and chibi-scheme. Though I think depending on the size of your game logic, it may make little sense to even bother with a scripting language.

There are real costs to building the abstractions needed in order to make a useful scripting environment.

[1] https://www.jetbrains.com/mps/

Tried to visit that site, but all I get is this message:

"Sorry, your browser is not fully supported.

There may be some issues with pages layout in your current browser. Please use an alternate browser until we resolve the issues. Thank you."

Since when is it OK to just refuse to serve a page if it's not 'the right' browser? Is this a thing now?

Script it out in python then replace the hot spots with c!
> 5. realize that I shouldn't be using some parts of C++ (exceptions, stdlib)

> 6. start to ponder if I really need even the good parts of C++

This reads like wisdom and maturity to me; unfortunate, but not surprising, that people are quick to judge.

Last game studio I worked at, we wouldn't have given up C++, but there were frequent conversations about its pitfalls and complexity, and quite a few rules and conventions recommending against, out outright prohibiting some C++ practices, exceptions, for example.

Before that, the last film studio I worked at, a bad experience with C++ led them to chuck it (before I got there) and go object oriented C. I learned their style of C and quite liked it. I missed operators and templates a bit, and it felt a little verbose, but I came to really appreciate the simplicity and explicitness.

Sounds like it wasn't an easy choice, but on a solo project that large you have to prioritize what makes you feel the most productive in the long term, and there are always tradeoffs.

As a long-time C++ coder, I need to add that project-specific prohibition of some C++ practices is a pretty normal, even recommended thing to do. Introducing such prohibitions is not a fault of C++.

Also, I observed that "bad experience with C++" is often related to someone using, while not completely understood, some more advanced C++ paradigm.

I don't use C++ for anything serious, can you explain what's wrong with exceptions and the std lib?
A good article, but what disturbs me is that the author, while obviously aware of relatively good C++ and programming practices, has somehow arrived in a place where he discounts essentially all of C++s core competencies... like claiming RAII is "far from optimal", that exception safety is "a constant mental overhead", and that copy and move semantics involve writing "a lot of code". These are fairly outrageous claims, and it all smells of total burnout, and losing sight of the forest for the trees, to me.

I feel if the author refocused on his C++ basics instead of bemoaning lots of peripheral crap (like OOP, and the unsuitability of the STL for game dev) he'd reconsider some joy in C++ again.

I think one of the main reasons why he did what he did is his motivation, or lack of it while working with C++. Whatever rational arguments would point out to C++ will be essentially meaningless if he is not happy writing with it. That's why discipline is so important in any work. Motivation can get you just so far. It is highly volatile and unreliable. I think it's safe to assume that the author soon will get tired of C and move to languages like python and write an article of how optimizations aren't that important compared to productivity and how critical parts can be written in C, etc. Great article for his perspective and some pros/cons of C/C++, but take it with a grain of salt.
I see unwillingness to adopt the modern and relatively extreme ways to use contemporary C++ well, only the old and simple painful ways to use "C with classes" with serious issues.

For example, the paragraph about loading and saving game state postulates "using the ideas of polymorphism and encapsulation", automatically throwing a lot of pointers and vtables in the way of reading and writing a binary blob like in the C engine. A serious C++ engine with a "data oriented" design would have the same arrays of primitive types and dumb structs as its C counterpart, merely dressed as std::vector or std::array.

> like claiming RAII is "far from optimal", that exception safety is "a constant mental overhead", and that copy and move semantics involve writing "a lot of code". These are fairly outrageous claims

I agree with the OP on all three counts. I don't think RAII is very nice (python-esque with-statement would be nicer IMO), exception safety is really a mental overhead unless you restrict exceptions to a minimum and the copy-assign-move semantics do add a bit of work to every class you introduce.

These are not outrageous claims, they're rather valid opinions. Feel free to disagree but I'm siding with OP on this one.

Overall I dislike C++'s value based semantics, not because it's inherently bad, but it's just so different to any other (reference based) languages that only a small minority of programmers know how to work with them. Attaching complex semantics to types (overloading, templates) and virtual functions/inheritance (when overused) makes reading code much harder and often you need to resort to stepping in the debugger to find out where a function call actually leads.

Well written C++ can be really nice at best, but unfortunately most C++ code bases out there seem to be either a bastard mix of C, Java and C++ styles or over-the-board boost-ey template mess. Neither of these extremes hits the sweet spot.

>These are fairly outrageous claims, and it all smells of total burnout, and losing sight of the forest for the trees, to me.

Maybe, I don't know. I have been a lot happier with C though, while still writing some C++ code during the year.

I agree wholeheartedly with most of this post, but ended up coming to a different conclusion to the author. I don't trust myself to write good, maintable and safe C, so instead my semi-toy game engine has been (and is being) authored in Nim instead, which I've found quite interesting. Writing safe wrappers over C-libraries is a challenge in and of itself!
Isn't Nim (and almost all of its standard library) garbage collected by default? I've been very intrigued by Nim but it seems that while it has nice native/C code generation, it opts into my least favorite element of "high-level" languages.
> When using OOP, like the idiomatic C++ coder does

Huh? Sure, you can go OO architecture astronaut in C++, but if that isn't a good model for your problem, don't do it. I see more of a focus on generic programming, anymore, in C++.

Excellent article. I'm not sure I agree with all the points, but none of them are stupid or necessarily wrong. It's a very constructive argument.

I've been thinking for a while that the problem with C++ is that 100 decisions have been made both in the library & language and in "best practice" that all individually are good, but the combined effect has been unfortunate.

I'm not quite getting from the article why you can't write in the C "subset" of C++ and add in a few of the more helpful parts of C++ though.

> I'm not quite getting from the article why you can't write in the C "subset" of C++ and add in a few of the more helpful parts of C++ though.

I think this is because of C++ name mangling, which prevents the creation of a quick and dirty reflection system. And maybe compilation times, which must be higher since the compiler has to deal with all of C++, even if you don't.

Completely agree, this is why most game developers use only a subset of C++ as "C with classes", and at the end of that thought process some are going back to C completely (I haven't made the jump yet though, but have been pondering this for at least 2 years). What I still like about C++:

- user-provided code called when an "object" goes out of scope

- operator overloading sometimes makes sense

- simple template-meta-programming sometimes makes sense (but could be replaced with other sorts of code-generation)

3rd party libraries are usually a pain to integrate when they have a C++ interface, and usually simple when they are just a C header, and when they can simply be dropped in as source into the project.

A good middle-ground is probably to build the building blocks in C, this way they are way better reusable then writing C++ code, also across languages, and tie the low-level buildings blocks together in whatever language one likes (even interpreted languages).

[edit: formatting]

A lot of games run on Mono/.net Java etc. IIRC these languages have far more overhead. (I could be wrong.) So unless you suspect you need >9000 fps OR you are going to be doing a LOT of processing / complex game you might not need to worry about it ?
As soon as I saw this headline, I knew there would be dozens of comments.

First of all, they are both great languages, no matter what anyone tries to tell you.

I went through this same dilemma and, while I have great respect for C, I soon realized that my situation would be more productive with C++ and its tools immediately available. For one thing, a lot of important libraries that are common in games and graphics have C++ interfaces, so if you use C you are asking of yourself to exclude some great tools out there, or, go through significant steps to wrap some of them (which would still involve some C++ anyway).

I would look at one if those new type and memory safe languages which are more pleasant to work with and usually faster than C/C++, esp. with concurrency. Pony, felix, nim, Julia, Ocaml, elixir, rust.
This reminded me of Banished [1], a game developed by a single developer who also wrote his own engine (though in C++). His development blog [2] goes into quite a lot of technical detail.

[1] http://www.shiningrocksoftware.com/game/

[2] http://www.shiningrocksoftware.com/

I can't help but think the author would benefit from some of the philosophy of James Hague (a game programmer):

http://prog21.dadgum.com/

Don't focus too much on technology, disconnected from what people (including you) might want to actually use. Otherwise you will not get the real inspirations -- even purely technical inspirations -- that come from something that you intend to use.

Has anyone attempted using Objective-C for game development outside of iOS gaming? It'd be interesting using it as an OO language substitute for C++.
Every one of his complaints has a good solution, albeit some not widely known. Except compile time, single source file or otherwise - the compiler is using lots of smarts and lots of library headers on your behalf.

That said, author has done a good job explaining his thought process in taking the rewarding-at-every-step path, given he's not a C++-wrangling junkie.

Are there any other sources of information on "modern C"? I'm thinking particualrly on how to handle memory allocations well and safely, and how to write clean containers and algorithms. It's been a long time since I wrote pure C and I'd like to try it again!
Wow, I had to change the brightness and contrast setting on my monitor just to read this article. What is the strategy behind this darkish font against black background? I wish more websites geared towards a reading audience actually provided a nice reading experience.
I have recently started using myrddin (compiler here https://github.com/oridb/mc ) as a c replacement.

It is still changing fast but I think it could be great for writing games in the future.

> are going somewhat off already by definition, as they're focusing primarily on safety, which is not the focus for most game code.

Depends on what you consider safety to be. A game engine that doesn't deadlock and doesn't crash should definitely be high priority!

Why not Rust for example? If I'd be making an engine, I'd tried that.
Thank you for this very detailed and interesting write up.
what are your thoughts on using D? I find it to be a better C++ and a step up from C.
I'd hazard to offer Rust :)

Someone has to.