Game Development Wiki
Advertisement

"A master in the art of life makes no much distinction between his work and play, his work and leisure, his mind and body, his education and recreation, his love and his religion. He just distinguishes which is which. Simply collecting his vision of excellence in every thing he does, leaving others to decide if he is playing or working. In his own eyes, he is always doing both." Zen Buddhist text

Objectives

  • To know what is an abstract data type (ADT), what is it and why it is best to use simple kinds of variables
  • To know how to implement an ADT in C language
  • To learn to modify data from an ADT through the use of pointers.

Welcome

Welcome to the first tutorial about C and game programming on this wiki. It will be an exciting task, because video games are within the most difficult type of software to program. However, it is a rewarding experience; when the reader has achieved a complete game program and many people play it. As the great programmer and author of books on videogames Andre Lamothe said, creating a video game is as if the developer were a demigod that is creating a new universe. The games seem to be a universe as they have a set of rules that some actors do (sprites) and overall goals. So, with this series of C tutorials you will learn to be a demigod creating universes in which players can interact to incarnate temporarily in the main character through the keyboard, mouse and joystick.

The art of programming is not like playing video games; it is more exciting, said the creator of Digipen, a video game training company for game developers and 3D artists. To become a good developer of games, first of all we should be regular players. If you do not know the main types of games you may not develop a game that meets the minimum standards of quality and users will find that it does not meet their expectations. Therefore, the first step is to know what kinds of games are there to get an idea of what kind of game you are going to implement.

2D games

Games have become much more complex and exciting than they were in their infancy. Now most new games are some kind of three-dimensional adventure, whether they are sports games, strategy, racing, wrestling, role-playing, or puzzle. However, the knowledge that this tutorial series will give you will be useful to develop games in two dimensions (2D). To make the jump to the world in 3D games, you need to learn the techniques of 2D games plus the knowledge of math (linear algebra) and other advanced topics, not covered on this wiki.

However, 2D games are not entirely outdated. There will always be public for a Tetris-style game or a game like Mario Brothers. The manner in which the reader can compete with the new 3D video games is taking advantage of what people like: playability. It is incredible that relatively simple games like Space Invaders and Pacman have had people entertained for decades. With what you learn in this tutorials, you can develop games like Space Invaders, Centipede, Asteroids, Pacman or, if practiced long enough, a game like Contra or Mario Brothers. But not without tons of work. A game programmer does not build himself from night to day.

Despite the big games are developed by a team of designers, programmers, artists and writers, it is still possible for one person to develop a set of good quality. If one looks at claims of successful games of the past, the main logic of the game was programmed by one or three people. Therefore, and based upon my personal experience (12 games made by myself), I know that this is possible.

Game libraries

And the most important thing is that now it's easier to program games (relatively speaking, because any kind of software is somewhat complex). In the past, to program games for the PC you needed to be an experienced Assembler programmer (Assembler guru) to access the video card, sound and joystick through interrupts and BIOS functions. Today, there are different libraries with specialized functions that facilitate the development of video games, such as DirectX and SDL. You program with them as you do with any other library and Assembler knowledge is not needed. Windows operating system is sufficiently sophisticated to avoid having to use difficult functions of yesteryear. In Windows 3.1, for example, handling of memory was 16-bit and, hence, in order to access the dynamic memory you could not use the classical functions called malloc and free. You had to request the memory, lock it, use it and unlock. It was a very tedious task compared with the straight use of malloc.

Now what you need to do is to master one of these development libraries. If you plan to use DirectX, you must also have basic knowledge of Windows programming. If you will use SDL, (what we do in these tutorials) you only need to learn how to handle this library. SDL encapsulates everything related to Windows (or Linux XWindows, if used in this system). In addition, obviously you need to know in depth the programming language (C in this case) and know how to compile and run programs.

On these tutorials, words such as double buffering, flipping page, blitting, sprites and finite state machines will be used daily. So check the articles when you need to know more about a topic.

André Lamothe suggestions

What is most exciting of learning to program video games is that after this, any kind of software (except for the operating system) will be much easier to program. The developers of video games do things that other programmers would consider impossible (as the great master Andre Lamothe said). Andre recommends people to program as if nothing were impossible. That way you can get very far. In his words (the bold is mine):

... You'd better forget everything you learned about the PC and what's supposed impossible. Think of programming as a game. It's the greatest game in the world. The object of the game is to do the impossible. Most of the programming to video-game programmer does would seem impossible to a programmer of ordinary applications. André Lamothe, game programmer, author of a lot of books on that subject and CEO of Xtreme Games LLC.

Therefore, we must defeat the impossible in programming video games. The best gaming market as Banjo-Kazooie, Quake, Need For Speed illustrate things that had been thought impossible a few decades ago (except for writers of science fiction, though).

Programming example

After this introduction to the tutorial, let's go into the field of C and data abstract types programming.

The most important feature of C to program games is the creation of abstract data types (ADT). The ADTis a level of abstraction higher after the basic types of language such as: int (whole), float (real), double (double precision real), char (characters). With the ADT can create new organizations that data in a game would be: sprites (all moving objects), states of sprites, records records, menus, buttons, animations, linked lists, players, levels, games , Events, etc..

To clarify this matter can come as early as:

// Code 1.1
// File includes.h 
typedef struct _sprite 
{ 
 int x, y / / position in the world 
 int speed; 
 int angle; / / degrees angle to where it moves 
 int frame; / / Table of animation 
 int framerates; / / velocity of animation (pictures) 
 int energy; / / Energy 
 // And so on
} Sprite; 

As a refresher, typedef is the keyword for creating abstract forms from a structure. This snippet creates the kind that has sprite data position, speed, angle, box animation, animation speed and energy. To use this kind would be something like this (in a program that already has WinMain function, WinProc and all that. See Chapter 2)

// Code 1.2 
# include "includes.h" 
… 
void InitGame (void) 
{ 
 Sprite sprite; 
 sprite.x = 0; 
 sprite.y 0; 
 sprite.speed = 0; // Initially is still 
 sprite.angle = 0; // Looking to the right 
 sprite.frame = 0; 
 sprite.framespeed = 10 // Change the animation every 10 frames 
 sprite.energy = 10; 
} 
… 

This feature sets a sprite modifying their data. A real program initializes this from a settlement or would use different values for energy and framerates depending on the sprite, which would use different functions initialization. Later we will see how we do at the moment the important thing here is to understand which types of data can be used as the basic types: declared and then assigned values. The difference here is that Sprite is a type compound and thus to compare their data is needed the operator period (.).

What we use a ADT? Why not use the loose (unstructured) variables?

This could be as follows:

// Code 1.3 
… 
void InitGame (void) 
{ 
 int spriteX, spriteY; 
 int spriteSpeed; 
 int spriteAngle; 
 int spriteFrame; 
 int spriteFrameSpeed; 
 int energy; 
 spriteX = 0; 
 spriteY = 0; 
 spriteSpeed = 0; 
 spriteAngle = 0; 
 spriteFrame = 0; 
 spriteFrameSpeed = 0; 
 spriteEnergy = 10; 
} 
…

This is somewhat equivalent to the first fragment (Code 1.2). However, has several flaws. The first is that if we need several sprites (and we will need) we should have parallel arrangements of the variables or have variables such as:

...
int spriteX2, spriteY2; 
...

Which is by any standard unworkable if we have several types of sprite. The second thing is that the data are encapsulated in the Code 1.2, but the remaining 1.3 loose. The advantage that the data is encapsulated is that if we need to do something with the data we have to spend only Sprite a pointer to the role that is going to do, as follows:

// Code 1.4 
// A feature that takes away a point energy to a sprite 
DamageSprite void (Sprite * sprite) 
( 
 sprite->energy -= damage; 
 // Check if the sprite ceased to exist 
 if (sprite-> energy == 0) 
 { 
  // The sprite is dead, do something 
  PlaySound ( "muerto.wav"); 
 } 
} 

This function is very simple. Get a pointer to a sprite and it diminishes their power at one point. To modify the data we use the sprite operator -> (arrow). What makes this operator is desreferenciar Sprite to access their data (it is as if we were to:

(*sprite).energy -= damage;

This is what is called pass by reference in C. You can also simple as int rates:

// Código 1.5
void swap(int *px, int *py)
{
 int temp ;
 temp = *px ;
 *px = *py;
 *py = temp ;
}
// the call
void doswap()
{
 int x , y;
 x = 1 ;
 y = 2 ;
 swap(&x, &y) ;
 // En x queda 2 y en y 1
}

What makes the role swap is to exchange values of x, and by reference. If passed by value values remain unchanged. To use the reference operator * use and modify the original values. That is what makes (*sprite).energy or, in abbreviated form for a TAD: sprite->energy.

Remember:

We use a TAD for not using parallel arrangements and to encapsulate the information in a single type. With that we can have arrangements Sprite.

All of the above join in the following code. If you did not understand some code earlier advise you to return and check to understand this block longer.

// Código 1.6: Sprites arrays
// Archivo sprites.c
#include "includes.h"
// Diez tipos de sprites
#define MAX_SPRITES	10
// Array of sprites
SPRITE sprites[MAX_SPRITES];
// The function to initialize them
void InitSprite(SPRITE * sprite)
{
 sprite->x= 0;
 sprite->y 0;
 sprite->speed = 0;		// Inicialmente está quieto
 sprite->angle = 0;		// Mirando a la derecha
 sprite->frame = 0;
 sprite->framespeed = 10;	// Cambiar cada 10 cuadros
 sprite->energy = 10;
}
void InitSprites()
{
 int i;
 for(i = 0; i < MAX_SPRITES; i++)
 {
  InitSprite(&sprites[i]);
 }	
}
void InitGame(void)
{
 ...
 InitSprites();
 ...
}

This code closes this chapter. My style is to enter the field from the start so that the reader curious about what can be achieved as soon as possible. If they found very difficult to advise you to review the key concepts of C-pointers, structures, step by reference, etc.. If you have not understood do not worry because the other chapters will be clarified the concepts outlined here.

Exercises

1. Show the code to declare a TAD animation. An animation must have a displacement x, y (a BMP file in which all are), a pointer to bmp (type SDL_Surface), width, height, number of tables animation.

2. Show the code for declaring a player named Player of TAD. Must have lives, score, color, name and sprite (sprites) partner. Hint:

typedef struct _player
{
 int score;	
 // Escribir el resto de campos
} PLAYER;

3. Declare and initialize a list of under 4 players. Lives, score and color should be 0 at all. The name of each should get out of a settlement (char * names [4]). The sprite must emerge from an array of sprites (Sprite sprites * [4]);

4. Declare a variable pointer of a player to create a dynamic array of players. The function will receive the number of players, ask the memory dynamically and initialize all fields to 0 (Hint: use the functions of memory management mem.h)

Advertisement