#include "Game.h"

CGame::CGame(IEngineCore *pEngineCore, bool postprocess, bool highdetail):
_pEngineCore(pEngineCore), _uiCounter(0), _bDoGame(false), _bDoGameOver(false), _uiScore(0), _fShaker(0.f),
	_bPaused(false)
{
	_pEngineCore->AddProcedure(EPT_PROCESS, &_s_Process, this);
	_pEngineCore->AddProcedure(EPT_RENDER, &_s_Render, this);

	_pEngineCore->GetSubSystem(ESS_RENDER, (IEngineSubSystem *&)_pRender);
	_pRender->GetRender2D(_pRender2D);
	_pRender->GetRender3D(_pRender3D);

	_pRender3D->SetPerspective(90.f, 0.1, 1000.f);

	pEngineCore->GetSubSystem(ESS_INPUT, (IEngineSubSystem *&)_pInput);

	IExtensionPlugin *ext_plugin;
	pEngineCore->GetPlugin("DGLE2_EXT",(IPlugin *&)ext_plugin);
	ext_plugin->GetGuiEngine(_pGUIEngine);

	_pMainFont = (IBitmapFont*)mapResources["MainFont"];
	_pBaseFont = (IBitmapFont*)mapResources["BaseFont"];
	_pGUIForms = (IGUIForms*)mapResources["Forms"];
	_pTexBall = (ITexture*)mapResources["Ball"];
	_pTexBlood = (ITexture*)mapResources["Blood"];
	_pTexSpark = (ITexture*)mapResources["Spark"];
	_pTexBg = (ITexture*)mapResources["Sky"];
	_pTexCur = (ITexture*)mapResources["Cursor"];
	_pMeshPlane = (IMesh*)mapResources["MeshPlane"];
	_pMeshBlock = (IMesh*)mapResources["MeshBlockSimple"];
	_pMeshSoplo = (IMesh*)mapResources["MeshBlockSoplo"];
	_pMan = (IModel*)mapResources["Man"];
	_pTexMan = (ITexture*)mapResources["ManTex"];

	TEngWindow win;
	_pEngineCore->GetCurrentWin(win);
	_uiResX = win.uiWidth;
	_uiResY = win.uiHeight;

	_pGUIForms->GetFormFromName("FormPause", _pQuitForm);
	TPoint2 d;
	_pQuitForm->GetDimension(d);
	_pQuitForm->SetPosition(TPoint2((_uiResX - d.x)/2, (_uiResY - d.y)/2));

	static int bb = false;

	if(!bb)
	{
		bb = true;
		IDCButton *p_btn;
		_pQuitForm->GetComponent("ButtonYes", (IDCComponent*&)p_btn);
		p_btn->AddEventListner(GCE_ON_CLICK, &_s_YesClick);

		_pQuitForm->GetComponent("ButtonNo", (IDCComponent*&)p_btn);
		p_btn->AddEventListner(GCE_ON_CLICK, &_s_NoClick);
	}

	IResourceManager *p_res_man;
	pEngineCore->GetSubSystem(ESS_RESOURCE_MANAGER, (IEngineSubSystem *&)p_res_man);

	if(!postprocess)
	{
		_pRT = NULL;
		_pPostprocess = NULL;
	}
	else
	{
		p_res_man->CreateTexture(_pRT, NULL, _uiResX, _uiResY, TCF_COLOR_RGB, (E_TEXTURE_LOAD_FLAGS)TEXTURE_LOAD_DEFAULT_2D);
		_pRender->CreatePostProcess(_pPostprocess);
		_pPostprocess->SetTargets(_pRT, NULL);
		_pPostprocess->SetBloomAmount(1.f);
		_pPostprocess->SetBloomThreshold(0.5);
	}

if(highdetail)
{
	_pRender3D->CreateLight(_pLight1);
	_pLight1->SetType(LT_DIRECTIONAL);
	_pLight1->SetDir(TPoint3(0.f, 0.f, -1.f));

	_pRender3D->CreateLight(_pLight2);
	_pLight2->SetType(LT_DIRECTIONAL);
	_pLight2->SetDir(TPoint3(0.f, -1.f, 0.f));


	p_res_man->CreateMaterial(_pMatAsphalt);
	_pMatAsphalt->SetAmbientColor(TColor4(0.f, 0.f, 0.f, 0.9));
	_pMatAsphalt->SetSpecularColor(TColor4(255,255,255,255));
	_pMatAsphalt->SetShininess(20.f);
	_pMatAsphalt->SetDiffuseTexture((ITexture*)mapResources["TexAsphaltDiff"]);
	_pMatAsphalt->SetSpecularTexture((ITexture*)mapResources["TexAsphaltSpec"]);
	_pMatAsphalt->SetNormalTexture((ITexture*)mapResources["TexAsphaltNormal"]);
	_pMatAsphalt->SetNormalTechnique(NT_NORMAL_MAP_3_COMPONENT);

	p_res_man->CreateMaterial(_pBlockMaterial);
	_pBlockMaterial->SetAmbientColor(TColor4(0.25, 0.25, 0.25, 0.9));
	_pBlockMaterial->SetSpecularColor(TColor4(255,255,255,255));
	_pBlockMaterial->SetShininess(8.f);
	_pBlockMaterial->SetDiffuseTexture((ITexture*)mapResources["TexBlockDiff"]);
	_pBlockMaterial->SetSpecularTexture((ITexture*)mapResources["TexBlockSpec"]);
	_pBlockMaterial->SetNormalTexture((ITexture*)mapResources["TexBlockNormal"]);
	_pBlockMaterial->SetNormalTechnique(NT_NORMAL_MAP_3_COMPONENT);

	for(int i = 0; i < 5; i++)
	{
		_pMeshHouse[i] = (IMesh*)mapResources["MeshHouse" + IntToStr(i+1)];
		p_res_man->CreateMaterial(_pMaterialHouse[i]);
		_pMaterialHouse[i]->SetDiffuseTexture((ITexture*)mapResources["TexHouse"+IntToStr(i+1)+"Diff"]);
		_pMaterialHouse[i]->SetAmbientColor(TColor4(0.2, 0.2, 0.2, 0.7));
		_pMaterialHouse[i]->SetDiffuseColor(TColor4(255,255,255,255));
		_pMaterialHouse[i]->SetSpecularColor(TColor4(255,255,255,255));
		_pMaterialHouse[i]->SetShininess(4.f);
		_pMaterialHouse[i]->SetSpecularTexture((ITexture*)mapResources["TexHouse"+IntToStr(i+1)+"Spec"]);
		_pMaterialHouse[i]->SetNormalTexture((ITexture*)mapResources["TexHouse"+IntToStr(i+1)+"Normal"]);
		_pMaterialHouse[i]->SetNormalTechnique(NT_NORMAL_MAP_3_COMPONENT);
		_pMaterialHouse[i]->SetEnvMask((ITexture*)mapResources["TexHouse"+IntToStr(i+1)+"Spec"]);
		_pMaterialHouse[i]->SetEnvTexture(_pTexBg);
		_pMaterialHouse[i]->SetEnvAmount(0.75);
	}
}
else
{
	_pLight1 = NULL;
	_pLight2 = NULL;
	_pMatAsphalt = NULL;
	_pBlockMaterial = NULL;
	for(int i = 0; i < 5; i++)
	_pMaterialHouse[i] = NULL;

	_pTexAsphalt = (ITexture*)mapResources["TexAsphaltDiff"];
	
	for(int i = 0; i < 5; i++)
	{
		_pMeshHouse[i] = (IMesh*)mapResources["MeshHouse" + IntToStr(i+1)];
		_pTexHouse[i] = (ITexture*)mapResources["TexHouse"+IntToStr(i+1)+"Diff"];
	}

	_pTexBlock = (ITexture*)mapResources["TexBlockDiff"];
}
	_uiLevel = 1;

	_NewGame();
}

CGame::~CGame()
{
	if(_pRT)
		_pRT->Free();
	
	if(_pPostprocess)
		_pPostprocess->Free();
	
	if(_pBlockMaterial)
		_pBlockMaterial->Free();

	for(int i = 0; i < 5; i++)
		if(_pMaterialHouse[i])
		_pMaterialHouse[i]->Free();

	if(_pLight1)
	_pLight1->Free();
	
	if(_pLight2)
	_pLight2->Free();
	
	if(_pMatAsphalt)
		_pMatAsphalt->Free();
	
	_pEngineCore->RemoveProcedure(EPT_PROCESS, &_s_Process, this);
	_pEngineCore->RemoveProcedure(EPT_RENDER, &_s_Render, this);

	if(_bPaused)
	_pGUIEngine->RemoveForm(_pQuitForm);
}

void  CGame::_YesClick()
{
	StartScene(GS_MENU);
}

void  CGame::_NoClick()
{
	_bPaused = false;
	_pGUIEngine->RemoveForm(_pQuitForm);
}

extern CGame *pGame;

void CALLBACK _s_YesClick(void *pSelf, void *pParametr)
{
	pGame->_YesClick();
}

void CALLBACK _s_NoClick(void *pSelf, void *pParametr)
{
	pGame->_NoClick();
}

void CGame::_Process()
{
	bool b_prsd;
	static uint ui_press_pause = 0;

	if(_bDoGameOver || _bPaused || _uiLinesLeft == 0)
	{
		static bool napr = false;
		float delta = _fYAngle - (napr ? 55.f : -55.f);
		if(fabs(delta) > 0.5)
			_fYAngle -= delta/fabs(delta)*0.25;
		
		if(fabs(_fYAngle)>54.f) napr = !napr;
	}

	if(_bPaused)
	{
		_uiCounter++;
		return;
	}

	_pInput->GetKey(KEY_ESCAPE, b_prsd);

	if(b_prsd && _uiCounter > 450)
	{
		_bPaused = true;
		_pGUIEngine->AddForm(_pQuitForm);
		return;
	}

	if(_uiLinesLeft == 0 && (_uiCounter - _uiVictoryCounter) > 250)
	{
		_uiLevel++;
		_NewGame();
	}

	if(_bDoGame && !_bDoGameOver)//process game
	{

		if(_uiCounter == 450) _NewBrick();

		if(_fShaker > 0.f)
			_fShaker -= 1.f;

		//fly bricks
		int k = 0;
		while(k != _stFlyBricks.size())
		{
			_stFlyBricks[k].z += 1.5;
			_stFlyBricks[k].x *= 1.1;

			if(_stFlyBricks[k].z > 100.f)
				_stFlyBricks.erase(_stFlyBricks.begin() + k);
			else k++;
		}

		//Process humans
		k = 0; int cnt = 1;
		while(k != _stHuman.size())
		{
			_stHuman[k]._fFrame += 0.4f;
			if((int)_stHuman[k]._fFrame >= 10.f)
				_stHuman[k]._fFrame = 0.f;

			float old_x = _stHuman[k].pos.x;

			if(_stHuman[k].angle == 0)
				_stHuman[k].pos.x += 0.035;
			else
				if(_stHuman[k].angle == -180)
					_stHuman[k].pos.x -= 0.035;

			if(_stHuman[k].pos.x < -12.75 || _stHuman[k].pos.x > 11.25 || _HumanCollide(_stHuman[k]))
			{
				_stHuman[k].pos.x = old_x;

				if(_stHuman[k].angle == 0)
					_stHuman[k].angle = -180;
				else
					_stHuman[k].angle = 0;

				if(_HumanCollide(_stHuman[k]))
				{
					_uiShowScore += 500*cnt;
							
					if(_uiShowScore > 6000)
						((ISoundSample*)mapResources["Excelnt"])->Play();
					else
					{
						if(cnt >= 3)
						((ISoundSample*)mapResources["Multikill"])->Play();
						((ISoundSample*)mapResources["Death"])->Play();
					}

					for(int l = 0; l < 5; l++)
					_stParticles.push_back(TEffect(ET_BLOOD, TPoint3(_stHuman[k].pos.x - 1.f + (float)(rand()%100)/100.f, _stHuman[k].pos.y + 2.f - (float)(rand()%200)/100.f, -4.4f)));

					_uiScore += 500*cnt;
					_uiShowPause = 0;
					cnt++;
					_stHuman.erase(_stHuman.begin() + k);

					continue;
				}
			}

			float old_y = _stHuman[k].pos.y;

			_stHuman[k].pos.y -= 0.2;
			if(_HumanCollide(_stHuman[k]) || _stHuman[k].pos.y < 0.f)
				_stHuman[k].pos.y = old_y;

			k++;
		}

		if(rand()%10 == 5 && _stHuman.size() < 3 + _uiLevel*2)
		{
			TMan t;
			int block = rand()%20;
			t.pos.y = block*BLOCK_SIZE;
			
			int i;
			if(rand()%2 == 0)
			{
				i = 0;
				t.pos.x = -12.5;
				t.angle = 0;
			}
			else
			{
				i = 9;
				t.pos.x = 11.f;
				t.angle = -180;
			}

			if((block == 0 && !_arrPole[i][0]) || (!_arrPole[i][block] && _arrPole[i][block - 1]))
				_stHuman.push_back(t);
		}

		//process effects
		k = 0;
		while(k != _stParticles.size())
		{
			if(_stParticles[k].particles.size() == 0)
				_stParticles.erase(_stParticles.begin() + k);
			else
			{
				int i = 0;
				while( i != _stParticles[k].particles.size())
				{
					if(_stParticles[k].type == ET_FIRE)
					{
						_stParticles[k].particles[i].pos.x += cos(_stParticles[k].particles[i].angle/180.f*3.14)*_stParticles[k].particles[i].speed*2.f;
						_stParticles[k].particles[i].pos.y += sin(_stParticles[k].particles[i].angle/180.f*3.14)*_stParticles[k].particles[i].speed*2.f - 0.025;
					}
					else
					{
						_stParticles[k].particles[i].pos.x += cos(_stParticles[k].particles[i].angle/180.f*3.14)*_stParticles[k].particles[i].speed/2.f;
						_stParticles[k].particles[i].pos.y += sin(_stParticles[k].particles[i].angle/180.f*3.14)*_stParticles[k].particles[i].speed/2.f - 0.01;
						if(_stParticles[k].particles[i].color.a > 0.1)
							_stParticles[k].particles[i].color.a -= 0.01;
					}
					_stParticles[k].particles[i].scale -= _stParticles[k].particles[i].speed/2.f;
					if(_stParticles[k].particles[i].scale < 0.001)
						_stParticles[k].particles.erase(_stParticles[k].particles.begin() + i);
					else
						i++;
				}
				k++;
			}
		}

		if(_uiCounter >= 450)
		{
			//Camera
			if(_uiLinesLeft != 0)
			{
				//XAngle
				float desired = 35.f -_stBrick.drawPos.y*1.5, delta = _fXAngle - desired;
			
				if(fabs(delta) > 0.5)
					_fXAngle -= delta/fabs(delta)*0.1;

				if(_fXAngle > 35.f) _fXAngle = 35.f;
				if(_fXAngle < -35.f) _fXAngle = -35.f;

				//YAngle
				desired = _stBrick.drawPos.x*2.f;
				delta = _fYAngle - desired;
				if(fabs(delta) > 0.5)
					_fYAngle -= delta/fabs(delta)*0.25;

				//Zoom
				desired = -_stBrick.drawPos.y*0.51724;
				delta = _fZoom - desired;

				if(fabs(delta) > 0.1)
					_fZoom -= delta/fabs(delta)*0.01;
 		
				if(_fZoom < -29.98) _fZoom = -29.98;
				if(_fZoom > -10.f) _fZoom = -10.f;
			}

			//Move bricks down if line
			if(!(_uiLines[0] == -1 && _uiLines[1] == -1 && _uiLines[2] == -1 && _uiLines[3] == -1))
			{
				if(_uiLineWait > 15)
				{
					for(int k = 3; k >= 0; k--)
						if(_uiLines[k] != -1)
						{
							if(_uiLines[k] < 19)
								for(int j = _uiLines[k] + 1; j < 20; j++)
									for(int i = 0; i < 10; i++)
										if(_arrPole[i][j])
										{
											_arrPole[i][j] = false;
											_arrPole[i][j - 1] = true;
										}

							_uiShowScore += 1000*(k+1);
							
							if(_uiShowScore > 6000)
								((ISoundSample*)mapResources["Excelnt"])->Play();
							else
								((ISoundSample*)mapResources["LineDone"])->Play();

							_uiScore += 1000*(k+1);
							_uiShowPause = 0;
							_uiLines[k] = -1;
							_uiLineWait = 0;

							if(_uiLinesLeft == 0)
							{
								//Level Done

								for(int j = 0; j < 20; j++)
								for(int i = 0; i < 10; i++)
								if(_arrPole[i][j])
								{
									_arrPole[i][j] = false;
									_stFlyBricks.push_back(TPoint3(-12.5 + i*BLOCK_SIZE, j*BLOCK_SIZE, 0.f));
									_stParticles.push_back(TEffect(ET_SMOKE, TPoint3(-12.5 + i*BLOCK_SIZE, j*BLOCK_SIZE + BLOCK_SIZE/2.f, -4.f)));
								}
							}


							return;
						}
				}
				else
					_uiLineWait++;

				return;
			}

			//Brick controls
			if(_uiLinesLeft != 0)
			{
			if(_stBrick.drawPos.y <= 50.f + BLOCK_SIZE*1.25)
			{
				_pInput->GetKey(KEY_DOWN, b_prsd);

				if(b_prsd && !_BrickCollision(TPoint2(_stBrick.pos.x, _stBrick.drawPos.y - BLOCK_SIZE)))
				{
					_stBrick.pos.y -= BLOCK_SIZE;
					_stBrick.uiWait = 0;
					_stBrick.drawPos.y = _stBrick.pos.y;
				}

				if(ui_press_pause > _uiGameSpeed/2)
				{
					_pInput->GetKey(KEY_UP, b_prsd);
					if(b_prsd) 
					{
						ui_press_pause = 0;
						((ISoundSample*)mapResources["Rotate"])->Play();
						_RotateBrick();
					}

					_pInput->GetKey(KEY_LEFT, b_prsd);
					if(b_prsd && !_BrickCollision(TPoint2(_stBrick.pos.x - BLOCK_SIZE, _stBrick.pos.y), 0.85) && !_BrickCollision(TPoint2(_stBrick.pos.x - BLOCK_SIZE, _stBrick.drawPos.y), 0.85))
					{
						ui_press_pause = 0;
						_stBrick.pos.x -= BLOCK_SIZE;
					}

					_pInput->GetKey(KEY_RIGHT, b_prsd);
					if(b_prsd && !_BrickCollision(TPoint2(_stBrick.pos.x + BLOCK_SIZE, _stBrick.pos.y), 0.85) && !_BrickCollision(TPoint2(_stBrick.pos.x + BLOCK_SIZE, _stBrick.drawPos.y), 0.85))
					{
						ui_press_pause = 0;
						_stBrick.pos.x += BLOCK_SIZE;
					}
				}

				if(_stBrick.uiWait == _uiGameSpeed)
				{
					if(_BrickCollision(TPoint2(_stBrick.pos.x, _stBrick.pos.y - BLOCK_SIZE)))
					{
						_bDoGameOver = !_AssignBrick();
						
						if(_bDoGameOver)
							return;

						uint counter = 0;

						//Check line
						for(int j = 0; j < 20; j++)
						{
							bool flag = true;
							for(int i = 0; i < 10; i++)
								if(!_arrPole[i][j]) flag = false;

							if(flag)
							{
								for(int i = 0; i < 10; i++)
								{
									_arrPole[i][j] = false;
									_stFlyBricks.push_back(TPoint3(-12.5 + i*BLOCK_SIZE, j*BLOCK_SIZE, 0.f));
									_stParticles.push_back(TEffect(ET_SMOKE, TPoint3(-12.5 + i*BLOCK_SIZE, j*BLOCK_SIZE + BLOCK_SIZE/2.f, -4.f)));
								}

								_uiLines[counter] = j;
								counter++;
							}
						}

						_uiLinesLeft -= counter;
						if(_uiLinesLeft < 0) _uiLinesLeft = 0;
						_uiVictoryCounter = _uiCounter;

						if(counter != 0)
							((ISoundSample*)mapResources["LineDone"])->Play();

						_NewBrick();
					}
					else
						_stBrick.pos.y -= BLOCK_SIZE;

					_stBrick.uiWait = 0;
				}
				else
				{
					if(fabs(_stBrick.drawPos.x - _stBrick.pos.x)>= BLOCK_SIZE/10.f)
						_stBrick.drawPos.x += -(_stBrick.drawPos.x - _stBrick.pos.x)/fabs(_stBrick.drawPos.x - _stBrick.pos.x)*BLOCK_SIZE/((float)_uiGameSpeed/2.f);

					if(!_BrickCollision(TPoint2(_stBrick.pos.x, _stBrick.pos.y - BLOCK_SIZE)))
					{
						float f = _stBrick.pos.y - BLOCK_SIZE/(float)_uiGameSpeed * (float)_stBrick.uiWait;
						//if(f > _stBrick.pos.y - BLOCK_SIZE)
						_stBrick.drawPos.y = f;
					}
					_stBrick.uiWait++;
				}

			}
			else
				_stBrick.drawPos.y -= 5.f;
			}
		if(_uiCounter % 2 == 0 && !_BrickCollision(TPoint2(_stBrick.pos.x, _stBrick.pos.y - BLOCK_SIZE)))
		for(int i = 0; i < 4; i++)
			for(int j = 0; j < 4; j++)
				if(_stBrick.form[i][j])
				{
					if(j == 3 || !_stBrick.form[i][j+1])
						_stParticles.push_back(TEffect(ET_FIRE, TPoint3(_stBrick.drawPos.x -BLOCK_SIZE*2 + i*BLOCK_SIZE, _stBrick.drawPos.y + BLOCK_SIZE*2 - j*BLOCK_SIZE - 1.5f, -4.f)));
				}		
		}
		else
		{
				for(ubyte i = 0; i < 255; i++)
				{
					_pInput->GetKey((E_KEYBOARD_KEY_CODES)i, b_prsd);
					if(b_prsd)
					{
						_uiCounter = 450;
						return;
					}
				}
		}
	}

	ui_press_pause++;
	_uiCounter++;
}

void CGame::_RotateBrick()
{
	TBrick old_brick = _stBrick;
	
	int empty_left = 0, empty_right = 0;

	for(int i = 0; i < 4; i++)
	if(!_stBrick.form[3-i][0] && !_stBrick.form[3-i][1] && !_stBrick.form[3-i][2] && !_stBrick.form[3-i][3])
	{
		empty_right++;
	}
	else
		break;

	for(int i = 0; i < 4; i++)
	if(!_stBrick.form[i][0] && !_stBrick.form[i][1] && !_stBrick.form[i][2] && !_stBrick.form[i][3])
	{
		empty_left++;
	}
	else
		break;

	_stBrick.form[0][0] = old_brick.form[0][3]; _stBrick.form[1][0] = old_brick.form[0][2]; _stBrick.form[2][0] = old_brick.form[0][1]; _stBrick.form[3][0] = old_brick.form[0][0];
	_stBrick.form[0][1] = old_brick.form[1][3]; _stBrick.form[1][1] = old_brick.form[1][2]; _stBrick.form[2][1] = old_brick.form[1][1]; _stBrick.form[3][1] = old_brick.form[1][0];
	_stBrick.form[0][2] = old_brick.form[2][3]; _stBrick.form[1][2] = old_brick.form[2][2]; _stBrick.form[2][2] = old_brick.form[2][1]; _stBrick.form[3][2] = old_brick.form[2][0];
	_stBrick.form[0][3] = old_brick.form[3][3]; _stBrick.form[1][3] = old_brick.form[3][2]; _stBrick.form[2][3] = old_brick.form[3][1]; _stBrick.form[3][3] = old_brick.form[3][0];

	bool failed = false;

	if(_BrickCollision(TPoint2(_stBrick.pos.x, _stBrick.pos.y)))
	{
		failed = true;

		//Try left
		for(int i = 0; i < empty_right; i++)
		{
			_stBrick.pos.x -= BLOCK_SIZE;
			if(!_BrickCollision(TPoint2(_stBrick.pos.x, _stBrick.pos.y)))
			{
				failed = false;
				break;
			}
		}

		if(failed) 
		{
			_stBrick.pos = old_brick.pos;

			//Try right
			for(int i = 0; i < empty_left; i++)
			{
				_stBrick.pos.x += BLOCK_SIZE;
				if(!_BrickCollision(TPoint2(_stBrick.pos.x, _stBrick.pos.y)))
				{
					failed = false;
					break;
				}
			}
		}

		if(failed) _stBrick.pos = old_brick.pos;
	}

	if(failed)
		_stBrick = old_brick;
	else
	{
		for(int i = 0; i < 4; i++)
		for(int j = 0; j < 4; j++)
			if(old_brick.form[i][j])
				_stParticles.push_back(TEffect(ET_SMOKE, TPoint3(_stBrick.drawPos.x -BLOCK_SIZE*2 + i*BLOCK_SIZE, _stBrick.drawPos.y + BLOCK_SIZE*2 - j*BLOCK_SIZE + 2.5f, -4.f)));
	}
}

bool CGame::_AssignBrick()
{
	for(int k = 0; k < 4; k++)
	for(int l = 0; l < 4; l++)
		if(_stBrick.form[k][l])
		{
			TRectF r(_stBrick.pos.x -BLOCK_SIZE*2 + k*BLOCK_SIZE + BLOCK_SIZE/4.f, _stBrick.pos.y + BLOCK_SIZE*2 - l*BLOCK_SIZE - BLOCK_SIZE/4.f, BLOCK_SIZE/2.f, BLOCK_SIZE/2.f);

			if(r.y > 20.f*BLOCK_SIZE - BLOCK_SIZE/2.f)
				return false;

			for(int i = 0; i < 10; i++)
				for(int j = 0; j < 20; j++)
					if(TRectF(-12.5 + i*BLOCK_SIZE, j*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE).IntersectRect(r))
					{
						_arrPole[i][j] = true;

						if(j == 0 || _arrPole[i][j - 1])
							_stParticles.push_back(TEffect(ET_SMOKE, TPoint3(-12.5 + i*BLOCK_SIZE, j*BLOCK_SIZE, -4.f)));
					}

			((ISoundSample*)mapResources["Down"])->Play();
			_fShaker = 10.f;
		}	

	return true;
}

bool CGame::_HumanCollide(TMan man)
{
	for(int k = 0; k < 4; k++)
	for(int l = 0; l < 4; l++)
		if(_stBrick.form[k][l])
		{
			TRectF r(man.pos.x - 0.5, man.pos.y + 1.f, 1.f, 1.8f);
	
			for(int i = 0; i < 10; i++)
				for(int j = 0; j < 20; j++)
					if(_arrPole[i][j] && TRectF(-12.5 + i*BLOCK_SIZE - 1.f, BLOCK_SIZE*1.3f + j*BLOCK_SIZE - BLOCK_SIZE, BLOCK_SIZE - 0.2, BLOCK_SIZE).IntersectRect(r))
						return true;
		}

	return false;
}

bool CGame::_BrickCollision(TPoint2 pos, float scale)
{	
	for(int k = 0; k < 4; k++)
	for(int l = 0; l < 4; l++)
		if(_stBrick.form[k][l] && (pos.y + BLOCK_SIZE*2 - l*BLOCK_SIZE < 0.f || 
			pos.x -BLOCK_SIZE*2.f + k*BLOCK_SIZE <= -12.5 - BLOCK_SIZE/2.f  || pos.x -BLOCK_SIZE*2.f + k*BLOCK_SIZE >= 12.5))
			return true;
			
	for(int k = 0; k < 4; k++)
	for(int l = 0; l < 4; l++)
		if(_stBrick.form[k][l])
		{
			TRectF r(pos.x -BLOCK_SIZE*2.f + k*BLOCK_SIZE + BLOCK_SIZE*(1.f-scale), pos.y + BLOCK_SIZE*2.f - l*BLOCK_SIZE - BLOCK_SIZE*(1.f-scale), BLOCK_SIZE - BLOCK_SIZE*(1.f-scale)*2.f, BLOCK_SIZE - BLOCK_SIZE*(1.f-scale)*2.f);
	
			for(int i = 0; i < 10; i++)
				for(int j = 0; j < 20; j++)
					if(_arrPole[i][j] && TRectF(-12.5 + i*BLOCK_SIZE, j*BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE).IntersectRect(r))
						return true;
		}

	return false;
}

void CGame::_NewBrick()
{
	_stBrick.pos = TPoint3(0.f, 50.f + BLOCK_SIZE*1.25, 0.f);
	_stBrick.drawPos = _stBrick.pos;
	_stBrick.drawPos.y += 150;

	_stBrick.uiWait = _uiGameSpeed;

	int d = 7;

	if(_uiLevel > 1)
		d = 8;
	if(_uiLevel > 2)
		d = 9;
	if(_uiLevel > 3)
		d = 10;
	if(_uiLevel > 4)
		d = 11;

	switch(rand()%d)
	{
	case 0:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 1; _stBrick.form[1][1] = 1; _stBrick.form[2][1] = 1; _stBrick.form[3][1] = 1;
		_stBrick.form[0][2] = 0; _stBrick.form[1][2] = 0; _stBrick.form[2][2] = 0; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 1:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 1; _stBrick.form[1][1] = 0; _stBrick.form[2][1] = 0; _stBrick.form[3][1] = 0;
		_stBrick.form[0][2] = 1; _stBrick.form[1][2] = 1; _stBrick.form[2][2] = 1; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 2:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 0; _stBrick.form[1][1] = 0; _stBrick.form[2][1] = 0; _stBrick.form[3][1] = 1;
		_stBrick.form[0][2] = 0; _stBrick.form[1][2] = 1; _stBrick.form[2][2] = 1; _stBrick.form[3][2] = 1;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 3:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 0; _stBrick.form[1][1] = 1; _stBrick.form[2][1] = 1; _stBrick.form[3][1] = 0;
		_stBrick.form[0][2] = 0; _stBrick.form[1][2] = 1; _stBrick.form[2][2] = 1; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 4:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 0; _stBrick.form[1][1] = 1; _stBrick.form[2][1] = 1; _stBrick.form[3][1] = 0;
		_stBrick.form[0][2] = 1; _stBrick.form[1][2] = 1; _stBrick.form[2][2] = 0; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 5:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 1; _stBrick.form[1][1] = 1; _stBrick.form[2][1] = 0; _stBrick.form[3][1] = 0;
		_stBrick.form[0][2] = 0; _stBrick.form[1][2] = 1; _stBrick.form[2][2] = 1; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 6:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 0; _stBrick.form[1][1] = 1; _stBrick.form[2][1] = 0; _stBrick.form[3][1] = 0;
		_stBrick.form[0][2] = 1; _stBrick.form[1][2] = 1; _stBrick.form[2][2] = 1; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 7:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 0; _stBrick.form[1][1] = 0; _stBrick.form[2][1] = 0; _stBrick.form[3][1] = 0;
		_stBrick.form[0][2] = 0; _stBrick.form[1][2] = 0; _stBrick.form[2][2] = 0; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 1; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 8:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 0; _stBrick.form[1][1] = 1; _stBrick.form[2][1] = 0; _stBrick.form[3][1] = 0;
		_stBrick.form[0][2] = 1; _stBrick.form[1][2] = 1; _stBrick.form[2][2] = 1; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 1; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 9:
		_stBrick.form[0][0] = 0; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 0;
		_stBrick.form[0][1] = 0; _stBrick.form[1][1] = 1; _stBrick.form[2][1] = 0; _stBrick.form[3][1] = 0;
		_stBrick.form[0][2] = 0; _stBrick.form[1][2] = 1; _stBrick.form[2][2] = 0; _stBrick.form[3][2] = 0;
		_stBrick.form[0][3] = 0; _stBrick.form[1][3] = 0; _stBrick.form[2][3] = 0; _stBrick.form[3][3] = 0;
		break;
	case 10:
		_stBrick.form[0][0] = 1; _stBrick.form[1][0] = 0; _stBrick.form[2][0] = 0; _stBrick.form[3][0] = 1;
		_stBrick.form[0][1] = 1; _stBrick.form[1][1] = 0; _stBrick.form[2][1] = 0; _stBrick.form[3][1] = 1;
		_stBrick.form[0][2] = 1; _stBrick.form[1][2] = 0; _stBrick.form[2][2] = 0; _stBrick.form[3][2] = 1;
		_stBrick.form[0][3] = 1; _stBrick.form[1][3] = 1; _stBrick.form[2][3] = 1; _stBrick.form[3][3] = 1;
		break;
	}
}

void CGame::_NewGame()
{
	_stBrick.pos = TPoint3(0.f, 350.f, 0.f);
	_stBrick.drawPos = _stBrick.pos;
	_uiCounter = 0;
	_uiGameSpeed = 20 - _uiLevel*2;
	if(_uiGameSpeed < 1) _uiGameSpeed = 1;
	ZeroMemory(_arrPole, 200);
	_fYAngle = 0.f;
	_fXAngle = -35.f;
	_fZoom = -30.f;
	_bDoGame = true;
	_bDoGameOver = false;
	_uiLines[0] = _uiLines[1] = _uiLines[2] = _uiLines[3] = -1;
	_uiLineWait = 0;
	_uiShowScore = 0;
	_uiShowPause = 400;
	_fShaker = 0.f;
	_stFlyBricks.clear();
	_stHuman.clear();
	_stParticles.clear();
	_uiLinesLeft = _uiLevel*5;
}

void CGame::_Render()
{
	if(_pPostprocess)
		_pRender->SetRenderTarget(_pRT);

	_pRender2D->Begin2D();
	_pTexBg->Draw2D(0, 0, _uiResX, _uiResY);
	_pRender2D->End2D();

	matrix_stack.Set(MatrixIdentity());

	if(_uiCounter/7.5 > 60)
	{
		matrix_stack.Mult2(MatrixTranslate(TPoint3(sin(_fShaker*2.f)*2.5, -25.f, _fZoom)));	
		matrix_stack.Mult2(MatrixRotate(_fXAngle, TPoint3(1.f, 0.f, 0.f)));
		matrix_stack.Mult2(MatrixRotate(_fYAngle, TPoint3(0.f, 1.f, 0.f)));
	}
	else
	{
		matrix_stack.Mult2(MatrixTranslate(TPoint3(0.f, -25.f, _uiCounter/2.5 > 115.f-29.98 ? -29.98 : -115.f + _uiCounter/2.5)));
		matrix_stack.Mult2(MatrixRotate(_uiCounter/2.f > 125.f ? -35.f : 90.f - _uiCounter/2.f, TPoint3(1.f, 0.f, 0.f)));
		matrix_stack.Mult2(MatrixRotate(60.f - _uiCounter/7.5, TPoint3(0.f, 1.f, 0.f)));
	}


	//Asphalt
	matrix_stack.Push();
	matrix_stack.Mult2(MatrixTranslate(TPoint3(0.f, 0.f, -25.f)));
	matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
	matrix_stack.Mult2(MatrixScale(TPoint3(500.f, 500.f, 500.f)));
	_pRender3D->SetMatrix(matrix_stack.Top(), false);
	if(_pMatAsphalt)
		_pMatAsphalt->Bind();
	else
		_pTexAsphalt->Bind();
	_pMeshPlane->Draw();
	matrix_stack.Pop();

	//Left Skyscraper
	if(_pMaterialHouse[2])
		_pMaterialHouse[2]->Bind();
	else
		_pTexHouse[2]->Bind();

	matrix_stack.Push();
	matrix_stack.Mult2(MatrixTranslate(TPoint3(-29.f, 30.f, -5.f)));
	matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
	matrix_stack.Mult2(MatrixScale(TPoint3(60.f, 60.f, 60.f)));
	_pRender3D->SetMatrix(matrix_stack.Top(), false);
	_pMeshHouse[2]->Draw(!_pMaterialHouse[2]);
	matrix_stack.Pop();
	
	//Right Skyscraper
	matrix_stack.Push();
	matrix_stack.Mult2(MatrixTranslate(TPoint3(27.f, 30.f, -5.f)));
	matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
	matrix_stack.Mult2(MatrixScale(TPoint3(60.f, 60.f, 60.f)));
	_pRender3D->SetMatrix(matrix_stack.Top(), false);
	_pMeshHouse[2]->Draw(!_pMaterialHouse[2]);
	matrix_stack.Pop();

	//Walls
	for(int i = 0; i < 25; i++)
	{
		matrix_stack.Push();
		matrix_stack.Mult2(MatrixTranslate(TPoint3(-350 + i*25.f, 30.f, -325+i*5.f)));
		matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
		matrix_stack.Mult2(MatrixScale(TPoint3(60.f, 60.f, 60.f)));
		_pRender3D->SetMatrix(matrix_stack.Top(), false);
		_pMeshHouse[2]->Draw(!_pMaterialHouse[2]);
		matrix_stack.Pop();
	}
	for(int i = 0; i < 20; i++)
	{
		matrix_stack.Push();
		matrix_stack.Mult2(MatrixTranslate(TPoint3(-250, 30.f, -325+i*25.f)));
		matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
		matrix_stack.Mult2(MatrixScale(TPoint3(60.f, 60.f, 60.f)));
		_pRender3D->SetMatrix(matrix_stack.Top(), false);
		_pMeshHouse[2]->Draw(!_pMaterialHouse[2]);
		matrix_stack.Pop();
	}
	for(int i = 0; i < 20; i++)
	{
		matrix_stack.Push();
		matrix_stack.Mult2(MatrixTranslate(TPoint3(250, 30.f, -325+i*25.f)));
		matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
		matrix_stack.Mult2(MatrixScale(TPoint3(60.f, 60.f, 60.f)));
		_pRender3D->SetMatrix(matrix_stack.Top(), false);
		_pMeshHouse[2]->Draw(!_pMaterialHouse[2]);
		matrix_stack.Pop();
	}

	//Clock tower
	if(_pMaterialHouse[0])
		_pMaterialHouse[0]->Bind();
	else
		_pTexHouse[0]->Bind();

	matrix_stack.Push();
	matrix_stack.Mult2(MatrixTranslate(TPoint3(-30.f, 32.f, -70.f)));
	matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
	matrix_stack.Mult2(MatrixRotate(45.f, TPoint3(0.f, 0.f, 1.f)));
	matrix_stack.Mult2(MatrixScale(TPoint3(120.f, 120.f, 120.f)));
	_pRender3D->SetMatrix(matrix_stack.Top(), false);
	_pMeshHouse[0]->Draw(!_pMaterialHouse[2]);
	matrix_stack.Pop();

	//Clock tower2
	matrix_stack.Push();
	matrix_stack.Mult2(MatrixTranslate(TPoint3(90.f, 32.f, 60.f)));
	matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
	matrix_stack.Mult2(MatrixRotate(-45.f, TPoint3(0.f, 0.f, 1.f)));
	matrix_stack.Mult2(MatrixScale(TPoint3(120.f, 120.f, 120.f)));
	_pRender3D->SetMatrix(matrix_stack.Top(), false);
	_pMeshHouse[0]->Draw(!_pMaterialHouse[2]);
	matrix_stack.Pop();

	//Clock tower3
	matrix_stack.Push();
	matrix_stack.Mult2(MatrixTranslate(TPoint3(-90.f, 32.f, 40.f)));
	matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
	matrix_stack.Mult2(MatrixScale(TPoint3(120.f, 120.f, 120.f)));
	_pRender3D->SetMatrix(matrix_stack.Top(), false);
	_pMeshHouse[0]->Draw(!_pMaterialHouse[2]);
	matrix_stack.Pop();

	//Clock tower4
	matrix_stack.Push();
	matrix_stack.Mult2(MatrixTranslate(TPoint3(120.f, 32.f, -65.f)));
	matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
	matrix_stack.Mult2(MatrixScale(TPoint3(120.f, 120.f, 120.f)));
	_pRender3D->SetMatrix(matrix_stack.Top(), false);
	_pMeshHouse[0]->Draw(!_pMaterialHouse[2]);
	matrix_stack.Pop();

	//Administration
	matrix_stack.Push();
	matrix_stack.Mult2(MatrixTranslate(TPoint3(20.f, 12.5f, -40.f)));
	matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
	matrix_stack.Mult2(MatrixRotate(-120.f, TPoint3(0.f, 0.f, 1.f)));
	matrix_stack.Mult2(MatrixScale(TPoint3(40.f, 40.f, 40.f)));
	_pRender3D->SetMatrix(matrix_stack.Top(), false);
	if(_pMaterialHouse[1])
		_pMaterialHouse[1]->Bind();
	else
		_pTexHouse[1]->Bind();
	_pMeshHouse[1]->Draw(!_pMaterialHouse[2]);
	matrix_stack.Pop();

	//Giant skyscraper
	float skyscrapers_1[12][3] = {{50.f,-60.f,0.f}, {20.f,-80.f,45.f},{-75.f,-120.f,60.f}, {-15.f,-130.f,45.f},
	{-120.f,-20.f,0.f}, {120.f,-15.f,0.f}, {-180.f,-100.f,0.f}, {180.f,-120.f,0.f},
	{0.f,-250.f,0.f}, {150.f,-180.f,0.f}, {90.f,-300.f,0.f}, {250.f,50.f,0.f}}; 

	if(_pMaterialHouse[3])
		_pMaterialHouse[3]->Bind();
	else
		_pTexHouse[3]->Bind();

	for(int i = 0; i < 12; i++)
	{
		matrix_stack.Push();
		matrix_stack.Mult2(MatrixTranslate(TPoint3(skyscrapers_1[i][0], 40.f, skyscrapers_1[i][1])));
		matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
		matrix_stack.Mult2(MatrixRotate(skyscrapers_1[i][2], TPoint3(0.f, 0.f, 1.f)));
		matrix_stack.Mult2(MatrixScale(TPoint3(80.f, 80.f, 80.f)));
		_pRender3D->SetMatrix(matrix_stack.Top(), false);
		_pMeshHouse[3]->Draw(!_pMaterialHouse[2]);
		matrix_stack.Pop();
	}

	//Skyscraper
	float skyscrapers_2[8][3] = {{30.f,-65.f,0.f}, {0.f,-85.f,-90.f},{-60.f,-10.f,65.f}, {55.f,5.f,0.f},
	{120.f,20.f,90.f}, {-40.f,-120.f,30.f}, {-110.f,-100.f,-30.f}, {110.f,-30.f,0.f}}; 

	if(_pMaterialHouse[4])
		_pMaterialHouse[4]->Bind();
	else
		_pTexHouse[4]->Bind();

	for(int i = 0; i < 8; i++)
	{
		matrix_stack.Push();
		matrix_stack.Mult2(MatrixTranslate(TPoint3(skyscrapers_2[i][0], 20.f, skyscrapers_2[i][1])));
		matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
		matrix_stack.Mult2(MatrixRotate(skyscrapers_2[i][2], TPoint3(0.f, 0.f, 1.f)));
		matrix_stack.Mult2(MatrixScale(TPoint3(40.f, 40.f, 40.f)));
		_pRender3D->SetMatrix(matrix_stack.Top(), false);
		_pMeshHouse[4]->Draw(!_pMaterialHouse[2]);
		matrix_stack.Pop();
	}

	//Pole
	//X: -12.5 - 12.5
	//Y: 50 - 0
	//2.5 - block size
	matrix_stack.Push();

	if(_pBlockMaterial)
		_pBlockMaterial->Bind();
	else
		_pTexBlock->Bind();

	matrix_stack.Mult2(MatrixTranslate(TPoint3(0.f, 1.25, -5.f)));

		for(int i = 0; i < 10; i++)
			for(int j = 0; j < 20; j++)
			if(_arrPole[i][j])
			{
				matrix_stack.Push();
				matrix_stack.Mult2(MatrixTranslate(TPoint3(-12.5 + i*BLOCK_SIZE, j*BLOCK_SIZE, 0.f)));
				matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));		
				matrix_stack.Mult2(MatrixScale(TPoint3(0.25, 0.25, 0.25)));
				_pRender3D->SetMatrix(matrix_stack.Top(), false);
				_pMeshBlock->Draw(!_pMaterialHouse[2]);
				matrix_stack.Pop();
			}

		//Draw fly bricks
		for(int i = 0; i < _stFlyBricks.size(); i++)
		{
			matrix_stack.Push();
			matrix_stack.Mult2(MatrixTranslate(_stFlyBricks[i]));
			matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));		
			matrix_stack.Mult2(MatrixScale(TPoint3(0.25, 0.25, 0.25)));
			_pRender3D->SetMatrix(matrix_stack.Top(), false);
			_pMeshBlock->Draw(!_pMaterialHouse[2]);
			matrix_stack.Pop();
		}

	//Draw current brick
	matrix_stack.Mult2(MatrixTranslate(_stBrick.drawPos));

	for(int i = 0; i < 4; i++)
		for(int j = 0; j < 4; j++)
			if(_stBrick.form[i][j])
			{
				matrix_stack.Push();
				matrix_stack.Mult2(MatrixTranslate(TPoint3(-BLOCK_SIZE*2 + i*BLOCK_SIZE, BLOCK_SIZE*2 - j*BLOCK_SIZE, 0.f)));
				matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));		
				matrix_stack.Mult2(MatrixScale(TPoint3(0.25, 0.25, 0.25)));
				_pRender3D->SetMatrix(matrix_stack.Top(), false);
				if(j == 3 || !_stBrick.form[i][j+1])
					_pMeshSoplo->Draw(!_pMaterialHouse[2]);
				else
					_pMeshBlock->Draw(!_pMaterialHouse[2]);
				matrix_stack.Pop();
			}

	matrix_stack.Pop();
	//End of pole

	_pRender->Unbind(EOT_MATERIAL);

	//People

	_pTexMan->Bind();
	for(int i = 0; i < _stHuman.size(); i++)
	{
		matrix_stack.Push();
		matrix_stack.Mult2(MatrixTranslate(TPoint3(_stHuman[i].pos.x, _stHuman[i].pos.y + 1.2f, _stHuman[i].pos.z-4.5f)));
		matrix_stack.Mult2(MatrixRotate(90.f, TPoint3(-1.f, 0.f, 0.f)));
		matrix_stack.Mult2(MatrixRotate(_stHuman[i].angle, TPoint3(0.f, 0.f, 1.f)));
		matrix_stack.Mult2(MatrixScale(TPoint3(2.f, 2.f, 2.f)));
		_pRender3D->SetMatrix(matrix_stack.Top(), false);
		_pMan->Draw(_stHuman[i]._fFrame);
		matrix_stack.Pop();
	}
	//Draw particles
	
	_pRender3D->PushStates(PSF_STATES);//engine bug fix
	_pRender3D->SetBlendMode(EBF_ADD);
	_pRender3D->ToggleDepthTest(false);

	for(int i = 0; i < _stParticles.size(); i++)
		for(int j = 0; j < _stParticles[i].particles.size(); j++)
		{
				_pRender3D->SetColor(_stParticles[i].particles[j].color);
				matrix_stack.Push();
				matrix_stack.Mult2(MatrixTranslate(_stParticles[i].particles[j].pos));
				matrix_stack.Mult2(MatrixRotate(_stParticles[i].particles[j].angle, TPoint3(0.f, 0.f, 1.f)));		
				TMatrix t = MatrixBillboard(matrix_stack.Top());
				_pRender3D->SetMatrix(MatrixScale(TPoint3(_stParticles[i].particles[j].scale, _stParticles[i].particles[j].scale, _stParticles[i].particles[j].scale)) * t, false);
				switch(_stParticles[i].type)
				{
				case ET_FIRE:  _pTexSpark->Draw3D(); break;
				case ET_BLOOD: _pTexBlood->Draw3D(); break;
				case ET_SMOKE: _pTexBall->Draw3D(); break;
				}
				matrix_stack.Pop();
		}

	_pRender3D->ToggleDepthTest(true);
	_pRender3D->SetColor(TColor4());
	_pRender3D->SetBlendMode(EBF_NONE);
	_pRender3D->PopStates();

	_pRender->Unbind(EOT_TEXTURE);

	if(_pPostprocess)
	{
		_pPostprocess->Perform();
		_pRender->SetRenderTarget(NULL);
	}

	_pRender2D->Begin2D();
	
	if(_uiCounter*3 < 250)
	_pRender2D->DrawRect(TRectF(0,0,_uiResX,_uiResY),TColor4(255,255,255, 255-_uiCounter*3), PF_FILL);

	uint w,h;
	string txt;
	
	if(_uiCounter > 250 && _uiCounter < 425)
	{
		uint w,h;
		string txt = "Level " + IntToStr(_uiLevel);
		_pMainFont->GetTextDimensions(txt.c_str(), w,h);
		_pMainFont->Draw2D((_uiResX - w)/2, (_uiResY - h)/2, txt.c_str(), TColor4(0,0,0, 255-_uiCounter));

		txt = "Make   " + IntToStr(_uiLinesLeft) + "   lines for TetRoX!";
		_pBaseFont->GetTextDimensions(txt.c_str(), w,h);
		_pBaseFont->Draw2D((_uiResX - w)/2, (_uiResY - h)/2 + (_uiResY - h)/8, txt.c_str(), TColor4(255,0,0, 255-_uiCounter));
	}

	if(_bDoGameOver)
	{
		string txt = "Game Over";
		_pMainFont->GetTextDimensions(txt.c_str(), w,h);
		_pMainFont->Draw2D((_uiResX - w)/2, (_uiResY - h)/4, txt.c_str(), TColor4(0,0,0, 255));
	}
	else
		if(_uiCounter >= 450)
		{
			if(_uiLinesLeft == 0)
			{
				string txt = "TetRoX     loves     you!";
				_pMainFont->SetScale(1.f);
				_pMainFont->GetTextDimensions(txt.c_str(), w,h);
				_pMainFont->Draw2D((_uiResX - w)/2, (_uiResY - h)/4, txt.c_str(), TColor4(255,0,0, 255 - (_uiCounter - _uiVictoryCounter)));
			}

			_pBaseFont->Draw2D(10, 10, ("Score: " + IntToStr(_uiScore)).c_str(), TColor4(0,0,0, 255));
			_pBaseFont->Draw2D(10, 40, ("Lines left: " + IntToStr(_uiLinesLeft)).c_str(), TColor4(0,0,0, 255));
			
			if(_uiShowPause < 350)
			{
				uint w,h;
				string txt = IntToStr(_uiShowScore);
				_pMainFont->SetScale(1.f + (_uiShowPause*1.25)/350.f);
				_pMainFont->GetTextDimensions(txt.c_str(), w,h);
				_pMainFont->Draw2D((_uiResX - w)/2, (_uiResY - h)/2, txt.c_str(), _uiShowScore > 6000 ?TColor4( 200,0,0, 255-_uiShowPause/2) : TColor4( 255,255,255, 255-_uiShowPause/2));
				_pMainFont->SetScale(1.f);
				_uiShowPause++;
			}
			else
				_uiShowScore = 0;
		}

	_pGUIEngine->Draw();

	TMouseStates ms;
	_pInput->GetMouseStates(ms);
	if(_bPaused)
	_pRender2D->DrawSpriteA(_pTexCur, TPoint2(ms.iX, ms.iY), TPoint2(20, 20), _uiCounter/2 % 11);

	_pRender2D->End2D();
}

void CALLBACK CGame::_s_Process(void *pParametr)
{
	((CGame*)pParametr)->_Process();
}

void CALLBACK CGame::_s_Render(void *pParametr)
{
	((CGame*)pParametr)->_Render();
}
