Wednesday, June 26, 2013

Week 7: Final Post

Alas, 16 long weeks have come and gone - and with it, the experience of a life time.

Indeed - this project has been a roller coaster of emotions, stress, and accomplishment.

After looking at the engine, assets, design, and game itself, I have a lot of thoughts going through my head. One is what a great learning experience it has been in regards to team-work, game design, and engine architecture.

First off, I would like to say kudos to my team for all of the effort they put into the game. It was a challenging project and was worth all the work that was put into it. Working on a code-base and a game with a team as this level has been a first for me and taught me a lot of lessons - especially about source control and how it is a requirement these days it seems. Many of the other teams can agree with me on that one.

Secondly, the game taught me about game design - from the conception of the game to the actual creation of it. Things change and issues cause delays. These seemed to be the two biggest setbacks for the design of the game. Content couldn't meet timelines, some content would just be too buggy, etc.

Finally, if I am to leave this project with any type of lesson - it is about the creation of software architecture. Particularly for games. I will be blunt - I would never use this engine again. If I had a time machine, I would go back and completely rebuild it in terms of design. The low level systems worked excellently - DirectX wrappers, file parsers, FMOD wrapper, camera wrapper - without a hitch. It was the game flow, states, and communication that caused the issues. First off, let me explain this in a technical way. The engine was designed heavily on the idea of OOP and so had lots of inheritance - mostly in relation to 'is-a'. This wasn't bad until I realized that rather than wide inheritance (which would be preferred) I had too deep of inheritance. This can be seen in the following manner.

Example of bad inheritance:

class Monster : public SpriteObject
class SpriteObject : public GameObject
class GameObject

Why is this wrong? First off, I broke a few rules by not following the best practice of virtual destructors, mostly because I did not know when to use them, and it is an unforgivable sin. Secondly,
I had SpriteObject a child of GameObject so that any class that was a child of SpriteObject could have a system for rendering a sprite and have data for movement, scale, and rotation. This was the wrong way to go about it.

What I should have done:

class Monster : public SpriteObject : public GameObject

This would have given Monster everything it needs with less issue. Also, it would have made adding, removing, altering, and creating game objects much simpler.

That was just one bad design flaw in the ChainEngine. The other one that is really two is complete failure to create a messaging system and a proper game flow. First, the messaging system. The need for a global message handler that took in data and processed it would have been a lot of help. Two things this would have done was avoid coupling and support class independence. Also, the messaging system would have been a supporter of proper game flow. The flow of a good engine would look similar to this:

if(!CheckWinConditions())
{
    GetInput();
    ProcessCharacterController();
    ProcessAI();
    CheckCollisions();
    HandleCollisions();
    UpdateCamera();
    Update();
    Render();
}
else
    OnWinCondition();

Then the message handler system could take data sent to it from each method and process it to be sent to the appropriate other methods for handling when needed. What our game engine did look like was something like this:

if(level0)
{
     character->Update() //this also contains all input from user
     weapon->Update(character) //used characters position passed my value
     hookshot->Update(character, weapon) //even more classes being passed by value
     level0->Update(character, weapon, hookshot) // unfortunately, this is also where most of the collision detection went about and also updated right here as well based on collisions, this was a huge design flaw.
     camera->Update(character)
     background->Update(camera)
...
}
if(level1)
{
    ""
}

Anyways, as you can see, this resulting in writing a lot of the same code for each level, as well as each monster, character, object, etc, included in it. It also caused a lot of coupling, a lot of passes by values which in turn resulted in a lot of function calls. This design broke our physics engine when it came to implement the hookshot.

All in all, I wouldn't say that it was a total piece of garbage engine, but it needed a lot of work. This is why I am glad we tackled creating our own engine, so that we could learn proper design of a game architecture and learn from our mistakes. After all it is programming, which means: Practice, Practice, Practice...

Indeed, I was sad to have the class end as I enjoy game programming and wish I could do more in a group. But, I came out of the class wiser in the ways of team work, game design, and engine architecture. Because of that, I can say that this project was a huge success.

Also, we have a website at http://rctaddict.adryheat.net/DeVry/GSP362/index.html , so check out the trailer!

Also, keep an eye on my Blog as I will be continuing it in a new section. This new portion of my blog will follow me as I design and code a 3D game engine using what I have learned in this class. The new engine will be called 'Kraken' and the posts will be found under that as well.

   


No comments:

Post a Comment