niit logo

How to make a game using C++


By NIIT Editorial

Published on 28/07/2021

8 minutes

With the advent of technology, computer games or online games have gained popularity. People of all ages enjoy playing games on their laptops, tablets and phones. With this increase in its usage, developers around the globe invest their time, creativity and skill in developing different types of games. This article will focus on a step-by-step procedure to create a game using C++.

 STEP 1: Choose your game library

A developer can write his own library for all the quintessential graphics or sound programming, or he can gain access to a game library. There are a lot of game libraries out in the public domain, but they all offer the same basic functionality.

Attributes required for a library:

Ø  A process to load and render images

Ø  A process to load and play audio

Ø  Simple image manipulation (rotation, etc.)

Ø  Primitive drawing capabilities (lines, dots, circles, rectangles, etc.)

Ø  Capability to render text

Ø  Ability to track time and wait

Ø  Capability to create and control threads (Not requires as such)

 

Most game libraries include:

Ø  SFML i.e., Simple Fast Multi-Media Library 

Ø  SDL i.e., Simple Direct Media Layer 

Ø  Allegro 

Ø  OpenGL (Rendering only, however, there are wrapper libraries like AllegroGL) 

Ø  DirectX (Windows only) 

Ø  Irrlicht (3D Library) 

 

STEP 2: Define the concept

The process of building a game starts here. To develop a game, you need to come with an idea for it. Once you have a basic idea of what game you want, start expanding on it. For instance, if you want to build a board game, think about the objective of the game or how you win the game? Suppose you want a game that has a story; you will need to create characters and a storyline.

An important thing to be kept in mind is that the concept should be well-defined as to what the game will be once it is finished. If your game is complex, you need to plan it out at its inception so that you don’t worry about the game while coding. You just need to keep in mind that the game will advance as you create it.

 

STEP 3: Plan your engine

This step is usually for complex games. You can use a pre-made engine or even write an “engine” of your own. So, a game engine is basically a super-powered library that provides a high level of functionality like physics, resource handling and game entity management. The developer can choose if he wants to use an existing engine or create his own. It actually depends on how much programming he actually wants to do. A pre-made game engine just makes it easy for a programmer to script gameplay or events.

Why “plan” your engine rather than “choose”? This is for the simple reason that most of the code you write and intend to reuse will culminate to be so looped with your game logic that it would become difficult to be reused. It should be kept in mind that the code should be readable, functional and organized instead of focussing on creating an absolutely reusable and super robust framework. The main emphasis should be on making the game and then creating portable modules.

 

STEP 4: Write your engine

This step will come into the picture when the programmer decides to make his own game engine. This step involves processes like core rendering, physics and file handling and not just the game itself. Usually, simple games don’t need much of a framework and can easily be programmed using a game library directly.

A very important factor that is often neglected in large games is the resource manager. Presumably, the resource manager is a class that is responsible for loading resources like graphics and sound. This resource manager ensures that resources are loaded only once and are unloaded when they are no longer needed. In this, the RAM isn’t infinite. The following is an example of a resource manager:

 

// #include <map>

// #include <string>

// #include <exception>

#include<bits/stdc++.h> // all header files included in one line

typedef const std::string Address;

 

namespace Exceptions {

 

        // thrown if user requests a resource URI not present in the manager's list

        class AddressNotFound : public std::runtime_error

        {

        public:

               AddressNotFound(const std::string& Message = "The specified Address(URI) was not found in the resource index.")

                       : runtime_error(Message) { }

        };

 

        // given when a resource allocation fails

        class Bad_resource_allocation : public std::runtime_error {

        public:

               Bad_resource_allocation(const std::string& Message = "Can not allocate memory for resource.")

                       : runtime_error(Message) {}

        };

}

 

template <class R_src> class Resource_managerB {

        typedef std::pair<Address, R_src*> resource_pair;

        typedef std::map<URI, R_src*> resource_list;

 

 

        resource_list R;

public:

        ~Resource_managerB() { unload_all(); }

 

        // Load the resource with the specified Address(URl)

        // the URI could represent, e.g, name of the file

        Address& Load(Address& Addr);

        // unload the resource with the specified address(URl)

        void Unload(Address& Addr);

        // unload all resources

        void unload_all();

 

        // give a pointer to the resource

        R_src* t_Ptr(Address& Addr);

        // get a Reference to the resource

        R_src& Get(Address& Addr);

};

 

template <class R_src>

Address& Resource_managerB<R_src>::Load(Address& Addr)

{

        // checking if the resource address (URl) is already in list

        // and if it is, we stop

        if (R.find(Addr) == R.end())

        {

               /* trying to allocate the resource

             NB: if the R_src template argument does not have a

               constructor, then this

               line will cause a compiler error */

               R_src* temp = new (std::nothrow) R_src(Addr);

               // if the resource is failed to get allocated

               // std::nothrow means that if allocation failed

               // temp will become 0

               if (!temp)

                       throw Exceptions::Bad_resource_allocation();

               // add the resource and it's Address(URI) to the manager's list

               R.insert(resource_pair(Addr, temp));

        }

        return Addr;

}

 

template <class R_src>

void Resource_managerB<R_src>::Unload(Address& Addr)

{

        // try to find the specified Address(URI) in the list

        resource_list::const_iterator itr = R.find(Addr);

        // if it is found...

        if (itr != R.end())

        {

               // ... deallocate it

               delete itr->second;

               // then delete it from list

               R.erase(Addr);

        }

}

 

template <class R_src>

void Resource_managerB<R_src>::unload_all()

{

        // go through each element in the resource list

        resource_list::iterator itr;

        for (itr = R.begin(); itr != R.end(); itr++)

               // delete each resource

               delete itr->second;

        // finally, clear the list

        R.clear();

}

 

template <class R_src>

R_src* Resource_managerB<R_src>::t_Ptr(Address& Addr)

{

        // find the specified address (URl) in the given list

        resource_list::const_iterator itr;

        // if it is there...

        if ((itr = R.find(Addr)) != R.end())

               // just return a pointer to the corresponding resource

               return itr->second;

        // ... else return 0

        return 0;

}

 

template <class R_src>

R_src& Resource_managerB<R_src>::get(Address& Addr)

{

        // get a Pointer to resource

        R_src* temp = t_Ptr(Addr);

        // if the resource was found...

        if (temp)

               // ... dereferencing the pointer so as to return a reference

               // to the resource

               return *temp;

        else

               // ... otherwise give an exception to notify the caller that

               // the resource was not found

               throw Exceptions::AddressNotFound();

}

 

 

 

Apart from this, the interface of the engine or framework is also important. While writing the logic of the game, it should be kept in mind to keep it simple and concise. Try to update all the game logic with one or two function calls. Using object-oriented principles like inheritance and pure virtual base classes is a good way to create a framework with sound structure. 

In the fragment given below, a base class of all game objects is defined:

class GameObject

class game_object

{

public:

    virtual ~game_object()=0;

 

    virtual Vector2f get_position();

 

    virtual bool interact(Object* o);

 

    virtual void draw(); //highly library dependent

};

 

In the above fragment, all the subclasses are now held to this interface. It is, therefore, possible to have one holding entity that will easily store and manage each and every object.

 

STEP 5: Media (audio and graphics)

This step includes adding audio and visuals to a game. There are a number of free graphics and sound effects available on Google. Two paramount tools for editing are Audacity and GIMP.

 

STEP 6: Write your game

After the programmer has chosen an engine, the next step is to start writing the game logic. The game framework should establish a base that structures object interaction and handles all rendering and low-level details.

The game logic defines the following:

Ø  object interaction (by defining a subclass of GameObject for example),

Ø  game rules (such as what constitutes winning or losing),

Ø  the initial state of the game (which map is loaded first, what items you start with, etc)

Ø  will contain the main game loop.

 

Let's talk about what the "main game loop" is. It is a loop that contains things that are being repeated continuously while the game is being played. This loop will use the following framework:

while (!Game.player_lost())

{

    universe.update(); //assume this universe object owns all of the GameObjects and updates them also

 

    screen.clear();

    world.draw(screen);

    screen.display();

 

    Proper_FPS(); 

}

 

STEP 7: Package and Distribute

The final step is to make your game available for people. All the required files can be packaged into a zip file, compressed archive or executable installer and then can be made available to the public.

 

Conclusion

To sum up, the above steps can be followed to create a game. Make sure to be organized and keep the code clean and readable. The main purpose of games is to have fun, so make sure that the game is fun as well.

If interested in a career in game development, then do explore NIIT's Game Development Certification.



Game Development Course

Becoming a Game Developer: A Course for Programmers. Design and Build Your Own Game using Unity.

Job Placement Assistance

Course duration: 20 weeks

call
Top