Chapter     27

Wrapping Up

The C++ programming language is a tool that will serve you well while trying to build video games. It provides low-level access to processors, which allows you to write efficient code for a wide variety of computer processors.

This book has shown you various techniques, features, and paradigms that you can apply to your own programming efforts. You’ve seen that C++ can be used to write procedural programs or object-oriented programs. Procedural programs can be created consisting only of functions, variables, and structs, whereas object-oriented programs are built from classes.

C++ extends these two paradigms by also allowing for generic programming. This type of programming is supported through the ability to create templates. Templates are used to create blueprints for classes with abstract types. The template compiler is responsible for creating specialized instances of template classes at compile time. C++ uses templates to provide the Standard Template Library. The STL supplies many data structures and algorithms so that you do not have to write every program from scratch.

An Overview of Text Adventure

This book ended with a very simple text adventure game that you can now expand into a full game if you wish. Listing 27-1 shows the Game class definition. This class encapsulates all of the types of programming C++ provides.

Listing 27-1. The Game Class Definition

class Game
        : public EventHandler
        , public QuitObserver
{
private:
        static const uint32_t m_numberOfRooms = 4;
        using Rooms = std::array<Room::Pointer, m_numberOfRooms>;
        Rooms m_rooms;
 
        Player m_player;
 
        Option::Pointer m_attackDragonOption;
        Option::Pointer m_attackOrcOption;
        Option::Pointer m_moveNorthOption;
        Option::Pointer m_moveEastOption;
        Option::Pointer m_moveSouthOption;
        Option::Pointer m_moveWestOption;
        Option::Pointer m_openSwordChest;
        Option::Pointer m_quitOption;
 
        Sword m_sword;
        Chest m_swordChest;
 
        using Enemies = std::vector<EnemyBase::Pointer>;
        Enemies m_enemies;
 
        std::mutex m_mutex;
        mutable std::unique_lock<std::mutex> m_finishedQueryLock{ m_mutex, std::defer_lock };
        bool m_playerQuit{ false };
        void SetPlayerQuit()
        {
                m_finishedQueryLock.lock();
                m_playerQuit = true;
                m_finishedQueryLock.unlock();
        }
 
        bool m_playerWon{ false };
        void SetPlayerWon()
        {
                m_finishedQueryLock.lock();
                m_playerWon = true;
                m_finishedQueryLock.unlock();
        }
        
        bool GetPlayerWon()
        {
                m_finishedQueryLock.lock();
                bool playerWon = m_playerWon;
                m_finishedQueryLock.unlock();
                return playerWon;
        }
 
        void InitializeRooms();
        void WelcomePlayer(const bool loaded);
        void GivePlayerOptions() const;
        void GetPlayerInput(std::stringstream& playerInput) const;
        void EvaluateInput(std::stringstream& playerInput);
public:
        Game();
        virtual ~Game();
 
        void RunGame();
 
        virtual void HandleEvent(const Event* pEvent);
 
        // From QuitObserver
        virtual void OnQuit();
 
        bool HasFinished() const
        {
                m_finishedQueryLock.lock();
                bool hasFinished = m_playerQuit || m_playerWon;
                m_finishedQueryLock.unlock();
                return hasFinished;
        }
};

The Game class shows how you can construct classes in C++. There is a parent class from which Game derives. This class provides an interface that includes virtual methods. The Game class overrides these virtual methods with specific instances of its own. A perfect example of this is the HandleEvent method.

Game also shows how you can customize STL templates for your own uses. There is an array of Room::Pointer instances as well as a vector of EnemyBase::Pointer instances. These types of pointers are created using type aliases. Type aliases in C++ allow you to create your own named types and are generally a good idea. If you ever need to change the type of an object at a later date you can get away with just changing the type alias. If you hadn’t used an alias you would be required to manually change every location where the type had been used.

There is also a mutex present in the Game class. This mutex is a clue to the fact that C++ allows you to write programs that can execute on multiple CPU cores at once. A mutex is a mutual exclusion object that allows you to ensure that only a single thread is accessing a single variable at one time.

Listing 27-2 contains the final source code for the Game::RunGame method. This method consists of code that shows how you can iterate over collections and use futures.

Listing 27-2. The Game::RunGame Method

void Game::RunGame()
{
        InitializeRooms();
 
        std::packaged_task< bool() > loaderTask{ LoadSaveGame };
        std::thread loaderThread{ std::ref{ loaderTask } };
        auto loaderFuture = loaderTask.get_future();
        while (loaderFuture.wait_for(std::chrono::seconds{ 0 }) != std::future_status::ready)
        {
                // Wait until the future is ready.
                // In a full game you could update a spinning progress icon!
                int32_t x = 0;
        }
        bool userSaveLoaded = loaderFuture.get();
        WelcomePlayer(userSaveLoaded);
 
        while (!HasFinished())
        {
                GivePlayerOptions();
 
                stringstream playerInputStream;
                GetPlayerInput(playerInputStream);
 
                EvaluateInput(playerInputStream);
 
                bool playerWon = true;
                for (auto& enemy : m_enemies)
                {
                        playerWon &= enemy->IsAlive() == false;
                }
 
                if (playerWon)
                {
                        SetPlayerWon();
                }
        }
 
        if (GetPlayerWon())
        {
                SerializationManager::GetSingleton().ClearSave();
                cout << "Congratulations, you rid the dungeon of monsters!" << endl;
                cout << "Type goodbye to end" << endl;
                std::string input;
                cin >>input;
        }
}

The range-based for loop can be used in conjunction with the auto keyword to provide easy, portable iteration over many STL collections. You can see it in action in RunGame where there is a loop over the m_enemies vector.

A paired_task is used to execute save game loading on a separate thread of execution. The std::thread::get_future method is used to acquire a future object that lets you know when the task you were executing has been completed. This approach to loading can be used to allow you to load games while updating a dynamic loading screen.

There is also an example of how to use cin and cout to read player input and write out messages to the console. Input and output are fundamental concepts for game developers as they are essential to providing the interactivity that players expect from games.

Summary

Game development is a fun but demanding field to enter. There are many areas to explore, learn, and attempt to master. Very few people become proficient in all areas of game development, but their programming skills are usually transferable. Programmers can specialize in graphics programming, network programming, gameplay programming, or other fields such as audio and animation. There will never be a shortage of tasks for programmers to undertake as most large games are written in C++ with code bases that have been around for 10 to 20 years. Engines such as Cryengine, Unreal, and Unity are written in C++ and provide support for scripting languages to create game logic. C++ is a perfect choice for someone looking to begin a career in game development that will take them into an AAA game development studio at some point.

I hope you’ve found this book an enjoyable entry into your journey down the path of your chosen career.

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

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