summaryrefslogtreecommitdiff
path: root/examples/tennis/Tennis.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/tennis/Tennis.cpp')
-rw-r--r--examples/tennis/Tennis.cpp291
1 files changed, 291 insertions, 0 deletions
diff --git a/examples/tennis/Tennis.cpp b/examples/tennis/Tennis.cpp
new file mode 100644
index 0000000..bc80bf5
--- /dev/null
+++ b/examples/tennis/Tennis.cpp
@@ -0,0 +1,291 @@
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <SFML/Graphics.hpp>
+#include <SFML/Audio.hpp>
+#include <cmath>
+#include <ctime>
+#include <cstdlib>
+
+#ifdef SFML_SYSTEM_IOS
+#include <SFML/Main.hpp>
+#endif
+
+std::string resourcesDir()
+{
+#ifdef SFML_SYSTEM_IOS
+ return "";
+#else
+ return "resources/";
+#endif
+}
+
+////////////////////////////////////////////////////////////
+/// Entry point of application
+///
+/// \return Application exit code
+///
+////////////////////////////////////////////////////////////
+int main()
+{
+ std::srand(static_cast<unsigned int>(std::time(NULL)));
+
+ // Define some constants
+ const float pi = 3.14159f;
+ const float gameWidth = 800;
+ const float gameHeight = 600;
+ sf::Vector2f paddleSize(25, 100);
+ float ballRadius = 10.f;
+
+ // Create the window of the application
+ sf::RenderWindow window(sf::VideoMode(static_cast<unsigned int>(gameWidth), static_cast<unsigned int>(gameHeight), 32), "SFML Tennis",
+ sf::Style::Titlebar | sf::Style::Close);
+ window.setVerticalSyncEnabled(true);
+
+ // Load the sounds used in the game
+ sf::SoundBuffer ballSoundBuffer;
+ if (!ballSoundBuffer.loadFromFile(resourcesDir() + "ball.wav"))
+ return EXIT_FAILURE;
+ sf::Sound ballSound(ballSoundBuffer);
+
+ // Create the SFML logo texture:
+ sf::Texture sfmlLogoTexture;
+ if(!sfmlLogoTexture.loadFromFile(resourcesDir() + "sfml_logo.png"))
+ return EXIT_FAILURE;
+ sf::Sprite sfmlLogo;
+ sfmlLogo.setTexture(sfmlLogoTexture);
+ sfmlLogo.setPosition(170, 50);
+
+ // Create the left paddle
+ sf::RectangleShape leftPaddle;
+ leftPaddle.setSize(paddleSize - sf::Vector2f(3, 3));
+ leftPaddle.setOutlineThickness(3);
+ leftPaddle.setOutlineColor(sf::Color::Black);
+ leftPaddle.setFillColor(sf::Color(100, 100, 200));
+ leftPaddle.setOrigin(paddleSize / 2.f);
+
+ // Create the right paddle
+ sf::RectangleShape rightPaddle;
+ rightPaddle.setSize(paddleSize - sf::Vector2f(3, 3));
+ rightPaddle.setOutlineThickness(3);
+ rightPaddle.setOutlineColor(sf::Color::Black);
+ rightPaddle.setFillColor(sf::Color(200, 100, 100));
+ rightPaddle.setOrigin(paddleSize / 2.f);
+
+ // Create the ball
+ sf::CircleShape ball;
+ ball.setRadius(ballRadius - 3);
+ ball.setOutlineThickness(2);
+ ball.setOutlineColor(sf::Color::Black);
+ ball.setFillColor(sf::Color::White);
+ ball.setOrigin(ballRadius / 2, ballRadius / 2);
+
+ // Load the text font
+ sf::Font font;
+ if (!font.loadFromFile(resourcesDir() + "tuffy.ttf"))
+ return EXIT_FAILURE;
+
+ // Initialize the pause message
+ sf::Text pauseMessage;
+ pauseMessage.setFont(font);
+ pauseMessage.setCharacterSize(40);
+ pauseMessage.setPosition(170.f, 200.f);
+ pauseMessage.setFillColor(sf::Color::White);
+
+ #ifdef SFML_SYSTEM_IOS
+ pauseMessage.setString("Welcome to SFML Tennis!\nTouch the screen to start the game.");
+ #else
+ pauseMessage.setString("Welcome to SFML Tennis!\n\nPress space to start the game.");
+ #endif
+
+ // Define the paddles properties
+ sf::Clock AITimer;
+ const sf::Time AITime = sf::seconds(0.1f);
+ const float paddleSpeed = 400.f;
+ float rightPaddleSpeed = 0.f;
+ const float ballSpeed = 400.f;
+ float ballAngle = 0.f; // to be changed later
+
+ sf::Clock clock;
+ bool isPlaying = false;
+ while (window.isOpen())
+ {
+ // Handle events
+ sf::Event event;
+ while (window.pollEvent(event))
+ {
+ // Window closed or escape key pressed: exit
+ if ((event.type == sf::Event::Closed) ||
+ ((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Escape)))
+ {
+ window.close();
+ break;
+ }
+
+ // Space key pressed: play
+ if (((event.type == sf::Event::KeyPressed) && (event.key.code == sf::Keyboard::Space)) ||
+ (event.type == sf::Event::TouchBegan))
+ {
+ if (!isPlaying)
+ {
+ // (re)start the game
+ isPlaying = true;
+ clock.restart();
+
+ // Reset the position of the paddles and ball
+ leftPaddle.setPosition(10.f + paddleSize.x / 2.f, gameHeight / 2.f);
+ rightPaddle.setPosition(gameWidth - 10.f - paddleSize.x / 2.f, gameHeight / 2.f);
+ ball.setPosition(gameWidth / 2.f, gameHeight / 2.f);
+
+ // Reset the ball angle
+ do
+ {
+ // Make sure the ball initial angle is not too much vertical
+ ballAngle = static_cast<float>(std::rand() % 360) * 2.f * pi / 360.f;
+ }
+ while (std::abs(std::cos(ballAngle)) < 0.7f);
+ }
+ }
+
+ // Window size changed, adjust view appropriately
+ if (event.type == sf::Event::Resized)
+ {
+ sf::View view;
+ view.setSize(gameWidth, gameHeight);
+ view.setCenter(gameWidth / 2.f, gameHeight /2.f);
+ window.setView(view);
+ }
+ }
+
+ if (isPlaying)
+ {
+ float deltaTime = clock.restart().asSeconds();
+
+ // Move the player's paddle
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up) &&
+ (leftPaddle.getPosition().y - paddleSize.y / 2 > 5.f))
+ {
+ leftPaddle.move(0.f, -paddleSpeed * deltaTime);
+ }
+ if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down) &&
+ (leftPaddle.getPosition().y + paddleSize.y / 2 < gameHeight - 5.f))
+ {
+ leftPaddle.move(0.f, paddleSpeed * deltaTime);
+ }
+
+ if (sf::Touch::isDown(0))
+ {
+ sf::Vector2i pos = sf::Touch::getPosition(0);
+ sf::Vector2f mappedPos = window.mapPixelToCoords(pos);
+ leftPaddle.setPosition(leftPaddle.getPosition().x, mappedPos.y);
+ }
+
+ // Move the computer's paddle
+ if (((rightPaddleSpeed < 0.f) && (rightPaddle.getPosition().y - paddleSize.y / 2 > 5.f)) ||
+ ((rightPaddleSpeed > 0.f) && (rightPaddle.getPosition().y + paddleSize.y / 2 < gameHeight - 5.f)))
+ {
+ rightPaddle.move(0.f, rightPaddleSpeed * deltaTime);
+ }
+
+ // Update the computer's paddle direction according to the ball position
+ if (AITimer.getElapsedTime() > AITime)
+ {
+ AITimer.restart();
+ if (ball.getPosition().y + ballRadius > rightPaddle.getPosition().y + paddleSize.y / 2)
+ rightPaddleSpeed = paddleSpeed;
+ else if (ball.getPosition().y - ballRadius < rightPaddle.getPosition().y - paddleSize.y / 2)
+ rightPaddleSpeed = -paddleSpeed;
+ else
+ rightPaddleSpeed = 0.f;
+ }
+
+ // Move the ball
+ float factor = ballSpeed * deltaTime;
+ ball.move(std::cos(ballAngle) * factor, std::sin(ballAngle) * factor);
+
+ #ifdef SFML_SYSTEM_IOS
+ const std::string inputString = "Touch the screen to restart.";
+ #else
+ const std::string inputString = "Press space to restart or\nescape to exit.";
+ #endif
+
+ // Check collisions between the ball and the screen
+ if (ball.getPosition().x - ballRadius < 0.f)
+ {
+ isPlaying = false;
+ pauseMessage.setString("You Lost!\n\n" + inputString);
+ }
+ if (ball.getPosition().x + ballRadius > gameWidth)
+ {
+ isPlaying = false;
+ pauseMessage.setString("You Won!\n\n" + inputString);
+ }
+ if (ball.getPosition().y - ballRadius < 0.f)
+ {
+ ballSound.play();
+ ballAngle = -ballAngle;
+ ball.setPosition(ball.getPosition().x, ballRadius + 0.1f);
+ }
+ if (ball.getPosition().y + ballRadius > gameHeight)
+ {
+ ballSound.play();
+ ballAngle = -ballAngle;
+ ball.setPosition(ball.getPosition().x, gameHeight - ballRadius - 0.1f);
+ }
+
+ // Check the collisions between the ball and the paddles
+ // Left Paddle
+ if (ball.getPosition().x - ballRadius < leftPaddle.getPosition().x + paddleSize.x / 2 &&
+ ball.getPosition().x - ballRadius > leftPaddle.getPosition().x &&
+ ball.getPosition().y + ballRadius >= leftPaddle.getPosition().y - paddleSize.y / 2 &&
+ ball.getPosition().y - ballRadius <= leftPaddle.getPosition().y + paddleSize.y / 2)
+ {
+ if (ball.getPosition().y > leftPaddle.getPosition().y)
+ ballAngle = pi - ballAngle + static_cast<float>(std::rand() % 20) * pi / 180;
+ else
+ ballAngle = pi - ballAngle - static_cast<float>(std::rand() % 20) * pi / 180;
+
+ ballSound.play();
+ ball.setPosition(leftPaddle.getPosition().x + ballRadius + paddleSize.x / 2 + 0.1f, ball.getPosition().y);
+ }
+
+ // Right Paddle
+ if (ball.getPosition().x + ballRadius > rightPaddle.getPosition().x - paddleSize.x / 2 &&
+ ball.getPosition().x + ballRadius < rightPaddle.getPosition().x &&
+ ball.getPosition().y + ballRadius >= rightPaddle.getPosition().y - paddleSize.y / 2 &&
+ ball.getPosition().y - ballRadius <= rightPaddle.getPosition().y + paddleSize.y / 2)
+ {
+ if (ball.getPosition().y > rightPaddle.getPosition().y)
+ ballAngle = pi - ballAngle + static_cast<float>(std::rand() % 20) * pi / 180;
+ else
+ ballAngle = pi - ballAngle - static_cast<float>(std::rand() % 20) * pi / 180;
+
+ ballSound.play();
+ ball.setPosition(rightPaddle.getPosition().x - ballRadius - paddleSize.x / 2 - 0.1f, ball.getPosition().y);
+ }
+ }
+
+ // Clear the window
+ window.clear(sf::Color(50, 50, 50));
+
+ if (isPlaying)
+ {
+ // Draw the paddles and the ball
+ window.draw(leftPaddle);
+ window.draw(rightPaddle);
+ window.draw(ball);
+ }
+ else
+ {
+ // Draw the pause message
+ window.draw(pauseMessage);
+ window.draw(sfmlLogo);
+ }
+
+ // Display things on screen
+ window.display();
+ }
+
+ return EXIT_SUCCESS;
+}