CSuperBrickBreaker.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:70k
源码类别:

游戏

开发平台:

Visual C++

  1. //////////////////////////////////////////////////////////////////////////////
  2. /// File:    CSuperBrickBreaker.cpp
  3. /// Purpose: Implementation of CSuperBrickBreaker Class
  4. ///////////////////////////////////////////////////////////////////////////////
  5. /// Configuation Management
  6. /// 
  7. /// Who         When          Description
  8. /// ===========================================================================
  9. /// R. Walter   28-Dec-2003   Initial Version/Release
  10. ///
  11. ///////////////////////////////////////////////////////////////////////////////
  12. /// Copyright 2003: Robert Walter   All rights reserved
  13. ///////////////////////////////////////////////////////////////////////////////
  14. /// HEADER FILE INCLUDES //////////////////////////////////////////////////////
  15. #include <stdio.h>
  16. #include "CSuperBrickBreaker.h"
  17. /// CLASS CONSTRUCTORS / DESTRUCTORS //////////////////////////////////////////
  18. ///////////////////////////////////////////////////////////////////////////////
  19. /// Method:  CSuperBrickBreaker --> default constructor
  20. /// Purpose: Initialize member variables
  21. ///////////////////////////////////////////////////////////////////////////////
  22. /// Receives: nothing
  23. /// Returns:  nothing
  24. ///////////////////////////////////////////////////////////////////////////////
  25. CSuperBrickBreaker::CSuperBrickBreaker()
  26. {
  27. m_game_state      = GS_INITIALIZE;
  28. m_game_type       = SBB_STANDARD;
  29. m_paused_state    = PS_RESUME;
  30. m_gameover_state  = GO_PLAYAGAIN;
  31. m_hit_top_boun_fg = false;
  32. m_new_level_fg = false;
  33. m_score = 0;
  34. m_file_stream.open("sbb_log.txt");
  35. return;
  36. }
  37. ///////////////////////////////////////////////////////////////////////////////
  38. /// Method:  ~CSuperBrickBreaker --> class destructor
  39. /// Purpose: Uninitialize member variables
  40. ///////////////////////////////////////////////////////////////////////////////
  41. /// Receives: nothing
  42. /// Returns:  nothing
  43. ///////////////////////////////////////////////////////////////////////////////
  44. CSuperBrickBreaker::~CSuperBrickBreaker()
  45. {
  46. m_file_stream.close();
  47.     return;
  48. }
  49. ///////////////////////////////////////////////////////////////////////////////
  50. /// Method:  BallRectIntersect
  51. /// Purpose: Determine the passed ball rect intersects the passed rectangle
  52. ///////////////////////////////////////////////////////////////////////////////
  53. /// Receives: RECT describing current position of ball
  54. ///           RECT describing brick or paddle being tested for interesection
  55. /// Returns:  EIntersect describing how ball rect intersected rectangle
  56. ///////////////////////////////////////////////////////////////////////////////
  57. EIntersect CSuperBrickBreaker::BallRectIntersect(RECT p_ball_rect, RECT p_rect)
  58. {
  59. bool l_contains_top_left  = false;
  60. bool l_contains_top_right = false;
  61. bool l_contains_bot_left  = false;
  62. bool l_contains_bot_right = false;
  63. // check if top-left corner of the ball is in the rectangle
  64. l_contains_top_left = ( (p_ball_rect.top  >= p_rect.top)  && (p_ball_rect.top  <= p_rect.bottom) &&
  65.                     (p_ball_rect.left >= p_rect.left) && (p_ball_rect.left <= p_rect.right) ) ;
  66. // check if top-right corner of the ball is in the rectangle
  67. l_contains_top_right = ( (p_ball_rect.top   >= p_rect.top)  && (p_ball_rect.top   <= p_rect.bottom) &&
  68.                      (p_ball_rect.right >= p_rect.left) && (p_ball_rect.right <= p_rect.right) ) ;
  69. // check if bottom-left corner of the ball is in the rectangle
  70. l_contains_bot_left = ( (p_ball_rect.bottom >= p_rect.top)  && (p_ball_rect.bottom <= p_rect.bottom) &&
  71.                     (p_ball_rect.left   >= p_rect.left) && (p_ball_rect.left   <= p_rect.right) ) ;
  72. // check if bottom-right corner of the ball is in the rectangle
  73. l_contains_bot_right = ( (p_ball_rect.bottom >= p_rect.top)  && (p_ball_rect.bottom <= p_rect.bottom) &&
  74.                      (p_ball_rect.right  >= p_rect.left) && (p_ball_rect.right  <= p_rect.right) ) ;
  75. if ( (l_contains_top_left) && (l_contains_top_right) )
  76. {
  77. return(IS_BOTTOM);
  78. }
  79. else if ( (l_contains_top_right) && (l_contains_bot_right) ) 
  80. {
  81. return(IS_LEFT);
  82. }
  83. else if ( (l_contains_bot_right) && (l_contains_bot_left) ) 
  84. {
  85. return(IS_TOP);
  86. }
  87. else if ( (l_contains_bot_left) && (l_contains_top_left) )
  88. {
  89. return(IS_RIGHT);
  90. }
  91. else if (l_contains_top_left)
  92. {
  93. // only the top left corner 'penetrated' the rectangle
  94. // if the top-left corner is farther from the bottom of the
  95. // rectangle than the right side, assume the ball interected
  96. // the right
  97. if  ( (p_rect.bottom - p_ball_rect.top) >= (p_rect.right - p_ball_rect.left) )
  98. {
  99. return(IS_RIGHT);
  100. }
  101. else
  102. {
  103. return(IS_BOTTOM);
  104. }
  105. }
  106. else if (l_contains_top_right)
  107. {
  108.         // only the top right corner 'penetrated' the rectangle
  109. // if the top-right corner is farther from the bottom of the
  110. // rectangle than the left side, assume the ball interected
  111. // the left
  112. if  ( (p_rect.bottom - p_ball_rect.top) >= (p_ball_rect.right - p_rect.left) )
  113. {
  114. return(IS_LEFT);
  115. }
  116. else
  117. {
  118. return(IS_BOTTOM);
  119. }
  120. }
  121. else if (l_contains_bot_right)
  122. {
  123.         // only the bottom right corner 'penetrated' the rectangle
  124. // if the bottom-right corner is farther from the top of the
  125. // rectangle than the left side, assume the ball interected
  126. // the left
  127. if  ( (p_ball_rect.bottom - p_rect.top) >= (p_ball_rect.right - p_rect.left) )
  128. {
  129. return(IS_LEFT);
  130. }
  131. else
  132. {
  133. return(IS_BOTTOM);
  134. }
  135. }
  136. else if (l_contains_bot_left)
  137. {
  138. // only the bottom left corner 'penetrated' the rectangle
  139. // if the bottom-left corner is farther from the top of the
  140. // rectangle than the right side, assume the ball interected
  141. // the right
  142. if  ( (p_ball_rect.bottom - p_rect.top) >= (p_rect.right - p_ball_rect.left) )
  143. {
  144. return(IS_RIGHT);
  145. }
  146. else
  147. {
  148. return(IS_BOTTOM);
  149. }
  150. }
  151. return(IS_NONE);
  152. }
  153. ///////////////////////////////////////////////////////////////////////////////
  154. /// Method:  CheckHitBrick
  155. /// Purpose: Determines if the ball (based on passed rectangle) hit a brick
  156. ///////////////////////////////////////////////////////////////////////////////
  157. /// Receives: RECT structure of current positon of a ball
  158. /// Returns:  EIntersect value describing how ball hit a brick
  159. ///////////////////////////////////////////////////////////////////////////////
  160. EIntersect CSuperBrickBreaker::CheckHitBrick(const RECT p_ball_rect, TBrick* p_hit_brick)
  161. {
  162. bool l_is_brick = IsBrickAtBallLocation(p_ball_rect, p_hit_brick);
  163. if (l_is_brick)
  164. {
  165. EIntersect l_intersect = IS_NONE;
  166. if (p_hit_brick->state == BS_NORMAL)
  167. {
  168. // determine which side of the brick the ball intersected.
  169. l_intersect = BallRectIntersect(p_ball_rect, p_hit_brick->rect);
  170. return(l_intersect);
  171. }
  172. }
  173. return(IS_NONE);
  174. }
  175. ///////////////////////////////////////////////////////////////////////////////
  176. /// Method:  CheckHitPaddle
  177. /// Purpose: Determines if the ball (based on passed rectangle) hit the paddle
  178. ///////////////////////////////////////////////////////////////////////////////
  179. /// Receives: RECT structure of current positon of a ball
  180. /// Returns:  EIntersect value describing how ball hit the paddle
  181. ///////////////////////////////////////////////////////////////////////////////
  182. EIntersect CSuperBrickBreaker::CheckHitPaddle(const RECT p_ball_rect)
  183. {
  184. TBallCorner m_ball_corner[4];
  185. EIntersect  l_result = IS_NONE;
  186. /*************************
  187. ** top left corner
  188. *************************/
  189. m_ball_corner[0].x = p_ball_rect.left;
  190. m_ball_corner[0].y = p_ball_rect.top;
  191.     /*************************
  192. ** top right corner
  193. *************************/
  194. m_ball_corner[1].x = p_ball_rect.right;
  195. m_ball_corner[1].y = p_ball_rect.top;
  196. /*************************
  197. ** bottom right corner
  198. *************************/
  199. m_ball_corner[2].x = p_ball_rect.right;
  200. m_ball_corner[2].y = p_ball_rect.bottom;
  201. /*************************
  202. ** bottom left corner
  203. *************************/
  204. m_ball_corner[3].x = p_ball_rect.left;
  205. m_ball_corner[3].y = p_ball_rect.bottom;
  206. int  j = 0;
  207. bool l_hit_paddle = false;
  208. RECT l_paddle_rect;
  209. ///////////////////////////////////////////////////////////////////////////
  210. /// loop through each of the ball corners to determine if the ball 
  211. /// struck the paddle
  212. ///////////////////////////////////////////////////////////////////////////
  213. while (j < 4)
  214. {
  215. l_hit_paddle = m_paddle.IsPaddleAtPosition
  216.            (
  217.        /* x */           m_ball_corner[j].x, 
  218.    /* y */           m_ball_corner[j].y, 
  219.    /* paddle rect */ &l_paddle_rect
  220.    );
  221. ///////////////////////////////////////////////////////////////////////
  222. /// if the ball hit the paddle, determine how (ie. which side) the
  223. /// ball intersected
  224. ///////////////////////////////////////////////////////////////////////
  225. if (l_hit_paddle)
  226. {
  227. l_result = BallRectIntersect(p_ball_rect, l_paddle_rect);
  228. if (l_result != IS_NONE)
  229. {
  230. return(l_result);
  231. }
  232. }
  233. j++;
  234. }
  235. return(l_result);
  236. }
  237. ///////////////////////////////////////////////////////////////////////////////
  238. /// Method:  DrawBalls
  239. /// Purpose: Draw the Super Brick Breaker game balls
  240. ///////////////////////////////////////////////////////////////////////////////
  241. /// Receives: nothing
  242. /// Returns:  true if balls successfully drawn, otherwise false
  243. ///////////////////////////////////////////////////////////////////////////////
  244. bool CSuperBrickBreaker::DrawBalls()
  245. {
  246. // draw all FREE and CAPTIVE balls 
  247. for (int i = 0; i < m_num_balls; i++)
  248. {
  249. if ( (m_ball[i].GetState() == FREE) || (m_ball[i].GetState() == CAPTIVE) )
  250. {
  251.             m_ball_rect = m_ball[i].GetBallRect();
  252. bool br = false;
  253. br = DrawRectangle(&m_ball_rect, m_white_clr);
  254. if (!br)
  255. {
  256. return(false);
  257. }
  258. }
  259. }
  260. return true;
  261. }
  262. ///////////////////////////////////////////////////////////////////////////////
  263. /// Method:  DrawBoundary
  264. /// Purpose: Draw the Super Brick Breaker boundary
  265. ///////////////////////////////////////////////////////////////////////////////
  266. /// Receives: nothing
  267. /// Returns:  true if bounday successfully drawn, otherwise false
  268. ///////////////////////////////////////////////////////////////////////////////
  269. bool CSuperBrickBreaker::DrawBoundary()
  270. {
  271. // draw left boundary
  272. bool br = false;
  273. // draw main boundary rectangles
  274. br = DrawRectangle(&m_left_boun_rect, m_boundary_clr);
  275. if (!br) 
  276. {
  277. return(false);
  278. }
  279. br = DrawRectangle(&m_top_boun_rect, m_boundary_clr);
  280. if (!br) 
  281. {
  282. return(false);
  283. }
  284. br = DrawRectangle(&m_right_boun_rect, m_boundary_clr);
  285. if (!br) 
  286. {
  287. return(false);
  288. }
  289. // draw 'light' 3d rectangles on boundary
  290. br = DrawRectangle(&m_left_3d_light_rect, m_3d_light_clr);
  291. if (!br) 
  292. {
  293. return(false);
  294. }
  295. br = DrawRectangle(&m_top_3d_light_rect, m_3d_light_clr);
  296. if (!br) 
  297. {
  298. return(false);
  299. }
  300. br = DrawRectangle(&m_right_3d_light_rect, m_3d_light_clr);
  301. if (!br) 
  302. {
  303. return(false);
  304. }
  305. // draw 'shadow' 3d rectangles on boundary
  306. br = DrawRectangle(&m_left_3d_shadow_rect, m_3d_shadow_clr);
  307. if (!br) 
  308. {
  309. return(false);
  310. }
  311. br = DrawRectangle(&m_top_3d_shadow_rect, m_3d_shadow_clr);
  312. if (!br) 
  313. {
  314. return(false);
  315. }
  316. br = DrawRectangle(&m_right_3d_shadow_rect, m_3d_shadow_clr);
  317. if (!br) 
  318. {
  319. return(false);
  320. }
  321. return(true);
  322. };
  323. ///////////////////////////////////////////////////////////////////////////////
  324. /// Method:  DrawBricks
  325. /// Purpose: Draw the Super Brick Breaker game bricks
  326. ///////////////////////////////////////////////////////////////////////////////
  327. /// Receives: nothing
  328. /// Returns:  true if bricks successfully drawn, otherwise false
  329. ///////////////////////////////////////////////////////////////////////////////
  330. bool CSuperBrickBreaker::DrawBricks()
  331. {
  332. int l_brick_cnt = m_bricks.GetBrickCount();
  333. for (int i = 0; i < l_brick_cnt; i++)
  334. {
  335. TBrick l_brick = m_bricks.GetBrick(i);
  336. bool br = false;
  337. if (l_brick.state == BS_NORMAL)
  338. {
  339. br = DrawRectangle(&l_brick.rect, l_brick.color);
  340. if (!br)
  341. {
  342. return(false);
  343. }
  344. br = Draw3DFrame(l_brick.rect);
  345. if (!br)
  346. {
  347. return(false);
  348. }
  349. }
  350. }
  351. return(true);
  352. }
  353. ///////////////////////////////////////////////////////////////////////////////
  354. /// Method:  DrawGameOverMenu
  355. /// Purpose: Draw the 'game over' menu in the playing area on top of 
  356. ///          bricks
  357. ///////////////////////////////////////////////////////////////////////////////
  358. /// Receives: nothing
  359. /// Returns:  true if the menu is successfully drawn, otherwise false
  360. ///////////////////////////////////////////////////////////////////////////////
  361. bool CSuperBrickBreaker::DrawGameOverMenu()
  362. {
  363. bool br = false;
  364. ///////////////////////////////////////////////////////////////////////////
  365. /// draw the game over shadow text
  366. ///////////////////////////////////////////////////////////////////////////
  367. br = DrawGDIText
  368.  (
  369.      /* text */ "Game Over", 
  370.  /* red */  212,
  371.  /* green */ 208, 
  372.  /* blue */ 200, 
  373.  /* font */ m_menu_font, 
  374.  /* x */ 172,
  375.  /* y */ 77
  376.  );
  377.     if (!br)
  378. {
  379. return(false);
  380. }
  381. ///////////////////////////////////////////////////////////////////////////
  382. /// draw the game over text
  383. ///////////////////////////////////////////////////////////////////////////
  384. br = DrawGDIText
  385.  (
  386.      /* text */ "Game Over", 
  387.  /* red */  255,
  388.  /* green */ 255, 
  389.  /* blue */ 255, 
  390.  /* font */ m_menu_font, 
  391.  /* x */ 170,
  392.  /* y */ 75
  393.  );
  394.     if (!br)
  395. {
  396. return(false);
  397. }
  398.     ///////////////////////////////////////////////////////////////////////////
  399. /// draw the play again shadow text
  400. ///////////////////////////////////////////////////////////////////////////
  401. br = DrawGDIText
  402.  (
  403.      /* text */ "Play Again", 
  404.  /* red */  212,
  405.  /* green */ 208, 
  406.  /* blue */ 200, 
  407.  /* font */ m_menu_font, 
  408.  /* x */ 289,
  409.  /* y */ 152
  410.  );
  411.     if (!br)
  412. {
  413. return(false);
  414. }
  415. ///////////////////////////////////////////////////////////////////////////
  416. /// draw the play again text
  417. ///////////////////////////////////////////////////////////////////////////
  418. br = DrawGDIText
  419.  (
  420.      /* text */ "Play Again", 
  421.  /* red */  255,
  422.  /* green */ 255, 
  423.  /* blue */ 255, 
  424.  /* font */ m_menu_font, 
  425.  /* x */ 287,
  426.  /* y */ 150
  427.  );
  428.     if (!br)
  429. {
  430. return(false);
  431. }
  432. ///////////////////////////////////////////////////////////////////////////
  433. /// draw the main menu shadow text
  434. ///////////////////////////////////////////////////////////////////////////
  435. br = DrawGDIText
  436.  (
  437.      /* text */ "Main Menu", 
  438.  /* red */  212,
  439.  /* green */ 208, 
  440.  /* blue */ 200, 
  441.  /* font */ m_menu_font, 
  442.  /* x */ 289,
  443.  /* y */ 207
  444.  );
  445.     if (!br)
  446. {
  447. return(false);
  448. }
  449. ///////////////////////////////////////////////////////////////////////////
  450. /// draw the main menu text
  451. ///////////////////////////////////////////////////////////////////////////
  452. br = DrawGDIText
  453.  (
  454.      /* text */ "Main Menu", 
  455.  /* red */  255,
  456.  /* green */ 255, 
  457.  /* blue */ 255, 
  458.  /* font */ m_menu_font, 
  459.  /* x */ 287,
  460.  /* y */ 205
  461.  );
  462.     if (!br)
  463. {
  464. return(false);
  465. }
  466. int l_menu_x = 0;
  467. int l_menu_y = 0;
  468. if (m_gameover_state == GO_PLAYAGAIN)
  469. {
  470. l_menu_x = 230;
  471. l_menu_y = 150;
  472. }
  473. else if (m_gameover_state == GO_MAINMENU)
  474. {
  475. l_menu_x = 230;
  476. l_menu_y = 205;
  477. }
  478. else
  479. {
  480. return(false);
  481. }
  482. ///////////////////////////////////////////////////////////////////////////
  483. /// draw the 'chosen (->)' game shadow
  484. ///////////////////////////////////////////////////////////////////////////
  485.     br = DrawGDIText
  486.  (
  487.      /* text */ "->", 
  488.  /* red */  212,
  489.  /* green */ 208, 
  490.  /* blue */ 200, 
  491.  /* font */ m_menu_font, 
  492.  /* x */ l_menu_x + 2,
  493.  /* y */ l_menu_y + 2
  494.  );
  495.     if (!br)
  496. {
  497. return(false);
  498. }
  499. ///////////////////////////////////////////////////////////////////////////
  500. /// draw the 'chosen (->)' game
  501. ///////////////////////////////////////////////////////////////////////////
  502. br = DrawGDIText
  503.  (
  504.      /* text */ "->", 
  505.  /* red */  255,
  506.  /* green */ 255, 
  507.  /* blue */ 255, 
  508.  /* font */ m_menu_font, 
  509.  /* x */ l_menu_x,
  510.  /* y */ l_menu_y
  511.  );
  512.     if (!br)
  513. {
  514. return(false);
  515. }
  516. return(true);
  517. }
  518. ///////////////////////////////////////////////////////////////////////////////
  519. /// Method:  DrawHeadingLine
  520. /// Purpose: Draw the Super Brick Breaker heading line
  521. ///          - game title
  522. ///          - turns remaining
  523. ///          - current level
  524. ///          - current score
  525. ///////////////////////////////////////////////////////////////////////////////
  526. /// Receives: nothing
  527. /// Returns:  true if heading line successfully drawn, otherwise false
  528. ///////////////////////////////////////////////////////////////////////////////
  529. bool CSuperBrickBreaker::DrawHeadingLine()
  530. {
  531. char       l_text[200];
  532. ostrstream l_stream(l_text, sizeof(l_text));
  533. l_stream << "SUPER BRICK BREAKER            TURNS   " << m_game_turns_remaining 
  534.      << "          LEVEL   " << m_level << "        SCORE      " 
  535.  << m_score << ends;
  536.     StartGDIDrawing();
  537. bool br = false;
  538. br = DrawGDIText
  539.  (
  540.      /* text */ l_text, 
  541.  /* red */  255,
  542.  /* green */ 255, 
  543.  /* blue */ 255, 
  544.  /* font */ m_plain_font, 
  545.  /* x */ 2,
  546.  /* y */ 2
  547.  );
  548.     if (!br)
  549. {
  550. return(false);
  551. }
  552. EndGDIDrawing();
  553. return(true);
  554. }
  555. ///////////////////////////////////////////////////////////////////////////////
  556. /// Method:  DrawMainMenu
  557. /// Purpose: Draw the main menu in the playing area on top of 
  558. ///          bricks
  559. ///////////////////////////////////////////////////////////////////////////////
  560. /// Receives: nothing
  561. /// Returns:  true if the main menu is successfully drawn, otherwise false
  562. ///////////////////////////////////////////////////////////////////////////////
  563. bool CSuperBrickBreaker::DrawMainMenu()
  564. {
  565.     bool br = false;
  566. ///////////////////////////////////////////////////////////////////////////
  567. /// draw the 'Standard' game shadow text
  568. ///////////////////////////////////////////////////////////////////////////
  569. br = DrawGDIText
  570.  (
  571.      /* text */ "Standard", 
  572.  /* red */  212,
  573.  /* green */ 208, 
  574.  /* blue */ 200, 
  575.  /* font */ m_menu_font, 
  576.  /* x */ 315,
  577.  /* y */ 152
  578.  );
  579.     if (!br)
  580. {
  581. return(false);
  582. }
  583. ///////////////////////////////////////////////////////////////////////////
  584. /// draw the 'Standard' game text
  585. ///////////////////////////////////////////////////////////////////////////
  586. br = DrawGDIText
  587.  (
  588.      /* text */ "Standard", 
  589.  /* red */  255,
  590.  /* green */ 255, 
  591.  /* blue */ 255, 
  592.  /* font */ m_menu_font, 
  593.  /* x */ 312,
  594.  /* y */ 150
  595.  );
  596.     if (!br)
  597. {
  598. return(false);
  599. }
  600. ///////////////////////////////////////////////////////////////////////////
  601. /// draw the 'Double' game shadow text
  602. ///////////////////////////////////////////////////////////////////////////
  603. br = DrawGDIText
  604.  (
  605.      /* text */ "Double", 
  606.  /* red */  212,
  607.  /* green */ 208, 
  608.  /* blue */ 200, 
  609.  /* font */ m_menu_font, 
  610.  /* x */ 314,
  611.  /* y */ 207
  612.  );
  613.     if (!br)
  614. {
  615. return(false);
  616. }
  617. ///////////////////////////////////////////////////////////////////////////
  618. /// draw the 'Double' game text
  619. ///////////////////////////////////////////////////////////////////////////
  620. br = DrawGDIText
  621.  (
  622.      /* text */ "Double", 
  623.  /* red */  255,
  624.  /* green */ 255, 
  625.  /* blue */ 255, 
  626.  /* font */ m_menu_font, 
  627.  /* x */ 312,
  628.  /* y */ 205
  629.  );
  630.     if (!br)
  631. {
  632. return(false);
  633. }
  634. ///////////////////////////////////////////////////////////////////////////
  635. /// draw the 'Escape' game shadow text
  636. ///////////////////////////////////////////////////////////////////////////
  637. br = DrawGDIText
  638.  (
  639.      /* text */ "Escape", 
  640.  /* red */  212,
  641.  /* green */ 208, 
  642.  /* blue */ 200, 
  643.  /* font */ m_menu_font, 
  644.  /* x */ 314,
  645.  /* y */ 262
  646.  );
  647.     if (!br)
  648. {
  649. return(false);
  650. }
  651. ///////////////////////////////////////////////////////////////////////////
  652. /// draw the 'Escape' game text
  653. ///////////////////////////////////////////////////////////////////////////
  654. br = DrawGDIText
  655.  (
  656.      /* text */ "Escape", 
  657.  /* red */  255,
  658.  /* green */ 255, 
  659.  /* blue */ 255, 
  660.  /* font */ m_menu_font, 
  661.  /* x */ 312,
  662.  /* y */ 260
  663.  );
  664.     if (!br)
  665. {
  666. return(false);
  667. }
  668. int l_game_menu_x = 0;
  669. int l_game_menu_y = 0;
  670. if (m_game_type == SBB_STANDARD)
  671. {
  672. l_game_menu_x = 255;
  673. l_game_menu_y = 150;
  674. }
  675. else if (m_game_type == SBB_DOUBLE)
  676. {
  677. l_game_menu_x = 255;
  678. l_game_menu_y = 205;
  679. }
  680. else if (m_game_type == SBB_ESCAPE)
  681. {
  682. l_game_menu_x = 255;
  683. l_game_menu_y = 260;
  684. }
  685. else
  686. {
  687. return(false);
  688. }
  689. ///////////////////////////////////////////////////////////////////////////
  690. /// draw the 'chosen (->)' game shadow
  691. ///////////////////////////////////////////////////////////////////////////
  692.     br = DrawGDIText
  693.  (
  694.      /* text */ "->", 
  695.  /* red */  212,
  696.  /* green */ 208, 
  697.  /* blue */ 200, 
  698.  /* font */ m_menu_font, 
  699.  /* x */ l_game_menu_x + 2,
  700.  /* y */ l_game_menu_y + 2
  701.  );
  702.     if (!br)
  703. {
  704. return(false);
  705. }
  706. ///////////////////////////////////////////////////////////////////////////
  707. /// draw the 'chosen (->)' game
  708. ///////////////////////////////////////////////////////////////////////////
  709. br = DrawGDIText
  710.  (
  711.      /* text */ "->", 
  712.  /* red */  255,
  713.  /* green */ 255, 
  714.  /* blue */ 255, 
  715.  /* font */ m_menu_font, 
  716.  /* x */ l_game_menu_x,
  717.  /* y */ l_game_menu_y
  718.  );
  719.     if (!br)
  720. {
  721. return(false);
  722. }
  723. return(true);
  724. };
  725. ///////////////////////////////////////////////////////////////////////////////
  726. /// Method:  DrawPaddle
  727. /// Purpose: Draw the paddle in the playing area
  728. ///////////////////////////////////////////////////////////////////////////////
  729. /// Receives: nothing
  730. /// Returns:  true if paddle successfully drawn, otherwise false
  731. ///////////////////////////////////////////////////////////////////////////////
  732. bool CSuperBrickBreaker::DrawPaddle()
  733. {
  734. bool br = false;
  735. m_paddle.GetPaddleRects(&m_paddle_cnt, m_paddle_rects);
  736. for (int i = 0; i < m_paddle_cnt; i++)
  737. {
  738. br = DrawRectangle(&m_paddle_rects[i], m_boundary_clr);
  739. if (!br)
  740. {
  741. return(false);
  742. }
  743. br = Draw3DFrame(m_paddle_rects[i]);
  744. if (!br)
  745. {
  746. return(false);
  747. }
  748. }
  749. return(true);
  750. }
  751. ///////////////////////////////////////////////////////////////////////////////
  752. /// Method:  DrawPausedMenu
  753. /// Purpose: Draw the 'game paused' menu in the playing area on top of 
  754. ///          bricks
  755. ///////////////////////////////////////////////////////////////////////////////
  756. /// Receives: nothing
  757. /// Returns:  true if the menu is successfully drawn, otherwise false
  758. ///////////////////////////////////////////////////////////////////////////////
  759. bool CSuperBrickBreaker::DrawPausedMenu()
  760. {
  761.     bool br = false;
  762. ///////////////////////////////////////////////////////////////////////////
  763. /// draw the game paused shadow text
  764. ///////////////////////////////////////////////////////////////////////////
  765. br = DrawGDIText
  766.  (
  767.      /* text */ "Game Paused", 
  768.  /* red */  212,
  769.  /* green */ 208, 
  770.  /* blue */ 200, 
  771.  /* font */ m_menu_font, 
  772.  /* x */ 242,
  773.  /* y */ 77
  774.  );
  775.     if (!br)
  776. {
  777. return(false);
  778. }
  779. ///////////////////////////////////////////////////////////////////////////
  780. /// draw the game paused text
  781. ///////////////////////////////////////////////////////////////////////////
  782. br = DrawGDIText
  783.  (
  784.      /* text */ "Game Paused", 
  785.  /* red */  255,
  786.  /* green */ 255, 
  787.  /* blue */ 255, 
  788.  /* font */ m_menu_font, 
  789.  /* x */ 240,
  790.  /* y */ 75
  791.  );
  792.     if (!br)
  793. {
  794. return(false);
  795. }
  796. ///////////////////////////////////////////////////////////////////////////
  797. /// draw the resume game shadow text
  798. ///////////////////////////////////////////////////////////////////////////
  799. br = DrawGDIText
  800.  (
  801.      /* text */ "Resume Game", 
  802.  /* red */  212,
  803.  /* green */ 208, 
  804.  /* blue */ 200, 
  805.  /* font */ m_menu_font, 
  806.  /* x */ 314,
  807.  /* y */ 152
  808.  );
  809.     if (!br)
  810. {
  811. return(false);
  812. }
  813. ///////////////////////////////////////////////////////////////////////////
  814. /// draw the resume game text
  815. ///////////////////////////////////////////////////////////////////////////
  816. br = DrawGDIText
  817.  (
  818.      /* text */ "Resume Game", 
  819.  /* red */  255,
  820.  /* green */ 255, 
  821.  /* blue */ 255, 
  822.  /* font */ m_menu_font, 
  823.  /* x */ 312,
  824.  /* y */ 150
  825.  );
  826.     if (!br)
  827. {
  828. return(false);
  829. }
  830. ///////////////////////////////////////////////////////////////////////////
  831. /// draw the main menu shadow text
  832. ///////////////////////////////////////////////////////////////////////////
  833. br = DrawGDIText
  834.  (
  835.      /* text */ "Main Menu", 
  836.  /* red */  212,
  837.  /* green */ 208, 
  838.  /* blue */ 200, 
  839.  /* font */ m_menu_font, 
  840.  /* x */ 314,
  841.  /* y */ 207
  842.  );
  843.     if (!br)
  844. {
  845. return(false);
  846. }
  847. ///////////////////////////////////////////////////////////////////////////
  848. /// draw the main menu text
  849. ///////////////////////////////////////////////////////////////////////////
  850. br = DrawGDIText
  851.  (
  852.      /* text */ "Main Menu", 
  853.  /* red */  255,
  854.  /* green */ 255, 
  855.  /* blue */ 255, 
  856.  /* font */ m_menu_font, 
  857.  /* x */ 312,
  858.  /* y */ 205
  859.  );
  860.     if (!br)
  861. {
  862. return(false);
  863. }
  864. int l_menu_x = 0;
  865. int l_menu_y = 0;
  866. if (m_paused_state == PS_RESUME)
  867. {
  868. l_menu_x = 255;
  869. l_menu_y = 150;
  870. }
  871. else if (m_paused_state == PS_MAINMENU)
  872. {
  873. l_menu_x = 255;
  874. l_menu_y = 205;
  875. }
  876. else
  877. {
  878. return(false);
  879. }
  880. ///////////////////////////////////////////////////////////////////////////
  881. /// draw the 'chosen (->)' game shadow
  882. ///////////////////////////////////////////////////////////////////////////
  883.     br = DrawGDIText
  884.  (
  885.      /* text */ "->", 
  886.  /* red */  212,
  887.  /* green */ 208, 
  888.  /* blue */ 200, 
  889.  /* font */ m_menu_font, 
  890.  /* x */ l_menu_x + 2,
  891.  /* y */ l_menu_y + 2
  892.  );
  893.     if (!br)
  894. {
  895. return(false);
  896. }
  897. ///////////////////////////////////////////////////////////////////////////
  898. /// draw the 'chosen (->)' game
  899. ///////////////////////////////////////////////////////////////////////////
  900. br = DrawGDIText
  901.  (
  902.      /* text */ "->", 
  903.  /* red */  255,
  904.  /* green */ 255, 
  905.  /* blue */ 255, 
  906.  /* font */ m_menu_font, 
  907.  /* x */ l_menu_x,
  908.  /* y */ l_menu_y
  909.  );
  910.     if (!br)
  911. {
  912. return(false);
  913. }
  914. return(true);
  915. }
  916. ///////////////////////////////////////////////////////////////////////////////
  917. /// Method:  DrawStartNextTurn
  918. /// Purpose: Draw the 'READY' text before actually beginning the next turn
  919. ///////////////////////////////////////////////////////////////////////////////
  920. /// Receives: nothing
  921. /// Returns:  true if the text is successfully drawn, otherwise false
  922. ///////////////////////////////////////////////////////////////////////////////
  923. bool CSuperBrickBreaker::DrawStartNextTurn()
  924. {
  925. bool br = false;
  926. ///////////////////////////////////////////////////////////////////////////
  927. /// draw the 'READY!' shadow text
  928. ///////////////////////////////////////////////////////////////////////////
  929. br = DrawGDIText
  930.  (
  931.      /* text */ "READY!", 
  932.  /* red */  212,
  933.  /* green */ 208, 
  934.  /* blue */ 200, 
  935.  /* font */ m_menu_font, 
  936.  /* x */ 302,
  937.  /* y */ 282
  938.  );
  939.     if (!br)
  940. {
  941. return(false);
  942. }
  943. ///////////////////////////////////////////////////////////////////////////
  944. /// draw the 'READY!' text
  945. ///////////////////////////////////////////////////////////////////////////
  946. br = DrawGDIText
  947.  (
  948.      /* text */ "READY!", 
  949.  /* red */  255,
  950.  /* green */ 255, 
  951.  /* blue */ 255, 
  952.  /* font */ m_menu_font, 
  953.  /* x */ 300,
  954.  /* y */ 280
  955.  );
  956.     if (!br)
  957. {
  958. return(false);
  959. }
  960. return(true);
  961. }
  962. ///////////////////////////////////////////////////////////////////////////////
  963. /// Method:  Draw3DFrame
  964. /// Purpose: Draw a 3D frame around the passed rectangle
  965. ///          NOTE: the frame is drawn around the INSIDE of the rectangle
  966. ///////////////////////////////////////////////////////////////////////////////
  967. /// Receives: rectangle around frame will be drawn
  968. /// Returns:  true if frame successfully drawn, otherwise false
  969. ///////////////////////////////////////////////////////////////////////////////
  970. bool CSuperBrickBreaker::Draw3DFrame(const RECT p_rect)
  971. {
  972. RECT l_frame_rect;
  973. bool br = false;
  974. // first - draw left light frame
  975. l_frame_rect.left = p_rect.left;
  976. l_frame_rect.top  = p_rect.top;
  977. l_frame_rect.right = p_rect.left + 1;
  978. l_frame_rect.bottom = p_rect.bottom;
  979. br = DrawRectangle(&l_frame_rect, m_3d_light_clr);
  980. if (!br)
  981. {
  982. return(false);
  983. }
  984. // second - draw top light frame
  985. l_frame_rect.left = p_rect.left;
  986. l_frame_rect.top  = p_rect.top;
  987. l_frame_rect.right = p_rect.right;
  988. l_frame_rect.bottom = p_rect.top + 1;
  989. br = DrawRectangle(&l_frame_rect, m_3d_light_clr);
  990. if (!br)
  991. {
  992. return(false);
  993. }
  994. // third - draw right shadow frame
  995. l_frame_rect.left = p_rect.right - 1;
  996. l_frame_rect.top = p_rect.top;
  997. l_frame_rect.right = p_rect.right;
  998. l_frame_rect.bottom = p_rect.bottom;
  999. br = DrawRectangle(&l_frame_rect, m_3d_shadow_clr);
  1000. if (!br)
  1001. {
  1002. return(false);
  1003. }
  1004. // last - draw bottom shadow frame
  1005. l_frame_rect.left = p_rect.left + 1;
  1006. l_frame_rect.top = p_rect.bottom - 1;
  1007. l_frame_rect.right = p_rect.right;
  1008. l_frame_rect.bottom = p_rect.bottom;
  1009. br = DrawRectangle(&l_frame_rect, m_3d_shadow_clr);
  1010. if (!br)
  1011. {
  1012. return(false);
  1013. }
  1014. return true;
  1015. }
  1016. ///////////////////////////////////////////////////////////////////////////////
  1017. /// Method:  GameInitialize
  1018. /// Purpose: Initialize any variable required by this game object
  1019. ///////////////////////////////////////////////////////////////////////////////
  1020. /// Receives: nothing
  1021. /// Returns:  true if game objects successfully initialized, otherwise false
  1022. ///////////////////////////////////////////////////////////////////////////////
  1023. bool CSuperBrickBreaker::GameInitialize()
  1024. {
  1025. // initialize color variables
  1026. InitializeColors();
  1027. m_menu_font = CreateFont 
  1028.      (
  1029.     /* height */ 60,
  1030.   /* width  */ 0, 
  1031.   /* escapement */ 0, 
  1032.   /* orientation */ 0, 
  1033.   /* weight */ FW_HEAVY, 
  1034.   /* italic */ FALSE, 
  1035.   /* underline */ FALSE, 
  1036.   /* strikeout */ FALSE, 
  1037.   /* char set */ DEFAULT_CHARSET, 
  1038.   /* output precision */ OUT_CHARACTER_PRECIS, 
  1039.   /* clip precision */ CLIP_DEFAULT_PRECIS, 
  1040.   /* font quality */ DEFAULT_QUALITY, 
  1041.   /* pitch and family */ DEFAULT_PITCH | FF_DONTCARE, 
  1042.   /* typeface name */ "MS Sans Serif"
  1043.   );
  1044. m_plain_font = CreateFont 
  1045.      (
  1046.     /* height */ 24,
  1047.   /* width  */ 0, 
  1048.   /* escapement */ 0, 
  1049.   /* orientation */ 0, 
  1050.   /* weight */ FW_HEAVY, 
  1051.   /* italic */ FALSE, 
  1052.   /* underline */ FALSE, 
  1053.   /* strikeout */ FALSE, 
  1054.   /* char set */ DEFAULT_CHARSET, 
  1055.   /* output precision */ OUT_CHARACTER_PRECIS, 
  1056.   /* clip precision */ CLIP_DEFAULT_PRECIS, 
  1057.   /* font quality */ DEFAULT_QUALITY, 
  1058.   /* pitch and family */ DEFAULT_PITCH | FF_DONTCARE, 
  1059.   /* typeface name */ "MS Sans Serif"
  1060.   );
  1061.     // initialize boundary rectangles
  1062. InitializePlayingArea();
  1063. // set the base properties for the bricks
  1064. // they are the same for all games
  1065.     m_bricks.SetTopLeftPosition(/* x */ DEFAULT_BRICK_START_X, /* y */ DEFAULT_BRICK_START_Y);
  1066.     m_bricks.SetBrickProperties
  1067.      (
  1068.      /* width */    DEFAULT_BRICK_WIDTH,
  1069.  /* height */   DEFAULT_BRICK_HEIGHT,
  1070.  /* h space */  DEFAULT_BRICK_HOR_SPACE,
  1071.  /* v_space  */ DEFAULT_BRICK_VER_SPACE
  1072.  );
  1073. bool br = false;
  1074. br = ProcessStateChange(/* new state */ GS_MAINMENU);
  1075. if (!br)
  1076. {
  1077. return(false);
  1078. }
  1079. return(true);
  1080. }
  1081. ///////////////////////////////////////////////////////////////////////////////
  1082. /// Method:  GameMain
  1083. /// Purpose: Perform the next game logic loop
  1084. ///////////////////////////////////////////////////////////////////////////////
  1085. /// Receives: nothing
  1086. /// Returns:  true if game loop successfully processed, otherwise false
  1087. ///////////////////////////////////////////////////////////////////////////////
  1088. bool CSuperBrickBreaker::GameMain()
  1089. {
  1090. bool br = false;
  1091.     ///////////////////////////////////////////////////////////////////////////
  1092. /// ensure we are in a 'Game Main' acceptable state:
  1093. /// - we cannot be in GS_INITIALIZE
  1094. ///////////////////////////////////////////////////////////////////////////
  1095. if (m_game_state == GS_INITIALIZE)
  1096. {
  1097. return(false);
  1098. }
  1099. ///////////////////////////////////////////////////////////////////////////
  1100. /// process the keyboard data (ie. move paddle, pause game, etc)
  1101. ///////////////////////////////////////////////////////////////////////////
  1102. br = ProcessKeyboard();
  1103. if (!br)
  1104. {
  1105. return(false);
  1106. }
  1107. ///////////////////////////////////////////////////////////////////////////
  1108. /// process the game objects -> if the game is not paused or awaiting the
  1109. /// start of the next turn
  1110. /// - move the paddle
  1111. /// - move the ball(s)
  1112. ///////////////////////////////////////////////////////////////////////////
  1113. if ( (m_game_state != GS_STARTTURN) && (m_game_state != GS_GAMEPAUSED) && (m_game_state != GS_GAMEOVER) )
  1114. {
  1115. br = ProcessPaddle();
  1116. if (!br)
  1117. {
  1118. return(false);
  1119. }
  1120. br = ProcessBalls();
  1121. if (!br)
  1122. {
  1123. return(false);
  1124. }
  1125. }
  1126. ///////////////////////////////////////////////////////////////////////////
  1127. /// start the next frame (scene)
  1128. ///////////////////////////////////////////////////////////////////////////
  1129. br = StartScene(m_black_clr);
  1130. if (!br)
  1131. {
  1132. return(false);
  1133. }
  1134. ///////////////////////////////////////////////////////////////////////////
  1135. /// draw the parts of the playing area not based on the 
  1136. /// current state of the game
  1137. /// - Boundary
  1138. /// - Bricks
  1139. /// - Paddle
  1140. /// - Score
  1141. /// - Turns Remaining
  1142. ///////////////////////////////////////////////////////////////////////////
  1143. br = DrawBoundary();
  1144. if (!br)
  1145. {
  1146. return(false);
  1147. }
  1148. br = DrawBricks();
  1149. if (!br)
  1150. {
  1151. return(false);
  1152. }
  1153. br = DrawPaddle();
  1154. if (!br)
  1155. {
  1156. return(false);
  1157. }
  1158. br = DrawBalls();
  1159. if (!br)
  1160. {
  1161. return(false);
  1162. }
  1163. br = DrawHeadingLine();
  1164. if (!br)
  1165. {
  1166. return(false);
  1167. }
  1168. ///////////////////////////////////////////////////////////////////////////
  1169. /// draw the playing area based on the current state
  1170. /// of the game
  1171. ///////////////////////////////////////////////////////////////////////////
  1172. switch(m_game_state)
  1173. {
  1174. case GS_MAINMENU:
  1175. {
  1176.             ///////////////////////////////////////////////////////////////////////////
  1177. /// draw the main menu text with the current item highlighted
  1178. ///////////////////////////////////////////////////////////////////////////
  1179. StartGDIDrawing();
  1180. br = DrawMainMenu();
  1181. if (!br)
  1182. {
  1183. return(false);
  1184. }
  1185. EndGDIDrawing();
  1186. } break;
  1187. case GS_STARTTURN:
  1188. {
  1189.             ///////////////////////////////////////////////////////////////////////////
  1190. /// draw the main menu text with the current item highlighted
  1191. ///////////////////////////////////////////////////////////////////////////
  1192. StartGDIDrawing();
  1193. br = DrawStartNextTurn();
  1194. if (!br)
  1195. {
  1196. return(false);
  1197. }
  1198. EndGDIDrawing();
  1199. } break;
  1200. case GS_GAMEPLAY:
  1201. {
  1202.             ///////////////////////////////////////////////////////////////////////////
  1203. /// no extra things to do
  1204. ///////////////////////////////////////////////////////////////////////////
  1205. } break;
  1206. case GS_GAMEPAUSED:
  1207. {
  1208.             ///////////////////////////////////////////////////////////////////////////
  1209. /// draw the paused menu
  1210. ///////////////////////////////////////////////////////////////////////////
  1211. StartGDIDrawing();
  1212. br = DrawPausedMenu();
  1213. if (!br)
  1214. {
  1215. return(false);
  1216. }
  1217. EndGDIDrawing();
  1218. } break;
  1219. case GS_GAMEOVER:
  1220. {
  1221.             ///////////////////////////////////////////////////////////////////////////
  1222. /// draw the game over menu
  1223. ///////////////////////////////////////////////////////////////////////////
  1224. StartGDIDrawing();
  1225. br = DrawGameOverMenu();
  1226. if (!br)
  1227. {
  1228. return(false);
  1229. }
  1230. EndGDIDrawing();
  1231. } break;
  1232. }
  1233.     ///////////////////////////////////////////////////////////////////////////
  1234. /// 'mark' the end of this frame and flip the back buffer
  1235. ///////////////////////////////////////////////////////////////////////////
  1236. br = EndScene();
  1237. if (!br)
  1238. {
  1239. return(false);
  1240. }
  1241. return(true);
  1242. }
  1243. ///////////////////////////////////////////////////////////////////////////////
  1244. /// Method:  GameShutdown
  1245. /// Purpose: Uninitialize any variable required by this game object
  1246. ///////////////////////////////////////////////////////////////////////////////
  1247. /// Receives: nothing
  1248. /// Returns:  true if game objects successfully uninitialized, otherwise false
  1249. ///////////////////////////////////////////////////////////////////////////////
  1250. bool CSuperBrickBreaker::GameShutdown()
  1251. {
  1252. return true;
  1253. };
  1254. ///////////////////////////////////////////////////////////////////////////////
  1255. /// Method:  InitializeBalls
  1256. /// Purpose: Set the 'ball' variables for the game
  1257. ///////////////////////////////////////////////////////////////////////////////
  1258. /// Receives: nothing
  1259. /// Returns:  nothing
  1260. ///////////////////////////////////////////////////////////////////////////////
  1261. void CSuperBrickBreaker::InitializeBalls()
  1262. {
  1263. m_balls_in_play = 0;
  1264. m_hit_top_boun_fg = false;
  1265. int m_temp_x = 23;
  1266. int m_temp_y = 295;
  1267. srand(GetTickCount());
  1268. m_temp_x += (rand()%120);
  1269. m_temp_y += (rand()%50);
  1270. m_ball[0].SetXPos(m_temp_x);
  1271. m_ball[0].SetYPos(m_temp_y);
  1272. m_ball[0].SetXVel(2);
  1273. m_ball[0].SetYVel(2);
  1274. m_ball[0].SetVelMultiplier(1);
  1275. m_ball[0].SetState(IDLE);
  1276. switch(m_game_type)
  1277. {
  1278. case SBB_STANDARD:
  1279. {
  1280. // no extra initialization required
  1281. } break;
  1282. case SBB_DOUBLE:
  1283. {
  1284. m_first_paddle_hit = false;
  1285. m_ball[1].SetXPos(23);
  1286. m_ball[1].SetYPos(295);
  1287. m_ball[1].SetXVel(2);
  1288. m_ball[1].SetYVel(2);
  1289. m_ball[1].SetVelMultiplier(1);
  1290. m_ball[1].SetState(IDLE);
  1291. } break;
  1292. case SBB_ESCAPE:
  1293. {
  1294. RECT m_ball_rect;
  1295. m_ball_rect.top = DEFAULT_BRICK_START_Y + (2 * (DEFAULT_BRICK_HEIGHT + DEFAULT_BRICK_VER_SPACE) ) - DEFAULT_BRICK_VER_SPACE;
  1296. m_ball_rect.left = DEFAULT_BRICK_START_X + (2 * (DEFAULT_BRICK_WIDTH + DEFAULT_BRICK_HOR_SPACE) ) - DEFAULT_BRICK_HOR_SPACE;
  1297. m_ball_rect.right = m_ball_rect.left + (2 * (DEFAULT_BRICK_WIDTH + DEFAULT_BRICK_HOR_SPACE) ) + DEFAULT_BRICK_HOR_SPACE;
  1298. m_ball_rect.bottom = m_ball_rect.top + (2 * (DEFAULT_BRICK_HEIGHT + DEFAULT_BRICK_VER_SPACE) ) + DEFAULT_BRICK_VER_SPACE;
  1299. if (m_game_turns_remaining < 5)
  1300. {
  1301. if ((m_ball[1].GetState() != CAPTIVE) && (!m_new_level_fg))
  1302. {
  1303. // the ball has been freed and has been lost, do nothing
  1304. }
  1305. else
  1306. {
  1307. m_ball[1].SetXPos(151);
  1308. m_ball[1].SetYPos(133);
  1309. m_ball[1].SetXVel(2);
  1310. m_ball[1].SetYVel(2);
  1311. m_ball[1].SetVelMultiplier(2);
  1312. m_ball[1].SetCaptiveRect(m_ball_rect);
  1313. }
  1314. }
  1315. else
  1316. {
  1317. m_ball[1].SetXPos(151);
  1318. m_ball[1].SetYPos(133);
  1319. m_ball[1].SetXVel(2);
  1320. m_ball[1].SetYVel(2);
  1321. m_ball[1].SetVelMultiplier(2);
  1322. m_ball[1].SetState(CAPTIVE);
  1323. m_ball[1].SetCaptiveRect(m_ball_rect);
  1324. }
  1325. m_ball_rect.top = DEFAULT_BRICK_START_Y + (2 * (DEFAULT_BRICK_HEIGHT + DEFAULT_BRICK_VER_SPACE) ) - DEFAULT_BRICK_VER_SPACE;
  1326. m_ball_rect.left = DEFAULT_BRICK_START_X + (8 * (DEFAULT_BRICK_WIDTH + DEFAULT_BRICK_HOR_SPACE) ) - DEFAULT_BRICK_HOR_SPACE;
  1327. m_ball_rect.right = m_ball_rect.left + (2 * (DEFAULT_BRICK_WIDTH + DEFAULT_BRICK_HOR_SPACE) ) + DEFAULT_BRICK_HOR_SPACE;
  1328. m_ball_rect.bottom = m_ball_rect.top + (2 * (DEFAULT_BRICK_HEIGHT + DEFAULT_BRICK_VER_SPACE) ) + DEFAULT_BRICK_VER_SPACE;
  1329. if (m_game_turns_remaining < 5)
  1330. {
  1331. if ((m_ball[2].GetState() != CAPTIVE) && (!m_new_level_fg))
  1332. {
  1333. // do nothing
  1334. }
  1335. else
  1336. {
  1337. m_ball[2].SetXPos(634);
  1338. m_ball[2].SetYPos(133);
  1339. m_ball[2].SetXVel(-2);
  1340. m_ball[2].SetYVel(2);
  1341. m_ball[2].SetVelMultiplier(2);
  1342. m_ball[2].SetCaptiveRect(m_ball_rect);
  1343. }
  1344. }
  1345. else
  1346. {
  1347. m_ball[2].SetXPos(634);
  1348. m_ball[2].SetYPos(133);
  1349. m_ball[2].SetXVel(-2);
  1350. m_ball[2].SetYVel(2);
  1351. m_ball[2].SetVelMultiplier(2);
  1352. //m_ball[2].SetState(CAPTIVE);
  1353. m_ball[2].SetCaptiveRect(m_ball_rect);
  1354. }
  1355. } break;
  1356. }
  1357. return;
  1358. };
  1359. ///////////////////////////////////////////////////////////////////////////////
  1360. /// Method:  InitializeBricks
  1361. /// Purpose: Set the 'bricks' variables for the game
  1362. ///////////////////////////////////////////////////////////////////////////////
  1363. /// Receives: nothing
  1364. /// Returns:  nothing
  1365. ///////////////////////////////////////////////////////////////////////////////
  1366. void CSuperBrickBreaker::InitializeBricks()
  1367. {
  1368. ///////////////////////////////////////////////////////////////////////////
  1369. /// reset the bricks based on the current game settings
  1370. ///////////////////////////////////////////////////////////////////////////
  1371. m_bricks.SetRowColProperties
  1372.      (
  1373.      /* num rows */   DEFAULT_BRICK_ROWS,
  1374.  /* num cols */   DEFAULT_BRICK_COLS,
  1375.  /* row colors */ m_brick_colors,
  1376.  /* row points */ m_brick_points,
  1377.  /* row vel */    m_brick_reflect_vel
  1378.  );
  1379. m_bricks.InitializeBricks();
  1380. ///////////////////////////////////////////////////////////////////////////
  1381. /// if we are playing ESCAPE, remove the bricks that 'hold' the 
  1382. /// two captive balls
  1383. ///////////////////////////////////////////////////////////////////////////
  1384. if (m_game_type == SBB_ESCAPE)
  1385. {
  1386. m_bricks.SetBrickState(/* row */ 3, /* col */ 3, /* state */ BS_SKIP);
  1387. m_bricks.SetBrickState(/* row */ 3, /* col */ 4, /* state */ BS_SKIP);
  1388. m_bricks.SetBrickState(/* row */ 4, /* col */ 3, /* state */ BS_SKIP);
  1389. m_bricks.SetBrickState(/* row */ 4, /* col */ 4, /* state */ BS_SKIP);
  1390. m_bricks.SetBrickState(/* row */ 3, /* col */  9, /* state */ BS_SKIP);
  1391. m_bricks.SetBrickState(/* row */ 3, /* col */ 10, /* state */ BS_SKIP);
  1392. m_bricks.SetBrickState(/* row */ 4, /* col */  9, /* state */ BS_SKIP);
  1393. m_bricks.SetBrickState(/* row */ 4, /* col */ 10, /* state */ BS_SKIP);
  1394. }
  1395. return;
  1396. }
  1397. ///////////////////////////////////////////////////////////////////////////////
  1398. /// Method:  InitializeColors
  1399. /// Purpose: Set the color variables from the DirectDraw color masks
  1400. ///////////////////////////////////////////////////////////////////////////////
  1401. /// Receives: nothing
  1402. /// Returns:  nothing
  1403. ///////////////////////////////////////////////////////////////////////////////
  1404. void CSuperBrickBreaker::InitializeColors()
  1405. {
  1406.     m_3d_light_clr  = RGBto16BitColor(/* red */ 255, /* green */ 255, /* blue */ 255);
  1407.     m_3d_shadow_clr = RGBto16BitColor(/* red */ 132, /* green */ 130, /* blue */ 132);
  1408.     m_black_clr     = RGBto16BitColor(/* red */   0, /* green */   0, /* blue */   0);
  1409.     m_blue_clr      = RGBto16BitColor(/* red */   0, /* green */   0, /* blue */ 255);
  1410.     m_boundary_clr  = RGBto16BitColor(/* red */ 214, /* green */ 211, /* blue */ 206);
  1411.     m_green_clr     = RGBto16BitColor(/* red */   0, /* green */ 130, /* blue */   0);
  1412.     m_red_clr       = RGBto16BitColor(/* red */ 255, /* green */   0, /* blue */   0);
  1413.     m_yellow_clr    = RGBto16BitColor(/* red */ 255, /* green */ 255, /* blue */   0);
  1414.     m_white_clr     = RGBto16BitColor(/* red */ 255, /* green */ 255, /* blue */ 255);
  1415. return;
  1416. };
  1417. ///////////////////////////////////////////////////////////////////////////////
  1418. /// Method:  InitializeNewGame
  1419. /// Purpose: Reset all the game variables based on the current game type
  1420. ///////////////////////////////////////////////////////////////////////////////
  1421. /// Receives: nothing
  1422. /// Returns:  nothing
  1423. ///////////////////////////////////////////////////////////////////////////////
  1424. void CSuperBrickBreaker::InitializeNewGame()
  1425. {
  1426. m_score = 0;
  1427. m_level = 1;
  1428. switch(m_game_type)
  1429. {
  1430. case SBB_STANDARD:
  1431. {
  1432. m_num_balls = 1;
  1433. m_game_turns_remaining = 5;
  1434. } break;
  1435. case SBB_DOUBLE:
  1436. {
  1437. m_num_balls = 2;
  1438.     m_game_turns_remaining = 3;
  1439. } break;
  1440. case SBB_ESCAPE:
  1441. {
  1442. m_num_balls = 3;
  1443.     m_game_turns_remaining = 5;
  1444. } break;
  1445. }
  1446. InitializeBalls();
  1447. InitializeNewLevel();
  1448. InitializeBricks();
  1449. InitializePaddle();
  1450. };
  1451. ///////////////////////////////////////////////////////////////////////////////
  1452. /// Method:  InitializeNewLevel
  1453. /// Purpose: Intialize the bricks and balls for the start of a new level
  1454. ///////////////////////////////////////////////////////////////////////////////
  1455. /// Receives: nothing
  1456. /// Returns:  nothing
  1457. /////////////////////////////////////////////////////////////////////////////// 
  1458. void CSuperBrickBreaker::InitializeNewLevel()
  1459. {
  1460. m_brick_colors[0] = m_red_clr;
  1461. m_brick_colors[1] = m_red_clr;
  1462. m_brick_colors[2] = m_yellow_clr;
  1463. m_brick_colors[3] = m_yellow_clr;
  1464. m_brick_colors[4] = m_green_clr;
  1465. m_brick_colors[5] = m_green_clr;
  1466. m_brick_colors[6] = m_blue_clr;
  1467. m_brick_colors[7] = m_blue_clr;
  1468. if (m_level >= 3)
  1469. {
  1470. int m_stop = m_level;
  1471. if (m_level > 7)
  1472. {
  1473. m_stop = 7;
  1474. }
  1475. for (int i = 0; i < m_stop; i++)
  1476. {
  1477.     m_brick_colors[i] = m_red_clr;
  1478. }
  1479.     }
  1480. for (int i = 0; i <= 7; i++)
  1481. {
  1482. if (m_brick_colors[i] == m_red_clr)
  1483. {
  1484. m_brick_points[i] = 16;
  1485. m_brick_reflect_vel[i] = 4;
  1486. }
  1487. else if (m_brick_colors[i] == m_yellow_clr)
  1488. {
  1489. m_brick_points[i] = 8;
  1490. m_brick_reflect_vel[i] = 3;
  1491. }
  1492. else if (m_brick_colors[i] == m_green_clr)
  1493. {
  1494. m_brick_points[i] = 4;
  1495. m_brick_reflect_vel[i] = 2;
  1496. }
  1497. else if (m_brick_colors[i] == m_blue_clr)
  1498. {
  1499. m_brick_points[i] = 2;
  1500. m_brick_reflect_vel[i] = 1;
  1501. }
  1502. }
  1503. switch(m_game_type)
  1504. {
  1505. case SBB_STANDARD:
  1506. {
  1507. // no extra initialization required
  1508. } break;
  1509. case SBB_DOUBLE:
  1510. {
  1511. // no extra initialization required
  1512. } break;
  1513. case SBB_ESCAPE:
  1514. {
  1515.     m_ball[1].SetState(CAPTIVE);
  1516. m_ball[2].SetState(CAPTIVE);
  1517. } break;
  1518. }
  1519. }
  1520. ///////////////////////////////////////////////////////////////////////////////
  1521. /// Method:  InitializePaddle
  1522. /// Purpose: Set the required default paddle properties and limits
  1523. ///////////////////////////////////////////////////////////////////////////////
  1524. /// Receives: nothing
  1525. /// Returns:  nothing
  1526. ///////////////////////////////////////////////////////////////////////////////
  1527. void CSuperBrickBreaker::InitializePaddle()
  1528. {
  1529. int l_cnt = 1;
  1530. switch(m_game_type) 
  1531. {
  1532. case SBB_STANDARD:
  1533.   {
  1534.      l_cnt = PADDLE_COUNT_STANDARD;
  1535.   }
  1536.   break;
  1537. case SBB_DOUBLE:
  1538.   {
  1539.      l_cnt = PADDLE_COUNT_DOUBLE;
  1540.   }
  1541.   break;
  1542. case SBB_ESCAPE:
  1543.   {
  1544.      l_cnt = PADDLE_COUNT_ESCAPE;
  1545.   }
  1546.   break;
  1547. }
  1548. m_paddle.SetBaseProperties
  1549.      (
  1550.      /* p_cnt*/        l_cnt, 
  1551.  /* p_hor_space */ DEFAULT_PADDLE_HOR_SPACE, 
  1552.  /* p_length */    DEFAULT_PADDLE_STANDARD_LENGTH, 
  1553.  /* p_height */    DEFAULT_PADDLE_HEIGHT
  1554.  );
  1555. m_paddle.SetPaddleLimits
  1556.      (
  1557.      /* p_min_limit */    23, 
  1558.  /* p_max_limit */    776, 
  1559.  /* p_bottom_limit */ 597
  1560.   );
  1561. };
  1562. ///////////////////////////////////////////////////////////////////////////////
  1563. /// Method:  InitializePlayingArea
  1564. /// Purpose: Set the boundary (playing area) rect variables
  1565. ///////////////////////////////////////////////////////////////////////////////
  1566. /// Receives: nothing
  1567. /// Returns:  nothing
  1568. ///////////////////////////////////////////////////////////////////////////////
  1569. void CSuperBrickBreaker::InitializePlayingArea()
  1570. {
  1571.     m_left_boun_rect.left   =   0;
  1572. m_left_boun_rect.top    =  30;
  1573. m_left_boun_rect.right  =  23;
  1574. m_left_boun_rect.bottom = 599;
  1575.     m_top_boun_rect.left   =   0;
  1576. m_top_boun_rect.top    =  30;
  1577. m_top_boun_rect.right  = 799;
  1578. m_top_boun_rect.bottom =  53;
  1579. m_right_boun_rect.left   = 776;
  1580. m_right_boun_rect.top    =  30;
  1581. m_right_boun_rect.right  = 799;
  1582. m_right_boun_rect.bottom = 599;
  1583. m_left_3d_light_rect.left   =   0;
  1584. m_left_3d_light_rect.top    =  30;
  1585. m_left_3d_light_rect.right  =   1;
  1586. m_left_3d_light_rect.bottom = 599;
  1587. m_left_3d_shadow_rect.left   =  22;
  1588. m_left_3d_shadow_rect.top    =  53;
  1589. m_left_3d_shadow_rect.right  =  23;
  1590. m_left_3d_shadow_rect.bottom = 599;
  1591. m_top_3d_light_rect.left   =   0;
  1592. m_top_3d_light_rect.top    =  30;
  1593. m_top_3d_light_rect.right  = 799;
  1594. m_top_3d_light_rect.bottom =  31;
  1595. m_top_3d_shadow_rect.left   =  22;
  1596. m_top_3d_shadow_rect.top    =  52;
  1597. m_top_3d_shadow_rect.right  = 776;
  1598. m_top_3d_shadow_rect.bottom =  53;
  1599. m_right_3d_light_rect.left   = 776;
  1600. m_right_3d_light_rect.top    =  53;
  1601. m_right_3d_light_rect.right  = 777;
  1602. m_right_3d_light_rect.bottom = 599;
  1603. m_right_3d_shadow_rect.left   = 798;
  1604. m_right_3d_shadow_rect.top    =  30;
  1605. m_right_3d_shadow_rect.right  = 799;
  1606. m_right_3d_shadow_rect.bottom = 599;
  1607.     m_playing_area_rect.left = 23;
  1608. m_playing_area_rect.top = 53;
  1609. m_playing_area_rect.right = 776;
  1610. m_playing_area_rect.bottom = 598;
  1611. return;
  1612. };
  1613. ///////////////////////////////////////////////////////////////////////////////
  1614. /// Method:  IsBrickAtBallLocation
  1615. /// Purpose: Determine if a brick is currently at the location of the ball
  1616. ///////////////////////////////////////////////////////////////////////////////
  1617. /// Receives: RECT describing current position of a ball
  1618. /// Returns:  true if a brick (with a NORMAL state) exists at the ball location
  1619. ///           pointer to TBrick structure of the brick that exists at the location
  1620. ///////////////////////////////////////////////////////////////////////////////
  1621. bool CSuperBrickBreaker::IsBrickAtBallLocation(const RECT p_ball_rect, TBrick* l_hit_brick)
  1622. {
  1623. TBallCorner l_ball_corner[4];
  1624. EIntersect  l_result = IS_NONE;
  1625. /*************************
  1626. ** top left corner
  1627. *************************/
  1628. l_ball_corner[0].x = p_ball_rect.left;
  1629. l_ball_corner[0].y = p_ball_rect.top;
  1630.     /*************************
  1631. ** top right corner
  1632. *************************/
  1633. l_ball_corner[1].x = p_ball_rect.right;
  1634. l_ball_corner[1].y = p_ball_rect.top;
  1635. /*************************
  1636. ** bottom right corner
  1637. *************************/
  1638. l_ball_corner[2].x = p_ball_rect.right;
  1639. l_ball_corner[2].y = p_ball_rect.bottom;
  1640. /*************************
  1641. ** bottom left corner
  1642. *************************/
  1643. l_ball_corner[3].x = p_ball_rect.left;
  1644. l_ball_corner[3].y = p_ball_rect.bottom;
  1645. int  j = 0;
  1646. ///////////////////////////////////////////////////////////////////////////
  1647. /// loop through each of the ball corners to determine if the ball 
  1648. /// struck the paddle
  1649. ///////////////////////////////////////////////////////////////////////////
  1650. while (j < 4)
  1651. {
  1652. bool l_is_brick = m_bricks.IsBrickAtPosition
  1653.          (
  1654.          /* x */     l_ball_corner[j].x, 
  1655.  /* y */     l_ball_corner[j].y, 
  1656.  /* brick */ l_hit_brick 
  1657.  );
  1658. if (l_is_brick)
  1659. {
  1660. if (( (l_ball_corner[j].x >= l_hit_brick->rect.left) && (l_ball_corner[j].x <= l_hit_brick->rect.right) )
  1661.     &&  ( (l_ball_corner[j].y >= l_hit_brick->rect.top)  && (l_ball_corner[j].y <= l_hit_brick->rect.bottom) )
  1662. && (l_hit_brick->state == BS_NORMAL) )
  1663. {
  1664.     return(true);
  1665. }
  1666. }
  1667. j++;
  1668. }
  1669. return(false);
  1670. }
  1671. ///////////////////////////////////////////////////////////////////////////////
  1672. /// Method:  ProcessBalls
  1673. /// Purpose: Set the 'ball' variables for the next frame
  1674. ///////////////////////////////////////////////////////////////////////////////
  1675. /// Receives: nothing
  1676. /// Returns:  true if the balls were handled (moved) successfully
  1677. ///////////////////////////////////////////////////////////////////////////////
  1678. bool CSuperBrickBreaker::ProcessBalls()
  1679. {
  1680. bool br = false;
  1681. if (m_game_state == GS_GAMEPAUSED)
  1682. {
  1683. return(true);
  1684. }
  1685. ///////////////////////////////////////////////////////////////////////////
  1686. /// loop through each ball
  1687. ///////////////////////////////////////////////////////////////////////////
  1688.     for (int i = 0; i < m_num_balls; i++)
  1689. {
  1690. int l_x_pos = m_ball[i].GetXPos();
  1691. int l_y_pos = m_ball[i].GetYPos();
  1692. int l_x_vel = m_ball[i].GetVelMultiplier() * m_ball[i].GetXVel();
  1693. int l_y_vel = m_ball[i].GetVelMultiplier() * m_ball[i].GetYVel();
  1694. RECT l_ball_rect;
  1695. EBallState l_ball_state = m_ball[i].GetState();
  1696. EIntersect l_intersect = IS_NONE;
  1697. if ( (l_ball_state == FREE) || (l_ball_state == CAPTIVE) )
  1698. {
  1699. ///////////////////////////////////////////////////////////////////////
  1700. /// set new ball position based on current velocity
  1701. ///////////////////////////////////////////////////////////////////////
  1702. l_x_pos += l_x_vel;
  1703. l_y_pos += l_y_vel;
  1704. m_ball[i].SetXYPos(l_x_pos, l_y_pos);
  1705. l_ball_rect.top    = l_y_pos;
  1706. l_ball_rect.left   = l_x_pos;
  1707. l_ball_rect.right  = l_x_pos + BALL_WIDTH;
  1708. l_ball_rect.bottom = l_y_pos + BALL_HEIGHT;
  1709.             ///////////////////////////////////////////////////////////////////////
  1710. /// process the ball as a free ball
  1711. ///////////////////////////////////////////////////////////////////////
  1712. if (l_ball_state == FREE)
  1713. {
  1714. ///////////////////////////////////////////////////////////////////
  1715. /// determine if the ball hit one of the playing area boundaries
  1716. ///////////////////////////////////////////////////////////////////
  1717.                 if (l_ball_rect.left <= m_playing_area_rect.left)
  1718. {
  1719. l_x_pos = m_playing_area_rect.left;
  1720. l_intersect = IS_RIGHT; // ie. intersect right side of left boundary
  1721. }
  1722.  if (l_ball_rect.right >= m_playing_area_rect.right)
  1723. {
  1724. l_x_pos = m_playing_area_rect.right - BALL_WIDTH;
  1725. l_intersect = IS_LEFT;
  1726. }
  1727.  if (l_ball_rect.top <= m_playing_area_rect.top)
  1728. {
  1729. l_y_pos = m_playing_area_rect.top;
  1730. l_intersect = IS_BOTTOM;
  1731. if (!m_hit_top_boun_fg)
  1732. {
  1733. m_hit_top_boun_fg = true;
  1734. m_paddle.SetLength(DEFAULT_PADDLE_SHORT_LENGTH);
  1735. }
  1736. }
  1737.  if (l_ball_rect.bottom >= m_playing_area_rect.bottom)
  1738. {
  1739. --m_balls_in_play;
  1740. m_ball[i].SetState(LOST);
  1741. if (m_balls_in_play == 0)
  1742. {
  1743. if (m_game_turns_remaining == 0)
  1744. {
  1745. ProcessStateChange(/* new state */ GS_GAMEOVER);
  1746. return(true);
  1747. }
  1748. else
  1749. {
  1750. --m_game_turns_remaining;
  1751. ProcessStateChange(/* new state */ GS_STARTTURN);
  1752. return(true);
  1753. }
  1754. }
  1755. }
  1756. ///////////////////////////////////////////////////////////////////
  1757. /// determine if the ball hit the paddle
  1758. ///////////////////////////////////////////////////////////////////
  1759. if (l_intersect == IS_NONE) // didn't hit the boundary
  1760. {
  1761. l_intersect = CheckHitPaddle(l_ball_rect);
  1762. if (l_intersect != IS_NONE)
  1763. {
  1764. // if we are playing 'Double' release the second ball on
  1765. // first hit of the paddle
  1766. if ( (!m_first_paddle_hit) && (m_game_type == SBB_DOUBLE) )
  1767. {
  1768. m_first_paddle_hit = true;
  1769. if (m_game_type == SBB_DOUBLE)
  1770. {
  1771. m_ball[1].SetState(FREE);
  1772. m_balls_in_play++;
  1773. }
  1774. }
  1775. }
  1776. }
  1777. ///////////////////////////////////////////////////////////////////
  1778. /// determine if the ball hit a brick
  1779. ///////////////////////////////////////////////////////////////////
  1780. if (l_intersect == IS_NONE) // didn't hit boundary or paddle
  1781. {
  1782. TBrick l_hit_brick;
  1783. l_intersect = CheckHitBrick(l_ball_rect, &l_hit_brick);
  1784. if (l_intersect != IS_NONE)
  1785. {
  1786. m_bricks.SetBrickState(l_hit_brick.row, l_hit_brick.col, BS_HIT);
  1787. m_score += l_hit_brick.point_value;
  1788. if (m_ball[i].GetVelMultiplier() > l_hit_brick.reflect_vel)
  1789. {
  1790. m_ball[i].SetVelMultiplier(m_ball[i].GetVelMultiplier() - 1);
  1791. }
  1792. else
  1793. {
  1794. m_ball[i].SetVelMultiplier(l_hit_brick.reflect_vel);
  1795. }
  1796. if (m_bricks.GetBricksRemaining() == 0)
  1797. {
  1798. m_new_level_fg = true;
  1799. m_level++;
  1800. InitializeNewLevel();
  1801. InitializeBalls();
  1802. InitializeBricks();
  1803. ProcessStateChange(/* new state */ GS_STARTTURN);
  1804. return(true);
  1805. }
  1806. }
  1807. }
  1808. if (l_intersect != IS_NONE)
  1809. {
  1810. m_ball[i].SetXYPos(l_x_pos, l_y_pos);
  1811. }
  1812. }
  1813. ///////////////////////////////////////////////////////////////////////
  1814. /// process the ball as a captive ball
  1815. ///////////////////////////////////////////////////////////////////////
  1816. else if (l_ball_state == CAPTIVE)
  1817. {
  1818. RECT   l_captive_rect = m_ball[i].GetCaptiveRect();
  1819. TBrick l_hit_brick;
  1820. int l_temp_x = 0;
  1821. int l_temp_y = 0;
  1822. if (l_ball_rect.left <= l_captive_rect.left)
  1823. {
  1824. l_intersect = IS_RIGHT;
  1825. l_temp_x = l_captive_rect.left;
  1826. l_temp_y = l_y_pos;
  1827. }
  1828. else if (l_ball_rect.top <= l_captive_rect.top)
  1829. {
  1830. l_intersect = IS_BOTTOM;
  1831. l_temp_x = l_x_pos;
  1832. l_temp_y = l_captive_rect.top;
  1833. }
  1834. else if (l_ball_rect.right >= l_captive_rect.right)
  1835. {
  1836. l_intersect = IS_LEFT;
  1837. l_temp_x = (l_captive_rect.right - BALL_WIDTH);
  1838. l_temp_y = l_y_pos;
  1839. }
  1840. else if (l_ball_rect.bottom >= l_captive_rect.bottom)
  1841. {
  1842. l_intersect = IS_TOP;
  1843. l_temp_x = l_x_pos;
  1844. l_temp_y = (l_captive_rect.bottom - BALL_HEIGHT);
  1845. }
  1846. if (l_intersect != IS_NONE)
  1847. {
  1848. bool l_is_brick = IsBrickAtBallLocation(l_ball_rect, &l_hit_brick);
  1849. if (l_is_brick)
  1850. {
  1851. if (l_hit_brick.state == BS_NORMAL)
  1852. {
  1853. // ball is still captive, set position to hit boundary
  1854. m_ball[i].SetXYPos(l_temp_x, l_temp_y);
  1855. }
  1856. else if (l_hit_brick.state == BS_NORMAL)
  1857. {
  1858. m_ball[i].SetState(FREE);
  1859. m_balls_in_play++;
  1860. }
  1861. }
  1862. else 
  1863. {
  1864. l_intersect = IS_NONE;
  1865. m_ball[i].SetState(FREE);
  1866. m_balls_in_play++;
  1867. }
  1868. }
  1869. }
  1870. if ( (l_intersect == IS_TOP) || (l_intersect == IS_BOTTOM) )
  1871. {
  1872.     m_ball[i].ReflectY();
  1873. }
  1874. else if ( (l_intersect == IS_LEFT) || (l_intersect == IS_RIGHT) )
  1875. {
  1876.     m_ball[i].ReflectX();
  1877. }
  1878. }
  1879. }
  1880. return(true);
  1881. };
  1882. ///////////////////////////////////////////////////////////////////////////////
  1883. /// Method:  ProcessKeyboard
  1884. /// Purpose: Process the DirectInput keyboard state information based 
  1885. ///          the current state of the game
  1886. ///////////////////////////////////////////////////////////////////////////////
  1887. /// Receives: nothing
  1888. /// Returns:  nothing
  1889. ///////////////////////////////////////////////////////////////////////////////
  1890. bool CSuperBrickBreaker::ProcessKeyboard()
  1891. {
  1892. bool br = false;
  1893. ///////////////////////////////////////////////////////////////////////////
  1894. /// retrieve the keyboard data from DirectInput
  1895. ///////////////////////////////////////////////////////////////////////////
  1896. br = GetKeyboardState(m_key_state);
  1897. if (!br)
  1898. {
  1899. return(false);
  1900. }
  1901. ///////////////////////////////////////////////////////////////////////////
  1902. /// interpret the keyboard data based on the current state
  1903. /// of the game
  1904. ///////////////////////////////////////////////////////////////////////////
  1905. switch(m_game_state)
  1906. {
  1907. case GS_MAINMENU:  /// the main menu is currently displayed to the player
  1908. {
  1909. ///////////////////////////////////////////////////////////////////////////
  1910.         /// user pressed escape --> end the game
  1911.         ///////////////////////////////////////////////////////////////////////////
  1912.             if (m_key_state[DIK_ESCAPE] & 0x80)
  1913. {
  1914. PostQuitMessage(0);
  1915. }
  1916.             ///////////////////////////////////////////////////////////////////////////
  1917.         /// user pressed up arrow --> set next game type
  1918.         ///////////////////////////////////////////////////////////////////////////
  1919. else if (m_key_state[DIK_UP] & 0x80)
  1920. {
  1921. switch(m_game_type)
  1922. {
  1923. case SBB_STANDARD:
  1924. {
  1925. m_game_type = SBB_ESCAPE;
  1926. } break;
  1927. case SBB_DOUBLE:
  1928. {
  1929. m_game_type = SBB_STANDARD;
  1930. } break;
  1931. case SBB_ESCAPE:
  1932. {
  1933. m_game_type = SBB_DOUBLE;
  1934. } break;
  1935. }
  1936. InitializeNewGame();
  1937. }
  1938. ///////////////////////////////////////////////////////////////////////////
  1939.         /// user pressed down arrow --> set next game type
  1940.         ///////////////////////////////////////////////////////////////////////////
  1941.             else if (m_key_state[DIK_DOWN] & 0x80)
  1942. {
  1943. switch(m_game_type)
  1944. {
  1945. case SBB_STANDARD:
  1946. {
  1947. m_game_type = SBB_DOUBLE;
  1948. } break;
  1949. case SBB_DOUBLE:
  1950. {
  1951. m_game_type = SBB_ESCAPE;
  1952. } break;
  1953. case SBB_ESCAPE:
  1954. {
  1955. m_game_type = SBB_STANDARD;
  1956. } break;
  1957. }
  1958. InitializeNewGame();
  1959. }
  1960. ///////////////////////////////////////////////////////////////////////////
  1961.         /// user pressed return or space bar --> start game based 
  1962. /// on currently selected game
  1963.         ///////////////////////////////////////////////////////////////////////////
  1964. else if ( (m_key_state[DIK_RETURN] & 0x80) || (m_key_state[DIK_SPACE] & 0x80) )
  1965. {
  1966. --m_game_turns_remaining;
  1967.                 br = ProcessStateChange(/* new state */ GS_STARTTURN);
  1968. if (!br)
  1969. {
  1970. return(false);
  1971. }
  1972. }
  1973. } break;
  1974. case GS_STARTTURN: /// the READY message is displayed to warn player of start
  1975.                /// of the next turn (or start of the game)
  1976. {
  1977. ///////////////////////////////////////////////////////////////////////////
  1978.         /// user pressed return or space bar --> move into game play state
  1979.         ///////////////////////////////////////////////////////////////////////////
  1980. if ( (m_key_state[DIK_RETURN] & 0x80) || (m_key_state[DIK_SPACE] & 0x80) )
  1981. {
  1982.                 br = ProcessStateChange(/* new state */ GS_GAMEPLAY);
  1983. if (!br)
  1984. {
  1985. return(false);
  1986. }
  1987. }
  1988. } break;
  1989. case GS_GAMEPLAY:  /// we are in a 'general' state of play (ie. the balls are 
  1990.                /// still in play and there are bricks remaining
  1991. {
  1992.             ///////////////////////////////////////////////////////////////////////////
  1993.         /// user pressed escape --> go to 'game paused' state
  1994.         ///////////////////////////////////////////////////////////////////////////
  1995.             if (m_key_state[DIK_ESCAPE] & 0x80)
  1996. {
  1997. br = ProcessStateChange(/* new state */ GS_GAMEPAUSED);
  1998. if (!br)
  1999. {
  2000. return(false);
  2001. }
  2002. //PostQuitMessage(0);
  2003. }
  2004. ///////////////////////////////////////////////////////////////////////////
  2005.         /// user pressed left arrow --> set negative paddle velocity
  2006.         ///////////////////////////////////////////////////////////////////////////
  2007. if (m_key_state[DIK_LEFT] & 0x80)
  2008. {
  2009. m_paddle.SetXVel(-PADDLE_VELOCITY);
  2010. }
  2011. ///////////////////////////////////////////////////////////////////////////
  2012.         /// user pressed right arrow --> set positive paddle velocity
  2013.         ///////////////////////////////////////////////////////////////////////////
  2014. else if (m_key_state[DIK_RIGHT] & 0x80)
  2015. {
  2016. m_paddle.SetXVel(PADDLE_VELOCITY);
  2017. }
  2018. } break;
  2019. case GS_GAMEPAUSED:
  2020. {
  2021.             ///////////////////////////////////////////////////////////////////////////
  2022.         /// user pressed up arrow --> set next paused menu selection
  2023.         ///////////////////////////////////////////////////////////////////////////
  2024. if (m_key_state[DIK_UP] & 0x80)
  2025. {
  2026. switch(m_paused_state)
  2027. {
  2028. case PS_RESUME:
  2029. {
  2030. m_paused_state = PS_MAINMENU;
  2031. } break;
  2032. case PS_MAINMENU:
  2033. {
  2034. m_paused_state = PS_RESUME;
  2035. } break;
  2036. }
  2037. }
  2038. ///////////////////////////////////////////////////////////////////////////
  2039.         /// user pressed down arrow --> set next game type
  2040.         ///////////////////////////////////////////////////////////////////////////
  2041.             else if (m_key_state[DIK_DOWN] & 0x80)
  2042. {
  2043. switch(m_paused_state)
  2044. {
  2045. case PS_RESUME:
  2046. {
  2047. m_paused_state = PS_MAINMENU;
  2048. } break;
  2049. case PS_MAINMENU:
  2050. {
  2051. m_paused_state = PS_RESUME;
  2052. } break;
  2053. }
  2054. }
  2055. ///////////////////////////////////////////////////////////////////////////
  2056.         /// user pressed return or space bar --> take next action based
  2057. /// on selected option
  2058.         ///////////////////////////////////////////////////////////////////////////
  2059. else if ( (m_key_state[DIK_RETURN] & 0x80) || (m_key_state[DIK_SPACE] & 0x80) )
  2060. {
  2061. switch(m_paused_state)
  2062. {
  2063. case PS_RESUME:
  2064. {
  2065. br = ProcessStateChange(/* new state */ GS_GAMEPLAY);
  2066. if (!br)
  2067. {
  2068. return(false);
  2069. }
  2070. } break;
  2071. case PS_MAINMENU:
  2072. {
  2073. br = ProcessStateChange(/* new state */ GS_MAINMENU);
  2074. if (!br)
  2075. {
  2076. return(false);
  2077. }
  2078. } break;
  2079. }
  2080. }
  2081. } break;
  2082. case GS_GAMEOVER:
  2083. {
  2084.             ///////////////////////////////////////////////////////////////////////////
  2085.         /// user pressed up arrow --> set next game over menu selection
  2086.         ///////////////////////////////////////////////////////////////////////////
  2087. if (m_key_state[DIK_UP] & 0x80)
  2088. {
  2089. switch(m_gameover_state)
  2090. {
  2091. case GO_PLAYAGAIN:
  2092. {
  2093. m_gameover_state = GO_MAINMENU;
  2094. } break;
  2095. case GO_MAINMENU:
  2096. {
  2097. m_gameover_state = GO_PLAYAGAIN;
  2098. } break;
  2099. }
  2100. }
  2101. ///////////////////////////////////////////////////////////////////////////
  2102.         /// user pressed down arrow --> set next game type
  2103.         ///////////////////////////////////////////////////////////////////////////
  2104.             else if (m_key_state[DIK_DOWN] & 0x80)
  2105. {
  2106. switch(m_gameover_state)
  2107. {
  2108. case GO_PLAYAGAIN:
  2109. {
  2110. m_gameover_state = GO_MAINMENU;
  2111. } break;
  2112. case GO_MAINMENU:
  2113. {
  2114. m_gameover_state = GO_PLAYAGAIN;
  2115. } break;
  2116. }
  2117. }
  2118. ///////////////////////////////////////////////////////////////////////////
  2119.         /// user pressed return or space bar --> take next action based
  2120. /// on selected option
  2121.         ///////////////////////////////////////////////////////////////////////////
  2122. else if ( (m_key_state[DIK_RETURN] & 0x80) || (m_key_state[DIK_SPACE] & 0x80) )
  2123. {
  2124. switch(m_gameover_state)
  2125. {
  2126. case GO_PLAYAGAIN:
  2127. {
  2128. InitializeNewGame();
  2129. br = ProcessStateChange(/* new state */ GS_STARTTURN);
  2130. if (!br)
  2131. {
  2132. return(false);
  2133. }
  2134. } break;
  2135. case GO_MAINMENU:
  2136. {
  2137. InitializeNewGame();
  2138. br = ProcessStateChange(/* new state */ GS_MAINMENU);
  2139. if (!br)
  2140. {
  2141. return(false);
  2142. }
  2143. } break;
  2144. }
  2145. }
  2146. } break;
  2147.     default: 
  2148. {
  2149. }
  2150. };
  2151. return(true);
  2152. }
  2153. ///////////////////////////////////////////////////////////////////////////////
  2154. /// Method:  ProcessPaddle
  2155. /// Purpose: Set the 'paddle' variables for the next frame
  2156. ///////////////////////////////////////////////////////////////////////////////
  2157. /// Receives: nothing
  2158. /// Returns:  true if the paddle was handled (moved) successfully
  2159. ///////////////////////////////////////////////////////////////////////////////
  2160. bool CSuperBrickBreaker::ProcessPaddle()
  2161. {
  2162.     ///////////////////////////////////////////////////////////////////////////
  2163. /// retrieve the current paddle position and velocity values
  2164. ///////////////////////////////////////////////////////////////////////////
  2165. int l_x_pos = m_paddle.GetXPos();
  2166. int l_x_vel = m_paddle.GetXVel();
  2167. int l_length = m_paddle.GetLength();
  2168. int l_paddle_right = (l_x_pos + l_length);
  2169. ///////////////////////////////////////////////////////////////////////////
  2170. /// set new paddle position based on current velocity
  2171. ///////////////////////////////////////////////////////////////////////////
  2172. l_x_pos += l_x_vel;
  2173. ///////////////////////////////////////////////////////////////////////////
  2174. /// ensure new paddle position is within game playing area
  2175. ///////////////////////////////////////////////////////////////////////////
  2176. if (l_x_vel < 0) // we are moving to the left
  2177. {
  2178. if (l_x_pos < m_playing_area_rect.left)
  2179. {
  2180. l_x_pos = m_playing_area_rect.left;
  2181. }
  2182. }
  2183.     else if (l_x_vel > 0) // we are moving to the right
  2184. {
  2185. if (l_paddle_right >= m_playing_area_rect.right)
  2186. {
  2187. l_x_pos = (m_playing_area_rect.right - l_length);
  2188. }
  2189. }
  2190. ///////////////////////////////////////////////////////////////////////////
  2191. /// move paddle to new location and reset velocity to zero
  2192. ///////////////////////////////////////////////////////////////////////////
  2193. if (l_x_vel != 0)
  2194. {
  2195. m_paddle.SetXPos(l_x_pos); 
  2196. m_paddle.SetXVel(0);
  2197. }
  2198. return(true);
  2199. };
  2200. ///////////////////////////////////////////////////////////////////////////////
  2201. /// Method:  ProcessStateChange
  2202. /// Purpose: Check the state change is valid and set the variables for the
  2203. ///          state change
  2204. ///////////////////////////////////////////////////////////////////////////////
  2205. /// Receives: nothing
  2206. /// Returns:  true if the state change was processed (moved) successfully
  2207. ///////////////////////////////////////////////////////////////////////////////
  2208. bool CSuperBrickBreaker::ProcessStateChange(EGameState m_new_game_state)
  2209. {
  2210. EGameState l_old_state = m_game_state;
  2211. m_game_state = m_new_game_state;
  2212. switch(m_new_game_state)
  2213. {
  2214. case GS_MAINMENU:
  2215. {
  2216. SetFrameRate(10);
  2217. InitializeNewGame();
  2218. } break;
  2219. case GS_STARTTURN:
  2220. {
  2221. if (m_game_state == GS_GAMEPAUSED)
  2222. {
  2223. InitializeNewGame();
  2224. }
  2225. SetFrameRate(10);
  2226. InitializeBalls();
  2227. InitializePaddle();
  2228. } break;
  2229. case GS_GAMEPLAY:
  2230. {
  2231. m_ball[0].SetState(FREE);
  2232. SetFrameRate(20);
  2233. m_balls_in_play = 1;
  2234. } break;
  2235. case GS_GAMEPAUSED:
  2236. {
  2237. SetFrameRate(10);
  2238. m_paused_state = PS_RESUME;
  2239. } break;
  2240. case GS_GAMEOVER:
  2241. {
  2242. m_gameover_state = GO_PLAYAGAIN;
  2243. for (int i = 0; i < m_num_balls; i++)
  2244. {
  2245. if (m_ball[i].GetState() == FREE)
  2246. {
  2247. m_ball[i].SetState(IDLE);
  2248. }
  2249. }
  2250. SetFrameRate(10);
  2251. }
  2252. }
  2253. return(true);
  2254. }
  2255. /// END OF FILE ///////////////////////////////////////////////////////////////