/*
	Trig Wars.
	Copyright (c) 2008, Darragh Coy.
	All rights reserved.
	Original work(s), source code & author(s) details available at: http://www.darraghcoy.com

	Redistribution and use in source and binary forms, with or without modification, are permitted 
	provided that the following conditions are met:

		* 	Redistributions of source code must retain the above copyright notice, this list of 
			conditions and the following disclaimer.
		* 	Redistributions in binary form must reproduce the above copyright notice, this list of 
			conditions and the following disclaimer in the documentation.
		* 	Neither the name of the author nor the names of contributors may be used to endorse or 
			promote products derived from this software without specific prior written permission.
		* 	The use of any third party libraries, modules or data files provided with the source 
			form of the program must follow and respect the individual licensing terms of these 
			components. You do not have permission to modify or circumvent the licensing terms for 
			provided third party components unless the third party licenses specifically allow this. 
			If you do not agree to the terms of provided third party components then you do not have 
			permission to use them in your derived work(s).
		* 	The terms of this license do not apply to separate (but related) distributions if supplied 
			by the author(s), only to the contents of this source distribution, derived works, and the 
			binaries produced by either modified or unmodified versions of the source code. The terms 
			of this license do not also apply to any third party libraries or components provided with 
			the source distribution. Such third party elements are licensed under their own separate 
			agreements.

	THIS SOFTWARE IS PROVIDED BY DARRAGH COY ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 
	BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
	ARE DISCLAIMED. IN NO EVENT SHALL DARRAGH COY BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
	EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
	OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
	OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
	IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

//=====================================================================================================================
/// @brief		Class representing the game hud. Draws the map & player score etc. for every frame.
//=====================================================================================================================

#include "Precompiled.h"
#include "Game\GameHud.h"
#include "Game\GameCore.h"
#include "Game\GameObjectManager.h"
#include "Windows\Window.h"
#include "Graphics\Display.h"
#include "Graphics\Camera2D.h"
#include "Graphics\BufferedPointRenderer.h"
#include "Graphics\PrimitivesRenderer.h"
#include "Graphics\BitmapFont.h"
#include "GameObjects\AIControlled.h"
#include "GameObjects\EnemyWaspManager.h"
#include "GameObjects\EnemyFactoryManager.h"
#include "GameObjects\EnemyPredatorManager.h"
#include "GameObjects\EnemyWasp.h"
#include "GameObjects\EnemyFactory.h"
#include "GameObjects\EnemyPredator.h"
#include "GameObjects\PlayerShip.h"

using namespace Game;

//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
/// Size of the map display. This is half extent size from it's center 
/// Coordinates are given in the native resolution of the screen.
//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

const Vec2f GameHud::MAP_SIZE = Vec2f( 100, 100 );

//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
/// Size of the map frame. This is the position of it's center. 
/// Coordinates are given in the native resolution of the screen.
//'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

const Vec2f GameHud::MAP_FRAME_SIZE = Vec2f(150,150);

/// Number of units to draw for the health bar:

const unsigned GameHud::HEALTH_BAR_UNITS = 32;

/// Size of each health bar unit

const Vec2f GameHud::HEALTH_UNIT_SIZE = Vec2f(30,60);

/// Horizontal spacing between each health bar unit

const float GameHud::HEALTH_UNIT_SPACING = -6;

//=====================================================================================================================
/// @brief		Creates the hud display
/// @pre		The game must exist
/// @pre		The game must have a window
/// @pre		The game must have a font
/// @pre		The game must have a texture manager
/// @pre		The game must have a vertex shader manager
/// @pre		The game must have a pixel shader manager
//=====================================================================================================================

GameHud::GameHud()
{
	// Make sure ok:

	ENSURE( GameCore::GetSingleton()							, "The game must exist"							);
	ENSURE( GameCore::GetSingleton()->GetWindow()				, "The game must have a window"					);
	ENSURE( GameCore::GetSingleton()->GetFont()					, "The game must have a font"					);
	ENSURE( GameCore::GetSingleton()->GetTextureManager()		, "The game must have a texture manager"		);
	ENSURE( GameCore::GetSingleton()->GetVertexShaderManager()	, "The game must have a vertex shader manager"	);
	ENSURE( GameCore::GetSingleton()->GetPixelShaderManager()	, "The game must have a pixel shader manager"	);
	
	// Get the game:
	
	GameCore * game = GameCore::GetSingleton();
	
	// Get the game fonts:
	
	m_font					= * game->GetFont(); 
	m_small_font			= * game->GetSmallFont();
	m_reading_font			= * game->GetReadingFont();
	m_reading_shadow_font	= * game->GetReadingShadowFont();
	
	// Make the camera:

	m_camera = new Camera2D
	(
		GameCore::GetSingleton()->GetWindow()	,
		Vec2f::Zero()							,
		GameCore::NATIVE_RES					,
		1										,
		1000
	);

	/// Clear these to null initially

	m_wasp_mgr		= 0;
	m_factory_mgr	= 0;
	m_predator_mgr	= 0;
	m_player		= 0;
	
	// Get the texture manager:
	
	TextureManager * tex_mgr = game->GetTextureManager();
	
	// Get the game display:
	
	Display * display = game->GetWindow()->GetDisplay();
	
	// Create our vertex format for rendering:
	
	{	
		VertexFormat::ElementUsage usages[] = 
		{
			VertexFormat::VF_USAGE_POSITION	,
			VertexFormat::VF_USAGE_COLOR	,
			VertexFormat::VF_USAGE_TEXCOORD
		};

		VertexFormat::ElementType types[] = 
		{
			VertexFormat::VF_TYPE_FLOAT3	,
			VertexFormat::VF_TYPE_COLOR		,
			VertexFormat::VF_TYPE_FLOAT2
		};
		
		m_vf = VertexFormat(display,3,usages,types);
	}

	// Load our textures:

	m_frame_tex			= tex_mgr->GetTexture("Textures\\MapFrame.dds");
	m_health_unit_tex	= tex_mgr->GetTexture("Textures\\HealthBarUnit.dds");
	
	// Load our vertex and pixel shaders
	
	m_ps = game->GetPixelShaderManager()->GetPixelShader("Shaders\\Textured.psh.bin");
	m_vs = game->GetVertexShaderManager()->GetVertexShader("Shaders\\Textured.vsh.bin");
	
	// Load shader uniform:
	
	if ( m_vs.IsValid() )
	{
		m_u_transform = m_vs.GetUniform("Transform");
	}
	
	// Now see if all our resources are valid:
	
	if 
	(
		m_font.IsValid()			&&
		m_small_font.IsValid()		&&
		m_ps.IsValid()				&&
		m_vs.IsValid()				&&
		m_vf.IsValid()				&&
		m_frame_tex.IsValid()		&&
		m_health_unit_tex.IsValid()	&&
		m_u_transform.IsValid()
	)
	{
		m_valid_resources = true;
	}
	else
	{
		m_valid_resources = false;
	}
}

//=====================================================================================================================
/// @brief		Destroys the map display
//=====================================================================================================================

GameHud::~GameHud()
{
	// Finished with camera

	m_camera->RemoveReference();

	// Remove references to any managers:

	if ( m_wasp_mgr		) m_wasp_mgr->RemoveReference();
	if ( m_factory_mgr	) m_factory_mgr->RemoveReference();
	if ( m_predator_mgr	) m_predator_mgr->RemoveReference();
	if ( m_player		) m_player->RemoveReference();
}

//=====================================================================================================================
/// @brief		Annouces the type name for this object.
/// @returns	Type name of this object
//=====================================================================================================================

const char * GameHud::GetTypeName() const
{
	return "GameHud";
}

//=====================================================================================================================
/// @brief		Draws the entire game hud
/// @pre		The game should exist
//=====================================================================================================================

void GameHud::Draw()
{
	// Make sure ok:
	
	ENSURE( GameCore::GetSingleton() , "The game should exist" )

	// Draw all hud elements: but only if valid resources
	
	if ( m_valid_resources )
	{		
		DrawMap();
		DrawScore();
		DrawHealthBar();
		
		// Get the game:
		
		GameCore * game = GameCore::GetSingleton();
		
		// Draw instructions etc:
		
		switch ( game->GetCurrentState() )
		{
			case GameCore::STATE_SHOW_INSTRUCTIONS:
			
				DrawInstructions();
			
			break;
			
			case GameCore::STATE_GAME_PAUSED:
			
				DrawGamePaused();
			
			break;
			
			case GameCore::STATE_GAME_OVER:
			
				DrawGameOver();
			
			break;
			
			case GameCore::STATE_GAME_WON:
			
				DrawGameWon();
			
			break;					
		}
	}
}

//=====================================================================================================================
/// @brief		Draws the player's score:
/// @pre		The game must exist
/// @pre		The game must have a game object manager
/// @pre		The game must have a font
/// @pre		The hud must have no invalid resources
//=====================================================================================================================

void GameHud::DrawScore()
{
	// Make sure ok:

	ENSURE( GameCore::GetSingleton() != 0					, "The game must exist"							)
	ENSURE( GameCore::GetSingleton()->GetFont()				, "The game must have a font"					)
	ENSURE( GameCore::GetSingleton()->GetObjectManager()	, "The game must have a game object manager"	)
	ENSURE( m_valid_resources == true						, "The hud must have no invalid resources"		)
	
	// Get the game:
	
	GameCore * game = GameCore::GetSingleton();
	
	// Get the player's score and round to an integer:
	
	int score = (int)( Float::Round( game->GetPlayerScore() , 0 ) );
	
	// Get half the view area:
	
	Vec2f vah = m_camera->GetViewArea() * 0.5f;
	
	// Convert the score to a string:
	
	std::string score_str = std::string("Current score: ") + String::ToString(score);
	
	// Draw the player's score in the top left of the screen:
		
	m_font.Draw( score_str , Vec3f( -vah.x + 20 , vah.y - 20 , -500 ) , m_camera->GetViewProjectionMatrix() );
}

//=====================================================================================================================
/// @brief		Draws the health bar
/// @pre		The game should exist
/// @pre		The game should have a game object manager
/// @pre		The player's health must never be negative
/// @pre		The hud must have no invalid resources
//=====================================================================================================================

void GameHud::DrawHealthBar()
{
	// Make sure ok:

	ENSURE( GameCore::GetSingleton() != 0					, "The game must exist"							)
	ENSURE( GameCore::GetSingleton()->GetObjectManager()	, "The game must have a game object manager"	)
	ENSURE( m_valid_resources == true						, "The hud must have no invalid resources"		)

	// Get the game:
	
	GameCore * game = GameCore::GetSingleton();
	
	// Get the view area:

	Vec2f va = m_camera->GetViewArea();
	
	// Get the view projection matrix from the camera:
	
	Matrix4f view_proj = m_camera->GetViewProjectionMatrix();	

	// Draw the health label:
	
	m_font.Draw( "Health" , Vec3f( -(va.x * 0.5f ) + 20 , -(va.y * 0.5f) + 80 , -500 ) , view_proj );
	
	// Update our reference to the player
	
	if ( m_player )
	{
		// See if dead and removed from the game
		
		if ( m_player->HasManager() == false )
		{
			// Remove our reference to the player: dead
			
			m_player->RemoveReference(); m_player = 0;
		}
	}
	else
	{
		// Try to find the player:
		
		m_player = game->GetObjectManager()->FindByType<PlayerShip>("PlayerShip");
		
		// If found add ref to it
		
		if ( m_player ) m_player->AddReference();
	}
	
	// Only if there is a player:
	
	if ( m_player )
	{
		// Make sure not negative health
		
		ENSURE( m_player->GetHealth() >= 0 , "The player's health must never be negative" )
		
		// Figure out how many health units to draw:
		
		int units = (int)(( m_player->GetHealth() / m_player->GetMaxHealth() ) * HEALTH_BAR_UNITS);
		
		// If zero then show at least one unit:
		
		if ( units <= 0 ) units = 1;
		
		// Current position to draw units at:
		
		Vec3f draw_pos = Vec3f( -va * 0.5f , -500 );
		
		// Account for draw string size
		
		draw_pos.x += m_font.GetSize("Health").x;
		
		// Now position:
		
		draw_pos.x += 60;
		draw_pos.y += 70;
		
		// Get the stack from the game:
		
		Stack & stack = game->GetStack();
		
		// Save the stack position:
		
		void * stack_pos = stack.GetPointer();
		
		// Draw each health bar:
		
		for ( int i = units ; i > 0 ; --i )
		{
			// Position to draw at:
		
			Vec3f p = draw_pos;
		
			// Point 1
		
			stack.Push(p);
			stack.Push((unsigned)(0xffffffff));
			stack.Push(Vec2f::Zero());
			
			// Point 2
			
			p.x += HEALTH_UNIT_SIZE.x;
		
			stack.Push(p);
			stack.Push((unsigned)(0xffffffff));
			stack.Push(Vec2f::UnitX());
			
			// Point 3
			
			p.y -= HEALTH_UNIT_SIZE.y;
		
			stack.Push(p);
			stack.Push((unsigned)(0xffffffff));
			stack.Push(Vec2f::One());
			
			// Point 4
		
			stack.Push(p);
			stack.Push((unsigned)(0xffffffff));
			stack.Push(Vec2f::One());
			
			// Point 5
			
			p.x -= HEALTH_UNIT_SIZE.x;
		
			stack.Push(p);
			stack.Push((unsigned)(0xffffffff));
			stack.Push(Vec2f::UnitY());
			
			// Point 6
			
			p.y += HEALTH_UNIT_SIZE.y;
		
			stack.Push(p);
			stack.Push((unsigned)(0xffffffff));
			stack.Push(Vec2f::Zero());
			
			// Move along draw pos:
			
			draw_pos.x += HEALTH_UNIT_SIZE.x + HEALTH_UNIT_SPACING;							
		}
		
		// Do setup for drawing:
				
		m_vs.Apply();
		m_ps.Apply();
		m_vf.Apply();
				
		m_health_unit_tex.Apply(0);
		
		m_u_transform.SetMatrix( view_proj );
		
		// Draw the health bars:
		
		game->GetWindow()->GetDisplay()->GetDevice()->DrawPrimitiveUP
		( 
			D3DPT_TRIANGLELIST						, 
			2 * units								,
			stack_pos								,
			( sizeof(float) * 5 ) + sizeof(unsigned)
		);
		
		// Restore the previous stack pointer
		
		stack.SetPointer(stack_pos);
	}
}

//=====================================================================================================================
/// @brief		Draws the map display
/// @pre		Game must exist
/// @pre		Game must have a buffered point renderer
/// @pre		Game must have a primitives renderer
/// @pre		Game must have a game object manager
/// @pre		The hud must have no invalid resources
/// @post		The game's stack pointer should be in the same place as when the function started
//=====================================================================================================================

void GameHud::DrawMap()
{
	// Make sure ok

	ENSURE( GameCore::GetSingleton()								, "Game must exist"								);
	ENSURE( GameCore::GetSingleton()->GetBufferedPointRenderer()	, "Game must have a buffered point renderer"	);
	ENSURE( GameCore::GetSingleton()->GetObjectManager()			, "Game must have a game object manager"		);
	ENSURE( GameCore::GetSingleton()->GetPrimitivesRenderer()		, "Game must have a primitives renderer"		);
	ENSURE( m_valid_resources == true								, "The hud must have no invalid resources"		);

	// Get the game:

	GameCore * game = GameCore::GetSingleton();

	// Get the buffered point renderer:

	BufferedPointRenderer * r = game->GetBufferedPointRenderer();

	// Get the stack from the game:

	Stack & stack = game->GetStack();

	// Debug only: 

	#ifdef DEBUG

		void * stack_ptr_original = stack.GetPointer();

	#endif

	// Store the number of points we are drawing here:

	unsigned num_points = 0;
	
	//=================================================================================================================
	// See if we have a predator manager:
	//=================================================================================================================
	
	#pragma region(DRAW_WASPS)

	if ( m_predator_mgr == 0 )
	{
		// Try to find in the game:

		GameObjectManager * mgr = game->GetObjectManager();

		// Do the search:

		m_predator_mgr = mgr->FindByType<EnemyPredatorManager>("EnemyPredatorManager");	

		// If found then add a reference to this object

		if ( m_predator_mgr ) m_predator_mgr->AddReference();
	}
	else
	{
		// Make sure it has not been removed from the game

		if ( m_predator_mgr->HasManager() )
		{	
			// Get all of the objects in use by the wasp manager

			Pool<AIControlled> * pool = m_predator_mgr->GetAIObjectPool();

			// Increment the number of points we will draw

			num_points += pool->GetUsedCount();
			
			// Get the color of all factories:
			
			unsigned col = EnemyPredator::SHAPE_COLOR.ToDxUnsigned();

			// Get enumerators to move through the pool

			Pool<AIControlled>::Enumerator i = pool->UsedObjects();
			Pool<AIControlled>::Enumerator e = pool->ListEnd();

			// Run through the pool:

			while ( i != e )
			{
				// Get this object and move on:

				AIControlled * ai = *i; ++i;

				// Push it's position and the color white onto the stack to be drawn as a point

				stack.Push( Vec3f( ai->GetPosition() , -250 ) 	);
				stack.Push( col									);
			}	
		}
		else
		{
			// This thing has been removed from the game: remove our reference to it

			m_predator_mgr->RemoveReference(); m_predator_mgr = 0;
		}
	}	
	
	#pragma endregion

	//=================================================================================================================
	// See if we have a wasp manager:
	//=================================================================================================================
	
	#pragma region(DRAW_WASPS)

	if ( m_wasp_mgr == 0 )
	{
		// Try to find in the game:

		GameObjectManager * mgr = game->GetObjectManager();

		// Do the search:

		m_wasp_mgr = mgr->FindByType<EnemyWaspManager>("EnemyWaspManager");	

		// If found then add a reference to this object

		if ( m_wasp_mgr ) m_wasp_mgr->AddReference();
	}
	else
	{
		// Make sure it has not been removed from the game

		if ( m_wasp_mgr->HasManager() )
		{	
			// Get all of the objects in use by the wasp manager

			Pool<AIControlled> * pool = m_wasp_mgr->GetAIObjectPool();

			// Increment the number of points we will draw

			num_points += pool->GetUsedCount();
			
			// Get the color of all factories:
			
			unsigned col = EnemyWasp::SHAPE_COLOR.ToDxUnsigned();

			// Get enumerators to move through the pool

			Pool<AIControlled>::Enumerator i = pool->UsedObjects();
			Pool<AIControlled>::Enumerator e = pool->ListEnd();

			// Run through the pool:

			while ( i != e )
			{
				// Get this object and move on:

				AIControlled * ai = *i; ++i;

				// Push it's position and the color white onto the stack to be drawn as a point

				stack.Push( Vec3f( ai->GetPosition() , -250 ) 	);
				stack.Push( col									);
			}	
		}
		else
		{
			// This thing has been removed from the game: remove our reference to it

			m_wasp_mgr->RemoveReference(); m_wasp_mgr = 0;
		}
	}
	
	#pragma endregion

	//=================================================================================================================
	// See if we have a factory manager:
	//=================================================================================================================
	
	#pragma region(DRAW_FACTORIES)

	if ( m_factory_mgr == 0 )
	{
		// Try to find in the game:

		GameObjectManager * mgr = game->GetObjectManager();

		// Do the search:

		m_factory_mgr = mgr->FindByType<EnemyFactoryManager>("EnemyFactoryManager");		

		// If found then add a reference to this object

		if ( m_factory_mgr ) m_factory_mgr->AddReference();
	}
	else
	{
		// Make sure it has not been removed from the game

		if ( m_factory_mgr->HasManager() )
		{	
			// Get all of the objects in use by the factory manager

			Pool<AIControlled> * pool = m_factory_mgr->GetAIObjectPool();

			// Increment the number of points we will draw

			num_points += pool->GetUsedCount();			
			
			// Get the color of all factories:
			
			unsigned col = EnemyFactory::SHAPE_COLOR.ToDxUnsigned();

			// Get enumerators to move through the pool

			Pool<AIControlled>::Enumerator i = pool->UsedObjects();
			Pool<AIControlled>::Enumerator e = pool->ListEnd();

			// Run through the pool:

			while ( i != e )
			{
				// Get this object and move on:

				AIControlled * ai = *i; ++i;

				// Push it's position and the color white onto the stack to be drawn as a point

				stack.Push( Vec3f( ai->GetPosition() , -250 ) 	);
				stack.Push( col									);
			}	
		}	
		else
		{
			// This thing has been removed from the game: remove our reference to it

			m_factory_mgr->RemoveReference(); m_factory_mgr = 0;
		}		
	}
	
	#pragma endregion
	
	// Get the viewing area of the camera:

	Vec2f view_area = m_camera->GetViewArea();	

	// Make sure the texture for the background is valid:

	if ( m_frame_tex.IsValid() )
	{
		// Get the primitives renderer
		
		PrimitivesRenderer * p = game->GetPrimitivesRenderer();
		
		// Draw the map background:
		
		p->DrawSprite
		(
			m_camera	,
			Vec2f		
			( 
				( view_area.x * 0.5f ) - ( MAP_FRAME_SIZE.x ),
				( view_area.y * 0.5f ) - ( MAP_FRAME_SIZE.y )
			),
			MAP_FRAME_SIZE,
			0xffffffff,
			m_frame_tex
		);	
	}

	// If we have points to draw then draw them:

	if ( num_points > 0 )
	{
		// Good: get the viewing and projection matrix from the camera

		Matrix4f view_proj = m_camera->GetViewProjectionMatrix();

		// Now make our own scaling matrix to size the map display to what we want:

		Matrix4f scale = Matrix4f::Scale
		( 
			( MAP_SIZE.x / GameCore::MAP_AREA.x ) ,
			( MAP_SIZE.x / GameCore::MAP_AREA.y )  
		);

		// Position the map to be up in the corner of the screeen:

		Matrix4f translate = Matrix4f::Translation
		( 
			( view_area.x * 0.5f ) - ( MAP_FRAME_SIZE.x ),
			( view_area.y * 0.5f ) - ( MAP_FRAME_SIZE.y ),
			0.0f
		);

		// Now draw the points with all these combined transforms:

		r->Draw( scale * translate * view_proj , num_points , stack );
	}
	
	// Draw the player's position: if the player is in the game
	
	if ( PlayerShip * ship = game->GetObjectManager()->FindByType<PlayerShip>("PlayerShip") )
	{
		// Get the primitives renderer
		
		PrimitivesRenderer * p = game->GetPrimitivesRenderer();
		
		// Position to draw a quad representing the player at
		
		Vec2f pos = Vec2f		
		( 
			( view_area.x * 0.5f ) - ( MAP_FRAME_SIZE.x ),
			( view_area.y * 0.5f ) - ( MAP_FRAME_SIZE.y )
		);
		
		// Get the ship position
		
		Vec2f ship_pos = ship->GetPosition();
		
		// Adjust for map position:
		
		pos += Vec2f
		(
			( ( ship_pos.x ) / GameCore::MAP_AREA.x ) * ( MAP_SIZE.x ),
			( ( ship_pos.y ) / GameCore::MAP_AREA.y ) * ( MAP_SIZE.y )
		);
		
		// Draw the player's position:
		
		p->DrawQuadOutline
		(
			m_camera			,
			pos + Vec2f(-4,+4)	,
			pos + Vec2f(+4,+4)	,
			pos + Vec2f(+4,-4)	,
			pos + Vec2f(-4,-4)	,
			0xff00ff00
		);
	}
	
	// Debug only: 

	#ifdef DEBUG

		ENSURE( stack_ptr_original == stack.GetPointer() , "The game's stack pointer should be in the same place as when the function started" );

	#endif
}

//=====================================================================================================================
/// @brief		Draws the instructions
/// @pre		The resources for the hud should be valid
//=====================================================================================================================

void GameHud::DrawInstructions()
{
	// Make sure ok

	ENSURE( m_valid_resources , "The resources for the hud should be valid" )
	
	// The instructions string
	
	const char * INSTRUCTIONS = 
	
	"Super important instructions:"
	"\n \n"
	"1 - Kill or be killed! Get the highest score.\n"
	"2 - Try to kill all enemies before they come back.\n"
	"3 - Use thumbsticks on XBOX-360 gamepad to move & shoot.\n"
	"4 - Use WASD and arrows on keyboard to move & shoot.\n"
	"5 - Press 'Back' or 'ESC' to exit.\n"
	"\n \n"
	"\n \n"
	"Press 'A' or 'Enter' to continue.";
	
	// Draw the instrutions:
	
	m_reading_shadow_font.DrawCentered(INSTRUCTIONS,Vec3f(4,196,-500),m_camera->GetViewProjectionMatrix());
	m_reading_font.DrawCentered(INSTRUCTIONS,Vec3f(0,200,-500),m_camera->GetViewProjectionMatrix());
}

//=====================================================================================================================
/// @brief		Draws the game over message
/// @pre		The resources for the hud should be valid
//=====================================================================================================================

void GameHud::DrawGameOver()
{
	// Make sure ok

	ENSURE( m_valid_resources , "The resources for the hud should be valid" )	
	
	// The game over string
	
	const char * GAME_OVER = 
	
	"Game over !!"
	"\n \n"
	"\n \n"
	"Press 'A' or 'Enter' to continue";
	
	// Draw the instrutions:
	
	m_reading_shadow_font.DrawCentered(GAME_OVER,Vec3f(4,-104,-500),m_camera->GetViewProjectionMatrix());
	m_reading_font.DrawCentered(GAME_OVER,Vec3f(0,-100,-500),m_camera->GetViewProjectionMatrix());	
}

//=====================================================================================================================
/// @brief		Draws the game won message
/// @pre		The resources for the hud should be valid
//=====================================================================================================================

void GameHud::DrawGameWon()
{
	// Make sure ok

	ENSURE( m_valid_resources , "The resources for the hud should be valid" )	
	
	// The game won string
	
	const char * GAME_WON = 
	
	"You win. That was one hell of a fight !!"
	"\n \n"
	"\n \n"
	"Press 'A' or 'Enter' to continue";
	
	// Draw the instrutions:
	
	m_reading_shadow_font.DrawCentered(GAME_WON,Vec3f(4,-104,-500),m_camera->GetViewProjectionMatrix());
	m_reading_font.DrawCentered(GAME_WON,Vec3f(0,-100,-500),m_camera->GetViewProjectionMatrix());
}

//=====================================================================================================================
/// @brief		Draws the game paused message
/// @pre		The resources for the hud should be valid
//=====================================================================================================================

void GameHud::DrawGamePaused()
{
	// Make sure ok

	ENSURE( m_valid_resources , "The resources for the hud should be valid" )	
	
	// The game over string
	
	const char * GAME_OVER = 
	
	"Game paused."
	"\n \n"
	"\n \n"
	"\n \n"
	"\n \n"
	"Press 'Start', 'P' or 'Pause' to continue";
	
	// Draw the instrutions:
	
	m_small_font.DrawCentered(GAME_OVER,Vec3f(0,-100,-500),m_camera->GetViewProjectionMatrix());	
}
