Game Programming Fundamentals

Aug 24, 2009

Programming Basics in Game Context

The goal of this section is certainly not to immediately transform someone with no prior programming experience into a game programmer. That takes time and practice, reading and trying, experimenting and thinking, over a period of weeks (basics), months (intermediate), and years (expert). This is not intended to take the place of a good book on programming, or practice – it’s here for warm up, review, or to complement other resources that are out there by providing a connection to how the most common code structures are used in videogame development.

My hope is that I can plant seeds of familiarity, and establish context of use for the various elements of programming. (Lost already, or a bit unclear on what programming is? Check out Newsletter Vol. 1!)

The following examples are given mostly in C code, taking advantage of a little bit of the flexibility given by a C++ compiler. C++, Objective-C, ActionScript 3, and Java use the same or nearly identical structures for the same functionality, and those are the major programming languages used to develop today’s console, downloadable, mobile, and web videogames.

Finally, the text in this section introduces a lot of material, in a very short space for the amount presented. If you’re new to programming, it will take more than one read, but there’s a good chance that you’ll pick up something new each time. Remember: programming is how every videogame on the market (Wii, online, mobile, 360, PS3, SNES, Atari, Arcade…), every piece of software you use (Office, Windows, FireFox…), and every electronic device works. There’s some patience involved in understanding how all these things work. Stick with it – you’ll be glad you did!

Whitespace

What it is:

Whitespace refers to the gaps between letters within program code, whether represented as tabs, spaces, or new-line breaks (as from the Enter key). Many modern programming languages treat all whitespace the same, meaning that whether you skip lines, indent a certain distance, put two spaces instead of one, or use tabs instead of spaces, the program code will work exactly the same way.

How it looks:

for(int i=0;i<5;i++){showNumber(i);doOtherThingToo();}

…works the same as, but is not as easy on human eyes as…

for(int i = 0; i < 5; i++) {
  showNumber(i);
  doOtherThingToo();
}

Example of a use in videogames:

When a program’s source code doesn’t compile correctly, especially for a beginning programmer, it’s frequently due to a mismatch between braces (the { and } symbols). Effective use of indentation to indicate how many pairs of braces are around code helps keep track of where braces should close. All errors in programming code are reported by the compiler using line numbers, which are only useful in leading the programmer to the problem if the code is broken onto new lines after each individual instruction is ended by its semicolon.

The Comment

What it is:

Text visible only to the human reader, that the computer ignores when it’s time to generate (“compile”) a program from the program code.

How it looks:

// Text after 2 slashes on the same line is a comment

/* ...and so is anything typed between the slash-star and the star slash. This type of comment, unlike the double-slash style, works on multiple lines. */

Example of a use in videogames:

If you program something at the start of a project, then return to that part of code weeks or months later, you may have trouble figuring out what you were intending when the original code was written. Does the collision detection algorithm assume two objects weren’t already overlapping in the previous frame? Is there a limit to how many badguys the game’s graphics code is intended to render at once? Comments are a perfect way to record this thinking alongside the code it’s relevant to, to ensure that it’s passed along to your future self, or anyone else that might wind up reading the code.

Names

What it is:

It is up to the programmer to create names for most things used in a program’s code – names to keep track of numbers that are being used differently, to refer to text phrases that serve different purposes, and names for different chunks of code to succinctly describe their functionality. The computer doesn’t care what these names mean to people (“drawStuff”, “ElvisPants”, and “BV3_aUiP0″ are all equally valid) – but their consistent usage in different parts of the program is how the programmer stores, changes, and checks values for different purposes.

Even though the computer can’t tell the difference between a function for updating the screen called “UpdateScreen” and one called “DogsGetExcited”, the former is a smarter choice because it reflects how the programmer is using the label. Note that whatever names you use inside your program are 100% invisible to the users and the outside world – they’re just a way to stay more organized about the numbers you’re shuffling around.

How it looks:

moveBadguys(); // good name for a code chunk

int playerPositionX; // clear name for a number

abc123(); // terribly unclear name

int r; // sloppy. radius? red? radiation? roundness?

Example of a use in videogames:

If you’re good with naming all the numbers, code sections, files, and other labels needed by your program, the code can become impressively clear to anyone browsing through it. That means less time is needed for writing extensive comments to explain exceptions or clarify meaning, and far less time will get drained into untangling confusion (or problems arising from confusion) based in poor name choices.

Sequence

What it is:

With only very rare exceptions (ex. very advanced topics related to PS3, XBox 360, and high-end computer programming), program code executes only 1 instruction at a time, 1 step at a time, top-to-bottom just like English text is read. Every instruction goes on its own line, for sake of human readability, and must end with a semicolon, for sake of machine readability.

How it looks:

doThing(); // happens first
doOtherThing(); // then this
lastThingHappening(); // happens last

Example of a use in videogames:

moveByPlayerInput();
detectCollisions();
drawEverythingToScreen();

…is a smarter order than…

detectCollisions();
moveByPlayerInput();
drawEverythingToScreen();

…because in the second ordering, character positions aren’t updated to account for collisions that could have happened by the player’s input until after the current frame is drawn to the screen. That means the player way wind up seeing things overlapping one another, which could have been easily avoided by simply switching 2 lines of code!

Functions

What it is:

A mostly self-contained solution to a recurring problem. In its simplest form, it’s simply a group of code that can be called from any other place in code, any number of times, with a one word label. More involved functions can accept input values for use in calculation, and/or can output new values reflecting the results of its processing. The parenthesis pair always show up after a function name when it’s called; if it is a function that takes input values, those values would be specified between the parenthesis.

Programming languages tend to have one initial entry function that always gets called: either main() in C/C++, or with a name matching the main file/class/program in Java/ActionScript. Code begins working from the top of that function, and keeps going until it reaches the bottom of it, getting sidetracked into functions called from it.

How it looks:

Declaration

void doThing(void) { // a function with no input/output
  // ...code goes here...
  // every time the function is called
  // this code will execute, top-to-bottom,
  // from the function's starting brace "{"
  // to the function's ending brace "}"
}

Call

doThing(); // does the "code goes here" from its braces
doThing(); // does that again (we called it again)

Example of a use in videogames:

Grouping related code together into functions helps organize code into more readable sections A function called drawStuff() might contain calls to all other draw functions, such as those used for drawing the background, player, enemies, powerups, weapon projectiles, and health information, which in turn could call other functions that handle the details of how to display the necessary images in the necessary places. This approach enables you to separately take a detailed or big picture look at different parts of the program, breaking the functionality up into understandable chunks. It also centralizes code that’s needed multiple times into 1 place, where it can be fixed or updated only once if something is found to be broken in its behavior.

In real-time videogames, there is generally one primary function that is set up to be called ~30 times per second, executing code in it from top to bottom. That function is expected to call other functions to update positions, check for user input, and redraw the display – anything that needs to happen constantly. Common names for this function, by convention, are draw(), update(), tick(), move(), or something similar, although they can usually be called anything the programming would like. Generally what function gets called, and how often it gets called, gets set up in the program’s initial entry function (explained in the “What it is” section above).

Includes

What it is:

Technically, it takes the contents of another file and dumps them word for word into the file that features the include statement.

Practically, it determines which pre-made functionality you have access to using. It works this way because most of the files we include are ones that define pre-made functions for us to call in our programs – the include statement automatically injects those definitions to the top of our file. Programming languages come with many libraries prepared for things like displaying text, reading keyboard input, accessing network hardware, and performing comparisons/manipulations of text.

How it looks:

#include <stdio.h> // lets us write text on the screen
// "stdio" stands for "STanDard Input Output"

…later in the code…

printf("This will show up, thanks to stdio.h!");

Example of a use in videogames:

Additional libraries can be downloaded from the internet (like Allegro, SDL, or DirectX in this case) that enable you to make simple function calls to load image/audio files into memory, change the screen resolution, display images to the screen, play sound effects, and handle fluid keyboard/mouse/joystick input. People have earned their PhD’s from finding faster ways to get a computer to draw a line – don’t waste your time trying to re-invent the wheel, when generations of computer researchers have been tackling very hard problems so that you won’t have to. Instead, find and include libraries that have their brilliant solutions inside them! This allows you to focus your programming on what your videogame does differently with those graphics, sounds, and input events, instead of how to simply get them to work.

Variable Declaration

What it is:

A Variable Declaration is a line of code that sets aside a named container for a value. It’s up to you as the programmer to come up with a name that you think is suitable. That value is often a number, a letter, a series of letters (“string”), or object (group of numbers, strings, and/or other objects) – to be saved, updated, and checked within code.

How it looks:

int health; // Lets us store/change/check 1 number
int lives; // To store/change/check a different number
// int stand for INTeger (meaning: a whole number)

Example of a use in videogames:

Every distinct horizontal position – how far a player, badguy, powerup, or particle is from the left side of the screen – must be tracked with a distinct variable.

Every distinct vertical position, too.

The same goes for how much health each character with health has, how many characters are alive at once, how much magic power the player has left, which powerups the player has in inventory, what level the player is on… if it’s something that has to be remembered even temporarily, and may not always be the same number, it needs a variable. You’ll be declaring lots and lots of variables.

Common Types

What it is:

A “type” is any form of variable. Some of the most common are int (integer, non-decimal number), float (floating point, refers to a number with accuracy finer than whole numbers), and char (character, i.e. letter).

How it looks:

int thisIsAWholeNumber;
float thisCanBeADecimalNumber;
char someonesFirstInitialCanBeSavedHere;

Example of a use in videogames:

The number of lives would be an integer, since it is counted in discrete units. A rocket projectile’s speed and position would be floats, since for smooth motion with acceleration finer variation is needed than whole numbers allow. A player’s initials on a high score screen would be stored as char.

Assignment

What it is:

The equal sign in programming, unlike the equal sign in math classes, is not the same to both sides of an equation. In fact, it isn’t used to write an equation – it’s used to create a statement of assignment. Where there’s a single equal sign, whatever is on the right side gets evaluated (added together, multiplied out, substituted in, etc.) then stored into the variable to the left of the equal sign. That is, a new value is assigned to that variable name.

How it looks:

int temporaryNumberStorage; // creates a variable label

temporaryNumberStorage = 5; // saves 5 to that variable
// read it as, "store 5 into temporaryNumberStorage"

// This next line is an example of what NOT to do:
5 = temporaryNumberStorage; // meaningless! BAD!
// Say, "store temporaryNumberStorage into 5"
// That sounds like nonsense, right?
// What does it mean to save anything into 5?
// Your computer doesn't know, either

…another example…

int num1;
int num2;

num1 = 9;
num2 = 35;
num1 = num1 + num2 - 2;
// num1 winds up 42 (from 9 + 35 - 2)
// num2 stays 35, because it's right of the = 

Example of a use in videogames:

Setting a player’s number of lives (assuming “int lives” has been declared earlier in the code):

lives = 7;

Subtracting 1 life:

lives = lives - 1;

Giving 2 extra lives:

lives = lives + 2;

Beware that the following line does not actually change the value of lives, since there is no equal sign acting as an assignment operator (=):

lives + 1; // Does not change anything! No = sign!

Since that previous method of adding or subtracting involves typing the variable name twice, there’s a slightly faster way that programmers invented to mark that addition or subtraction that saves into a variable with the assignment operator (=):

Subtracting 1 life:

lives -= 1;

Giving 2 extra lives:

lives += 2;

You can write it either way. “Var = Var + num;” is the same as typing in “Var += num;” and that also works for multiplication (*), divison (/), and subtraction (-). Lastly, the addition or subtraction by 1 is so common in code that there’s a way to do that without using the assignment operator:

Subtracting 1 life:

lives--;

Add 1 life:

lives++;

(That’s where the programming language C++ got it’s name. It’s the same as the C programming language, but with stuff added on top.)

The Object

What it is:

A way to organize multiple variables together into a meaningfully named grouping. As with function names and variable names, the programmer invents these names, ideally choosing a name that reflects how the group of variables is intended to be used. In C, it shows up as a struct, which only contains a grouping of variables, but in C++ and most other more recent languages it can be class, which has the ability to also group functions, plus a few other benefits.

How it looks:

struct character {
  int health;
  int x, y;
};

character thePlayer;
character badGuy;

thePlayer.x // variable for the player's x position
badGuy.health // for the badguy's health value

Example of a use in videogames:

Objects – whether structs in C or classes in newer programming languages – are essential to keeping organized a project grows to include many different kinds of characters, environment pieces, data formats, and other conceptual groupings of variables. The example above is a very simple, fairly typical use, but could be expanded to account for each character’s image, mood, momentum, rotation, animation frame, inventory, etc.

The Array

What it is:

An array is a way to store a sequence of variables, such that they share a common label (think street name) but different index numbers to distinguish them from one another (think house/building address).

How it looks:

// The number in [brackets] declares array size.
// Array addresses start at 0, so the highest number
// we can use is 1 less than the size of the array.
// Defining array size [3] gives us [0],[1], and [2].

int numbers[3]; // creates memory for 3 int variables
numbers[0] = 1000;
numbers[2] = 70; // acts as 3 separate numbers!
numbers[1] = numbers[2] + numbers[0];

// numbers[0] winds up as 1000
// numbers[1] winds up as 1070
// numbers[2] winds up as 70

// 3 separate numbers, 1 common label

Example of a use in videogames:

Any time there are many of something, and each something behaves the same way or based on similar rules, there is probably an array or similar data structure involved. Particle effects, enemy characters, units on the battlefield, projectiles, and so on are often tracked using arrays, utilizing The Object structure of a language to group each individual thing’s variables together.

An array of letters (“characters” or chars) forms a “string”, or word/phrase which can be used as a name, displayed on screen as text, etc.

The If Statement (Conditional)

What it is:

Checking whether one or more mathematical comparisons or functions evaluate to true, and only doing a section of code if it is. Valid comparisons include:

a < b (a is less than b?)
a > b (a is greater than b?)
a <= b (a is less than or equal to b?)
a >= b (a is greater than or equal to b?)
a != b (a is not equal to b?)
a == b (a is equal to b? Remember, 1 equal sign is assignment!)

Multiple statements can be combined via boolean logic

(a < b) && (b > c) meaning (a < b AND ALSO b > c?)
(a < b) || (b > c) meaning (EITHER a < b OR b > c?)

How it looks:

if(lives > 0) { // "if the player is alive"
  // ...move and draw the player here...
} // otherwise code skips ahead to here

Example of a use in videogames:

Killing a character when it runs out of health, forcing the player to stay on screen if the x or y positions go outside an acceptable range, checking whether a gun needs to be reloaded before allowing it to initiate the reload animation/code, etc.

The Else and Else-If Statements

What it is:

Using a section of code only if the result of an if statement turned out false.

How it looks:

if(lives > 0) { // "is the player alive?"
  // ...move and draw the player here...
} else if(continues > 0) { // "has continues?"
  // ...go to the continue screen...
} else { // "if the player isn't"
  // ...play sad music...
  // ...go to game over screen...
}

// Note that you can have as many else-ifs as needed
// You can even just have an else right after an if
// The presence of any else or else-if is optional
// If there's an else, it must come last in the chain

Example of a use in videogames:

It’s extremely common to use this type of series of evaluations in games for a computer controlled enemy to evaluate circumstances with a pre-determined priorty, to handle a series of circumstances that might cause a collision to detonate a projectile, or to handle menu item selection.

The switch-case sequence (not covered here, but easy to find on the internet) is an alternate construction available if the else-if chain is checking matches against consecutive integers (is it 1? otherwise, 2? otherwise, 3? etc.).

The While Loop

What it is:

It works a lot like an If Statement, except that when it closing brace is reached by the code, it checks the While condition again. When the while condition is still true, it goes through the code between its braces another time; if the while condition’s comparison expression is false, then code continues after its closing brace.

How it looks:

while( gameHasBeenLost == 0 ) {
  useMouseInput();
  moveEnemies();
  updateScreen();
  if( health < 0 ) {
    gameHasBeenLost = 1;
  }
}

Example of a use in videogames:

Its most common usage is shown immediately above – the game’s logic and screen updates occur constantly within a while loop, until something happens within the program (a key is pressed, a menu item is clicked, lives run out, etc,) causing its comparison expression (here “gameHasBeenLost IS EQUAL TO 0″) to no longer be true.

Take heed that with any loop, the risk of an “infinite loop” – code that never stops executing – appears if nothing inside it happens that will turn its expression condition false. If your program is being run in an old terminal, and seems to be stuck, CTRL+C will bail from it. If all else fails, CTRL+ALT+DEL (PC Windows) or Force Quit (Mac) will easily and safely terminate a program that is trapped in an infinite loop.

Note that the above usage is no longer common in certain newer languages, particular ActionScript 3, which instead handles game logic best in the form of setting up a timer to call a particular function some number of times per second. (Not shown here.)

The For Loop

What it is:

The For Loop groups together a common and very useful pattern of programming: set up a variable to be used in a while loop, declare the comparison expression for the while loop to evaluate, and do something each time through the loop to affect the loop’s variable. It’s commonly demonstrated as an easy way to count from one number to another, but it can also be used to scan across every letter in a word, check every pixel of an image, or call a function on every badguy/item in the world.

How it looks:

for(int count=0; count<100; count++) {
  // ...do something here...
  // it will happen 100 times.
}

…that behaves exactly the same as this…

int count=0;
while(count<100) {
  // ...do something here...
  // it will happen 100 times.
  count = count + 1; // Remember! Same as "count++;"
}

Example of a use in videogames:

Going through each badguy and updating their position, where each badguy is an object in an array, by calling a function on the badguy in the array position denoted by the for loop’s counting variable.

(Originally posted as part of GameDevLessons.com Vol. 5 Sec. 1)

Este artículo está disponible en español. Traducción por cortesía de Andrés de Pedro.

7 Comments

  1. [...] code aspects could make sense in videogame making, there’s a section to address that in Text Lessons Vol. 5. If you’re needing some help getting a C++ project started with Allegro in order to track the [...]

  2. [...] the explanatory comments in the source itself, anyone with conceptual and structural familiarity with programming should be able to make sense of it, or at least well enough to make [...]

  3. [...] Vol 5 Beg – Videogame Development Usage of Common Programming Structures [...]

  4. [...] Once comfortable with the basics of programming, check out this decoder showing how programmings basics fit into game programming. [...]

  5. [...] Classes can be used to better organize the data above. X/Y pairs are often contained in a Point or Vector class. Both vectors are often grouped into a larger class, along with the image used (goblin, in this case), plus the functions used to handle the character’s movement and updates on the screen. [...]

  6. [...] Once you have the program compiling – on whichever operating system you prefer – for next steps, read through the comments in the project’s main.cpp file. See if you can figure out how to modify the text to perform some of the remaining tasks. For a conceptual explanation of programming, check out Text Lessons Vol. 1. For a detailed introduction to different programming structures as they relate to videogame programming, check out Text Lessons Vol. 5. [...]

All contents Copyright ©2012 Chris DeLeon, solely to prevent others from copyrighting it.
Permission to reproduce, modify, and distribute this content granted without special request.

Site production by Ryan Burrell.