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.
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?
Counter-example: 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.)
As far as initializing the hardware, that's a relatively small, one-off piece of code that's different for every platform (including consoles) anyway.
This leads to a situation where copy-paste at the start of the project may be the best way to reuse good stuff. Otherwise too many assumptions change. If you try to make it a parametric problem, you usually just find out you introduced accidental coupling later.
Huh? I don't know what the numbers are but I'd hazard a guess that the majority of games out there (at least those written by more than one person) use a 3rd party commercial game engine.
So, I believe it might be interesting to do something of a thought experiment, and imagine that C itself is just the language; and for a moment, imagine that it does have some modern standard library; only its modules are unfortunately somewhat scattered over "teh Internets", but probably just a quick googling away. And to see what comes out of that, and how "modern" one could actually make it feel.
Please bear in mind I'm not up to date with modern C. But this thread reminded me of some stuff I've glanced over here or there at some point, and made me wonder. Personally, I believe the result would not reach 100% high-level-ness of Go or the likes, but I have a feeling it might come uncomfortably near...
OOP, RAII, C++ allocators, exceptions, references, vtables (see my post about runtime recompiling), templates (mostly), C++ standard library (I'd have to write my own vector for fast compilation. I'd have to write my own hash map to get contiguous storage (IIRC))
C is by no means optimal, but it's still one of the least bad languages to write games with.
- RAII you only get if you use it.
- exceptions you only get if you enable them.
- references. no overhead.
- vtables. you only get them if you need them.
- templates. no overhead runtime.
- C++ standard library. you only get it if you need it.
- what's wrong with vector ? hash map ?
(References make the type system more complex for little benefit. Templates create massive amounts of complexity and slow down my iteration loop. Already explained what's wrong with std::vector and std::unordered_map.)
- I missed your vector and unordered_map discussion.
- "more complex" is not a useful metric to compare the language systems. Similar, I can easily say, that C pointer arithmetic is creates more complex situations when verifying that code is safe to use.
It's true that complexity somewhat depends on the context. Complexity of a language is a useful metric when talking about mental overhead of the programmer (which translates to productivity), and when writing custom tools for the language, both of which are relevant when developing a game engine. Safety has traditionally been a quite small priority in gamedev. I assumed this was the context.
I, personally, cannot since I've never seen a AAA game in C. However, I've never seen a AAA game compiling under 10 seconds. Or under a minute. Just linking with a console SDK libs is about a minute if you have a fast machine.
I.e. - use dynamic link libraries
- use create static libraries
- carefully manage your dependencies. i.e. only include what you actually need.
- hot reload game logic (where quick iteration is more important)
- compile cache.
- ssd disk
- fast processor
- and yes, agreed. 100kloc is still small.
But the point is, that I'd like a language that is fast to compile by default. C seems pretty promising, as doing a full unity build of my 25kloc codebase takes something like 3 seconds. Not sure how much of that is actually compilation, and how much IO. I'm expecting the project to grow to something like 100-200kloc, and hopefully never have to spend time figuring out why the compilation takes too long, and instead use that time to do something productive.
It's true that there should be no need to write these things yourself. The alternative C++ gives is not really tempting. A language designed for demanding game development doesn't exist (yet), so one evaluates which is the least worse option.
Qt, I believe, also comes with a bunch of "standard library" stuff unrelated to UIs.
In my experience, most of the people who say they don't need OOP or generics end up implementing a limited (or even a full-fledged) version of these things themselves.
Much also depend on how much you really need dynamic allocation - it can be optional.
I think this is one of the biggest disadvantage of a mostly standards based, no particular organization in charge type of language like C, as opposed to, say, python.
I am fortunate that, at the moment, my needs are mostly casual and very rarely performance focused. If I needed C I would just STFU and use C, accumulating my own workarounds for the dispersed nature of its resources.
Most of the dynamically-sized containers I end up needing are one of vector, map, set, or list. For the latter three, there's <sys/tree.h> and <sys/queue.h> on most BSDs which provide intrusive macro-based implementations. Sure, they're a bit more clunky to use than e.g., std::map, but I'm neither concerned with their speed nor their reliability (insofar as their implementation).
Naturally, when you need to reach for a less-common data structure (e.g., a bloom filter or B+ tree) you'll have to look elsewhere, but feels like the same situation as if you were using C++'s STL.
It's not for everybody.
"Containers" are actually quite easy without bespoke libraries in 'C'.
And sorting is built-in.
A simple example: http://www.codeproject.com/Articles/108830/Inheritance-and-P...
Throwing languages at problems is in itself a Tower of Babel problem. We need to emphasize mechanism and not tools. But people gain reputation not by producing correct implementation but by leading revolutions against the status quo.
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 ...