domingo, 30 de mayo de 2021

How to set up a new C++ project in Visual Studio 2019

1. Download and execute the Visual Studio Community 2019 Installer from the Microsoft website. Then select Visual Studio Community 2019 and click on the Install button. If you already installed Visual Studio 2019, you can move on to step 4.


2. You will be asked to select the packages you want to install. This tutorial is for C++ but you can select other packages if you like. The basic C++ package you should install is the one called "Desktop development with C++" (which is not necessarily for desktop only as I use it to develop for other platforms too).


2.1 I recommend to also go to the Individual components tab and select the Git extension and Git for Windows:




3. After installing, a menu will let you choose Visual C++ as your default setting. *



4. A folder will be needed where our development solutions will be placed. I called mine just "solutions".



5. You can then create a new solution and project as follows:
5.1 Open Visual Studio 2019 and click on Create a new project.



5.2 Select Windows Desktop Wizard as project template, then click on Next




5.3 Then type the Project name (such as MyFirstProject) and the name of the folder in the "Location"  box, then click on Create



5.4 In the window that pops-up next, select "Console Application" as the Application type and check the Empty Project checkbox.



5.5 Click on OK and the project and project files will be created automatically as shown below.





6. After setting up the project, you will be able to add files to it from the samples you find here or browsing the web. If  you want to test some code you can write a hello world example as follows:

6.1 Right click on the project name in the Solution Explorer in Visual Studio (at the right or left of the edit area) and in the pop-up menu select Add -> New item



6.2 Select Visual C++ -> C++ file (.cpp) and type the name of the file, such as "main.cpp" at the name box. Then Click on "Add" to create the file.




6.3 Type or copy the following code into the main.cpp file:

#include <stdio.h>

int main()
{
    printf("Hello world!\n");
    return 0;
}



6.4 Press F7 (or ctrl+shift+b if you didn't set up Visual C++ settings) to build the executable and F5 to execute in debug mode. 





For starting coding in your new project, you can continue reading the next tutorial which explains the basic structure of a C/C++ program.

If you didn't set up Visual C++ settings during install you can do it later by going to menu tools -> import and export settings -> reset all settings and the option will appear again. The screenshot shown is from that window because I had no fresh install of Visual Studio to see the window appear during the first run.

How to set up a new C++ project in Visual Studio 2017

1. Download and execute the Visual Studio Community 2017 Installer from the Microsoft website. Then select Visual Studio Community 2017 and click on the Install button. If you already installed Visual Studio 2017, you can move on to step 4.


2. You will be asked to select the packages you want to install. This tutorial is for C++ but you can select other packages if you like. The basic C++ package you should install is the one called "Desktop development with C++" (which is not necessarily for desktop only as I use it to develop for other platforms too).


2.1 I recommend to also go to the Individual components tab and select the Git extension and Git for Windows:




3. After installing, a menu will let you choose Visual C++ as your default setting. *



4. A folder will be needed where our development solutions will be placed. I called mine just "solutions".



5. You can then create a new solution and project as follows:
5.1 Open Visual Studio 2017 and go to menu File -> New -> Project.



5.2 Select Visual C++ -> Windows Desktop -> Windows Desktop Wizard. Then type the name of the project and the name of the folder in the "Location" box, then click on OK. Another window will show more options.



5.3 Select "Console Application" as the Application type and check the Empty Project checkbox.



5.4 Click on OK and the project and project files will be created automatically as shown below.





6. After setting up the project, you will be able to add files to it from the samples you find here or browsing the web. If  you want to test some code you can write a hello world example as follows:

6.1 Right click on the project name in the Solution Explorer in Visual Studio  (at the right or left of the edit area) and in the pop-up menu select Add -> New item



6.2 Select Visual C++ -> C++ file (.cpp) and type the name of the file, such as "main.cpp" at the name box. Then Click on "Add" to create the file.




6.3 Type or copy the following code into the main.cpp file:

#include <stdio.h>

int main()
{
    printf("Hello world!\n");
    return 0;
}



6.4 Press F7 (or ctrl+shift+b if you didn't set up Visual C++ settings) to build the executable and F5 to execute in debug mode. 





For starting coding in your new project, you can continue reading the next tutorial which explains the basic structure of a C/C++ program.

If you didn't set up Visual C++ settings during install you can do it later by going to menu tools -> import and export settings -> reset all settings and the option will appear again. The screenshot shown is from that window because I had no fresh install of Visual Studio to see the window appear during the first run.

How to set up a new C++ project in Visual Studio 2013

- Download and install Visual Studio 2013 (Express or the version you like) from the Microsoft website (it's free to try), preferably the latest Visual Studio you can find (such as VS2019--ie. not VS2013).  I recommend downloading it in English because all the references on the internet and here are mostly in English.
- After installing, a menu will let you choose Visual C++ as your default setting. *
- A folder will be needed where our development solutions will be placed, which I often call "Dev" because it's short and straightforward.
- You can then create a new solution and project as follows:

  -- Open Visual Studio 2013
  -- Go to menu File -> New -> Project.
  -- Select Visual C++ -> Win32 -> Win32 Console Application
  -- Type the name of the project and the name of the folder in the "Location" box, then click on OK. Another window will show more options.
  -- Select "Application Settings" and check the Empty Project checkbox.
  -- Click on Finish and the project and project files will be created.

After that you will be able to add files to this new project from the samples you find here or browsing the web. If  you want to test you can write a hello world as follows:

 - Right click on the project name in the Solution Explorer in Visual Studio  (at the right or left of the edit area)
 - Select Add -> New item
 - Select Visual C++ -> C++ file (.cpp)
 - Type the name of the file, such as "main.cpp" at the name box.
 - Click on "Add" to create the file.
 - Then type the following code into the main.cpp file:

#include <stdio.h>

void main()
{
    printf("Hello world!\n");
}



 - Press F7 (or ctrl+shift+b if you didn't set up Visual C++ settings) to build the executable and F5 to execute in debug mode. Press Ctrl+F5 to execute without closing the console window after execution so you can see the program output.

For starting coding in your new project, you can continue reading the next tutorial which explains the basic structure of a C/C++ program.

* If you didn't set up Visual C++ settings during install you can do it later by going to menu tools -> import and export settings -> reset all settings and the option will appear again.

domingo, 29 de junio de 2014

Kill! Kill! Kill!

At this point, the only thing missing for the game to make any sense is to add our player the ability to attack and kill the enemies. For achieving this we're going to move some members from our SCharacter struct to a new struct that we can call SMovingObject, which will be used then by SCharacter and a new struct called SShot:

// Represents different types of elements that can be positioned in the game world
struct SMovingObject 
{
    int         x, z;             // Coordinates in tile map
    SVector2    PositionDeltas;   // The position inside the tile
    float       Direction;        // rotation angle in radians
    float       Speed;            // cells/second
};

// Inherits
members from SMovingObject for storing position and physics information
struct SCharacter : public SMovingObject
{   // Inheritance prevents duplicating code and facilitate higher-level constructs
    SCharacterPoints MaxPoints; // the maximum game points that can be set to a particular character
    SCharacterPoints CurrentPoints; // the current value of the character points, updated on game events
};

// Also inherits members from SMovingObject for storing position and physics information
struct SShot : public SMovingObject
{
    int Damage; // Value that will be substracted from the character's health points
};


This makes all members declared in SMovingObject to be part of SCharacter and SShot:

SShot myShot;
myShot.Speed = 10;
// Speed is originally from SMovingObject

SCharacter myChar;
myChar.Direction = 0.0f;
// the same as Direction


We can now add a new member into our game struct in order to store the shot list:

struct SGame
{
    SMap Map;
    SCharacter Player;
    std::vector<SCharacter> Enemies;
    std::vector<SShot> Shots; // Declare the shot list
};


We're going to need some code to setup a new shot and release it into the game world:

void shoot( SGame* gameObject, SPoint2 origin, float direction )
{
    SShot newShot;
    newShot.Damage           = 10; // 10 HP
    newShot.Speed            = 10.0f; // 10 tiles per second
    newShot.PositionDeltas   = origin; // the position where the shot was generated
    newShot.Direction        = direction; // the direction of the shot trajectory
    newShot.x = newShot.z = 0; // reset this so it's updated with refreshPosFromDeltas()
    refreshPosFromDeltas( &newShot ); // update tile coordinates
    gameObject->Shots.push_back( newShot ); // copy as new element at the end of the shot list
}


The update() step will also require a new function for updating position of the world shots, handle hits to enemies and remove shots that get outside the map. In order to remove the shots from the list, we're going to use the std::vector::iterator which is like a cursor of the vector. I would never use std::vector but it's good for beginners. The code for removing a shot from the list would look something like the one below:

    std::vector<SShot>::iterator iShot = gameObject->Shots.begin(); // get iterator at the begin of the list
    int indexShot = 0; // we still need to keep track of the index
    while( iShot != gameObject->Shots.end() ) // while the iterator didn't reach the end
    {
        SShot* currentShot = &gameObject->Shots[indexShot];


       
// remove shot if reached the end of the screen

        if( currentShot->x < 0 || currentShot->z < 0
            || currentShot->x >= gameObject->Map.Width || currentShot->z >= gameObject->Map.Depth
        )
        {
            iShot = gameObject->Shots.erase( iShot ); // get valid iterator
            continue; // keep at the current index
        }

        iShot++; // move iterator to the next position
        indexShot++; // next position means next index

    }

We can also use similar code to remove the shot if it hit an enemy:

        if( gameObject->Map.EnemyCells[currentShot->z][currentShot->x] != INVALID_ENEMY )
        { // damage enemy and remove shot
            gameObject->Enemy[gameObject->Map.EnemyCells[currentShot->z][currentShot->x]].CurrentPoints.HP -= iShot->Damage;
            gameObject->Player.CurrentPoints.XP += iShot->Damage;
            iShot = gameObject->Shots.erase( iShot );
            continue; // keep at the current position/index
        }


or to remove the enemy when it reached 0 health:

        if( currentEnemy->CurrentPoints.HP <= 0 )
        { // remove enemy if zero health
            gameObject->Player.CurrentPoints.XP += iEnemy->MaxPoints.HP;
            iEnemy = gameObject->Enemy.erase( iEnemy ); 
            continue; // keep at the current enemy index
        }


Now we're only missing to update the shot position from the direction and speed and time. For this we define a basis vector (x=1, y=0) and rotate it by the angle to get the final direction:

        // Calculate direction vector
        SVector2 dirVector = SVector2(1, 0).Rotate( currentShot->Direction );


        // integrate speed*time*direction
        shotDeltas->x += currentShot->Speed*fLastFrameTime*dirVector.x;
        shotDeltas->y += currentShot->Speed*fLastFrameTime*dirVector.y; 


        // refresh cell coordinates now that we have accumulated the distance
        refreshPosFromDeltas( currentShot );


I also decided we can change the display if the player win or lost and I took as reference the player health and the amount of enemies to not overcomplicate things, but the right way of doing it is to have a variable to keeps track of the game states, so you must NOT do things like this:

// Use this function to draw our game data
void draw( const SGame* gameObject )

{
    printf("- draw() called.\n");

    if( gameObject->Player.CurrentPoints.HP <= 0 )
        drawGameOver(false); // lose
    else if( gameObject->Enemy.size() == 0 )
        drawGameOver(true); // win
    else
    {
        drawASCIIMap( gameObject );
    }
    drawASCIIGameInfo( gameObject );
};


You can find the complete working code for this tutorial and other tutorials in the repository at google code. I hope you liked the game we just wrote -a program which can be written in one or two days if you're experienced in programming-. In the following tutorial series I will be explaining how to create a proper Windows window and add some nice 2D sprite animations to this game.

sábado, 28 de junio de 2014

Improving the direction system.

Until now, our SVector2D structure had only the ability to hold two values for representing the point or vector we needed to use. This was enough back then but it makes very complicated to perform operations between vectors because we had to manually update those values on the game functions.

Fortunately, C++ allows something called operator overloading and it allows us to define operators that makes easier to work with our mathematical structures. This enables us to work with vectors more comfortably by defining the operations as part of the SVector2 struct, so we can do something like:

SVector2 vA = {1, 2}, vB = {3, 4}, vC; // define two vector variables and assign some values
vC = vA+vB; // add vector A to vector B and store the result in vector C


We can do this by adding the following definition as part of our SVector2 class:

struct SVector2

    // add another vector to the current vector and return the result
    SVector2 operator + ( const SVector2& other ) const
    {   // The const modifier ensures no member variables of the structure are modified
        SVector2 result;
        result.x = x + other.x;
        result.y = y + other.y;
        return result;
    }
};


The method above will declare a new vector where to store the result, and take the x and y values from the left vector and add them to the x and y values of the vector placed at the right of the operator +. The vector instance storing the resulting values will then be returned as result of the operation.

We can also add methods to our SVector2 structure in a similar manner:

struct SVector2

    // Multiply vector elements by a scalar value
    void    Scale( float _scalar )
    {   // This method can't be const because it requires modifying member variables
        x *= _scalar;
        y *= _scalar;
    };     

};

This allows us to modify the values of our member variables without having the arithmetic operations inside our game functions. In this case the previous code enables scaling the vector by a simple call to the Scale() member function:

SVector2 vA = {1, 2}; // define a vector
vA.Scale( 2.0f ); // multiply vector elements by 2

C++ also enables to define constructors, which are methods that are called automatically when creating a new instance from a structure. This enables to make the code simpler by allowing us to initialize the member values from parameters, much like this:

SVector2 vA(1, 2); // initialize vA with constructor
SVector2 vC = vA + SVector2(3, 4); // initialize SVector2 with constructor

Constructors are named as the structure they construct:

typedef struct SVector2
{
    // --- member variables
    float x, y;

    // constructors
    SVector2(){ /* do nothing */ };
    SVector2( float _x, float _y ){ x = _x; y = _y; };

};

I won't dive into vector math right now because it would be too long and there are plenty of information on vector math for games out there. You can find the other methods added by looking at our point.h file, but now we are going to assume they're already there and start using them for something more interesting.

We're now going to improve our character direction system by taking advantage of our new vector methods and operators, because currently the direction is calculated only for updating the position but then it gets lost, and this is a problem because we will want to add other functions related to the player's direction (such as shooting)  and we need the information to remain available for other update functions. In order to achieve this, we're going to define a new member variable at the SCharacter struct called Direction, which will hold the rotation angle of the character in relation to a reference vector, which we're going to define as (x=1, y=0).

struct SCharacter
{
    float Direction; // rotation angle in radians
    /* ... more members follow ... */


We can then update our player direction code in order to calculate this value from the keys pressed:

void updatePlayer( SGame* gameObject, float fLastFrameTime  )
{

    // Query key states
    bool _keyUP     = GetAsyncKeyState('W') ? true : false,
        _keyDOWN    = GetAsyncKeyState('S') ? true : false,
        _keyLEFT    = GetAsyncKeyState('A') ? true : false,
        _keyRIGHT   = GetAsyncKeyState('D') ? true : false;

    SVector2 dir = {0,0};
    // Determine final direction from keys pressed
    if(_keyRIGHT)
        dir.x ++; //dir.x = 1;
    if(_keyLEFT)
        dir.x --; //dir.x = -1;
    if(_keyUP)
        dir.y --; //dir.y = -1;
    if(_keyDOWN)
        dir.y ++; //dir.y = 1;


    // normalize the new direction vector (make it a unit length so we can multiply it by speed to get velocity vector)
    dir.Normalize();


    // we want to walk only if a direction key was pressed
    bool dirKeyPressed = _keyRIGHT || _keyLEFT || _keyUP || _keyDOWN;
    if( dirKeyPressed )
    {
        gameObject->Player.Direction = SVector2(1, 0).AngleWith(dir); // get angle in radians
        if( dir.y < 0 ) // negate rotation if more than 180º
            gameObject->Player.Direction = gameObject->Player.Direction*-1;

        // Increase 50% speed if left shift pressed.
        float fSpeed = GetAsyncKeyState(VK_LSHIFT) ? gameObject->Player.Speed*1.5f : gameObject->Player.Speed;

        // scale direction depending on speed and time to get total displacement
        dir.Scale(fSpeed*fLastFrameTime);

        // integrate our calculated displacement
        gameObject->Player.PositionDeltas = gameObject->Player.PositionDeltas + dir;
    }

    /* .. more update code ... */

This will give us a better direction system that will allow us to determine the direction for projectiles shot by the player and enable a more precise rotation control for game characters.We can also translate this value to other rotation or direction representations by taking advantage of our new SVector2 methods:

    // Calculate direction vector from angle in radians.
    SVector2 dirVector = SVector2(1, 0).Rotate(gameObject->Player.Direction);
    // Calculate rotation degrees from angle in radians.
    float degrees = gameObject->Player.Direction/(float)GAME_2PI*360;


We can display these values at our draw() step in order to check they're working properly:

    printf( "- Player direction: (%f, %f)\n"
            "- Player angle: %f radians or %f degrees\n"
            dirVector.x, dirVector.y, gameObject->Player.Direction, degrees );


The complete code for this tutorial can be downloaded from the repository. In the next tutorial we're going to see how to use this information to add a shooting system to the player character, which will transform our current program into a playable game. See you there!



lunes, 23 de junio de 2014

Improving character movement.

In this tutorial we're going to add a smoother movement with a configurable speed for the characters of our previous program. For this we're going to be using a new data type which is called float and allows storing real numbers (or an approximation to them):

float mySpeed = 4.5678f; // units per second

By taking advantage of the frame time information received at the update() function, we can move our character the fraction corresponding to that time instead of moving it an entire cell.

if( GetKeyState(VK_UP) )
   
player->y -= player->Speed*fLastFrameTime; // decrease by speed*time as we learned in high school


The problem with our previous implementation is that our x and y coordinates are declared as integer types for using as array indices, which causes all the information after the decimal point to get lost:

float mySpeed = 4.5678f; // units per second
int myIntegerSpeed = mySpeed; // myIntegerSpeed will store only the integer value 4 and the decimal information such as 0.5678 will be lost.

So in order to circumvent this we will add a new structure for holding continuous space coordinates like this one:

struct SPoint2D
{
    float x, y;
};


typedef SPoint2D SVector2D; // Gives our structure another name (SVector2D)

We can now use this structure inside our character structure to store the distance between the cell origin (x=0 , y=0) to the player position, which will always be less than 1 because if we reached 1 of one cell it means that we are in the 0 of the next cell (because 1 is the size of a cell). The structure will then look similar to this one:

struct SCharacter // holds character data
{
    int x, z; // Coordinates in tile map
    SVector2D PositionDeltas; // location inside the (x, z) cell, being (0.5, 0.5) the center of the cell
    float Speed; // cells per second
 
    /* other character variables follow... */
};

We can then configure some speed for the enemies during the setup() step: 

// use this function to initialize enemies 
void setupEnemies( SGame* gameObject )
{
#define INITIAL_ENEMY_COUNT 5
    for( int iEnemy=0; iEnemy < INITIAL_ENEMY_COUNT; iEnemy++ )
    {
        SCharacter newEnemy;
        newEnemy.Speed = float(iEnemy);
// generate the speed from the enemy index
        newEnemy.PositionDeltas = {0,0}; // reset this to a valid value between 0 and 1
        /* other setup code... */


And also to our player character:

// Use this function to setup player at level startup.
void setupPlayer( SGame* gameObject )
{
    gameObject->Player.PositionDeltas = {0,0};
    gameObject->Player.Speed    = 5.0f;
    /* other player initialization code... */


Now that we have our data structures set up and the values initialized, we can start using them during the update() step to calculate the movement that happened in the time step of the frame:

void updatePlayer( SGame* gameObject, float fLastFrameTime  )
{
    SVector2D* playerDelta = &gameObject->Player.PositionDeltas; // get memory address of our data (pointer to data)

    float fSpeed = gameObject->Player.Speed; // get player speed
    // Update position from speed*time

    if(GetAsyncKeyState(VK_UP))
        playerDelta->y -= fSpeed*fLastFrameTime; // decrease by speed*time
    if(GetAsyncKeyState(VK_DOWN))
        playerDelta->y += fSpeed*fLastFrameTime; // increase by speed*time
    if(GetAsyncKeyState(VK_RIGHT))
        playerDelta->x += fSpeed*fLastFrameTime; // increase by speed*time
    if(GetAsyncKeyState(VK_LEFT))
        playerDelta->x -= fSpeed*fLastFrameTime; // decrease by speed*time

    // refresh tile coordinates after accumulating the distance walked
    refreshPosFromDeltas( &gameObject->Player );

}

We define an auxiliary function that will update the x, z coordinates of the tile for each unit accumulated in our deltas after calculating the displacement from the time. Then if we have x = 10 and deltas.x = 2.5f after accumulating the displacement, we shall increase x and decrease deltas.x by one until x = 12 and deltas.x = 0.5:

void refreshPosFromDeltas( SCharacter* character )
{
    SVector2D* charDeltas = &character->PositionDeltas; // get pointer to deltas
   
    // Update X coordinate until deltas.x  < 1
    while( charDeltas->x >= 1.0f )
    {
        character->x += 1.0f;

        charDeltas->x -= 1.0f;
    }
    // Update X coordinate until deltas.x  >= 0
    while( charDeltas->x < 0.0f )
    {
        character->x -= 1;
        charDeltas->x += 1.0f;
    }
    /* Do the same for the Y coordinate */

}

We also need to implement these changes in the code for the enemy updates:

    for( unsigned int iEnemy=0; iEnemy < gameObject->Enemy.size(); iEnemy++ )
    {
        SCharacter* currentEnemy = &gameObject->Enemy[iEnemy]; // get pointer to character
        SVector2D* enemyDelta = &currentEnemy->PositionDeltas; // get pointer to deltas to be updated
        float fEnemySpeed = currentEnemy->Speed; // get enemy speed
       
        if( gameObject->Player.x < currentEnemy->x )
            enemyDelta->x -= fEnemySpeed*fLastFrameTime; // decrease speed*time
        else if( gameObject->Player.x > currentEnemy->x )
            enemyDelta->x += fEnemySpeed*fLastFrameTime; // increase speed*time
   
        if( gameObject->Player.z < currentEnemy->z )
            enemyDelta->y -= fEnemySpeed*fLastFrameTime; // decrease speed*time
        else if( gameObject->Player.z > currentEnemy->z )
            enemyDelta->y += fEnemySpeed*fLastFrameTime; // increase speed*time

        // refresh cell coordinates now that we have accumulated the distance walked
        refreshPosFromDeltas( currentEnemy );
        /* more enemy update code follows */
 


This will be enough for our game characters to move smoothly depending on the actual time elapsed between frames instead of moving a whole cell on each update, giving more realism to the movement of the characters and making the game more enjoyable.

The complete code and binaries for this tutorial can be found in the repository at google code. In the next tutorial we will be adding a persistent direction system and our vector struct in order to set a base to add bullets and a improve the character controls and enemy AI. See you there!

sábado, 21 de junio de 2014

Organizing the source code into different files.

As our program gets larger it's convenient to organize the source code into different files. In this tutorial we're going to talk about how to use the header files which are intended to share pieces of program to other files.

For creating a new header file go to menu Project->Add->New item (or right click on the project in the solution explorer and select the same option). A window will pop up, then select Header file in the window and set the name to game.h:



We're going to place in this file some code that will be used from main.cpp, so in main.cpp we need to include it:

#include "game.h" // use "" for files found in the project folder, contrary to <stdio.h> or <vector>

Now we can place some of the code into the file. We're going to move all the #define lines, the #include for <vector> and the structure declarations to game.h. We're also going to add the following lines at the end of game.h:

// -- these game functions need to be included at main.cpp in order to use them
void setupMap( SGame* gameObject );     // initialize map layers
void setupPlayer( SGame* gameObject );  // initialize player
void setupEnemies( SGame* gameObject ); // initialize enemy list

void updateMap( SGame* gameObject, float fTimeElapsed );     // update tiles
void updatePlayer( SGame* gameObject, float fTimeElapsed );  // update player
void updateEnemies( SGame* gameObject, float fTimeElapsed ); // update enemy AI and refresh enemy layer

void drawASCIIMap( const SGame* gameObject ); // take the map data and print it on the console
void drawASCIIGameInfo( const SGame* gameObject ); // print the player and misc info


We're also going to be adding files that will contain a timer object that we will be using for querying the time elapsed between game frames. We're going to need this in the next tutorials to improve animation, AI and more. These files will be called timer.h and timer.cpp and will define a structure called STimer that we will be able to use in any of our projects. It will also contain the following member variables and methods:

    // members
    float       LastTime; // the time calculated by the last Frame() call.
   
    // methods
    void        Reset(); // Reset timer
    void        Frame(); // Calculate time elapsed since the last Frame() or Reset() call.


We're going to need this file included in our main.cpp in order to use the STimer object in our main loop, in which we're going to declare an instance of the timer and query Frame() on every loop iteration so we can send the time delta to the update() function:

int main( void ) // start application from here
{
    SGame gameInstance;
    STimer timer; // declare our timer instance

    setup( &gameInstance ); // call setup() and send the address of our data as parameters

    int frameCounter=0; // declare a variable to keep track of the frame number
    while( true ) // execute block {} while what's inside () is true
    {
        timer.Frame(); // Query time elapsed since last Frame() call

        printf("Current frame number: %i\n"
            "Last frame time: %f\n", frameCounter, timer.LastTime );
        update( &gameInstance, timer.LastTime ); // send time elapsed to update() call
        draw( &gameInstance ); // render game data


We're also be modifying our functions at main.cpp to work with the declared functions at game.h and we're going to move all the remaining code to a new game.cpp file where the game functions will be defined. So our setup() function will now look somewhat like this:

// Use this function to setup our game data
void setup( SGame* gameObject ) // Accepts an address pointing to an SGame instance
{
    printf("- setup() called.\n");

    // call setup game functions
    setupMap(gameObject); // initialize map
    
    setupPlayer(gameObject); // initialize player  
    setupEnemies(gameObject); // initialize enemy list
};


We're also be updating our update() and draw() functions the same way and moving all the game code into our game.cpp functions, which will now look similar to the following:

// Use this function to update the map tiles
void updateMap( SGame* gameObject, float fLastFrameTime  )
{
}


// Use this function to update the player
void updatePlayer( SGame* gameObject, float fLastFrameTime  )
{
    if(GetAsyncKeyState(VK_UP))
        gameObject->Player.z -= 1; // decrease by 1
    if(GetAsyncKeyState(VK_DOWN))
        gameObject->Player.z += 1; // increase by 1
    if(GetAsyncKeyState(VK_RIGHT))
        gameObject->Player.x ++; // increase by 1
    if(GetAsyncKeyState(VK_LEFT))
        gameObject->Player.x --; // decrease by 1 

}

We should end up with a file structure similar to the one shown below and it should still build and run as it previously did:



The complete files for this tutorial can be found in the repository I made for the tutorials at google code. After the code is better organized we can start looking at improving our game systems and making a proper game in which you can do something more interesting than just run and get your health lowered up to negative values.

In the next tutorial we will be improving the way our characters move and enable a configurable speed for each of them. See you there!