So why do we need a new language for games? Isn’t the world full of languages at this point? Is it really true that in all the dozens of active languages out there, none of them is suitable for making video games?
A year ago Blow gave a talk where he said he didn’t want to use any of the extant languages because they contribute to an ongoing “general insanity” going on in software development. It’s a long and multi-faceted argument, but if I had to boil it down to a soundbite I’d say that there’s a general desire to hide the hardware away behind abstractions and this is making our software slow.
I’m not qualified to support or refute that argument, so if you think Blow is wrong then you’ll have to take it up with him. I’m going to come at the argument from a different angle…
Invading Another Language
Personally, it seems like it would be a bad idea to co-opt the likes of Go, Rust, or D for game development. If you look, you can see these languages are “nearly” ready for game development. To date, nobody has shipped a seriousReminder: By “serious” I mean a proper 3D simulation and not something programmatically trivial like a side-scroller. game in any of these languagesWe do have commercial 3D games made with Unity, and thus C#. But for the most part I think everyone gets why C# isn’t a viable alternative for AAA game development.. Which means the tools aren’t there. Which means the main adherents of these languages are not game developers. At the same time, there must be a reason that game developers haven’t already embraced these languages. We have to allow for the possibility that these alternate languages are missing some features that game developers are likely to need.
Switching over to an extant language and changing it to suit the needs of game development would be significantly more controversial than just starting your own language. Maybe the C++ refugees would be welcomed with open arms at first, but as soon as they began demanding changes or complaining about limitations it would cause rifts. Maybe the language would be forked, or maybe a bunch of features would be added that existing users don’t like or need. Or maybe the incoming game developers would need to cajole and plead for every feature. If the only C++ refugee was Jon Blow all by his lonesome, the community would probably tell him to go make his own damn language if this one doesn’t suit him.
Shamus, what are you talking about? What are these special features game developers supposedly need? A general programming language is suitable for general tasks, and that includes games! What is it you think you’ll need?
I’ll come back to this question later in the series. For now just humor me.
I realize I have to be really careful here, because suggesting that language X isn’t suitable to a given task will quickly rally all the supporters of X against you. Everyone will feel the need to defend the honor of their favorite language. They will gather to inform you that actually, X is FANTASTIC and you’re just bad at using it and maybe you should do some research before running your mouth. If you claim that NO extant language is suitable, then you’ll find yourself at war with the adherents of every language simultaneously.
This really does put the game developer in a “damned if you do, damned if you don’t, and damned if you compromise” type situation. If you ask for language features to suit the problem you’re trying to solve, then people will just accuse you of being ignorant or entitled. If you go off to make your own language, people will accuse you of being a naive fool. If you stick with what you’ve got, then people will accuse you of being stuck in the past. Your only escape is to pick a language, pay the high cost of transitioning, and then fall in line behind the faithful.
Game Developer: Man, this job is a drag. I wish there was an alternative to C++.
Foo Evangelist: You should try the Foo language! It’s amazing.
Game Developer: I don’t think this new Foo language will do what I need.
Foo Apologist: You can’t criticize Foo! You don’t know anything about it.
Game Developer: Okay, I’ve just spent half a year learning the language, adapting libraries, and attempting to build a game. Foo really doesn’t have feature X, and I need it.
Foo Grognard: X is a stupid feature. I’ve been making web and mobile apps for a decade and I’ve never needed anything like that. We don’t need to clutter up the language with obscure features for lazy game developers. Go use C++ if you want those kinds of weird-ass features.
Rather than try to convince you that alternative languages are insufficient, I’m going to try to sell you on the more general idea that – all other things being equal – a language devised specifically for games would be better than any of those other choices.
With that in mind, I want to talk about what I think are the four main challenges of games programming:
1. State Transformation
All programs change the state of the machine. As a result of running the program and entering input, internal variables change, new data is written to disk, the contents of the screen are changed, and data is broadcast over the network where it will cause further state changes on other machines. If there was a program that didn’t cause state changes, then there would be no point in running it because it would, by definition, do nothing. However, I think games really do face some unique problems with regard to the frequency, intensity, and variety of the state changes. Not only do games change a lot of state very quickly, but the types of transformations and the causes of those transformations are incredibly complex.
In a game you can have situations where the player shoots a gun that fires a bullet that hits a barrel that triggers an explosion that generates a physics event that knocks over a physics object that lands on a mook and kills them, which results in spawning loot that lands within the player’s pickup radius and is added to their inventory. A single input action caused a state change for seven different objects spanning multiple gameplay systems.
Even worse, it’s not a linear chain reaction like the previous paragraph suggested. The state changes actually branch outward as they cascade through the system. The explosion also spawned a particle emitter, which will in turn spawn particles. The death of the mook will lead to a new mook being spawned sometime in the next few seconds, somewhere nearby. Shooting the gun creates sound effects, creates more particles, and updates the state of the gun itself to deal with the reduced ammo count and kick. Information on the player’s HUD is changed. Damage floaties will spawn at the location of the mook’s former head. Other AI actors in the area will change behavior. The player earns experience. The physics event shoves a bunch of small objects around, which creates even more particles as the debris kick up dust. That single pull of the trigger expands outward, touching countless gameplay systems and eventually altering many megabytes of memory.
Not only are the changes myriad and complex, the causes for those changes are also complex. State changes in response to player input, AI behavior, the rules of the simulation, and information coming over the network. This is one of the reasons AAA game devs shy away fromOr openly despise and denounce. strict Object Oriented Programming. OOP encourages you to wall off all of your different objects. A bank transaction should not be able to change the name of the customer, and so on.
But in a game where all of the different systems are tightly connected and interact in complex ways, you can’t treat each system like a black box and consider it in isolation.
In strict OOP, systems that interfere with the ideal of encapsulationSealing one chunk of code off from other systems. are referred to as cross-cutting concerns. The problem is that modern game design pushes us towards situations where nearly everything is a cross-cutting concern.
In a game, that dumpster is actually 3 different conceptual systems: There’s the model that needs to be rendered, there’s the collision hull that makes it run into things, and there’s the physics object that gets knocked around (and knocks other things around) once the shooting starts. All three of these things are very different, they’re used at different times and in different places by different systems, and they need to be packed in memory with similar objects for efficient processing. If your collision hulls are mixed in with other types of game objects in a big generic list of random crap, then doing batch operations on those objects will be expensive.
Somewhere in the chaos, you look at the data and notice that the mook’s body is a million meters outside of the bounds of the gameworld and you have no idea where to look to find the cause of the problem. Literally any of these systems might have caused a change or a side-effect that altered the position of the mook in ways you can’t think of just now. Debugging becomes very difficult. Bugs are hard to reproduce and harder still to track down.
Yes, other programming domains have lots of state change. In accounting a single transaction will take some money from one account, add it to another account, and record the transactions in many different places. I’ll bet the error-checking and handshaking between financial computing systems is monstrously fussy and it always has to contend with the Two Generals Problem. There’s a lot of state change, but it follows fairly predictable lines. Every state change is an explicit part of the spec. You’re not going to have a weird edge-case deposit that changes the customer’s first name, issues a new credit card to everyone over 18, and modifies the street address of the bank.
In gaming, having emergent state change is considered a bonus. “Oh look. I broke this wall which released water which put out a fire, even though that wasn’t a specifically coded or scripted event. Cool!” In just about any other domain, non-spec interactions are a serious bug!
Mass state change is almost a design imperative in the world of games. Designers are always pushing for more complexity, more interactivity between systems, and more reaction to player input. We want fires to burn things, flowing water to displace things, light to illuminate things, wind to shove things, and explosions to destroy things. Characters should push foliage out of the way, leave footprints, trigger sound effects, make sounds, stir up dust, interact with objects in the environment like chairs and doors, and exert force on physics objects. As we work toward making our simulations more interesting, we make them increasingly interconnected and unwieldy. This makes it challenging to keep the program running fast. It also makes bugs more likely, and makes them harder to find when they show up.
2. Performance Always Matters
Video games are not the only domain where performance matters, but games are rather unique in the sheer complexity of their performance needs.
Sure, every programmer wants their code to run fast, but in games the user will experience performance fluctuations in realtime. They can both see and feel dropped frames. That 16ms stutter will be infuriating and uncomfortable to a gamer trying to line up a headshot, while (say) a video editor will just accept the occasional stutter as part of the job. A Pixar-style render farm needs speed, but if there’s an optimization that occasionally stalls all rendering for half a second in order to speed up the overall job, then that’s totally acceptable in the world of offlineIn this context, “offline rendering” just means “not realtime”. Like, you start the render process and then go have lunch. rendering. Photoshop needs to run its filters as fast as possible, but the vast majority of the time has the program sitting idle and waiting for user input. It’s completely acceptable for the interface to momentarily stutterOr even go unresponsive for multiple consecutive seconds! when the user applies a complex filter to a large image. But games don’t just need to be fast, they need to be consistently fast. They need to be fast across multiple types of processors running vastly different simulations. Productivity software can get away with exhibiting mildly annoying interface hiccups that would be called egregious and unplayable in a video game.
Remember that I’m not saying that games programming is harder or that game programmers have it tougher. Other fields have their challenges, but not many of them have this particular challenge where performance needs to be both high and uniform. I’m not saying mountain climbing is harder than cross-country skiing, I’m saying mountain climbers will have problems that skiers don’t. Skiers probably have their own unique problems. If so, they’re free to come up with their own programming language to deal with them.
I think I lost the plot on that last analogy. Whatever. You get the idea.
This problem isn’t going to go away. If you put on the infinity gauntlet and snapped your fingers to make every processor ten times faster, game designers would instantly find a use for all of that power and we’d once again be up against performance limits. We already have technologies sitting around, waiting until we have enough spare power to support them:
- Real-time fluid dynamics that integrates with physics so a designer can dump a megaliter of water into a space and let the deluge push stuff around and create structural failures without needing to cheat with pre-scripted behavior.
- More particles, bodies, and debris so the game doesn’t need to constantly tidy up loose bits and clear up smoke.
- Turn more of the environment over to physics objects that can be broken and destroyed.
- More ambient NPCs moving around to make the world feel more aliveHitman does REALLY well with this, but I imagine the team has to put in a lot of work to make the huge crowds possible. If we had more power, it would be easier to pull this off and more game designers would want to use it..
Performance always matters, so therefore we’re always going to need a language that allows us to do low-level optimizations that would be seen as unreasonable in most other domains.
3. CPU + GPU
It’s been a while since I did a Terrible Car Analogy™, so let’s do one of those.
Imagine you’re driving a box truck. In the back you’ve got a load of sound effects, physics events, and gameplay updates. These need to be delivered to a warehouse on the other side of the country. You’re navigating a complex interchange between three different roads and trying to make sure you’re always in the proper lane. You’re trundling along with your load of data and everything is going good.
However, you’ve only got half the shipment. The other half is the graphics rendering. That’s being delivered by a different vehicle. This vehicle is monumentally faster than your humble box truck. It drives at hypersonic speeds. Maybe it’s bright green and says NVIDIA on the side. It’s so fast that if this was a real car and not a terrible metaphor, the front end of the car would create a compression zone that would surround the car in plasma, like a spaceship going through re-entry. It would also probably kill everyone it passed, which would be basically everything on or near the road.
You can’t control this other car directly, and instead you have to use the driver helpfully provided by Nvidia. You have a one-way radio that you can use to give directions. The driver doesn’t understand your native language, but Nvidia has a phrasebook of stuff the driver understands.
The rocket car is insanely fast, but it’s also limited. It can’t use toll roads, it can’t handle making left-hand turns, and it doesn’t understand stop signs. The designers never intended it to go through roundabouts. You can do it, but you’ll lose all your speed advantage because the car will loop through the roundabout 200 times before proceeding with the route. Likewise, it can’t really handle stop signs properly so it always stops for 5 full minutes before proceeding through the intersection. You can’t really see where the rocket car is or track it directly, so you have to shout your directions over the radio and hope for the best. If it doesn’t show up on time, it’s very hard to figure out what went wrong or where it wound up.
Your goal is to get your box truck and the rocket car to the same location using different routes, and the delivery isn’t complete until you both get there. When you do, you’re done rendering the frame and you can get started delivering the next one.
The routes are always changing, and just when you feel like you’ve got a handle on things you get a new rocket-car driver with a slightly different skill set and new ways of misinterpreting your directions.
There’s a lot wrong with this analogy. In fact, it’s mostly random horseshit. This isn’t what graphics programming is like at all. However, the two scenarios are similar in levels of intensity and insanity. This isn’t what it’s like to write a rendering engine, but this is what it feels like.
The graphics hardware is ridiculously fast, but also sort of limited and difficult to use. It’s very easy to slip up and waste a lot of the available power.
Shamus, the vast majority of programmers don’t need to interface with the hardware like this. Most of us use graphics engines or game engines provided by someone else, and those other programmers have solved a lot of problems for us.
It’s true! A lot of problems are indeed solved. Mostly. But I’ve never heard of a AAA game that was able to use a general game engine right out of the box. Every time I listen to a GDC talk from a programmer, at some point they’ll allude to all the work they had to do customizing the engine to suit their game. Maybe the engine doesn’t support open-world gameplay, or streaming content, or procgen environments, or realtime modifications to level geometry, or some other thing. if you’re doing anything remotely unconventional with your rendering then you’ll probably need to crawl down into the guts of the rendering pipeline and make changes. That puts you on that crazy road trip with the NVIDIA rocket car, so you’d better know what you’re doing beforehand.
John Carmack once claimed that rocket science was “simple” compared to graphics programming. He even had the audacity to say this to a bunch of NASA engineers. And to be clear: He might be the only living person to have done both of these things professionally.
Because of this dance between the various bits of hardware, even a small bottleneck can lead to serious performance costs. Despite the massive gains we’ve made in raw processing power over the years, we still haven’t reached the point where we can afford to sacrifice a few extra cycles in exchange for making life easier for our poor programmers.
You could argue that maybe we should stop pushing the hardware and just settle for the graphics of yesteryear, which would give us 90% of the visuals for a fraction of the computing cost. That’s a worthwhile idea to explore, but now we’re talking less about a technology problem and more about a business / cultural problem: How do we convince the suits to stop wasting so much time and money chasing graphical fidelity? I mean, if we can’t even disabuse them of obviously stupid ideas, then what are the odds we can change their minds on less obvious ones like this? The people signing paychecks want MOAR GRAFIX, and that’s the reality engineers are living in.
Even if the industry did somehow lose interest in chasing the shiniest pixels, I’m not sure it would help. VR is forever hungry for framerate and consumers really do want 60FPS. Moreover, console makers are always trying to limit the cost of their machines. If we started asking less from our hardware, then Sony and Microsoft would probably be less aggressive about stuffing their gaming machines full of power in order to cut costsEither to lose less money on each unit sold, or so they could lower the retail price to undercut their rival.. In that case, we’d be right up against the wall again – we’d have just barely enough power to do what we need and CPU cycles would still be precious.
4. Design Through Programming
A bank is going to start with an incredibly detailed and rigorous specification, and the project involves turning that inflexible spec into code. No financial system is going to set their engineers loose with a directive like, “Just play around a bit and see what design gives the most correct results.” In many fields, you know exactly what you want before you write your first line of code.
In video games the spec is more fluid and open to changes in response to playtesting. Jon Blow refers to this as “Design through programming”, which is a common approach when your lead designer and lead programmer are the same person.
Obviously this varies by genre and studio. If a game is following a well-understood design pattern like “Cinematic first person shooter” then the spec will probably be fairly stable. On the other hand if you’re doing something weird and unconventional like Portal, Miegakure, Manifold Garden, Gravity Rush, and Antichamber, then there is no firm spec. You have to experiment to see what’s possible and what’s fun. Likewise if you’re making something full of complex interacting systems like Dishonored, Prey 2017 or Deus Ex, then you’re probably going to have to iterate a lot to get all the systems working in harmony.
In either case, if you’re trying to design a game during the process of building it, then refactoring code becomes a major concern. You thought you’d only have a couple of bad guys in the scene at a time when you started, but now that the gameplay is taking shape you realize you need dozens. The animators really made a lot of fantastic animations and blending those all together is expensive, so now you have performance problems you couldn’t have foreseen at the start.
5. Extra Bonus Challenge
I know I only said there were four challenges but I wanted to sneak this one in. It’s a sort of extra layer of challenge on top of all the others that you need to do all that crap using whatever random, cobbled-together heaps of parts people have sitting on their desks. There are hundreds of oh-so-slightly different variants of graphics cards, several generations of chipsets with different features, many different processors with different numbers of cores, different memory pools and different versions of Windows devouring some portion of all those resources. Some people overclock, other people don’t have all the latest updates, and everyone has different usability needs.
Also, did I mention the consoles? They’re more like PCs than they’ve ever been before, but they’ve still got a lot of unique quirks you’ll need to account for.
It’s true that this particular challenge faces anyone making desktop apps, but it all becomes that much more complex when you combine it with the other four challenges above.
So this is the challenge of game development: We need to make programs that handle tons of complicated state change, we need them to run consistently fast, we need to do so using the complex and tightly constrained framework that exists between the CPU and the graphics hardware, we need to do it in a situation where the spec is fluid and refactoring is common, and we need to get it running on most of the endless permutations of consumer-grade hardware. These aren’t the only challenges of game programming, but I think these are the big ones. These four-ish challenges are interconnected and they tend to exacerbate each other. These things are so important and so universal that I think it could make sense to devise a language specifically to help with these problems.
Again, I’m not promising that Jai is going to magically make everything better. I’m just saying that I find it plausible that this particular collection of problems could be better solved using a language specifically designed for the job.
 Reminder: By “serious” I mean a proper 3D simulation and not something programmatically trivial like a side-scroller.
 We do have commercial 3D games made with Unity, and thus C#. But for the most part I think everyone gets why C# isn’t a viable alternative for AAA game development.
 Or openly despise and denounce.
 Sealing one chunk of code off from other systems.
 In this context, “offline rendering” just means “not realtime”. Like, you start the render process and then go have lunch.
 Or even go unresponsive for multiple consecutive seconds!
 Hitman does REALLY well with this, but I imagine the team has to put in a lot of work to make the huge crowds possible. If we had more power, it would be easier to pull this off and more game designers would want to use it.
 Either to lose less money on each unit sold, or so they could lower the retail price to undercut their rival.
Trashing the Heap
What does it mean when a program crashes, and why does it happen?
Here is a 13 part series where I talk about programming games, programming languages, and programming problems.
Quakecon Keynote 2013 Annotated
An interesting but technically dense talk about gaming technology. I translate it for the non-coders.
The Terrible New Thing
Fidget spinners are ruining education! We need to... oh, never mind the fad is over. This is not the first time we've had a dumb moral panic.
Fixing Match 3
For one of the most popular casual games in existence, Match 3 is actually really broken. Until one developer fixed it.