I decided it's time to add something more interesting than a simple rectangle of smiley walls without having to talk about more advanced topics such as textures and sprite collisions, so I decided to change our program into something that looks more like a game by adding a player (represented by a P) and an enemy (E):
(I know it would be too generous to call this a game, but the game isn't much further either).
I also thought that it would be nice if the enemy was kind of aggressive, so I made it run towards and into the player and hurt him by 1 each time they share the same cell:
So what we're going to do next is add some variables to hold our character positions (such as the player or an enemy character):
struct SCharacter // we're gonna use these bunch of variables for representing all our game characters
{
int HealthPoints; // declare an integer for the character life points
int x, y; // coordinates in map or array
};
SCharacter playerCharacter; // Declare a variable of type SCharacter for the player
SCharacter enemyCharacter; // and another SCharacter instance for the enemy
We should also update our functions to take these as parameters so we can use them at the setup() draw() and update() steps:
void setup( SMap* activeMap, SCharacter* player, SCharacter* enemy ); // Accepts addresses pointing to SMap and SCharacter data
void update( SMap* activeMap, SCharacter* player, SCharacter* enemy ); // We can now modify our player and enemy data from these functions
void draw( SMap someMap, SCharacter player, SCharacter enemy ); // Accepts a copy of the data found in the game structures.
This will require to call them by sending the new parameters added:
setup( &gameMap, &playerCharacter, &enemyCharacter ); // call setup() and send the address of our data as parameters
update( &gameMap, &playerCharacter, &enemyCharacter ); // update frame, send map address to update() call
draw( gameMap, playerCharacter, enemyCharacter ); // render frame, send copy of the data to be displayed by draw() We will then set some valid data to our player and enemy. For this we can add some code to the setup() function:
// set some initial configuration to the game characters
player->HP = 100; enemy->HP = 100;
player->x = 5, player->z = 5;
enemy->x = 25, enemy->z = 15;And in the update() step we're going to add some code for the enemy to walk towards the player, and reset to a random position once it hit the player:
if( player->x < enemy->x )
enemy->x = enemy->x-1; // decrease enemy x if player in that direction
else if( player->x > enemy->x )
enemy->x = enemy->x+1; // increase enemy x if player in that direction
if( player->z < enemy->z )
enemy->z = enemy->z-1; // decrease enemy z if player in that direction
else if( player->z > enemy->z )
enemy->z = enemy->z+1; // increase enemy z if player in that direction
if( player->z == enemy->z
&& player->x == enemy->x )
{
player->HP -= 1; // Decrease player life if enemy position matches player position
enemy->x = rand()%activeMap->Width, enemy->z = rand()%activeMap->Depth; // set a random position for the enemy so it has to walk again to reach the player
}
Now the only thing that is missing is to improve our draw() step in order to draw the player and enemy. We're going to check if the coordinates match with the player position and then draw a letter representing the player ('P'), and if they don't match, we compare the coordinates with the enemy position, drawing an 'E' if match, and if none of the previous conditions is met, we're going to draw the letter for the tile as we did before.
Our map render loop will then become something like this:
for( int z=0; z< someMap.Depth; z++ ) // iterate over every row
{
for( int x=0; x< someMap.Width; x++ ) // iterate over every column for the z row
{
if( player.x == x && player.z == z )
printf( "%c", 'P' ); // draw the player
else if( enemy.x == x && enemy.z == z )
printf( "%c", 'E' ); // draw the enemy
else
printf( "%c", someMap.FloorCells[z][x] ); // draw the tile at (x,z) as an ascii character
}
printf( "\n" ); // \n is the code character for "new line" inside a text. We use it to display the next cells in the next row.
}These few and simple modifications added our first artificial intelligence signs to our program and now we are ready to expand all this into something more interesting, preparing it for later being represented with some fancy 2d or 3d animations and particle physics.
The complete code for the program will still be quite compact, though this is going to change so I recommend downloading TortoiseSVN which I will also be explaining how to use for a development project and for downloading the code for next tutorials.
In the incoming tutorials we are going to be adding keyboard control to our player and modifying our current program in order to support more enemies and with more interesting properties than just health points. See you there!





No hay comentarios:
Publicar un comentario