⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lvtetrisengine.cpp

📁 俄罗斯方块
💻 CPP
字号:
#include <e32base.h>
#include <eikenv.h>
#include <e32Math.h>

#include "LvtetrisEngine.h"
#include <lvtetris.mbg>
#include <lvtetris.rsg>

// construct and destruct

// NewL()
CLvtetrisEngine* CLvtetrisEngine::NewL()
{
	CLvtetrisEngine* self = new (ELeave) CLvtetrisEngine;
	CleanupStack::PushL(self);

	self->ConstructL();

	CleanupStack::Pop(self);

	return self;
}


// CLvtetrisEngine()
CLvtetrisEngine::CLvtetrisEngine() : iGrid()
{}


// ~
CLvtetrisEngine::~CLvtetrisEngine()
{
iBmpBlock.DeleteAll();
iBmpBlock.Reset();

delete iBmpBackground;
iBmpBackground = NULL;

iGamePauseInforTxt.DeleteAll();
iGamePauseInforTxt.Reset();

iGameOverInforTxt.DeleteAll();
iGameOverInforTxt.Reset();
}

void CLvtetrisEngine::ConstructL()
{
	LoadResL();
	// Make the seed
	TTime time;
	time.HomeTime();
	iSeed = time.Int64();
}

////////////////////////////////////////////////////////////////////////////////

// Method

// handel all key relatively
TGameStatus CLvtetrisEngine::Command(TInt aCommand)
{
	switch(aCommand)
	{
		case EKeyRightArrow :			// right
		case '6' :
		{
			MoveTo(iBlockPos + TPoint(1, 0));	
		}
		break;

		case EKeyLeftArrow :			// left
		case '4' :
		{
			MoveTo(iBlockPos + TPoint(-1, 0));
		}
		break;

		case EKeyUpArrow :				// up
		case '2' :
		case '5' :
		case 63557 :
		{
			Rotate();
		}
		break;

		case EKeyDownArrow :			// down
		case '8' :
		{
			while(MoveTo(iBlockPos + TPoint(0, 1)));
		}
		break;
			
		case EKeyDevice1:
			return GAMEMENUING;

		default:
		break;
	}
	return GAMERUNNING;
}

// move down the block automatic
TInt8 CLvtetrisEngine::Run()
{
	TInt8 flag = 0;				// default not update view
	
	if(!iStateRunning)			// game is not running
	{
		iStateRunning = 1;
		StartNewGame();
	}
	else
	{
		if(!iDelay)
		{
			if(!MoveTo(iBlockPos + TPoint(0, 1)))	// if can't move down the block
			{
				if(!FixBlock())		// check if the block is out of bound
				{
					iStateRunning = 0;
					return 1;		// Game over
				}
				TInt eliminate = CheckRows();
				
				if(eliminate)
				{
					Calculate(eliminate);
				}

				NewBlock();		// create a new one
			}
			flag = 2;			// update view
		}
	
		iDelay = iDelay ? --iDelay : 5-iLevel;
	}

	return flag;
}


////////////////////////////////////////////////////////////////////////////////

// Other Methods

// MoveTo()			Move the Block to a new position if possible
TBool CLvtetrisEngine::MoveTo(const TPoint& aNewPos)
{
	if(iGrid.DoesCollide(iBlock, aNewPos))
		return 0;

	iBlockPos = aNewPos;		// don't update View here to make Model Independent

	return 1;					// Move successful
}

// Rotate()
void CLvtetrisEngine::Rotate()
{
	if(iStateRotateDir == 0)
		iStateRotateDir = -1;
	iBlock.Rotate(iStateRotateDir);		// default state , deasil

	if(iGrid.DoesCollide(iBlock, iBlockPos))
		iBlock.Rotate( (TInt8)-iStateRotateDir );	// rotate back	
}


// NewBlock()
void CLvtetrisEngine::NewBlock()
{
	iBlock		= iBlockNext;
	iBlockNext	= TBlock::RandomBlock(iSeed, iStateDifficulty);

	iBlockPos     = TPoint(4, -3);
}

// StartNewGame()
void CLvtetrisEngine::StartNewGame()
{
	// Game State
	iLevel				= 1;
	iLine				= 0;
	iStateScore			= 0;
	//iStateRotateDir	= 0;
	//iStateDifficulty	= 0;

	// create new Grid
	iGrid			= TGrid::NewGrid();
	// Start Lines
	if(iStateStartLines)
		StartLines(iStateStartLines);
		//StartLines(18);
	// create a block
	iBlockNext	= TBlock::RandomBlock(iSeed, iStateDifficulty);

	NewBlock();

	iDelay = 0;
}

// GetRowContent()			
void CLvtetrisEngine::GetRowContent(TUint8 aRow, TFixedArray<TUint8, KGridX>& aRowContent)
{
	int i;

	for(i = 0; i < KGridX; i++)
	{
		if(IsBlock(TPoint(i, aRow))) 
			aRowContent[i] = iBlock.Type();
		else 
			aRowContent[i] = iGrid.iContent[aRow][i];
	}
}

// if the position is a block
TBool CLvtetrisEngine::IsBlock(const TPoint& aPos) const
{
	if(TRect(iBlockPos, TSize(4, 4)).Contains(aPos))
		return (iBlock.RowMask(aPos.iY-iBlockPos.iY) & (1<<(3-aPos.iX+iBlockPos.iX))) > 0;

	return false;
}

// FixBlock()	-- fix the block  -- be called if the current block can't move 
// @ return 0	-- game over
// @ return 1	-- continue game and put the block into the content
TBool CLvtetrisEngine::FixBlock()
{
	TInt i;
	// check if it is outside the board
	for (i = 0; i < -iBlockPos.iY; i++)
		if (iBlock.RowMask(i))
			return 0;

	iGrid.PutBlock(iBlock, iBlockPos);
		return 1;
}

// 
TInt CLvtetrisEngine::CheckRows()
{
	TInt offset=0, i, j;

	for (i = KGridY-1; i >= 0; i--)
	{
		if (iGrid.iMask[i]==0xffffU)
		{
			offset++;
			iLine++;
			continue;
		}

		if (offset > 0)
		{
			iGrid.iMask[i+offset]=iGrid.iMask[i];
			for (j = 0; j < KGridX; j++)
				iGrid.iContent[i+offset][j]=iGrid.iContent[i][j];
		}
	}

	for (i = 0; i < offset; i++)
	{
		iGrid.iMask[i] = 0x003f;
		for (j=0; j < KGridX; j++)
			iGrid.iContent[i][j] = 0;
	}

	return offset;		// row's num to eliminate
}

void CLvtetrisEngine::Calculate(TInt rows)
{
	switch(rows)
	{
		case 1:
		{
			iStateScore += 10;
		}break;

		case 2:
		{
			iStateScore += 25;
		}break;

		case 3:
		{
			iStateScore += 50;
		}break;

		case 4:
		{
			iStateScore += 80;
		}break;

		default:break;
	}
	iStateScore += iStateDifficulty * 15;
	iStateScore += iStateStartLines;
	iStateScore += iLevel * 2;

	if(iStateScore >= 500 * iLevel)
	{
		iLevel++;
	}
	if(iLevel > 10)
	{
		iLevel = 0;
		iStateDifficulty++;
		iStateDifficulty %= 3;
	}
	
}

void CLvtetrisEngine::StartLines(TUint8 aLines)
{
	if(aLines >= 19)
		return ;
	
	TInt i, j;
	for(i = KGridY - 1; i >= KGridY - aLines; --i)
	{
		for(j = 0; j < KGridX; ++j)
		{
			TInt content = Math::Rand(iSeed) % 2;
			if(content)
			{
				iGrid.iContent[i][j] = (TInt8)(Math::Rand(iSeed) % BLOCKNUM + 1);
			
				iGrid.iMask[i] |= (1 << (15 - j));
			}
		}
	}

}

void CLvtetrisEngine::LoadResL()
{
// Load bmps from mmp file
_LIT(KPathName, "\\System\\Apps\\LvTetris\\Lvtetris.mbm");

CEikonEnv* eikonEnv = CEikonEnv::Static();

// Load Blocks
iBmpBlock.At(0) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris1);
iBmpBlock.At(1) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris2);
iBmpBlock.At(2) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris3);
iBmpBlock.At(3) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris4);
iBmpBlock.At(4) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris5);
iBmpBlock.At(5) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris6);
iBmpBlock.At(6) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris7);
iBmpBlock.At(7) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris8);
iBmpBlock.At(8) = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetris9);
// Load background
//iBmpBackground = eikonEnv->CreateBitmapL(KPathName, EMbmLvtetrisBackground24);

iGamePauseInforTxt[0]	 = eikonEnv->AllocReadResourceL(R_GAME_PAUSE_LINE1);
iGamePauseInforTxt[1]	 = eikonEnv->AllocReadResourceL(R_GAME_PAUSE_LINE2);
iGameOverInforTxt[0] = eikonEnv->AllocReadResourceL(R_GAME_OVER_LINE1);
iGameOverInforTxt[1] = eikonEnv->AllocReadResourceL(R_GAME_OVER_LINE2);

iGamePauseInforPos[0]	 = TPoint(10,90);
iGamePauseInforPos[1]	 = TPoint(10,110);
iGameOverInforPos[0] = TPoint(10,90);
iGameOverInforPos[1] = TPoint(10,110);
}

void CLvtetrisEngine::DrawTetris(CFbsBitGc* aBackBufferGc)
{
	TInt xPos, yPos;
	TUint8 i, j;
	// draw background
//	aBackBufferGc->BitBlt(TPoint(0, 0), iBmpBackground);

	// draw blocks
	yPos = 0;
	TFixedArray<TUint8, KGridX> arr;
	for(i = 0; i < KGridY; i++)
	{
		xPos = 9;
		GetRowContent(i, arr);
		for(j = 0; j < KGridX; j++)
		{
			TUint8 blockType = arr[j];
			if(blockType)
			{
				TPoint pos = TPoint(xPos, yPos);
		 		aBackBufferGc->BitBlt(pos, iBmpBlock.At(blockType%COLORNUM));
			}
			xPos += 9;
		}
		yPos += 10;
	}

	// draw Info
	const CFont* font;
	font = CEikonEnv::Static()->NormalFont();
	aBackBufferGc->UseFont(font);
	aBackBufferGc->SetPenColor(TRgb(215, 136, 20));
	aBackBufferGc->SetBrushStyle(CGraphicsContext::ENullBrush);

	TBuf<6> info;
	// score
	info.Num(iStateScore);
	aBackBufferGc->DrawText(info, TRect(TPoint(122, 90), TSize(45, 15)), 15, CGraphicsContext::ECenter, 0);
	// line
	info.Num(iLine);
	aBackBufferGc->DrawText(info, TRect(TPoint(122, 118), TSize(45, 15)), 15, CGraphicsContext::ECenter, 0);
	// Level
	info.Num(iLevel);
	aBackBufferGc->DrawText(info, TRect(TPoint(122, 145), TSize(45, 15)), 15, CGraphicsContext::ECenter, 0);

	aBackBufferGc->DiscardFont();

	// draw Next Block
	aBackBufferGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
	aBackBufferGc->SetBrushColor(KRgbBlack);
	yPos = 29;
	for(i = 0; i < 4; i++)
	{
		xPos = 130;
		for(j = 0; j < 4; j++)
		{
			if((iBlockNext.RowMask(i) & (1<<(3-j))))
				aBackBufferGc->DrawRect(TRect(TPoint(xPos, yPos), TSize(6, 6)));
			xPos += 7;
		}
		yPos += 7;
	}

}

void CLvtetrisEngine::DrawGamePauseInfor(CFbsBitGc* aBackBufferGc)
{
	_LIT(KPauseFontName,"Roman");
	CFont* pauseFont;
	TFontSpec pauseFontSpec(KPauseFontName, 10);
	
	pauseFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
	
	CBitmapDevice* pausescreenDevice=CEikonEnv::Static()->ScreenDevice();
	pausescreenDevice->GetNearestFontInPixels(pauseFont,pauseFontSpec);
	aBackBufferGc->UseFont(pauseFont);
	
	aBackBufferGc->SetPenColor(KRgbRed);
	aBackBufferGc->DrawText(*iGamePauseInforTxt.At(0), iGamePauseInforPos[0]);
	aBackBufferGc->DrawText(*iGamePauseInforTxt.At(1), iGamePauseInforPos[1]);	
	// delete created Font
	aBackBufferGc->DiscardFont();
	pausescreenDevice->ReleaseFont(pauseFont);
}

void CLvtetrisEngine::DrawGameOverInfor(CFbsBitGc* aBackBufferGc)
{
	_LIT(KOverFontName,"Roman");
	CFont* overFont;
	TFontSpec overFontSpec(KOverFontName, 10);
	
	overFontSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold);
	
	CBitmapDevice* overscreenDevice=CEikonEnv::Static()->ScreenDevice();
	overscreenDevice->GetNearestFontInPixels(overFont,overFontSpec);
	aBackBufferGc->UseFont(overFont);
	
	aBackBufferGc->SetPenColor(KRgbRed);
	aBackBufferGc->DrawText(*iGameOverInforTxt.At(0), iGameOverInforPos[0]);
	aBackBufferGc->DrawText(*iGameOverInforTxt.At(1), iGameOverInforPos[1]);
	// delete created Font
	aBackBufferGc->DiscardFont();
	overscreenDevice->ReleaseFont(overFont);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -