DESKTOP

Inside A PC Game Program

12/5/2012 9:12:23 AM

The hardware manual was a programming tutorial, rather than a ‘how to use other people’s software’ book

There's a vast gulf of technical knowledge between programmers, who are immersed in the day-to-day agony of coding huge million-line PC games, and tech-savvy gamers, who know how to install new PC hardware, update their drivers and configure software. Back when I started making games for fun, this gulf didn’t exist, due to machines such as the Sinclair ZX81 homw computer.

Description: Old Sinclair ZX81 programming code might look simple, but today’s gamers are basically doing the same thing – just more of it

Old Sinclair ZX81 programming code might look simple, but today’s gamers are basically doing the same thing – just more of it

By modern standards, the ZX81 is a joke. Its 1KB of RAM wouldn’t even hold a single icon for a modern smartphone, and its 8-bit processor wasn’t much faster than using an abacus. However, it was great for encouraging people to become programmers, because it shipped with no software other than the basic operating system. If you wanted to see the words ‘hello world’ on the screen, you had to write a (simple) program to display it. The manual for the hardware was actually a programming tutorial, rather than a ‘hwo to use other people’s software’ book. Those were the days.

As a games coder, when you chat to keen hardcore gamers who want to know more about how modern games are made, the most common question that comes up is ‘how on earth do I start?’ as well as ‘where is the actual “game” bit?’. The slightly jaded and cynical answer these days is to use Unity, and plug some models and scripts into it. That’s great, and much easier than ground-up coding, but I’m old-school enough to suggest that to really understand how games work, and to make something really fast, efficient and original, you need to learn programming from the ground up.

Back in my ZX81 days, it seemed so simple, since programming looked like this:

10 print “Custom PC rocks!”

20 Goto 10

That’s a simple infinite loop, and a complete program that all makes sense. But how do you go from that to Far Cry 3? The first big problem that people encounter is the idea of ‘object-oriented programming’, which is often C++ in PC gaming terms. Object-oriented programming isn’t as weird as it sounds; conceptually, it’s similar to the way languages such as Sinclair Basic used ‘GOTO’ and ‘GOSUB’. In other words, instead of writing a long list of instructions for the PC, the code that gets to run is scattered all over the place, and the current location in that code is constantly bouncing back and forth using the modern equivalent of ‘GOTO’, ‘GOSUC’ and ‘RETURN’

Object-oriented code such as C++ just makes it much more explicit. For example, there’s some code in my last game (Gratuitous Tank Battles) that draws all the units’ health bars, and that code is effectively a ‘subroutine’. Modern debuggers let you ‘step through’ code, which means you can watch the CPU bounce up and down, and back and forth, from one subroutine to another as the game runs. In C++, we don’t call them subroutines; instead, we bunch them into groups called classes. The wording we use to jump in and out of their code is a little different, but it’s fundamentally the same. Unless the game is multithreaded, the CPU is going through the instructions one step at a time.

Newcomers to programming often grasp that, but they still stare at the thousands of files in a modern game and think ‘yes, but where on earth does it all start and end?’ This is a good question.

A PC game is normally an EXE file of some sort. It might use code handily placed in other files (normally DLLs), but it all starts with a single EXE file, even if it’s just a little ‘stub’ program that asks you to choose a screen resolution and then launches the real EXE file. Windows knows there’s a special location within every EXE file where the action starts, and it calls this bit of code (or ‘function’ in C++) WinMain. If you look inside any PC game, you’ll find the code for WinMain somewhere. What happens next is anyone’s guess, because approaches vary, but WinMain is definitely in there.

WinMain is effectively that ’10 print “Custom PC rocks!”’ code from earlier. It’s a sequence of instructions through which the PC steps, and the game ends when it reaches the bottom. The basic gist of WinMain code is to initialize the game (probably quite a lot of work), show a splash screen (or graphics card adverts) and then jump into an infinite ‘loop’, which can only ever be left when the game’s quit button is pressed (or you shortcut the whole lot by pressing ALT-F4). The actual ‘game’ code – the part that draws aliens and lets you shoot lasers – is somewhere inside that loop.

Description: Gratuitous tank battles in action – the code that draws all the units’ health bars is effectively a ‘subroutine’

Gratuitous tank battles in action – the code that draws all the units’ health bars is effectively a ‘subroutine’

In Windows, this is slightly complicated by the fact that a game also needs to tell Windows to interrupt it if certain other Windows events happen. Many games rely on Windows to handle tasks such as minimizing or maximizing the game window, Alt-Tab support and keyboard and mouse input. All of this is handled by ‘message’, which is the basis of how Windows works.

Essentially, you say to Windows ‘if you a message about the mouse, and I’m running, tell me here!’, and a message is sent to you whenever the mouse moves and so on. You check your ‘message queue’ every frame in that loop. If you think that means your game is sent a lot of messages every second, you’d be right. Around 95 per cent of the code isn’t handling messages though – it’s in that infinite loop I mentioned. In very simple form, it goes something like this:

            Start loop

            Check for player input

            Process background tasks (such as AI, physics)

            ‘Lock’ the screen (technically the backbuffer)

            Draw to the screen

            “Unlock’ and ‘Flip’ to show the newly drawn frame to the player

            Let Windows have control back for a millisecond or two

            End Loop

Of course, it’s ten billion times more complex than that, but conceptually, that’s what’s happening, and that represents a single frame of game time. Ideally, we have what we call ‘headroom’ in there, and we can pad out that millisecond at the end so that we don’t run the game too fast.

Some games, such as Gratuitous Space Battles, try to run as fast as they can, and scale their background tasks (bullet movement and so on) accordingly. Others, such as Gratuitous Tank Battles, assume a fixed amount of time has passed and skip entire frames of drawing if they need to catch up with real-time instead. Some games make it horrendously more complex by spinning off separate threads to handle physics, AI and even input.

The latest versions of DirectX mean that even rendering can be multithreaded too, but if you’re even considering that approach, you’re probably already a senior coder with more than ten years of experience.

In my last game, that loop is called ‘Game: :GameProc () ’ and it has 80 lines of code. Of those 80 lines, 41 contain the code that works out if Alt-Tab has been hit, and tries to recover from it. As with all game code, you need to jump through around ten other hoops to get to the actual game. In my case, there’s a special ‘object’ that represents the current ‘mode’ of the game, such as the main menu, options screen or an actual battle. If it’s the latter, the specific ‘battle’ objects code is called effectively the equivalent of ‘GOTO battleobject’. A few more bits of bouncing around gets us to code such as ‘SIM Battle: : Process () ’, where you find the real meat and potatoes code such as ‘SIM_GetAirstrickes () -> Process () ’.

Game code is far more involved than most people think. Imagine a million lines of algebra connected to each other by tens of thousands of links, where a typo in just one of them will cause a crash. That’s basically C++, but ultimately, behind the scary terms and complex relationships, it’s just a lot of over the place. My apologies to any hardened programmers reading this – I know I’ve simplified to oblivion.

 

Other  
 
Most View
The JauBird BlueBuds X - Wireless Comforts For Yuppies
Maingear Nomad 15 – Don’t Judge A Gaming Laptop By Its Cover
Nintendo WII U - Modern HD Gaming Console (Part 2)
A Trio From HIS: 7970 IceQ X² GHz Edition, 7950 IceQ X² Boost Clock And 7850 IceQ Turbo X Graphics Cards Review (Part 2)
Zalman LQ-320 CPU Cooler
QPad Pro MK-50 Gaming Keyboard - Eliminate Multi-Key Read Issuers
Windows Server 2008 and Windows Vista : Administering GPOs (part 1) - Creating GPOs, Linking GPOs
Lenovo IdeaPad Yoga 13 - Convertible Laptop (Part 2)
T-Mobile’s Samsung Galaxy Note II Review (Part 3)
Handwriting Input And Recognition (Part 2)
Top 10
Microsoft Exchange Server 2010 : Configuring Anti-Spam and Message Filtering Options (part 4) - Preventing Internal Servers from Being Filtered
Microsoft Exchange Server 2010 : Configuring Anti-Spam and Message Filtering Options (part 3) - Defining Block List Exceptions and Global Allow/Block Lists
Microsoft Exchange Server 2010 : Configuring Anti-Spam and Message Filtering Options (part 2) - Filtering Connections with IP Block Lists
Microsoft Exchange Server 2010 : Configuring Anti-Spam and Message Filtering Options (part 1) - Filtering Spam and Other Unwanted E-Mail by Sender, Filtering Spam and Other Unwanted E-Mail by Recipien
Microsoft Exchange Server 2010 : Creating and Managing Remote Domains (part 3) - Configuring Messaging Options for Remote Domains , Removing Remote Domains
Microsoft Exchange Server 2010 : Creating and Managing Remote Domains (part 2) - Creating Remote Domains
Microsoft Exchange Server 2010 : Creating and Managing Remote Domains (part 1) - Viewing Remote Domains
Microsoft Exchange Server 2010 : Creating and Managing E-Mail Address Policies (part 3) - Editing and Applying E-Mail Address Policies , Removing E-Mail Address Policies
Microsoft Exchange Server 2010 : Creating and Managing E-Mail Address Policies (part 2) - Creating E-Mail Address Policies
Microsoft Exchange Server 2010 : Creating and Managing E-Mail Address Policies (part 1) - Viewing E-Mail Address Policies