Reader small image

You're reading from  SFML Game Development

Product typeBook
Published inJun 2013
Reading LevelIntermediate
PublisherPackt
ISBN-139781849696845
Edition1st Edition
Languages
Tools
Right arrow
Authors (5):
 Artur Moreira
Artur Moreira
author image
Artur Moreira

Artur Moreira is a game development enthusiast who ultimately aims to start a new game development company in his home country. He has been programming games and game-related software for over 4 years. Most of the effort in that time was put in creating an open source game-making library with lots of flexibility and portability. The library is called Nephilim and is known for supporting all major desktop and mobile operating systems, making game development fully crossplatform and fast. Alongside this big project, he keeps making his own prototypes and games for educational and commercial purposes. Aside from the programming, he also puts some focus in creative areas such as 3D modeling, digital painting, and music composing.
Read more about Artur Moreira

 Henrik Vogelius Hansson
Henrik Vogelius Hansson
author image
Henrik Vogelius Hansson

Henrik Vogelius Hansson has always been in love with both games and programming. He started his education fairly early and continued on into the indie scene with Defrost Games and their game Project Temporality. The next company that hired him was Paradox Development Studio where he got to work on titles such as Crusader Kings 2. Beside the game companies, Henrik has also been very active in the SFML community and has even provided a binding for Ruby called rbSFML.
Read more about Henrik Vogelius Hansson

Jan Haller
Jan Haller
Henrik Valter Vogelius
Henrik Valter Vogelius
View More author details
Right arrow

Chapter 7. Warfare Unleashed – Implementing Gameplay

In Chapter 5, Diverting the Game Flow – State Stack and Chapter 6, Waiting and Maintenance Area – Menus, you have seen how to handle menus and states, now it is time to return to the actual game. Up till now, we have built a world that can contain various entities, and implemented the basic interaction mechanisms through updates, drawing, and commands. However, this is not particularly interesting as long as the world is empty.

In this chapter, we are going to populate the world, and implement the core part of the game; the actual gameplay with enemies, weapons, battles, and goodies. We are going to cover the following topics:

  • Enemy aircraft controlled by a simple artificial intelligence

  • Projectiles such as a machine gun or missiles

  • Pickups that improve the player's equipment

  • Collision detection and response between entities in the scene graph

  • The world's update cycle and automatic removal of entities

Equipping the entities


You have heard about entities for the first time in Chapter 3, Forge of the Gods – Shaping Our World, where we built the World class and the scene graph. As a quick reminder, the SceneNode base class was inherited by the Entity class. Entities are the central part of this chapter. It's all about the interaction between entities of different kinds. Before starting to implement all those interactions, it is reasonable to think about crucial properties our entities need to have.

Introducing hitpoints

Since, we are preparing our airplanes for the battlefield, we need to provide them with new specific attributes. To our class definition of Entity, we add a new member variable that memorizes the current hitpoints. Hitpoints (HP) are a measure for the hull integrity of an entity; the entity is destroyed as soon as the hitpoints reach or fall below zero.

In addition to the member variable, we provide member functions that allow the modification of the hitpoints. We do not provide...

Creating enemies


Enemies are other instances of the Aircraft class. They appear at the top of the screen and move downwards, until they fly past the bottom of the screen. Most properties are the same for the player and enemies, so we only explain the new aircraft functionality.

Movement patterns

By default, enemies fly downwards in a straight line. But it would be nice if different enemies moved differently, giving the feeling of a very basic artificial intelligence (AI). Thus, we introduce specific movement patterns. Such a pattern can be described as a sequence of directions to which the enemy airplane heads. A direction consists of an angle and a distance.

struct Direction
{
                           Direction(float angle, float distance);
    float                  angle;
    float                  distance;
};

Our data table for aircraft gets a new entry for the sequence of directions as shown in following code:

struct AircraftData
{
    int                     hitpoints;
    float    ...

Adding projectiles


Finally, time to add what makes a game fun. Shooting down stuff is essential for our game. The code to interact with the W orld class is already defined, thanks to the actions in Player and to the existing Entity base class. All that's left is to define the projectiles themselves.

We start with the Projectile class. We have normal machine gun bullets and homing missiles represented by the same class. This class inherits from the Entity class and is quite small, since it doesn't have anything special that differentiates it from other entities apart from collision tests, which we will talk about later.

class Projectile : public Entity
{
    public:
        enum Type
        {
            AlliedBullet,
            EnemyBullet,
            Missile,
            TypeCount
        };

    public:
                            Projectile(Type type, const TextureHolder& textures);

        void                guideTowards(sf::Vector2f position);
        bool                isGuided...

Picking up some goodies


Now we have implemented enemies and projectiles. But even if the player shot enemy airplanes down, and had exciting battles, he wouldn't remark that his success changes anything. You want to give the player the feeling that he is progressing in the game. Usual for this game genre are power-ups that the enemies drop when they are killed. So let's go ahead and implement that in our game.

Now this is the same story as with the projectile. Most of the things we need have already been implemented; therefore, this will be quite easy to add. What we want is only an entity that, when the player touches it, applies an effect to the player and disappears. Not much work with our current framework.

class Pickup : public Entity
{
    public:
        enum Type
        {
            HealthRefill,
            MissileRefill,
            FireSpread,
            FireRate,
            TypeCount
        };

    public:
                               Pickup(Type type,const TextureHolder...

Collision detection and response


Now that our world is full of entities, let's implement interactions between them. Most interactions occur in the form of a collision; two airplanes collide and explode, projectiles of the player's Gatling gun perforate an enemy, and a pickup is collected by the player, and so on.

First, we write a function that computes the bounding rectangle of an entity. This is the smallest possible rectangle that completely contains the entity. As such, it represents an approximation of the entity's shape, which makes computations simpler. Here is an example implementation: getWorldTransform() multiplies the sf::Transform objects from the scene root to the leaf. sf::Transform::transformRect() transforms a rectangle, and may enlarge it if there is a rotation (since the rectangle has to remain axis-aligned). sf::Sprite::getGlobalBounds() returns the sprite's bounding rectangle relative to the aircraft.

sf::FloatRect Aircraft::getBoundingRect() const
{
    return getWorldTransform...

An interacting world


A lot of game logic has been implemented in the different entities, now we look at functionality that is defined in the World class. You have already seen the collision in the last section.

Cleaning everything up

During the game, entities are destroyed in battle, and have to be removed from the scene graph. We do not remove them instantly. Once in a frame, we iterate through the scene graph, check which nodes have been destroyed, and detach them from their parents. To find out whether a node has been destroyed, we write the virtual function SceneNode::isDestroyed(). By default, it returns false. A derived entity may specify a condition under which it returns true. Usually, this will be the case when the hitpoints are zero or less (that is, the entity is destroyed).

bool Entity::isDestroyed() const
{
    return mHitpoints <= 0;
}

In addition, we add a virtual function that checks if a scene node should be removed from the scene graph. By default, this is true as soon as...

Victory and defeat


Equipped with the Eagle aircraft, you can accept the challenge to maneuver through a mission. Depending on your skill, you may reach the end of the level and become a pilot legend. Or you fall victim to the enemy fleet and die in a horrible plane crash.

Anyway, the player should be informed by the game about his fate. In most games, there are victory and defeat conditions. In our airplane game, a mission is complete if you cross the level's border at the end. A mission is failed if your plane is destroyed. To display this information, we have written GameOverState that displays an appropriate message. Of course, this can be extended to show high scores, statistics, or save the game between multiple missions. But the basic principle remains the same. We reuse the states and GUI from the previous chapters. Since their implementation should be clear, we do not paste their code here. However, you are free to look at the original code base at any time.

Summary


This was probably the most difficult chapter up to now, as it combines all the game-related features we have developed in earlier chapters: resources, world, entities, input, and commands. Despite all the things to consider, it became apparent that the existing framework made a lot of new tasks simple to achieve.

In this chapter, you learned about essential gameplay mechanics and their interaction. We added projectiles to represent bullets and homing missiles. We let enemies spawn, follow certain movement patterns, fire in regular intervals, and drop pickups upon destruction. Collision detection and response was implemented, and we discussed performance considerations. Eventually, we managed the world's update cycle, and cleaned up destroyed entities.

Now that the game foundation has been built, we are ready to add more graphical content. In the next chapter, we are going to add a variety of visual effects to improve the appearance of our game.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
SFML Game Development
Published in: Jun 2013Publisher: PacktISBN-13: 9781849696845
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Authors (5)

author image
Artur Moreira

Artur Moreira is a game development enthusiast who ultimately aims to start a new game development company in his home country. He has been programming games and game-related software for over 4 years. Most of the effort in that time was put in creating an open source game-making library with lots of flexibility and portability. The library is called Nephilim and is known for supporting all major desktop and mobile operating systems, making game development fully crossplatform and fast. Alongside this big project, he keeps making his own prototypes and games for educational and commercial purposes. Aside from the programming, he also puts some focus in creative areas such as 3D modeling, digital painting, and music composing.
Read more about Artur Moreira

author image
Henrik Vogelius Hansson

Henrik Vogelius Hansson has always been in love with both games and programming. He started his education fairly early and continued on into the indie scene with Defrost Games and their game Project Temporality. The next company that hired him was Paradox Development Studio where he got to work on titles such as Crusader Kings 2. Beside the game companies, Henrik has also been very active in the SFML community and has even provided a binding for Ruby called rbSFML.
Read more about Henrik Vogelius Hansson