I found some example code online so I personally don't know what the difference between mutex is and not.
The problem with the screenshot is that it alter between frames so a screenshot will not be able to show the multiple position (same as when you circle the mouse the eye can see 8-10 pointers at the same time because of refresh rate).
I got it working though and the error was simply because both the client and server were sending the same data causing multiple inputs. I fixed it by simply telling the server to send ball position and right flipper while the client only sends information about the left one.
Heres my code for future reference, feel free to give me advice on how to make it better other than implement better ball logic and actually using headers, classes and functions
Oh, and another thing, I can't make a release static on the way the project is set up so I can't share my game with people that don't have visual studio installed on their pc. It do however work if I exclude network and audio for some reason. Any ideas?
#ifdef SFML_STATIC
#pragma comment(lib, "glew.lib")
#pragma comment(lib, "freetype.lib")
#pragma comment(lib, "jpeg.lib")
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "gdi32.lib")
#endif // SFML_STATIC
#include <SFML/Graphics.hpp>
#include <cmath>
#include <iostream>
#include <ostream>
#include <fstream>
#include <sstream>
#include <SFML/Audio.hpp>
#include <SFML/Network.hpp>
const int FPS = 60, WINDOWWIDTH = 320, WINDOWHEIGHT = 180;
const unsigned short PORT = 5000;
const std::string IPADDRESS("123.456.789.1");
const float PI = 3.14159265359, shapeRadius = 5;
int score = 0;
int inputSend1 = 0, inputSend2 = 0;
bool serverPick = false;
sf::RenderWindow window(sf::VideoMode(WINDOWWIDTH, WINDOWHEIGHT), "Pong");
sf::Vector2f ballV, ballP, playerV, playerP, opponentP, inputSend3;
sf::CircleShape shape(shapeRadius);
sf::Texture brickTxt;
sf::Sprite brickSpr, opponentSpr, middleSpr;
sf::Event event;
sf::Font font1;
sf::Text scoreText;
sf::TcpSocket socket;
sf::Mutex globalMutex;
sf::SoundBuffer buffer;
sf::Sound sound;
void windowCloser(), sync(void), server(void), client(void);
//main
int main(int argc, char* argv[])
{
if (!brickTxt.loadFromFile("resources/brick.png"));
if (!font1.loadFromFile("resources/arial.ttf"));
if (!buffer.loadFromFile("resources/jump.wav"));
sound.setBuffer(buffer);
sf::Thread* thread = 0;
char who = 'a';
while (who != 'S' && who != 'C')
{
std::cout << "Server or Client? S/C ";
std::cin >> who;
toupper(who);
if (who == 'S')
server();
if (who == 'C')
client();
}
brickSpr.setTexture(brickTxt);
opponentSpr.setTexture(brickTxt);
middleSpr.setTexture(brickTxt);
shape.setFillColor(sf::Color::White);
ballP.x = WINDOWWIDTH/2;
ballP.y = WINDOWHEIGHT/2;
playerP.x = 0;
playerP.y = WINDOWHEIGHT / 2;
opponentP.x = WINDOWWIDTH - opponentSpr.getGlobalBounds().width;
opponentP.y = WINDOWHEIGHT / 2;
ballV.x = 3;
ballV.y = 3;
middleSpr.setScale(0.5, 6.7);
middleSpr.setPosition(WINDOWWIDTH / 2, 0);
thread = new sf::Thread(&sync);
thread->launch();
if (thread)
{
thread->wait();
delete thread;
}
//main loop
while (window.isOpen())
{
event;
windowCloser();
ballP.x = inputSend3.x + ballV.x;
ballP.y = inputSend3.y + ballV.y;
shape.setPosition(ballP.x, ballP.y);
playerP.y = inputSend1;
opponentP.y = inputSend2;
playerP.y = playerP.y + playerV.y;
opponentP.x = WINDOWWIDTH - opponentSpr.getGlobalBounds().width;
brickSpr.setPosition(playerP.x, playerP.y);
opponentSpr.setPosition(opponentP.x, opponentP.y);
if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
{
playerP.y -= 5;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
{
playerP.y += 5;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
opponentP.y -= 5;
}
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
opponentP.y += 5;
}
if (shape.getPosition().x < -10)
{
score = 0;
ballV.x = -ballV.x;
ballP.x = (WINDOWWIDTH / 2);
ballP.y = (WINDOWHEIGHT / 2);
}
if (shape.getPosition().x > WINDOWWIDTH + 10)
{
score = 0;
ballV.x = -ballV.x;
ballP.x = (WINDOWWIDTH / 2);
ballP.y = (WINDOWHEIGHT / 2);
}
if (shape.getPosition().y > (WINDOWHEIGHT-WINDOWHEIGHT))
{
ballV.y = -ballV.y;
}
if (shape.getPosition().y < (WINDOWHEIGHT-shapeRadius*2))
{
ballV.y = -ballV.y;
}
//collision
if (brickSpr.getGlobalBounds().intersects(shape.getGlobalBounds()))
{
sound.play();
ballP.x = 6;
ballV.x = -ballV.x;
score++;
}
if (opponentSpr.getGlobalBounds().intersects(shape.getGlobalBounds()))
{
sound.play();
ballP.x = WINDOWWIDTH - 12;
ballV.x = -ballV.x;
score++;
}
std::ostringstream scoreString;
scoreString << score;
scoreText.setString(scoreString.str());
scoreText.setFont(font1);
scoreText.setColor(sf::Color::White);
scoreText.setPosition((WINDOWWIDTH / 2)+10, 0);
if (!serverPick)
{
globalMutex.lock();
inputSend1 = playerP.y;
globalMutex.unlock();
}
if (serverPick)
{
globalMutex.lock();
inputSend2 = opponentP.y;
inputSend3.x = ballP.x;
inputSend3.y = ballP.y;
globalMutex.unlock();
}
sync();
window.clear();
window.draw(shape);
window.draw(brickSpr);
window.draw(opponentSpr);
window.draw(middleSpr);
window.setFramerateLimit(FPS);
window.draw(scoreText);
window.display();
}
return 0;
}
void windowCloser()
{
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
window.close();
}
}
void sync(void)
{
if (serverPick)
{
sf::Packet packetSend;
globalMutex.lock();
packetSend << inputSend3.x << inputSend3.y << inputSend2;
globalMutex.unlock();
socket.send(packetSend);
sf::Packet packetReceive;
socket.receive(packetReceive);
packetReceive >> inputSend1;
}
if (!serverPick)
{
sf::Packet packetSend;
globalMutex.lock();
packetSend << inputSend1;
globalMutex.unlock();
socket.send(packetSend);
sf::Packet packetReceive;
socket.receive(packetReceive);
packetReceive >> inputSend3.x >> inputSend3.y >> inputSend2;
}
}
void server(void)
{
sf::TcpListener listener;
listener.listen(PORT);
listener.accept(socket);
std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
serverPick = true;
}
void client(void)
{
if (socket.connect(IPADDRESS, PORT) == sf::Socket::Done)
{
std::cout << "\nConnected\n" << std::endl;
serverPick = false;
}
else
{
std::cout << "Can't connect.";
}
}