Adding progression and difficulty levels

By now, we have a fully functioning game but we still haven't ensured the game is challenging and addictive for the user. We must engage the player by increasing the intensity and difficulty of the game progressively. In our previous game, we had the option of designing levels that get more difficult, but this game isn't level based and is different every time.

With that in mind, a bit of spice is added by creating a variety of formations in which the enemies will spawn on screen. These formations will be increasingly difficult with the difficulty completely based on how long the user has managed to survive. We define a few enums and constants in GameGlobals.h before writing the functions that will add progression to our game:

enum ESkillTimer
{
  E_SKILL1 = 10,
  E_SKILL2 = 30,
  E_SKILL3 = 45,
  E_SKILL4 = 60,
  E_SKILL5 = 90,
  E_SKILL6 = 120,
};

First up, we have an enum called ESkillTimer that represents the skill level in terms of the number of seconds the user has survived the game. Next, we have enum EEnemyFormation defined as follows:

enum EEnemyFormation
{
  E_FORMATION_RANDOM_EASY = 0,
  E_FORMATION_VERTICAL_EASY,
  E_FORMATION_HORIZONTAL_EASY,
  E_FORMATION_POLYGON_EASY,
  E_FORMATION_RANDOM_MEDIUM,
  E_FORMATION_VERTICAL_MEDIUM,
  E_FORMATION_HORIZONTAL_MEDIUM,
  E_FORMATION_POLYGON_MEDIUM,
  E_FORMATION_RANDOM_HARD,
  E_FORMATION_VERTICAL_HARD,
  E_FORMATION_HORIZONTAL_HARD,
  E_FORMATION_POLYGON_HARD,
  E_FORMATION_MAX  //12
};

EEnemyFormation is an enum representing the various types of formations the enemies will be positioned in when they are added to the GameWorld. Next, we have a few arrays pre-defined as follows:

const int GameGlobals::skill1_formations[] = {0, 4};
const int GameGlobals::skill2_formations[] = {4, 4, 
  4, 4, 1, 1, 1, 2, 2, 2};
const int GameGlobals::skill3_formations[] = {4, 4, 
  4, 8, 8, 1, 1, 2, 2, 5, 5, 5, 6, 6, 6, 3, 3};
const int GameGlobals::skill4_formations[] = {4, 4, 
  8, 8, 8, 5, 5, 5, 6, 6, 6, 3, 3, 3, 7, 7, 7};
const int GameGlobals::skill5_formations[] = {8, 8, 
  8, 3, 3, 3, 5, 5, 6, 6, 9, 9, 10, 10, 7, 7, 7};
const int GameGlobals::skill6_formations[] = {8, 8, 
  8, 5, 5, 6, 6, 9, 9, 10, 10, 7, 7, 7, 11, 11, 11};

We also have arrays that specify the frequency of the various formations for a specific skill level. We will stitch these different bits of information together in the GetEnemyFormationType function:

EEnemyFormation GameWorld::GetEnemyFormationType()
{
  // return a formation type from a list of formation types, based on time user has been playing
  // the longer the user has survived, the more difficult the formations will be
  if(seconds_ > E_SKILL6)
  {
    int random_index = CCRANDOM_0_1() * GameGlobals::skill6_formations_size;
    return (EEnemyFormation)(GameGlobals::skill6_formations[random_index]);
  }
  else if(seconds_ > E_SKILL5)
  {
    int random_index = CCRANDOM_0_1() * GameGlobals::skill5_formations_size;
    return (EEnemyFormation)(GameGlobals::skill5_formations[random_index]);
  }
  else if(seconds_ > E_SKILL4)
  {
    int random_index = CCRANDOM_0_1() * GameGlobals::skill4_formations_size;
    return (EEnemyFormation)(GameGlobals::skill4_formations[random_index]);
  }
  else if(seconds_ > E_SKILL3)
  {
    int random_index = CCRANDOM_0_1() * GameGlobals::skill3_formations_size;
    return (EEnemyFormation)(GameGlobals::skill3_formations[random_index]);
  }
  else if(seconds_ > E_SKILL2)
  {
    int random_index = CCRANDOM_0_1() * GameGlobals::skill2_formations_size;
    return (EEnemyFormation)(GameGlobals::skill2_formations[random_index]);
  }
  else if(seconds_ > E_SKILL1)
  {
    int random_index = CCRANDOM_0_1() * GameGlobals::skill1_formations_size;
    return (EEnemyFormation)(GameGlobals::skill1_formations[random_index]);
  }
  else
  {
    return E_FORMATION_RANDOM_EASY;
  }
}

This function first checks up to which skill level the user has managed to survive and then returns an appropriate formation for the respective skill level. Even though the formations are chosen randomly, we still have control over how often a given formation can pop up for a given difficulty level. All we need to do is increase or decrease the number of occurrences of a formation type within the array for a skill level.

Now that we have the type of formation based on difficulty, we can proceed by actually adding the enemies to the game in the AddEnemyFormation function:

void GameWorld::AddEnemyFormation()
{
  // fetch an enemy formation
  EEnemyFormation type = GetEnemyFormationType();
  // fetch a list of positions for the given formation
  vector<CCPoint> formation = GameGlobals::GetEnemyFormation(
    type, boundary_rect_, player_->getPosition());
  int num_enemies_to_create = formation.size();  
  int num_enemies_on_screen = enemies_->count();
  // limit the total number of enemies to MAX_ENEMIES
  if(num_enemies_on_screen + num_enemies_to_create >= MAX_ENEMIES)
  {
    num_enemies_to_create = MAX_ENEMIES - num_enemies_on_screen;
  }
  // create, add & position enemies based on the formation
  for(int i = 0; i < num_enemies_to_create; ++i)
  {
    Enemy* enemy = Enemy::create(this);
    enemy->setPosition(formation[i]);
    enemy->Spawn(i * ENEMY_SPAWN_DELAY);
    addChild(enemy, E_LAYER_ENEMIES);
    enemies_->addObject(enemy);
  }
}

This function begins by fetching the type of formation to create and passes it into the GetEnemyFormation function of the GameGlobals class. The GetEnemyFormation function will return a vector of CCPoint that we will use to position the enemies. At any given point, the total number of enemies on screen should not exceed 250, which in this case is held by constant MAX_ENEMIES defined in GameGlobals.h. We ensure the preceding condition is met and then run a loop where we create an Enemy object, set its position, call its Spawn function, and finally add it to the screen as well as the enemies_ CCARRAY.

By adding progression to Inverse Universe, we complete our fourth game. I have skipped discussing some of the functionality in the chapter, such as the BackgroundManager class, the way enemy formations are created and some of the helper functions. You will find the code for such features and more in the source bundle. Rest assured the comments will be enough to explain what's happening.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.226.34.197