SFML Pong, but object oriented

pong.cpp 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. ////////////////////////////////////////////////////////////
  2. // Headers
  3. ////////////////////////////////////////////////////////////
  4. #include <SFML/Graphics.hpp>
  5. #include <SFML/Audio.hpp>
  6. #include <cmath>
  7. #include <ctime>
  8. #include <cstdlib>
  9. #include "Ball.h"
  10. #include "Paddle.h"
  11. #ifdef SFML_SYSTEM_IOS
  12. #include <SFML/Main.hpp>
  13. #endif
  14. using namespace std;
  15. string resourcesDir()
  16. {
  17. #ifdef SFML_SYSTEM_IOS
  18. return "";
  19. #else
  20. return "resources/";
  21. #endif
  22. }
  23. ////////////////////////////////////////////////////////////
  24. /// Entry point of application
  25. ///
  26. /// \return Application exit code
  27. ///
  28. ////////////////////////////////////////////////////////////
  29. int main()
  30. {
  31. srand(static_cast<unsigned int>(time(NULL)));
  32. // Define some constants
  33. const float pi = 3.1415;
  34. const int gameWidth = 800;
  35. const int gameHeight = 600;
  36. // Create the window of the application
  37. sf::RenderWindow window(sf::VideoMode(gameWidth, gameHeight, 32), "SFML Pong",
  38. sf::Style::Titlebar | sf::Style::Close);
  39. window.setVerticalSyncEnabled(true);
  40. // Load the sounds used in the game
  41. sf::SoundBuffer ballSoundBuffer;
  42. if (!ballSoundBuffer.loadFromFile(resourcesDir() + "ball.wav"))
  43. return EXIT_FAILURE;
  44. sf::Sound ballSound(ballSoundBuffer);
  45. // Create the left paddle
  46. Paddle leftPaddle;
  47. // Create the right paddle
  48. Paddle rightPaddle;
  49. // Create the ball
  50. Ball ball;
  51. // Load the text font
  52. sf::Font font;
  53. if (!font.loadFromFile(resourcesDir() + "sansation.ttf"))
  54. return EXIT_FAILURE;
  55. // Initialize the pause message
  56. sf::Text pauseMessage;
  57. pauseMessage.setFont(font);
  58. pauseMessage.setCharacterSize(40);
  59. pauseMessage.setPosition(170, 150);
  60. //pauseMessage.setFillColor(sf::Color::White);
  61. #ifdef SFML_SYSTEM_IOS
  62. pauseMessage.setString("Welcome to SFML pong!\nTouch the screen to start the game");
  63. #else
  64. pauseMessage.setString("Welcome to SFML pong!\nPress space to start the game");
  65. #endif
  66. // Define the paddles properties
  67. sf::Clock AITimer;
  68. const sf::Time AITime = sf::seconds(0.1f);
  69. const float paddleSpeed = 400.f;
  70. float rightPaddleSpeed = 0.f;
  71. float ballAngle = 0.f; // to be changed later
  72. sf::Clock clock;
  73. bool isPlaying = false;
  74. while (window.isOpen())
  75. {
  76. // Handle events
  77. sf::Event event;
  78. while (window.pollEvent(event))
  79. {
  80. // Window closed or escape key pressed: exit
  81. if ((event.type == sf::Event::Closed) ||
  82. ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
  83. {
  84. window.close();
  85. break;
  86. }
  87. // Space key pressed: play
  88. if (((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) ||
  89. (event.type == sf::Event::TouchBegan))
  90. {
  91. if (!isPlaying)
  92. {
  93. // (re)start the game
  94. isPlaying = true;
  95. clock.restart();
  96. // Reset the position of the paddles and ball
  97. leftPaddle.setPosition(10 + leftPaddle.getSize().x / 2, gameHeight / 2);
  98. rightPaddle.setPosition(gameWidth - 10 - leftPaddle.getSize().x / 2, gameHeight / 2);
  99. ball.setPosition(gameWidth / 2, gameHeight / 2);
  100. // Reset the ball angle
  101. do
  102. {
  103. // Make sure the ball initial angle is not too much vertical
  104. ballAngle = (rand() % 360) * 2 * pi / 360;
  105. }
  106. while (abs(cos(ballAngle)) < 0.7f);
  107. }
  108. }
  109. // Window size changed, adjust view appropriately
  110. if (event.type == sf::Event::Resized)
  111. {
  112. sf::View view;
  113. view.setSize(gameWidth, gameHeight);
  114. view.setCenter(gameWidth/2.f, gameHeight/2.f);
  115. window.setView(view);
  116. }
  117. }
  118. if (isPlaying)
  119. {
  120. float deltaTime = clock.restart().asSeconds();
  121. // Move the player's paddle
  122. if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) &&
  123. (leftPaddle.getY() - leftPaddle.getSize().y / 2 > 5))
  124. {
  125. leftPaddle.move(0.f, -paddleSpeed * deltaTime);
  126. }
  127. if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) &&
  128. (leftPaddle.getY() + leftPaddle.getSize().y / 2 < gameHeight - 5))
  129. {
  130. leftPaddle.move(0.f, paddleSpeed * deltaTime);
  131. }
  132. if (sf::Touch::isDown(0))
  133. {
  134. sf::Vector2i pos = sf::Touch::getPosition(0);
  135. sf::Vector2f mappedPos = window.mapPixelToCoords(pos);
  136. leftPaddle.setPosition(leftPaddle.getX(), mappedPos.y);
  137. }
  138. // Move the computer's paddle
  139. if (((rightPaddleSpeed < 0.f) && (rightPaddle.getY() - leftPaddle.getSize().y / 2 > 5.f)) ||
  140. ((rightPaddleSpeed > 0.f) && (rightPaddle.getY() + leftPaddle.getSize().y / 2 < gameHeight - 5.f)))
  141. {
  142. rightPaddle.move(0.f, rightPaddleSpeed * deltaTime);
  143. }
  144. // Update the computer's paddle direction according to the ball position
  145. if (AITimer.getElapsedTime() > AITime)
  146. {
  147. AITimer.restart();
  148. if (ball.getY() + ball.getRadius() > rightPaddle.getY() + leftPaddle.getSize().y / 2)
  149. rightPaddleSpeed = paddleSpeed;
  150. else if (ball.getY() - ball.getRadius() < rightPaddle.getY() - leftPaddle.getSize().y / 2)
  151. rightPaddleSpeed = -paddleSpeed;
  152. else
  153. rightPaddleSpeed = 0.f;
  154. }
  155. // Move the ball
  156. float factor = ball.getSpeed() * deltaTime;
  157. ball.move(cos(ballAngle) * factor, sin(ballAngle) * factor);
  158. #ifdef SFML_SYSTEM_IOS
  159. const string inputString = "Touch the screen to restart";
  160. #else
  161. const string inputString = "Press space to restart or\nescape to exit";
  162. #endif
  163. // Check collisions between the ball and the screen
  164. if (ball.getX() - ball.getRadius() < 0.f)
  165. {
  166. isPlaying = false;
  167. pauseMessage.setString("You Lost!\n" + inputString);
  168. }
  169. if (ball.getX() + ball.getRadius() > gameWidth)
  170. {
  171. isPlaying = false;
  172. pauseMessage.setString("You Won!\n" + inputString);
  173. }
  174. if (ball.getY() - ball.getRadius() < 0.f)
  175. {
  176. ballSound.play();
  177. ballAngle = -ballAngle;
  178. ball.setPosition(ball.getX(), ball.getRadius() + 0.1f);
  179. }
  180. if (ball.getY() + ball.getRadius() > gameHeight)
  181. {
  182. ballSound.play();
  183. ballAngle = -ballAngle;
  184. ball.setPosition(ball.getX(), gameHeight - ball.getRadius() - 0.1f);
  185. }
  186. // Check the collisions between the ball and the paddles
  187. // Left Paddle
  188. if (ball.getX() - ball.getRadius() < leftPaddle.getX() + leftPaddle.getSize().x / 2 &&
  189. ball.getX() - ball.getRadius() > leftPaddle.getX() &&
  190. ball.getY() + ball.getRadius() >= leftPaddle.getY() - leftPaddle.getSize().y / 2 &&
  191. ball.getY() - ball.getRadius() <= leftPaddle.getY() + leftPaddle.getSize().y / 2)
  192. {
  193. if (ball.getY() > leftPaddle.getY())
  194. ballAngle = pi - ballAngle + (rand() % 20) * pi / 180;
  195. else
  196. ballAngle = pi - ballAngle - (rand() % 20) * pi / 180;
  197. ballSound.play();
  198. ball.setPosition(leftPaddle.getX() + ball.getRadius() + leftPaddle.getSize().x / 2 + 0.1f, ball.getY());
  199. }
  200. // Right Paddle
  201. if (ball.getX() + ball.getRadius() > rightPaddle.getX() - leftPaddle.getSize().x / 2 &&
  202. ball.getX() + ball.getRadius() < rightPaddle.getX() &&
  203. ball.getY() + ball.getRadius() >= rightPaddle.getY() - leftPaddle.getSize().y / 2 &&
  204. ball.getY() - ball.getRadius() <= rightPaddle.getY() + leftPaddle.getSize().y / 2)
  205. {
  206. if (ball.getY() > rightPaddle.getY())
  207. ballAngle = pi - ballAngle + (rand() % 20) * pi / 180;
  208. else
  209. ballAngle = pi - ballAngle - (rand() % 20) * pi / 180;
  210. ballSound.play();
  211. ball.setPosition(rightPaddle.getX() - ball.getRadius() - leftPaddle.getSize().x / 2 - 0.1f, ball.getY());
  212. }
  213. }
  214. // Clear the window
  215. window.clear(sf::Color(50, 200, 50));
  216. if (isPlaying)
  217. {
  218. // Draw the paddles and the ball
  219. window.draw(leftPaddle);
  220. window.draw(rightPaddle);
  221. window.draw(ball);
  222. }
  223. else
  224. {
  225. // Draw the pause message
  226. window.draw(pauseMessage);
  227. }
  228. // Display things on screen
  229. window.display();
  230. }
  231. return EXIT_SUCCESS;
  232. }