Defining the properties of the tower

The basic characteristics of a tower can be summarized as follows:

  • It will have a specified range
  • It will fire at one or more enemies that enter its range
  • It will do one or more kinds of damage to its enemies
  • It will cost money to build or upgrade, and can be sold

Based on these characteristics, we shall define the following properties for a tower in our game:

  • Physical damage
  • Magical damage
  • Speed damage
  • Range of fire
  • Rate of fire
  • Cost to build

These properties are varied enough to build a simple yet interesting game. With the help of a skilled level designer, you can even make the player enjoy hours of satisfying gameplay.

Let's quickly take a look at the XML structure that is defined to accommodate the data for the towers in this game:

<TowerDataSetList>

  <TowerDataSet bullet_name="TD_bullet01.png" is_lightning="false" is_rotating="true">
    <TowerData sprite_name="TD_t01gun01.png" range="1.5" physical_damage="10" magical_damage="0" speed_damage="1.0" speed_damage_duration="0" fire_rate="1.5" cost="100" />
    <TowerData sprite_name="TD_t01gun02.png" range="2" physical_damage="25" magical_damage="0" speed_damage="1.0" speed_damage_duration="0" fire_rate="1.0" cost="175" />
    <TowerData sprite_name="TD_t01gun03.png" range="3" physical_damage="30" magical_damage="0" speed_damage="1.0" speed_damage_duration="0" fire_rate="0.5" cost="250" />
  </TowerDataSet>
  .
  .
  .
</TowerDataSetList>

The root element of this XML document is titled TowerDataSetList, which defines a list of TowerDataSet tags. A TowerDataSet tag represents nothing but the various levels or upgrades that a given tower can possess. For this game, I have defined that each tower will possess three levels or upgrades, each defined within a TowerData tag. The various attributes from the XML file are summarized in the following table:

Tag

Attribute

Description

TowerDataSet

bullet_name

This is the name of the sprite for the bullet shot by this tower

TowerDataSet

is_lightning

This is true if this tower will shoot a bolt of lightning

TowerDataSet

is_rotating

This is true if the tower's sprite will rotate towards its target

TowerData

sprite_name

This is the name of the sprite for this tower

TowerData

range

This is the range for this tower, in multiples of tile size

TowerData

physical_damage

This is the physical damage this tower will do to an enemy

TowerData

magical_damage

This the magical damage this tower will do to an enemy

TowerData

speed_damage

This is the amount by which this tower will slow down an enemy

TowerData

speed_damage_duration

This is the duration for which this tower will slow down an enemy

TowerData

fire_rate

This is the interval at which this tower will fire

TowerData

cost

This is the cost to build/upgrade this tower

For Pumpkin Defense, I used this architecture to create just three towers (with three upgrades each): one that does physical damage, one that does magical damage, and one that slows down the enemy for a given period of time. This information is stored in the tower_data.xml file inside the source bundle for this chapter. Incidentally, I gave the magical tower a cool ability of casting a lightning bolt at enemies.

All these properties are parsed and stored inside structs TowerDataSet and TowerData inside our global data class GameGlobals. Let's take a quick look at the declaration of these structures, starting with TowerDataSet in the GameGlobals.h file:

struct TowerDataSet
{
  char bullet_name_[256];
  bool is_lightning_;
  bool is_rotating_;
  vector<TowerData*> tower_data_;

  TowerDataSet() : is_lightning_(false),
  is_rotating_(false)
  {
    sprintf(bullet_name_, "%s", "");
    tower_data_.clear();
  }

  ~TowerDataSet()
  {
    for(int i = 0; i < NUM_TOWER_UPGRADES; ++i)
    {
      delete tower_data_[i];
    }
    tower_data_.clear();
  }
};

As you'd expect, the TowerDataSet structure mirrors the TowerDataSet tag. It contains a char array to store the bullet name and two flags to represent if this tower will rotate towards an enemy or if this tower will shoot bolts of lightning instead of bullets.

Finally, you will see a vector holding pointers to the TowerData objects. Let's glance at the TowerData structure from GameGlobals.h:

struct TowerData
{
  char sprite_name_[256];
  float range_;
  float physical_damage_;
  float magical_damage_;
  float speed_damage_;
  float speed_damage_duration_;
  float fire_rate_;
  int cost_;

  TowerData() : range_(0.0f),
  physical_damage_(0.0f),
  magical_damage_(0.0f),
  speed_damage_(0.0f),
  speed_damage_duration_(0.0f),
  fire_rate_(0.0f),
  cost_(0)
  {
    sprintf(sprite_name_, "%s", "");
  }
};

Once again, the TowerData structure is a mirror image of the TowerData tag. Its members are identical to the attributes of the TowerData tag detailed in the preceding code and hence we will skip discussing them.

What is important to note is that our static class GameGlobals maintains a vector named tower_data_sets_ containing pointers to TowerDataSet objects. When the game is launched, the LoadData function from GameGlobals is called and the tower_data.xml file is parsed to fill up the tower_data_sets_ vector with the relevant information. Whenever the player creates a new tower, that tower reads all its properties from one of the objects within this vector.

In a similar way, let's define the properties of the enemy.

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

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