CGameTetris.cpp
上传用户:snevogroup
上传日期:2008-06-06
资源大小:432k
文件大小:8k
源码类别:

Symbian

开发平台:

C/C++

  1. // 2005-8-31 修正了按键响应慢的错误
  2. #include <e32base.h>
  3. #include <eikenv.h>
  4. #include <e32Math.h>
  5. #include "CGameTetris.h"
  6. #include <images.mbg>
  7. // construct and destruct
  8. // NewL()
  9. CGameTetris* CGameTetris::NewL()
  10. {
  11. CGameTetris* self = new (ELeave) CGameTetris;
  12. CleanupStack::PushL(self);
  13. self->ConstructL();
  14. CleanupStack::Pop(self);
  15. return self;
  16. }
  17. // CGameTetris()
  18. CGameTetris::CGameTetris() : iGrid()
  19. {}
  20. // ~
  21. CGameTetris::~CGameTetris()
  22. {
  23. iBmpBlock.DeleteAll();
  24. delete iBmpBackground;
  25. }
  26. void CGameTetris::ConstructL()
  27. {
  28. // load game resource
  29. LoadResL();
  30. // Make the seed
  31. TTime time;
  32. time.HomeTime();
  33. iSeed = time.Int64();
  34. }
  35. ////////////////////////////////////////////////////////////////////////////////
  36. // Method
  37. // handel all key relatively
  38. TBool CGameTetris::Command(TInt aCommand)
  39. {
  40. switch(aCommand)
  41. {
  42. case EKeyRightArrow : // right
  43. case '6' :
  44. {
  45. MoveTo(iBlockPos + TPoint(1, 0));
  46. }return 1;
  47. case EKeyLeftArrow : // left
  48. case '4' :
  49. {
  50. MoveTo(iBlockPos + TPoint(-1, 0));
  51. }return 1;
  52. case EKeyUpArrow : // up
  53. case '2' :
  54. case '5' :
  55. case 63557 :
  56. {
  57. Rotate();
  58. }return 1;
  59. case EKeyDownArrow : // down
  60. case '8' :
  61. {
  62. while(MoveTo(iBlockPos + TPoint(0, 1)));
  63. }return 1;
  64. default:return 0;
  65. }
  66. }
  67. // move down the block automatic
  68. TInt8 CGameTetris::Run()
  69. {
  70. TInt8 flag = 0; // default not update view
  71. if(!iStateRunning) // game is not running
  72. {
  73. iStateRunning = 1;
  74. StartNewGame();
  75. }
  76. else
  77. {
  78. if(!iDelay)
  79. {
  80. if(!MoveTo(iBlockPos + TPoint(0, 1))) // if can't move down the block
  81. {
  82. if(!FixBlock()) // check if the block is out of bound
  83. {
  84. iStateRunning = 0;
  85. return 1; // Game over
  86. }
  87. TInt eliminate = CheckRows();
  88. if(eliminate)
  89. {
  90. Calculate(eliminate);
  91. if(eliminate == 4)
  92. iStateWellDone = 1; // well done
  93. iStateClearRow = 1; //  explode sound
  94. }
  95. NewBlock(); // create a new one
  96. }
  97. flag = 2; // update view
  98. }
  99. iDelay = iDelay ? --iDelay : 10-iLevel;
  100. }
  101. return flag;
  102. }
  103. // Draw()
  104. void CGameTetris::Draw(CFbsBitGc* aBackBufferGc)
  105. {
  106. TInt xPos, yPos;
  107. TUint8 i, j;
  108. // draw background
  109. aBackBufferGc->BitBlt(TPoint(0, 0), iBmpBackground);
  110. // draw blocks
  111. yPos = 0;
  112. TFixedArray<TUint8, KGridX> arr;
  113. for(i = 0; i < KGridY; i++)
  114. {
  115. xPos = 9;
  116. GetRowContent(i, arr);
  117. for(j = 0; j < KGridX; j++)
  118. {
  119. TUint8 blockType = arr[j];
  120. if(blockType)
  121. {
  122. TPoint pos = TPoint(xPos, yPos);
  123.   aBackBufferGc->BitBlt(pos, iBmpBlock.At(blockType%COLORNUM));
  124. }
  125. xPos += 9;
  126. }
  127. yPos += 10;
  128. }
  129. // draw Info
  130. const CFont* font;
  131. font = CEikonEnv::Static()->NormalFont();
  132. aBackBufferGc->UseFont(font);
  133. aBackBufferGc->SetPenColor(TRgb(215, 136, 20));
  134. aBackBufferGc->SetBrushStyle(CGraphicsContext::ENullBrush);
  135. TBuf<6> info;
  136. // score
  137. info.Num(iStateScore);
  138. aBackBufferGc->DrawText(info, TRect(TPoint(122, 90), TSize(45, 15)), 15, CGraphicsContext::ECenter, 0);
  139. // line
  140. info.Num(iLine);
  141. aBackBufferGc->DrawText(info, TRect(TPoint(122, 118), TSize(45, 15)), 15, CGraphicsContext::ECenter, 0);
  142. // Level
  143. info.Num(iLevel);
  144. aBackBufferGc->DrawText(info, TRect(TPoint(122, 145), TSize(45, 15)), 15, CGraphicsContext::ECenter, 0);
  145. aBackBufferGc->DiscardFont();
  146. // draw Next Block
  147. aBackBufferGc->SetBrushStyle(CGraphicsContext::ESolidBrush);
  148. aBackBufferGc->SetBrushColor(KRgbBlack);
  149. yPos = 29;
  150. for(i = 0; i < 4; i++)
  151. {
  152. xPos = 130;
  153. for(j = 0; j < 4; j++)
  154. {
  155. if((iBlockNext.RowMask(i) & (1<<(3-j))))
  156. aBackBufferGc->DrawRect(TRect(TPoint(xPos, yPos), TSize(6, 6)));
  157. xPos += 7;
  158. }
  159. yPos += 7;
  160. }
  161. }
  162. ////////////////////////////////////////////////////////////////////////////////
  163. // Other Methods
  164. // MoveTo() Move the Block to a new position if possible
  165. TBool CGameTetris::MoveTo(const TPoint& aNewPos)
  166. {
  167. if(iGrid.DoesCollide(iBlock, aNewPos))
  168. return 0;
  169. iBlockPos = aNewPos; // don't update View here to make Model Independent
  170. return 1; // Move successful
  171. }
  172. // Rotate()
  173. void CGameTetris::Rotate()
  174. {
  175. if(iStateRotateDir == 0)
  176. iStateRotateDir = -1;
  177. iBlock.Rotate(iStateRotateDir); // default state , deasil
  178. if(iGrid.DoesCollide(iBlock, iBlockPos))
  179. iBlock.Rotate( (TInt8)-iStateRotateDir ); // rotate back
  180. }
  181. // NewBlock()
  182. void CGameTetris::NewBlock()
  183. {
  184. iBlock = iBlockNext;
  185. iBlockNext = TBlock::RandomBlock(iSeed, iStateDifficulty);
  186. iBlockPos     = TPoint(4, -3);
  187. }
  188. // StartNewGame()
  189. void CGameTetris::StartNewGame()
  190. {
  191. // Game State
  192. iLevel = 1;
  193. iLine = 0;
  194. iStateScore = 0;
  195. //iStateRotateDir = 0;
  196. //iStateDifficulty = 0;
  197. // create new Grid
  198. iGrid = TGrid::NewGrid();
  199. // Start Lines
  200. if(iStateStartLines)
  201. StartLines(iStateStartLines);
  202. //StartLines(18);
  203. // create a block
  204. iBlockNext = TBlock::RandomBlock(iSeed, iStateDifficulty);
  205. NewBlock();
  206. iDelay = 0;
  207. }
  208. // GetRowContent()
  209. void CGameTetris::GetRowContent(TUint8 aRow, TFixedArray<TUint8, KGridX>& aRowContent)
  210. {
  211. int i;
  212. for(i = 0; i < KGridX; i++)
  213. {
  214. if(IsBlock(TPoint(i, aRow))) 
  215. aRowContent[i] = iBlock.Type();
  216. else 
  217. aRowContent[i] = iGrid.iContent[aRow][i];
  218. }
  219. }
  220. // if the position is a block
  221. TBool CGameTetris::IsBlock(const TPoint& aPos) const
  222. {
  223. if(TRect(iBlockPos, TSize(4, 4)).Contains(aPos))
  224. return (iBlock.RowMask(aPos.iY-iBlockPos.iY) & (1<<(3-aPos.iX+iBlockPos.iX))) > 0;
  225. return false;
  226. }
  227. // FixBlock() -- fix the block  -- be called if the current block can't move 
  228. // @ return 0 -- game over
  229. // @ return 1 -- continue game and put the block into the content
  230. TBool CGameTetris::FixBlock()
  231. {
  232. TInt i;
  233. // check if it is outside the board
  234. for (i = 0; i < -iBlockPos.iY; i++)
  235. if (iBlock.RowMask(i))
  236. return 0;
  237. iGrid.PutBlock(iBlock, iBlockPos);
  238. return 1;
  239. }
  240. // 
  241. TInt CGameTetris::CheckRows()
  242. {
  243. TInt offset=0, i, j;
  244. for (i = KGridY-1; i >= 0; i--)
  245. {
  246. if (iGrid.iMask[i]==0xffffU)
  247. {
  248. offset++;
  249. iLine++;
  250. continue;
  251. }
  252. if (offset > 0)
  253. {
  254. iGrid.iMask[i+offset]=iGrid.iMask[i];
  255. for (j = 0; j < KGridX; j++)
  256. iGrid.iContent[i+offset][j]=iGrid.iContent[i][j];
  257. }
  258. }
  259. for (i = 0; i < offset; i++)
  260. {
  261. iGrid.iMask[i] = 0x003f;
  262. for (j=0; j < KGridX; j++)
  263. iGrid.iContent[i][j] = 0;
  264. }
  265. return offset; // row's num to eliminate
  266. }
  267. void CGameTetris::Calculate(TInt rows)
  268. {
  269. switch(rows)
  270. {
  271. case 1:
  272. {
  273. iStateScore += 10;
  274. }break;
  275. case 2:
  276. {
  277. iStateScore += 25;
  278. }break;
  279. case 3:
  280. {
  281. iStateScore += 50;
  282. }break;
  283. case 4:
  284. {
  285. iStateScore += 80;
  286. iStateWellDone = ETrue;
  287. }break;
  288. default:break;
  289. }
  290. iStateClearRow = ETrue;
  291. iStateScore += iStateDifficulty * 15;
  292. iStateScore += iStateStartLines;
  293. iStateScore += iLevel * 2;
  294. if(iStateScore >= 500 * iLevel)
  295. {
  296. iLevel++;
  297. iStateLevelUp = ETrue;
  298. }
  299. if(iLevel > 10)
  300. {
  301. iLevel = 0;
  302. iStateDifficulty++;
  303. iStateDifficulty %= 3;
  304. }
  305. }
  306. // 
  307. void CGameTetris::LoadResL()
  308. {
  309. // Load bmps from mmp file
  310. _LIT(KPathName, "\System\Apps\Tetris\images.mbm");
  311. CEikonEnv* eikonEnv = CEikonEnv::Static();
  312. // Load Blocks
  313. iBmpBlock.At(0) = eikonEnv->CreateBitmapL(KPathName, EMbmImages1);
  314. iBmpBlock.At(1) = eikonEnv->CreateBitmapL(KPathName, EMbmImages2);
  315. iBmpBlock.At(2) = eikonEnv->CreateBitmapL(KPathName, EMbmImages3);
  316. iBmpBlock.At(3) = eikonEnv->CreateBitmapL(KPathName, EMbmImages4);
  317. iBmpBlock.At(4) = eikonEnv->CreateBitmapL(KPathName, EMbmImages5);
  318. iBmpBlock.At(5) = eikonEnv->CreateBitmapL(KPathName, EMbmImages6);
  319. iBmpBlock.At(6) = eikonEnv->CreateBitmapL(KPathName, EMbmImages7);
  320. iBmpBlock.At(7) = eikonEnv->CreateBitmapL(KPathName, EMbmImages8);
  321. iBmpBlock.At(8) = eikonEnv->CreateBitmapL(KPathName, EMbmImages9);
  322. // Load background
  323. iBmpBackground = eikonEnv->CreateBitmapL(KPathName, EMbmImagesBackground24);
  324. }
  325. void CGameTetris::StartLines(TUint8 aLines)
  326. {
  327. if(aLines >= 19)
  328. return ;
  329. TInt i, j;
  330. for(i = KGridY - 1; i >= KGridY - aLines; --i)
  331. {
  332. for(j = 0; j < KGridX; ++j)
  333. {
  334. TInt content = Math::Rand(iSeed) % 2;
  335. if(content)
  336. {
  337. iGrid.iContent[i][j] = (TInt8)(Math::Rand(iSeed) % BLOCKNUM + 1);
  338. iGrid.iMask[i] |= (1 << (15 - j));
  339. }
  340. }
  341. }
  342. }