PongGame.cpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. * Copyright (c) 2011 Nokia Corporation.
  3. */
  4. #include <stdlib.h>
  5. #include <memory.h>
  6. #include <stdio.h>
  7. #include <math.h>
  8. #include "PongApp.h"
  9. #include "PongGame.h"
  10. PongGame::PongGame(PongApp *app, bool singlepl) {
  11. singlePlayer = singlepl;
  12. pongApp = app;
  13. quitAnimation = -1.0f; // not enabled when below zero
  14. runTime = 0.0f;
  15. currentLevel = 1;
  16. currentScore = 0;
  17. displayScore = 0;
  18. if (singlePlayer) {
  19. pads[0] = new PongObject( app,PO_PLAYERPAD ); // Human player
  20. pads[1] = new PongObject( app,PO_COMPUTERPAD ); // AI player
  21. } else {
  22. pads[0] = new PongObject( app,PO_PLAYERPAD ); // Human player
  23. pads[1] = new PongObject( app,PO_PLAYERPAD2 ); // Second human player.
  24. };
  25. ball = new PongObject( app, PO_BALL ); // Ball
  26. m_ballDefaultSpeed = 0.8f; // unit / sec
  27. scoreIncreaseCounter = 0;
  28. gameState = PGS_ABOUTTOSTART;
  29. stateCounter = 0.0f;
  30. resetBall();
  31. }
  32. PongGame::~PongGame() {
  33. if (ball) delete ball;
  34. if (pads[0]) delete pads[0];
  35. if (pads[1]) delete pads[1];
  36. }
  37. void PongGame::levelCompleted() {
  38. if (gameState != PGS_RUNNING) return;
  39. pongApp->getGameEngine()->stopSensors();
  40. pongApp->playSoundEffect( pongApp->sampleLevelCompleted, 1.0f );
  41. stateCounter = 0.0f;
  42. if (singlePlayer) {
  43. gameState = PGS_LEVELFINISHED;
  44. } else {
  45. // game over, player 1 wins
  46. gameState = PGS_2PL_PLAYER1WINS;
  47. };
  48. }
  49. void PongGame::gameOver() {
  50. if (gameState != PGS_RUNNING) return;
  51. pongApp->getGameEngine()->stopSensors();
  52. pongApp->playSoundEffect( pongApp->sampleGameOver, 1.0f );
  53. stateCounter = 0.0f;
  54. if (singlePlayer) {
  55. gameState = PGS_GAMEOVER;
  56. } else {
  57. // game over, player 2 wins
  58. gameState = PGS_2PL_PLAYER2WINS;
  59. };
  60. }
  61. void PongGame::resetBall() {
  62. memset( ball->direction(), 0, sizeof( float ) * 3 );
  63. memset( ball->position(), 0, sizeof( float ) * 3 );
  64. ball->position()[0] = -0.1f + (rand() & 255)*0.2f / 255.0f;
  65. }
  66. bool PongGame::update( const float frameTime,
  67. bool *buttons, float *pointerX, float *pointerY ) {
  68. runTime += frameTime;
  69. if (quitAnimation>=0.0f) {
  70. quitAnimation += frameTime;
  71. if (quitAnimation>=1.0f) return false; // die
  72. };
  73. scoreIncreaseCounter++;
  74. if (scoreIncreaseCounter>4) {
  75. displayScore = currentScore*3/4 + displayScore/4;
  76. if (displayScore<currentScore) displayScore++;
  77. scoreIncreaseCounter = 0;
  78. }
  79. // Button more right will be the one controlling Pad2.
  80. int leftButton = -1;
  81. int rightButton = -1;
  82. if (buttons[0]) {
  83. if (pointerX[0]<-0.2f) leftButton = 0;
  84. if (pointerX[0]>0.2f) rightButton = 0;
  85. };
  86. if (buttons[1]) {
  87. if (pointerX[1]<-0.2f && (pointerX[1]<pointerX[0] || leftButton==-1)) leftButton = 1;
  88. if (pointerX[1]>0.2f && (pointerX[1]>pointerX[0] || rightButton==-1)) rightButton = 1;
  89. };
  90. if (leftButton!=-1) {
  91. pads[0]->update( frameTime, ball, buttons[leftButton], pointerX[leftButton], pointerY[leftButton] );
  92. } else
  93. pads[0]->update( frameTime, ball );
  94. if (rightButton!=-1)
  95. pads[1]->update( frameTime, ball, buttons[rightButton], pointerX[rightButton], pointerY[rightButton] );
  96. else
  97. pads[1]->update( frameTime, ball );
  98. ball->update( frameTime, 0 );
  99. pads[0]->ballHitCheck( frameTime, ball );
  100. pads[1]->ballHitCheck( frameTime, ball );
  101. stateCounter += frameTime;
  102. switch (gameState) {
  103. case PGS_LEVELFINISHED:
  104. if (buttons[0] && !exbuttonDown) {
  105. // Give some scores for clearing the level
  106. currentScore += (currentLevel)*100;
  107. m_ballDefaultSpeed+=0.1f;
  108. currentLevel++;
  109. gameState = PGS_ABOUTTOSTART;
  110. stateCounter = 0.0f;
  111. exbuttonDown = true;
  112. return true;
  113. };
  114. break;
  115. case PGS_ABOUTTOSTART:
  116. if (buttons[0] && !exbuttonDown) {
  117. gameState = PGS_RUNNING;
  118. pongApp->getGameEngine()->startSensors();
  119. resetBall();
  120. stateCounter = 0.0f;
  121. exbuttonDown = true;
  122. return true;
  123. };
  124. break;
  125. case PGS_GAMEOVER:
  126. case PGS_2PL_PLAYER1WINS:
  127. case PGS_2PL_PLAYER2WINS:
  128. if (buttons[0] && !exbuttonDown && quitAnimation<0.0f) {
  129. /*
  130. gameState = PGS_ABOUTTOSTART;
  131. resetBall();
  132. displayScore = 0;
  133. currentScore = 0;
  134. currentLevel = 1;
  135. stateCounter = 0.0f;
  136. exbuttonDown = true;
  137. */
  138. quitAnimation = 0.0f;
  139. return true;
  140. };
  141. break;
  142. case PGS_RUNNING:
  143. {
  144. // if ball's horizontal speed is too slow
  145. // push ball away from horizontal centre
  146. if (fabsf(ball->direction()[0]) < 0.2f) {
  147. float to_x_center = fabsf(ball->position()[0]);
  148. float d = 1.0f - to_x_center;
  149. if (d>0.0f) {
  150. //d*=0.1f;
  151. if (ball->position()[0] < 0.0f)
  152. ball->direction()[0] -= d *frameTime;
  153. else
  154. ball->direction()[0] += d *frameTime;
  155. };
  156. }
  157. // Control the ball's speed
  158. float *ballDir = ball->direction();
  159. float ballSpeed = sqrtf( ballDir[0] * ballDir[0] + ballDir[1] * ballDir[1] );
  160. //if (ballSpeed>m_ballDefaultSpeed) {
  161. float newSpeed = ballSpeed + (m_ballDefaultSpeed - ballSpeed) * frameTime*2.0f;
  162. ballDir[0] = ballDir[0] / ballSpeed * newSpeed;
  163. ballDir[1] = ballDir[1] / ballSpeed * newSpeed;
  164. //};
  165. break;
  166. }
  167. }
  168. exbuttonDown = buttons[0];
  169. return true;
  170. }
  171. void PongGame::render() {
  172. float vis = runTime;
  173. if (vis>1.0f) vis = 1.0f;
  174. if (quitAnimation>=0.0f) vis-=quitAnimation;
  175. pads[0]->render(vis);
  176. pads[1]->render(vis);
  177. ball->render(vis);
  178. char testr[64];
  179. FontWriter *writer = pongApp->getFontWriter();
  180. float a = stateCounter;
  181. if (a>1.0f) a = 1.0f;
  182. writer->setColor( 1.0f,
  183. 1.0f,
  184. 1.0f,
  185. vis);
  186. if (singlePlayer) {
  187. sprintf(testr, "level %.3d score %.5d", currentLevel, displayScore );
  188. } else {
  189. sprintf(testr, "2player fight" );
  190. };
  191. writer->writeText(testr, -0.85f, pongApp->getTop()-0.05f, 0.04f );
  192. switch (gameState) {
  193. case PGS_RUNNING:
  194. break;
  195. case PGS_2PL_PLAYER1WINS:
  196. strcpy(testr, "player 1 wins" );
  197. writer->setColor( 1.0f, 1.0f, 1.0f, a );
  198. a/=12.0f;
  199. writer->writeText( testr, -writer->getTextWidth(testr,a)/2.0f, 0.0f, a );
  200. break;
  201. case PGS_2PL_PLAYER2WINS:
  202. strcpy(testr, "player 2 wins" );
  203. writer->setColor( 1.0f, 1.0f, 1.0f, a );
  204. a/=12.0f;
  205. writer->writeText( testr, -writer->getTextWidth(testr,a)/2.0f, 0.0f, a );
  206. break;
  207. case PGS_ABOUTTOSTART:
  208. if ( singlePlayer )
  209. sprintf(testr, "level %d start", currentLevel );
  210. else
  211. strcpy(testr, "fight!");
  212. writer->setColor( 1.0f, 1.0f, 1.0f, a );
  213. a/=12.0f;
  214. writer->writeText( testr, -writer->getTextWidth(testr,a)/2.0f, 0.0f, a );
  215. break;
  216. case PGS_LEVELFINISHED:
  217. sprintf(testr, "level complete" );
  218. writer->setColor( 1.0f, 1.0f, 1.0f, a );
  219. a/=12.0f;
  220. writer->writeText( testr, -writer->getTextWidth(testr,a)/2.0f, 0.0f, a );
  221. break;
  222. case PGS_GAMEOVER:
  223. strcpy(testr, "game over" );
  224. writer->setColor( 1.0f, 1.0f, 1.0f, a );
  225. a/=12.0f;
  226. writer->writeText( testr, -writer->getTextWidth(testr,a)/2.0f, 0.0f, a );
  227. break;
  228. }
  229. }