Research Coding Projects 3D

Turonix

Video

Description

This was my first game I made inside DAE.
I already re-wrote it with some more advanced coding techniques, but the gameplay is still the same.
Also it is more a fan-based game than an arcade game (which was the original assignment), but I.m a huge fan of the DragonBallZ series and my teachers where oke with it.
All the sprite, backgrounds , sounds, etc. belong to their specific owners.
I'd like to thank Toei Animation and Akira Toriyama for making this game possible
All the coding is done by myself.

Engine

  • Custom Framework

Language

  • C++

You need to have 2 Xbox controllers to be able to play the game.
Only in the menu you can navigate using the keyboard.

Download Code Download Source Code Download BinDownload Binaries

Screenschots

image carousel

Code Demonstaration

Content Processor & ContentManager

As you might have seen inside the video or in the screenshots this game has a lot of bitmaps.
I was not planning on including every bitmap with a hardcoded path inside my project so I started researching how XNA processes his content.
The way I solved it is, I made 2 classes one that processes the content and one that loads the content.
The content processor has a root directory just like XNA's contentmanager has a root directory.
All folders and sub-folders inside this directory are parsed and checked if they have the right extention (BMP, PNG, TGA, WAV, MP3, AVI, MPG, MP4, WMV).
When a file with the right exetention has been found the processor sorts it inside a vector of ResourceData structures.
A Resource data structure looks as followed:


struct ResourceData
{
	//Constructor
	ResourceData()
	:pResource(nullptr)
	, Name(_T(""))
	, Path(_T(""))
	, ID(-1)
	, Type(-1)
	{}
	ResourceData(Resource* resource, const std::tstring& name, const std::tstring& path, int id, int type)
	: pResource(resource)
	, Name(name)
	, Path(path)
	, ID(id)
	, Type(type)
	{}
	
	//To reduce some space I deleted these two methods
	//I did write them down in the actual code
	//operator==
	//operator=

	//Members
	Resource* pResource;
	std::tstring Name;
	std::tstring Path;
	int ID;
	int Type;
};		

As you can see the path is stored inside this vector, later the contentmanager will use this path to create the resource.
The processor also has a search/filter part, this search part will make sure that only the files with the search criteria will be processed.
The part that will always be loaded is if the processor finds a file/directory with the name "Misc".
The following code is an example on how the contentprocessor loads bitmaps.


switch (m_vecResources[m_ResourceCounter].Type)
{
case Caller::Bitmap:
	m_vecResources[m_ResourceCounter].pResource = new Bitmap(m_vecResources[m_ResourceCounter].Path);
	break;
case Caller::Audio:
	m_vecResources[m_ResourceCounter].pResource = new Audio(m_vecResources[m_ResourceCounter].Path);
	break;
case Caller::Video:
	m_vecResources[m_ResourceCounter].pResource = new Video(m_vecResources[m_ResourceCounter].Path, GAME_ENGINE->GetWindow(), 0, 0, GAME_ENGINE->GetWidth(), GAME_ENGINE->GetHeight());
	dynamic_cast<Video*>(m_vecResources[m_ResourceCounter].pResource)->Play();
	break;
}		

Animated Bitmap

The animated bitmap class is also a big part of this game.
Because many sprites have a sprite sheet and need to be animated during the game I made a class that will help me a little.
The constructor of an animated bitmap class look something like this.


AnimatedBitmap(DOUBLE2 startposition, int type, const std::tstring& filename ,int amountanimations = 1, int stages = 1);
				

The first parameter speaks for himself it's the initial position of the bitmap.
The type of the bitmap can be HORIZONTAL or VERTICAL depending on how the sprite sheet is arranged.


The next parameter is the filename of the bitmap this is not the path just the name of the file.
Because the content manager already loaded the spritesheet we just need to ask for the name of the bitmap and the contentmanager will return the bitmap.
Then will enter how mush animations our spritesheet has per row, and how many stages it has.
The next image has 5 animations and 2 stages.


With these parameters the class can generate a rect that will move over the spritesheet.
Next code will show a how to create an animated bitmap.


AnimatedBitmap* transformation_firststage = new AnimatedBitmap(DOUBLE2(), AnimatedBitmap::HORIZONTAL, _T("Transform0") + CharacterTypeSerializer::ToString(m_pStatsManager->GetCharacterType()), 8, 1);

transformation_firststage->SetFrameDelay(7);
transformation_firststage->SetRepeat(false);
transformation_firststage->Hide();
				

The class has diffrent methods to adjust the animation to the users needs.
  • SetFrameDelay() = how many frame need to pass to switch to the next animation.
  • SetRepeat() = does the spritesheet need to loop or not.
  • Hide() = hide the bitmap at the start of the game.
There are much more methods that you can call on the animated bitmap class.
You can find them inside the source code.

SceneManager

The last thing I wanted to talk about is the scenemanager.
The scenemanager manages all the scenes that are inside the game.
If a scene needs to be activated you can just call SetActiveScene("Scenename") giving the name of the scene as parameter.
What will happen is that the scenemanager will check if the scene already exists.
If the scene exists but the content is not loaded yet, the active scene will become a loadingscene.
the loadingscene will initalize and load all the content of the scene.
If all that is done the scene will be acivated again.
Now that the content is loaded the scene will be activated.


//SceneManager
bool SceneManager::SetActiveScene(const std::tstring& name)
{
	for (int i = 0; i < (int)m_vecScenes.size(); ++i)
	{
		if (m_vecScenes[i])
		{
			if (m_vecScenes[i]->GetName() == name)
			{
				if (m_vecScenes[i]->IsContentLoaded())
				{
					if (m_ActiveScene)
					{
						m_ActiveScene->Deactivate();
						m_ActiveScene = m_vecScenes[i];
						m_ActiveScene->Activate();

						return true;
					}
					else
					{
						OutputDebugString(_T("No active scene found.\n"));
						return false;
					}
				}
				else
				{
					if (!m_LoadingScene)
					{
						m_LoadingScene = new LoadingScene();
						m_LoadingScene->ProcessContent(_T(".\\Content\\") + m_LoadingScene->GetName());
						m_LoadingScene->GetContentManager()->ForceTick();

						m_LoadingScene->Initialize();
						m_LoadingScene->LoadContent();

						m_LoadingScene->SetLoadingScene(m_vecScenes[i]);

						if (!m_ActiveScene)
							m_ActiveScene = m_LoadingScene;

						AddScene(m_LoadingScene);
						SetActiveScene(_T("LoadingScene"));

						return true;
					}
					else
					{
						m_LoadingScene->SetLoadingScene(m_vecScenes[i]);
						SetActiveScene(_T("LoadingScene"));

						return true;
					}
				}
			}
		}
	}

	//Create scene if not existing
	AddScene((TypeFactory::CreateObject(name)));
	SetActiveScene(name);

	return false;
}