Thursday, April 3, 2014

Sample Video Game Technical Proposal and Execution Plan

A good technical plan can go a long way in helping you attract developers and acquire funding. The following plan was a part of the development package for the game Genesis Seed that was submitted to Activision for their 2011 Independent Games Competition. The project was cancelled but we still have a lot of useful information and resources from it.

Note: The numbers in the work breakdown are not to create a game from scratch. This technical proposal gives details on how to finish the project.

Leave a comment if you would like more information.


Thursday, February 27, 2014

Squared Game Engine High-level Overview



Developing a game engine can be a lot of work. Over the years, I’ve developed quite a few game engines, and I’ve learned a lot of lessons doing it. I want to share some of those lessons by giving a very high level overview of my current game engine.

When developing my current game engine, I wanted it to be modular and expandable. Because of this, I decided to make the engine into separate libraries and I tried to limit dependencies between libraries to the most minimal extent possible. This methodology also carried over to the way I designed my individual classes. Limiting dependencies is one of the most important things that I feel is needed to write clean maintainable code. Below is a diagram of the main libraries that I created for the Squared Game Engine. Note that these are libraries and not classes and that the graph shows the dependencies.



I keep to this strictly. The code in DSquaredCore knows nothing about SquaredDPublic and should never directly or indirectly try to access anything inside of it. DSquaredNet “knows” about DSquaredLogic, but DSquaredLogic should never try to access DSquaredNet. Keeping these strict dependencies has helped my quickly spot design issues in other parts of the code. Sometimes code needs to be made quickly to get things done, but fooling around with the dependencies is unacceptable.

But what is in all of those libraries? Here’s a quick overview.

SquaredDPublic
The purpose of classes and functions under this namespace and library are to provide a multiplatform framework from which the game can be built from. For platform support and graphics, I have separate libraries for each platform that link with the rest of the application. For example, I currently have two WindowsDirectX9 and a WindowsDirectX11. When one of those libraries is linked with the application, the other classes in this namespace will use them to provide graphics and input support for the application. Initially, this namespace was just a bunch of utility functions, but it’s been morphing into the basic game framework. For the 3D engine, the code in SquaredDPublic has been locked. The next version is being built alongside an experimental 2D engine. In the future, I want SquaredDPublic to be able to be the base for any type of game. Currently this code is closed source, but I in the future I want to release the source code of it with demos. That’s why I named it SquaredDPublic.

DSquaredCore
I developed DSquaredCore to be the core components of a game and able to exist with or without graphics, sound, and user input. DSquaredCore provides functionality but it was meant as a hub to which other modules should link to. I did this because I wanted to be able to build a graphical game, and at the same time be able to build a console-based server only version. The code in this library includes the game state manager, the game loop, and the component-based entity system. The code in this library was developed to work with the code in SquaredDPublic, but it can work with any graphics engine as long as the proper “bridge” code is written for it.

DSquaredLogic
DSquaredLogic as its name implies has the code that includes most of the simulation logic. It provides classes for physics and collision detection (via NVidia PhysX), AI, and the base character controllers. The classes in this library are focused on the game logic needed once gameplay starts. It also has some basic code for initializing levels. The code was written with expansion in mind so there are many places for linking in extra features. The game uses component-based entities so AI and physics components are defined in this library.

DSquaredNet
DSquaredNet uses RakNet4 to provide networking capabilities to the game. It has classes that plug into DSquaredLogic to handle network connections and synchronization. One major design decision that I made early on was I wanted to be able to make a server only console app without graphics using only DSquaredCore, DSquaredLogic, and DSquaredNet.

DSquaredGame
DSquaredGame provides functionality to link the engines core systems with SquaredDPublic to make a game with graphics, sound, and user input. DSquaredGame provides all of the graphics entity components. DSquaredGame was designed for 3D games and doesn't provide any 2D support apart from what's provided in SquaredDPublic. The GUI system is totally separate and interfaces with SquaredDPublic directly to to access the 2D functions. 

SquaredDGame
The code in this library started out as game specific code. Over time I saw that it could be reused so I extracted the code into it's own library. The code in this library helps to bind everything together. This code is not needed when making a game using the engine, but it greatly simplifies the task of making 3D multiplayer games. Game specific code under normal circumstances will only need to access the code in this library. Game Specific Code

There are some other things that in the code that I didn't mention, but these are the main parts. From this, you can get a basic understand of the engine’s modular design. 

Thursday, February 13, 2014

Fun with Modern C++ and Smart Pointers

C++ has changed over the years. With the new C++11 standard, we now have smart pointers, but what are they and how are they different from normal pointers.

Raw Pointer Primer
There are two basic ways to create a variable in C++: stack variables and heap allocations. Stack variables are defined inside a certain scope and as long as you're in that scope, the variable will exist. Heap allocations (dynamically allocated memory), variables typically declared with new or malloc, aren't not defined within a scope and will exist until the memory is freed.

Here's an example:

void foo()
{
    // Object A of class CSomeClass has been declared inside the scope of foo
    CSomeClass A;

    // do some stuff
    ....

    // you can even call other functions and use A as a parameter
    Func1(A); // This could be pass by value or pass by reference depending on Func1's declaration

    Func2(&A); // Passes a pointer to A

    // at the end of this  function, the scope will end and A will automatically be destroyed
}
Now with this function, every time another function calls foo, A will be created and then destroyed when the function exits. Not bad right. What about this?

void foo()
{
    // Object A of class CSomeClass has been declared inside the scope of foo
    CSomeClass *A = new CSomeClass; 

    // do some stuff
    ....

    // you can even call other functions and use A as a parameter
    Func1(*A); // This could be pass by value or pass by reference depending on Func1's declaration

    Func2(A); // Passes pointer A of CSomeClass (Edited)

    // MEMORY LEAK
    // at the end of this  function, the scope will end, but A was created on the heap
    // delete should be called here
}
So with dynamic memory allocations, you must free the memory. So why you might ask do we even need dynamic memory allocations? Well one, to declare variables on the stack, you need to know exactly what you'll need at compile time. If you want to be able to create arrays of various sizes depending on user input, or if you're making a game and want to load variable amount of resources, you'll need to use dynamic memory allocations.
Take this example:

int num_students;

// First get the number of students in the class
std::cout << "How many students are in the class?"
std::cin >> num_students;

// Create a dynamic students array
CStudent *student_array = new CStudent[num_students];

// Do some stuff with the data
....

// call the array version of delete to free memory
delete [] student_array;

In the previous situation, you must use dynamic memory because the size of the array is determined by the user. How can smart pointers help?

Smart Pointers
(chief reference: Smart Pointers (Modern C++) on MSDN)

Smart pointers allow you to create dynamic memory allocations but defined them inside a scope or an owner. This way, when the owner goes out of focus, the data will be automatically deleted. Smart pointers have been implemented using templates and to use them, you must include the header . Smart pointers are in the std namespace. I will only discuss unique_ptr's here. So how do you create a unique_ptr?


std::unique_ptr apples(new Base(L"apples")); // Where Base is the class type

You create a unique_ptr like a typical template and then pass the raw pointer to initialize the variable. After that, you can use the unique_ptr, just as you would any other pointer.

class Base
{
    public:
        Base(const std::wstring &string)
        :m_string(string)
        {
        }

        virtual void Display() const
        {
            std::wcout << L"Base:" << m_string << std::endl;
        }

    private:
        std::wstring m_string;
};

int main()
{
    // declare some unique_ptrs. This pointers can have only one owner and cannot be copied. Only moved.
    std::unique_ptr<Base> apples(new Base(L"apples"));

    apples->Display();
}

unique_ptr's can also be passed to other functions, but you must pass by reference. Passing by value will result in a compiler error. With unique_ptr's, only one can own the pointer, but if you pass by value you will make a copy of the unique_ptr which in essence makes two unique_ptr's that own the same block of memory. You can also use unique_ptr's with derived class and virtual functions and get the typical C++ behavior.
class Base
{
    public:
        Base(const std::wstring &string)
        :m_string(string)
        {
        }

        virtual void Display() const
        {
            std::wcout << L"Base:" << m_string << std::endl;
        }

    private:
        std::wstring m_string;
};

class Derived : public Base
{
    public:
        Derived(const std::wstring &string)
        :Base(string)
        {
        }

        virtual void Display() const
        {
            std::wcout << L"Derived:::";
            __super::Display(); // __super is MS specific. Others should use Base::Display();
        }
};

int main()
{
    // declare some unique_ptrs. This pointers can have only one owner and cannot be copied. Only moved.
    std::unique_ptr<Base> apples(new Base(L"apples"));
    std::unique_ptr<Base> oranges(new Derived(L"oranges"));

    apples->Display();
    oranges->Display();
}

This is very useful when dealing with vectors as the next example show.
std::vector <std::unique_ptr<Base>> test_vector;

test_vector.push_back(std::unique_ptr<Base>(new Base(L"apples")));
test_vector.push_back(std::unique_ptr<Base>(new Derived(L"oranges")));

In the above example, you can use the vector of unique_ptr's in the same way you would if it was a vector of raw Base pointers, but there is one nice benefit. If this vector had raw pointers, you'd have to make sure you manual free the pointers before you clear the vector or erase an element, but with unique_ptr's, all of that is handled for you.

Conclusion
I hope this information was helpful. I am in no way an expert so if you anyone sees something glaring that I missed, feel free to leave a "kind" comment. If you would like to know more about smart pointers, I suggest checking out the like on msdn.