Why I Write Games in C
jonathanwhiting.com
jonathanwhiting.com
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 ...
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.)
Deleted comment
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.
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.
Wow, that sounds pretty nice. I wish I had a window to look out of.
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.
And if I remember correctly then focusing close for a long time doesn't affect your vision but can cause headache.
But to say you never compile anything in Clojure is wrong.
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).
- 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)
However, it doesn't make necessarily sense put the restrictions across the complete source code of game, just because the game logic benefits from it.
Actually, swift, es6, C++ 14, C# come very close these days. in terms of language features.
In my experience, the runtime/build system/packaging/community become bigger factors when choosing between them than the language itself.
Can you describe very briefly how you have the server set up? I've wanted to add this to my c hobby projects for a long time and would enjoy any tidbits of the practicalities involved.
Have you considered letting the compiler produce DWARF-formatted debug information and using an existing DWARF library to handle the symbol to address mapping? I've had good success with this method for controlling embedded systems from a desktop PC, though not when the host and target are the same computer.
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?
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...
http://stackoverflow.com/questions/384121/creating-a-module-...
Through out his complete series haven't seen any unittests for example.
So I my book. No unittests => crappy code.
His use of vtables is completely unrelated to the feature.
This is why I say supposedly zero-cost because although your users may not pay for them, you as a developer will pay for them through either slow compilations or alternatively slow debug builds.
C++ can be a good tool if you have the right discipline, however the discipline is hard to follow if you bring a lot of dependencies in.
C-structs work fine. In my experience, for things like games, C-structs are capable of doing everything you need objects to do. The lack of polymorphism and other OO stuff, makes C code easier to reason about and maintain.
There is a school of thought that it's the opposite of helpful. They would say it's better to have functions doing stuff with data (either taking it as input and returning as output or modifying some structures which should be mutable). "Objects doing things" don't fit to that model.
Also, STL syntax is ugly and hard to work with; Qt's is a lot easier, which is another reason they replace STL's functionality with their own. (Boost, similarly, has its own style of syntax.)
(If you're referring to any macros related to the signal/slot mechanism, that's because C++ itself has no such mechanism natively so of course it's going to require extra macros and a preprocessor to provide that.)
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.
The main developer being a bottleneck is one. His intense focus has led to a bunch of neat features, but it's also made the language a bit crazy and incoherent and, in some cases, unfinished -- as if the author lost interest halfway through. The syntax is beautiful in some places, weirdly warty in others (the {.pragma.} syntax is a particular eyesore). It's full of odd, quirky features that seem like the author had a sudden idea but never considered if it was a good one to give a permanent place in the language. At such a young age it already feels crufty.
Nim is also not strict enough for my taste. Supporting nil (as default behavior) in this day and age is not really acceptable.
Also I don't like the Python-style with no end-marker. I'll be glad if Araq does plan to provide another syntax for Nim. But I fear the style war in the community.
Things I like about Nim: 1. Unified function syntax call, which makes my code more OO-like. 2. Many customizable operators and easy to grasp operator precedence. 3. The pegs library is small but very nice. I began Nim programming with it, wrote handy grammar validators with it, and finally got parser trees in pure Nim for the ASTs. Really fun. Not much, because I hope Nim could be simpler and get the most practical features done right. I am dizzy with its syntax and STL now.
What are your reasons for disliking Python-like syntax?
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.
(I'll also shoot whoever tells me having several syntaxes is a deal breaker.)
I am a Nim fan too, but I doubt that Nim would fulfill the requirements of the author of this article.
At the very beginning of his post, the author says, "[the language] has to be reliable. I can't afford to spend my time dealing with bugs I didn't cause myself." One of the main reasons why I abandoned Nim after having used it more or less regularly for a couple of years is that so many things are still changing, and that compiler bugs pop too often. With every new Nim release I have got unexpected problems in recompiling my codes. This is the main reason why, despite still being a Nim lover, I have stopped using it for my projects. AFAIK, there is still no idea when Nim 1.0 will be released; there have been some optimistic announcements of its being imminent, but so far none of them has lead to such a release.
Later in the blogpost, the author adds another requirement: I do not want to spend my time porting old games to new platforms, I want to make new games. I need a platform that I am confident will be around for a while. Honestly, I think nobody can be sure where Nim will be a couple of years from now. There is practically just one coder (Araq) which understand the compiler internals, and by his own admission he suffers from a severe NIH syndrome which disperses Nim's scarce manpower. As an example, a tool so potentially useful as nimsuggest has been in a non working alpha stage for years because of the lack of people able to work on it (don't know if this is still true, though). IMO, this makes the future of Nim uncertain.
Don't misunderstand me, I still love the language and wish it can reach a state similar to Rust or Julia (which have a much larger and professional community of developers and are supported financially by a number of players). But I think that promoting it in this thread is a bit out of context: Nim is good when you want to toy with a nice language which gets so many things right (macros!), not when your primary objective is to have some language that just works and can be trusted in the mid-to-long term.
Some highlights: Nimble package manager [1], Jester web framework [2], NES emulator [3], NimForum [4], SDL GUI library [5]
And if you want some smaller code examples: http://nim-by-example.github.io/, https://github.com/def-/nim-advent-of-code-2015, https://github.com/def-/nim-unsorted
1: https://github.com/nim-lang/nimble
2: https://github.com/dom96/jester
3: https://github.com/def-/nimes
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.
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.
Between using preprocessor directives in C and multiple inheritance in C++ (comes with associated complexity in the resulting client code), I'd always pick the latter.
[1] https://github.com/llvm-mirror/llvm/blob/release_37/include/... [2] https://github.com/llvm-mirror/llvm/blob/release_37/include/...
E.g. in FreeBSD an mbuf can be on two lists at once: http://svnweb.freebsd.org/base/head/sys/sys/mbuf.h?revision=...
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.
Libarray (and my other C libraries; Libvec etc) have served me very well on a 20k LOC project. With ~150 source files, the entire project builds from fresh in 20 seconds on a i7-2620M. Rebuilds are super-fast; with proper Makefile specification, there's no need to rerender/recompile the templated files.
Businesses who want to use my work in nonfree software are welcome to get in touch to negotiate such a license.
IMHO, for anyone who has seriously considered the morality and ethics of software licensing options, the AGPL is the obvious choice. I'm surprised it isn't more popular. It was a shame large donors strongarmed the FSF into splitting it from the GPL, and that the FSF kept pushing the GPL as it's go-to license.
https://github.com/freebsd/freebsd/blob/master/sys/sys/queue...
http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/sys/sys/queue.h...
Apparently, the implementation is complex enough to drive an ordinary mortal like myself insane, but it is hidden behind a very simple interface, and it is blazingly fast. It only gave me problems when trying to use boehmgc, because it does not detect pointers stored in a Judy tree.
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.
is that really true? i feel like a game ought to fit into a functionally pure paradigm much better, because a game should really only depend on player input, and that can be modelled much easier as RenderIO (WorldState b -> PlayerInput a -> WorldState b) , but not having actually written any, this is just my assumption...
The problem with games are that they have a lot of state, and a lot of loopy state. You end up in a place where you have a set of entities which are organized into a graph and you need to traverse this graph and destructively update some elements in a way that is visible immediately to all elements. You can do this in Haskell, but... It won't be easy. Definitely much tougher than doing it in C, and at the end of the day your game written in idiomatic Haskell will be more complicated and less performant than the C solution.
Also, see: http://prog21.dadgum.com/3.html http://prog21.dadgum.com/23.html
I think he talks about in in this QuakeCon 2013 segment: https://www.youtube.com/watch?v=1PhArSujR_A
Ocaml and F# are more forgiving (some would say more practical) since they employ mutability as first class design element.
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...
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.
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.
Nope, not in Rust AFAIK. Indie games in Haskell are around. Off the top of my mind, Niki and the Robots is written in Haskell.
> Often I find that when people recommend a technology for game development, no professional game studios ever seem to use them.
I was not so much recommending tech, just found these languages would fit nicely the list he assembled.
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.
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.
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.
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.
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.
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:
[1]: http://liballeg.org/
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.
> 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.
Using classes as simple modules - encapsulating a set of functionality - can still lead to a very procedural style without all of the extras.
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.
It looks like several (https://code.google.com/p/bullet/issues/detail?id=43) people (https://github.com/bulletphysics/bullet3/issues/130) have written C apis for bullet already, for that reason. Vala, .NET, LuaJIT and Rust all get mentioned.
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.
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#game-development
I'd also suggest looking over https://www.reddit.com/r/gogamedev.
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)>
I tried to use it when I took over maintenance of a Delphi application developed in-house, because I had no prior experience with Delphi or Pascal. Both FreePascal and Delphi felt very, very similar to ObjectPascal and Delphi. Unfortunately, Lazarus crashed on me a lot both on Linux and OS X, so I gave up on it rather quickly. But it might work better on Windows.
Free Pascal (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/
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
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.
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...
So the obvious choices would be LibGDX and Lwjgl 3 (which is written mostly in Kotlin). As for tutorials, it's close enough to Java that you can rewrite anything pretty much word for word (albeit with a slightly different syntax), and there's a Java -> Kotlin translator in IDEA. It keeps the semantics very close to Java, but with some sugar and niceties. It really is the 'Java replacement' that languages like Scala and Ceylon attempted to be.
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++.
This one feature had kept me using Tcl for a long time.
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...
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.
My comment is not meant to bash Rust, on the contrary it is very promising and the fact that it is used to write Servo is likely to significantly speed up its maturation. But as author notes, if you are developing a project under a deadline you don't have time for bugs you didn't cause yourself. So old boring technology is the way to go.
It's certainly not as old-and-boring stable as C, but it's a lot closer than you'd think.
Dropbox is using Rust in production? Great news! But I'll wait when a thousand of organizations use Rust in production before advocating its use in my own organization. Also, judging by this comment: https://www.reddit.com/r/programming/comments/3w8dgn/announc... they had incredible rapport with the language core team. That is a luxury not every team using Rust is going to have.
Still, great news. I guess I must implement some kind of little personal project in Rust and in the process help iron out a few more quirks.
Also, the OP said that compile time was a priority, and compiling Rust code is closer to C++ speed than C.
It's often less about being safe currently and more about being resilient to breaking after further changes in code. I've worked with some C++ codebases that rely on complicated invariants to be safe (so the code looks safe now), and stuff breaks down when certain changes are made. Programming with a C++11 style greatly reduces but does not eliminate this.
It takes a while to get a hang of this, but once you figure out the "Rust way" of moving data/references around you tend to hit these errors very rarely. Of course, this takes time to learn which you may not have :)
But yes, there are things which Rust could improve upon here, like nonlexical scopes and SEME regions. Which may come soon.
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.
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.]
In general, I think memory safety and data race freedom speed you up other than for small throwaway programs, because memory issues are so awful to debug (even with things like Valgrind).
The reason people might want to avoid it can be the same as "Why not D". The answer to that is that it doesn't offer enough over C and C++, which is where Rust is different, and why I think Rust will be huge.
glium is arguably the best idiomatic OpenGL binding in any language anywhere.
I program in OpenGL with Rust every day as part of my job these days.
On the contrary, it seems both the Xbox One and PS4 are doing a roaring trade, with gaming overtaking Hollywood in terms of market size and revenue
The global life to date figures are 12.4 million Wii Us sold since November, 2012. 19.2 million Xbox Ones and 35.3 million PS4 sold since November, 2013.
Contrast that with PC shipments, where 70 million in one quarter is considered a bad result: http://betanews.com/2015/10/09/pc-shipments-decline-in-windo...
Or contrast it with the iPad's quarterly sales: http://www.statista.com/statistics/269915/global-apple-ipad-...
In FY2014 Apple sold 250 million iOS devices: http://www.geeky-gadgets.com/apple-to-sell-its-billionth-ios...
Add in Android phones and tablets and the games consoles are dwarfed in comparison, even the 3DS which has sold the most of the current games console generation.
1. https://en.wikipedia.org/wiki/Steam_(software)
2. http://recode.net/2014/02/26/a-long-tail-of-whales-half-of-m...
It doesn't matter if an individual does or doesn't pay for a game on their phone. What matters is revenue. Worldwide iOS and Android games revenue has outgrown consoles: http://fortune.com/2015/01/15/mobile-console-game-revenues-2...
>It doesn't matter if an individual does or doesn't pay for a game on their phone. What matters is revenue. Worldwide iOS and Android games revenue has outgrown consoles: http://fortune.com/2015/01/15/mobile-console-game-revenues-2....
Do you have any better source than a mobile analytics firm speculation? I for one have no clue where to get console game sales and where that firm got them is a mystery.
1. https://en.wikipedia.org/wiki/Steam_(software)#cite_note-12
Tencent is the biggest video game company in the world by revenue: http://www.newzoo.com/free/rankings/top-25-companies-by-game...
There are more mobile gamers in China than there are people in America: https://www.techinasia.com/china-mobile-gamers-america-peopl...
Games consoles aren't competitive with that scale.
http://mobilesyrup.com/2015/11/22/mobile-game-revenue-will-s...
http://theesa.ca/wp-content/uploads/2015/11/ESAC_2015_Bookle...
Console game revenues down by 32% since 2013, mobile game revenues up by 20%. Mobile games on trend to overtake console games and investment is being directed to mobile studios and titles. Don't take it personally, it's just how it is.
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-...
[2] https://www.nngroup.com/articles/response-times-3-important-...
Do you happen to know of any benchmarks, or non-anecdotal evidence?
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.
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.
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.
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.
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...
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.
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!
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.
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.
On even the medium size projects I work on, the compile time difference between C and C++ can be magnitudes.
C++ encourages templates, which are typically included by everything, which in turn causes lots of files to need to be recompiled.
Both C/C++ have fragile ABIs so if you have built libraries and you change their memory layout, you need to recompile world. And in some cases, even if your library is internal and not external to your project, a bad build system or a bug can fail to detect this kind of change leading to subtle bugs/crashes, which then in turn encourages developers to do full rebuilds periodically.
It is hard to find real world data converting C++ to C to measure compile times because nobody wants to invest in rewrites like this. However, I am also among those people that have shifted back to pure C from C++ and seen compile times improve by magnitudes. I sometimes work on slow devices, like the Raspberry Pi, and this really magnifies the difference. (On this, the C parts can take 10-20 minutes, and the C++ parts are measured in many hours.)
This one person recently wrote about he switched back to C from C++. He mentions his build times went from about 10 minutes to 4 seconds.
http://chrismdp.com/2015/04/how-i-doubled-the-speed-of-my-ga...
C, with its simpler grammar and the absence of template, tend to re-compile under 5seconds even for sizeable projects.
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.
By "recompilation", I actually meant incremental compilation. I have yet to see a C++ project in my day job that takes less than 10 seconds. Not a deal breaker, but kinda flow-disrupting. As for full re-compilation, I have known one C++ project that took less than 5 minutes. The rest always took more than 10 minutes.
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.
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"?
First of all I've worked with Unity myself and I know how nice it is. It's not the end-all-be-all of game development and it's not suitable for all genres.
Second, like someone else said, this is about a language - not a framework. Unity locks you into C#.
Third, the guy says himself 'I absolutely DO NOT mean to say "hey, you should use C too".'. He's not forcing you to write games in C, he's enjoying writing games in C and explaining why.
If you want to be a good developer, especially a good game developer, consider listening to people who have opinions and experiences different to yours and are willing to explain them. Evaluate their argument. Come up with a rebuttal, share your own experience, by all means - but don't be rude, aggressive, pompous, or a number of other things you are being right now.
This is why the games industry has a NIH problem. Not because people want to develop in C, but because every single dev has their own idea of what is right, what is wrong, and EVERYBODY ELSE is wrong. You want to fix the industry's NIH syndrome? You start by listening.
And as a sidenote, the guy didn't say "Why I'm implementing my own physics/graphics/sound/UI engine". He said he's using C. There's a lot of C libs for games. I don't know if you know this, but Unity isn't the first framework and C# isn't the first language.
What is in this binary executable that makes the computer print "hello world"? I started digging. I found assembly. I found disassembly. I got into cracking and exploits. SoftICE. Unlimited ammo in games. Patching. Sniffing serialzz in shareware. Etc etc.
My point is, if I had just been happy with
printf("Hello, world!\n")
and moved on, I wouldn't have the incredible understanding I do now for what goes on under the hood. I wouldn't know what an executable is, or how to bend it to my will. This knowledge has always been powerful for me.Game programming is like this too. You can install Unity and make a basic game, hell maybe even make a few bucks off it. But what the hell is happening under the hood? What if you need to do something Unity isn't capable of? Where does that leave you?
Maybe some people want to just make a game and be done with it. But I like to know why what I built is actually working. It's worth the time it takes. OpenGL extensions, FBOs, triangulation, etc are all complicated and hard to understand, but once you know how it all works you know what's possible and what isn't, and you don't need a (proprietary!!) framework making that decision for you.
I'm not trying to be glib, and I know that's not the answer you're looking for but it would leave them switching to Unreal or any other engine most likely, not going "down" the complexity scale.
Also, think of the most successful indie game ever made (Minecraft). It was written in Java (a much maligned language, wrongfully IMO), with a very thin framework (Lwjgl), and it's made its creator a billionaire.
If you're doing a game in a relatively mature genre, then yes, engines are great and will save you a ton of time. However if you want to do something completely outside the box, sometimes you save a lot of headache by just simply writing it yourself.
My guess is, the author would have taken more time learning Unity than implementing this game.
Antichamber was a 7 year long hack on Unreal Engine, it's really not a drop-in game.
> [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).
Second, Im talking about the hundreds of tested possible compossibilities of the game you envisioned, regardless if you make it in ensambler or JavaScript. C# is just the language they choosed for their API (unity is written in c++ fwiw)