SFML Pong, but object oriented

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