AI PART 1

The AI for this game will be iterated upon in stages. The first thing we need to achieve is for an enemy to first follow a player.

As mentioned previously our players and enemies are now belong to our GameWorld in code. This essentially means that the player code and the enemy code can access each other’s variables such as position & health. These 2 variables are important, because the enemy will need to know the player’s X & Y position to be able to move towards them and they will need to access the player’s health to pass damage to them (when they attack).

As the game is in pseudo 3D, we will use a Z coordinate for the player (and enemy), this for the most part will be the same as the Y position except when the player jumps, in which case Y will go up and down, while Z will remain the same. The reason we need this is so the enemy does not follow the player’s actual Y position on screen when they jump. The player is simply jumping up and down from a Y position, hence Z can be used.

So for the code the first thing we will do is make the enemy check the position and distance of the player, we write this like so:

enemy->target_dist_x = distance(enemy->xpos,gameWorld->player1.xpos);

enemy->target_dist_z = distance(enemy->zpos,gameWorld->player1.zpos);

The enemy holds variables for the target distance for X and Z. We call a function I wrote called distance and pass 2 arguments, the enemy’s X position and the player’s X position. This is a very simple function that returns the difference between 2 values.

int distance(int a, int b)

{

int distance;
distance = (b-a);
return distance;

}

So now we have distance values for both X and Z we can start to do something with it. Another variable we will use for the enemy will be SIGHT_RANGE, this will be the distance the player will need to be to the enemy before the enemy thinks about doing something, otherwise they will Idle.

if (enemy->target_dist_x > -SIGHT_RANGE && enemy->target_dist_x < SIGHT_RANGE)

{

ChooseMovement(enemy, gameWorld);

SwitchEnemyState(PLAYER_STATE_WALK, enemy, gameWorld);

}

else

{

SwitchEnemyState(PLAYER_STATE_IDLE, enemy, gameWorld);

}

As you can see if the player is within range we then call a ChooseMove function. This is basically the enemy deciding whether to move to the front or back of the player. In the future this will take in many other factors such as other enemies already being in those positions, but for now it is simple.

if (enemy->target_dist_x < 0)

{

PositionFront(enemy, gameWorld);

}

else

{

PositionBack(enemy, gameWorld);

}

So if the X target distance value is negative then they will move to the front of the player. If it is positive then they will move to the back.

PositionFront and PositionBack are 2 functions we use to start to control the movement of the enemy. ATTACK_RANGE is a variable we will use to set the distance an enemy should place themselves away from the player to attack. So we do the following for positioning in front of the player (to the right).

if (enemy->xpos > gameWorld->player1.xpos+ATTACK_RANGE)

{

enemy->xvector = enemy->xspd*sign(enemy->target_dist_x);

}

else if (enemy->xpos < gameWorld->player1.xpos+ATTACK_RANGE-10)

{

enemy->xvector = enemy->xspd*-sign(enemy->target_dist_x);

}

Walk(enemy);

Here we are saying if the enemy is not yet at in position then set their X vector (the variable we use to move the enemy) to their walk speed in the direction of the player.

Else if the enemy is too close (i.e. on top of the player) then move back a bit.

At the end we call the Walk function which uses the X vector to move the enemy’s X position like so:

enemy->xpos += enemy->xvector;

We do the same for the Z position. This is what it looks like: