Some of you may have seen my previous post asking if my code was efficient and easy to read.
I have made some more improvements to it by adding sounds, visual count down and checking if the window has focus. Before I carry on with my program I would like to know if this is efficient and easy to read.
Here is the zip file containing all the resources.
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "ResourcePath.hpp"
#include <cstdint>
#include <iostream>
using std::cout;
using std::endl;
//Version
std::string ver = "V0.3";
//Create Text and font variables
sf::Text text;
sf::Font font;
// for eliminating magic numbers
enum class Players
{
PlayerOne,
PlayerTwo
};
//Make this class Drawable
class Paddel : public sf::Drawable
{
// for member data perfered to be started with m prefix
float mSpeed;
sf::Vector2f mBorder;
sf::Vector2f mPosition;
sf::Vector2u mScreenSize;
sf::RectangleShape mShape;
public:
Paddel(sf::Vector2u screenSize, Players player)
// member data perfered be initilaized as contructor's initilaized list
: mScreenSize(screenSize)
, mBorder(8, 6)
, mSpeed(5.f)
{
sf::Vector2f size = sf::Vector2f(20, 100);
//Which player
switch (player)
{
case Players::PlayerOne:
//If player one set position to border
mPosition = mBorder;
break;
default:
//Else set positionX to (screenWidth - paddelWidth) - borderWidth
mPosition.x = (mScreenSize.x - size.x) - mBorder.x;
//positionY = borderY
mPosition.y = mBorder.y;
}
//Set size and position of drawable shape
mShape.setSize(size);
mShape.setPosition(mPosition);
}
void moveUp()
{
//Get closer to 0 (Top of screen)
mPosition.y -= mSpeed;
//If gone too far add speed
if (mPosition.y < mBorder.y)
mPosition.y += mSpeed;
mShape.setPosition(mPosition);
}
//Do the same opposite way round
void moveDown()
{
mPosition.y += mSpeed;
if (mPosition.y >(mScreenSize.y - mBorder.y) - mShape.getSize().y)
mPosition.y -= mSpeed;
mShape.setPosition(mPosition);
}
//Override sf::Drawable function
void draw(sf::RenderTarget& target, sf::RenderStates states) const override
{
// sf::RectangleShape has its own defualt RenderStates
target.draw(mShape, states);
}
};
int main()
{
//Initilise screen size and Window
sf::RenderWindow Window(sf::VideoMode(800,600), "Ping Pong " + ver, sf::Style::Titlebar | sf::Style::Close);
sf::Vector2u screenSize(Window.getSize().x,Window.sf::Window::getSize().y);
//Create Text
bool enableText = true;
bool countdown = false;
if(!font.loadFromFile(resourcePath() + "Pacifico.ttf"))
{
cout << "No Font File" << endl;
enableText = false;
} else {
text.setFont(font);
text.setCharacterSize(50);
text.setColor(sf::Color::White);
}
//Limit frame rate and enable vertical sync
Window.setFramerateLimit(60);
Window.setVerticalSyncEnabled(true);
//Load resume sound
sf::SoundBuffer countdownBuffer;
sf::SoundBuffer startBuffer;
if(!countdownBuffer.loadFromFile(resourcePath() + "3_2_1.ogg") || !startBuffer.loadFromFile(resourcePath() + "Go.ogg"))
return -1;
sf::Sound countdownSound;
sf::Sound startSound;
countdownSound.setBuffer(countdownBuffer);
startSound.setBuffer(startBuffer);
//Seporate left from right
sf::RectangleShape middleBar(sf::Vector2f(10,screenSize.y));
cout << "Screen X / 2: " << screenSize.x/2 << endl;
middleBar.setPosition(screenSize.x/2,0);
middleBar.setFillColor(sf::Color::Red);
//Create player paddels
Paddel playerOne(screenSize, Players::PlayerOne);
Paddel playerTwo(screenSize, Players::PlayerTwo);
//Use this for refresh time
const sf::Time TimePerFrame = sf::seconds(1.f / 60.f);
sf::Clock clock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
sf::Time elapsedTime;
//Should ping pong be running
bool play = true;
bool hasFocus = true;
//int lastFocus = 1;
bool firstLoad = true;
//Game loop
while (Window.isOpen())
{
//Clear screen and emplt Events
Window.clear();
sf::Event Event;
//If window receves events
while (Window.pollEvent(Event))
{
//Which events
switch(Event.type)
{
//Did the user close the window
case sf::Event::Closed:
//Close it
Window.close();
break;
//If this is the second time or more this code has looped
if(!firstLoad)
{
//Did the window gane focus aka did the user click on it
case sf::Event::GainedFocus:
{
//Set variables
hasFocus = true;
play = true;
//Prevent this from haponing again
sf::Clock focusGap;
}
break;
//Did the window lose focus aka did the user select another application
case sf::Event::LostFocus:
{
hasFocus = false;
play = false;
sf::Clock focusGap;
}
break;
default:
break;
}
}
}
if(hasFocus)
{
if(sf::Keyboard::isKeyPressed(sf::Keyboard::P))
{
sf::Clock resume;
if(play == true)
{
play = false;
//Pause a bit to prevent toggling too fast
while(resume.getElapsedTime().asSeconds() < 0.15)
continue;
} else {
//We are counting down
countdown = true;
play = true;
text.setPosition(screenSize.x/2, screenSize.y/2);
text.setString("3");
//Clear window and draw stuff
Window.clear();
Window.draw(playerOne);
Window.draw(playerTwo);
Window.draw(middleBar);
//Draw text
Window.draw(text);
Window.display();
//Play first beep (3)
countdownSound.play();
//Start clocks
sf::Clock soundRepeat;
sf::Clock soundGap;
int stages = 1;
//Run for 3 seconds (beeps 2,1 and GO!)
while(soundRepeat.getElapsedTime().asSeconds() < 4)
{
if(stages == 1)
text.setString("2");
else
text.setString("1");
//If 1 second has been since last beep and beeps are 2 or 1
if(soundGap.getElapsedTime().asSeconds() >= 1 && stages <= 2)
{
cout << stages << endl;
//Clear window and draw stuff
Window.clear();
Window.draw(playerOne);
Window.draw(playerTwo);
Window.draw(middleBar);
//Draw text
Window.draw(text);
Window.display();
//Play beep
countdownSound.play();
stages ++;
soundGap.restart();
//If 1 second has been since last beep and we want the GO! beep
} else if(soundGap.getElapsedTime().asSeconds() >= 1 && stages > 2){
text.setString("GO!");
text.setPosition((screenSize.x/2)-(text.getCharacterSize()-2),screenSize.y/2);
soundGap.restart(); //This prevents sound glitch
Window.clear();
Window.draw(playerOne);
Window.draw(playerTwo);
Window.draw(middleBar);
//Draw text
Window.draw(text);
Window.display();
startSound.play();
}
}
}
}
}
//Do refresh time calculation stuff
elapsedTime = clock.restart();
timeSinceLastUpdate += elapsedTime;
//If user wants to play
if (play)
{
//If screen should refresh
if (timeSinceLastUpdate > TimePerFrame)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
playerOne.moveUp();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
playerOne.moveDown();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
playerTwo.moveUp();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
playerTwo.moveDown();
if (sf::Keyboard::isKeyPressed(sf::Keyboard::P))
play = false;
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
Window.close();
}
//Draw stuff
Window.draw(middleBar);
Window.draw(playerOne);
Window.draw(playerTwo);
Window.display();
//Everything has run at least once
if(firstLoad)
firstLoad = false;
}
}
}