Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved-ish] Movement Lag on Client  (Read 9618 times)

0 Members and 1 Guest are viewing this topic.

io

  • Jr. Member
  • **
  • Posts: 52
  • z/OS by day, SFML by night
    • View Profile
[Solved-ish] Movement Lag on Client
« on: March 04, 2013, 08:29:31 pm »
====
Update
====

Last update 6.21AM 10Mar2013 -8 GMT

Click:  http://en.sfml-dev.org/forums/index.php?topic=10803.msg74965#msg74965
to jump to latest update.

~~~~~~~~~~~~

I'm giving a dabble at SFML networking and I have what I think is probably a very basic issue/fundamental misunderstanding on my part.

I have created a server that sends out commands to a client in order to move a rectangle, however the client end is always lagged compared to the server as can be seen here:



I haven't tried implementing UDP yet, and from what I've been reading real time movement should be implemented with UDP (I think most games are using UDP for this type of stuff/TCP for the chat). 

Is my understanding correct and I should move to UDP, or should TCP be able to handle something like this?

I can think of one possible way to eliminate this lag.  When the key is pressed on the server end have a move left sent and the client will continuously move until a move left end is received.. and this should synch it up better, but I'm wondering if there is a better approach.  Another possibility I thought of is just send the exact coords of where the client rectangle should be.

Thanks!  Any input/advice is greatly appreciated as always.


main.cpp
//#include "VoIP.hpp"
#include "tcp_issue.hpp"


int main( int argc, char* argv[])
{
    //voip example
    //voipExample();

    if( argc > 2 )
    {

        //tcp/udp issue
        issueServer( argv[1], argv[2] ); //[server,client] [tcp,udp]
    }

    return EXIT_SUCCESS;
}
 


tcp_issue.hpp
#include <SFML/Graphics.hpp>
#include <string>

const float MOVE_SPEED = 70;
const int PORT = 7777;

sf::TcpSocket socket;
sf::UdpSocket usocket;
sf::Mutex globalMutex;

std::string command = "";

bool quit = false;

void tcpServerListen();
void tcpClient();
void tcpSend();

void udpServer();
void udpClient();
void udpSend();

void issueServer( std::string mode, std::string method )
{
    std::cout << "Incoming mode: " << mode << std::endl;
    std::cout << "Incoming method: " << method << std::endl;

    sf::Thread threadServerTCP(&tcpServerListen);
    sf::Thread threadClientTCP(&tcpClient);
    sf::Thread threadServerUDP(&udpServer);
    sf::Thread threadClientUDP(&udpClient);

    if( mode.compare("server") == 0 )
    {
        std::cout << "Starting in server mode.\n";
        if( method.compare("tcp") == 0 )
        {
            std::cout << "Launching server tcp thread\n";
            threadServerTCP.launch();
        }
        else
        {
            std::cout << "Launching server udp thread\n";
            threadServerUDP.launch();
        }
    }
    else
    {
        std::cout << "Starting in client mode.\n";
        if( method.compare("tcp") == 0 )
        {
            std::cout << "Starting tcp client thread.\n";
            threadClientTCP.launch();
        }
        else
        {
            std::cout << "Starting udp client thread.\n";
            threadClientTCP.launch();
        }
    }


    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Playground");

    sf::Clock Clock;
    sf::Time time;

    sf::RectangleShape rectangle;
    rectangle.setSize(sf::Vector2f(100, 50));
    rectangle.setOutlineColor(sf::Color::Red);
    rectangle.setOutlineThickness(5);
    rectangle.setPosition(10, 20);

    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                quit = true;

                if( method.compare("tcp") == 0 )
                    threadClientTCP.wait();
                else
                    threadClientUDP.wait();

                window.close();
            }
            if (event.type == sf::Event::KeyPressed)
            {
            }
        }
        if( mode.compare("server") == 0 )
        {
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
            {
                globalMutex.lock();
                command = "left";
                globalMutex.unlock();

                if( method.compare("tcp") == 0 )
                    tcpSend();
                else
                    udpSend();

                rectangle.move(-1*MOVE_SPEED*time.asSeconds(),0);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
            {
                globalMutex.lock();
                command = "down";
                globalMutex.unlock();

                if( method.compare("tcp") == 0 )
                    tcpSend();
                else
                    udpSend();

                rectangle.move(0,1*MOVE_SPEED*time.asSeconds());
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
            {
                globalMutex.lock();
                command = "right";
                globalMutex.unlock();

                if( method.compare("tcp") == 0 )
                    tcpSend();
                else
                    udpSend();

                rectangle.move(1*MOVE_SPEED*time.asSeconds(),0);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
            {
                globalMutex.lock();
                command = "up";
                globalMutex.unlock();

                if( method.compare("tcp") == 0 )
                    tcpSend();
                else
                    udpSend();

                rectangle.move(0,-1*MOVE_SPEED*time.asSeconds());
            }
        }
        else
        {
            if (command.compare("left") == 0)
            {
                rectangle.move(-1*MOVE_SPEED*time.asSeconds(),0);

                globalMutex.lock();
                command = "";
                globalMutex.unlock();
            }

            if (command.compare("down")  == 0 )
            {
                rectangle.move(0,1*MOVE_SPEED*time.asSeconds());

                globalMutex.lock();
                command = "";
                globalMutex.unlock();
            }

            if (command.compare("right")  == 0 )
            {
                rectangle.move(1*MOVE_SPEED*time.asSeconds(),0);

                globalMutex.lock();
                command = "";
                globalMutex.unlock();
            }

            if (command.compare("up")  == 0 )
            {
                rectangle.move(0,-1*MOVE_SPEED*time.asSeconds());

                globalMutex.lock();
                command = "";
                globalMutex.unlock();
            }

        }


        window.draw( rectangle );
        window.display();
        window.clear();

        time = Clock.restart();
    }
}

void tcpSend()
{
        sf::Packet packetSend;
        globalMutex.lock();
        packetSend << command;
        globalMutex.unlock();
        command = "";
        socket.send(packetSend);
}

void udpSend()
{
}

void tcpServerListen()
{
    sf::TcpListener listener;
    listener.listen(PORT);
    listener.accept(socket);
    std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
}

void udpServer()
{
}


void udpClient()
{
}


void tcpClient()
{
        if(socket.connect("127.0.0.1", PORT) == sf::Socket::Done)
                std::cout << "Connected\n";
    else
        std::cout << "FAILURE\n";

    while( !quit )
    {
                std::string msg;
                sf::Packet packetReceive;
                socket.receive(packetReceive);

                packetReceive >> msg;

                if( !msg.empty() )
                {
            std::cout << "Command Received: " << msg << std::endl;
            globalMutex.lock();
            command = msg;
            globalMutex.unlock();
                }
    }
}
 

[attachment deleted by admin]
« Last Edit: March 13, 2013, 01:38:49 am by io »

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Movement Lag on Client
« Reply #1 on: March 05, 2013, 01:13:47 am »
Just a thought, try limiting your framerate to start with, packets aren't intended to be sent as fast as your cpu can run the main loop. On top of limiting framerate, try limiting your server packets to about 30 packets per second at tops since you really dont need to send any faster than that.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

io

  • Jr. Member
  • **
  • Posts: 52
  • z/OS by day, SFML by night
    • View Profile
Re: Movement Lag on Client
« Reply #2 on: March 05, 2013, 03:47:04 am »
Thanks for the suggestions.  I've added the frame limit line and limited the packets being sent as suggested (I think I implemented it correctly, packet limiting is probably not the cleanest, but I think it does the trick for right now). 

Still no go:   

Client is falling behind.  At the very end when server goes diagonal up-right, client only goes one way, but this is a separate issue that I need to look into.



tcp_issue.hpp
#include <SFML/Graphics.hpp>
#include <string>



const float MOVE_SPEED = 70;
const int PORT = 7777;

sf::TcpSocket socket;
sf::UdpSocket usocket;
sf::Mutex globalMutex;

std::string command = "";

bool quit = false;

void tcpServerListen();
void tcpClient();
void tcpSend();

void udpServer();
void udpClient();
void udpSend();

void issueServer( std::string mode, std::string method )
{
    int packet_counter = 0;
    int packet_storage = 0;

    std::cout << "Incoming mode: " << mode << std::endl;
    std::cout << "Incoming method: " << method << std::endl;

    sf::Thread threadServerTCP(&tcpServerListen);
    sf::Thread threadClientTCP(&tcpClient);
    sf::Thread threadServerUDP(&udpServer);
    sf::Thread threadClientUDP(&udpClient);

    if( mode.compare("server") == 0 )
    {
        std::cout << "Starting in server mode.\n";
        if( method.compare("tcp") == 0 )
        {
            std::cout << "Launching server tcp thread\n";
            threadServerTCP.launch();
        }
        else
        {
            std::cout << "Launching server udp thread\n";
            threadServerUDP.launch();
        }
    }
    else
    {
        std::cout << "Starting in client mode.\n";
        if( method.compare("tcp") == 0 )
        {
            std::cout << "Starting tcp client thread.\n";
            threadClientTCP.launch();
        }
        else
        {
            std::cout << "Starting udp client thread.\n";
            threadClientTCP.launch();
        }
    }


    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Playground");
    window.setFramerateLimit(30);


    sf::Clock Clock;
    sf::Clock Packet_Clock;
    sf::Time time;

    sf::RectangleShape rectangle;
    rectangle.setSize(sf::Vector2f(100, 50));
    rectangle.setOutlineColor(sf::Color::Red);
    rectangle.setOutlineThickness(5);
    rectangle.setPosition(10, 20);

    while (window.isOpen())
    {
        time = Clock.restart();
        if( Packet_Clock.getElapsedTime().asSeconds() >= 1 )
        {
            packet_counter = 0;
            packet_storage = 0;
            Packet_Clock.restart();
        }

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                quit = true;

                if( method.compare("tcp") == 0 )
                    threadClientTCP.wait();
                else
                    threadClientUDP.wait();

                window.close();
            }
            if (event.type == sf::Event::KeyPressed)
            {
            }
        }
        if( mode.compare("server") == 0 )
        {
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
            {
                packet_counter = (Packet_Clock.getElapsedTime().asMilliseconds()/33);

                if( packet_counter > packet_storage )
                {
                    packet_storage = packet_counter;
                    globalMutex.lock();
                    command = "left";
                    globalMutex.unlock();

                    if( method.compare("tcp") == 0 )
                        tcpSend();
                    else
                        udpSend();
                }

                rectangle.move(-1*MOVE_SPEED*time.asSeconds(),0);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
            {
                packet_counter = (Packet_Clock.getElapsedTime().asMilliseconds()/33);

                if( packet_counter > packet_storage )
                {
                    packet_storage = packet_counter;
                    globalMutex.lock();
                    command = "down";
                    globalMutex.unlock();

                    if( method.compare("tcp") == 0 )
                        tcpSend();
                    else
                        udpSend();
                }

                rectangle.move(0,1*MOVE_SPEED*time.asSeconds());
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
            {
                packet_counter = (Packet_Clock.getElapsedTime().asMilliseconds()/33);

                if( packet_counter > packet_storage )
                {
                    packet_storage = packet_counter;
                    globalMutex.lock();
                    command = "right";
                    globalMutex.unlock();

                    if( method.compare("tcp") == 0 )
                        tcpSend();
                    else
                        udpSend();
                }

                rectangle.move(1*MOVE_SPEED*time.asSeconds(),0);
            }

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
            {
                packet_counter = (Packet_Clock.getElapsedTime().asMilliseconds()/33);

                if( packet_counter > packet_storage )
                {
                    packet_storage = packet_counter;
                    globalMutex.lock();
                    command = "up";
                    globalMutex.unlock();

                    if( method.compare("tcp") == 0 )
                        tcpSend();
                    else
                        udpSend();
                }

                rectangle.move(0,-1*MOVE_SPEED*time.asSeconds());
            }
        }
        else
        {
            if (command.compare("left") == 0)
            {
                rectangle.move(-1*MOVE_SPEED*time.asSeconds(),0);

                globalMutex.lock();
                command = "";
                globalMutex.unlock();
            }

            if (command.compare("down")  == 0 )
            {
                rectangle.move(0,1*MOVE_SPEED*time.asSeconds());

                globalMutex.lock();
                command = "";
                globalMutex.unlock();
            }

            if (command.compare("right")  == 0 )
            {
                rectangle.move(1*MOVE_SPEED*time.asSeconds(),0);

                globalMutex.lock();
                command = "";
                globalMutex.unlock();
            }

            if (command.compare("up")  == 0 )
            {
                rectangle.move(0,-1*MOVE_SPEED*time.asSeconds());

                globalMutex.lock();
                command = "";
                globalMutex.unlock();
            }

        }


        window.draw( rectangle );
        window.display();
        window.clear();
    }
}

void tcpSend()
{
        sf::Packet packetSend;
        globalMutex.lock();
        packetSend << command;
        globalMutex.unlock();
        command = "";
        socket.send(packetSend);
}


void tcpServerListen()
{
    sf::TcpListener listener;
    listener.listen(PORT);
    listener.accept(socket);
    std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
}

void tcpClient()
{
        if(socket.connect("127.0.0.1", PORT) == sf::Socket::Done)
                std::cout << "Connected\n";
    else
        std::cout << "FAILURE\n";

    while( !quit )
    {
                std::string msg;
                sf::Packet packetReceive;
                socket.receive(packetReceive);

                packetReceive >> msg;

                if( !msg.empty() )
                {
            std::cout << "Command Received: " << msg << std::endl;
            globalMutex.lock();
            command = msg;
            globalMutex.unlock();
                }
    }
}


void udpServer()
{
}

void udpClient()
{
}

void udpSend()
{
}

 
« Last Edit: March 05, 2013, 03:51:07 am by io »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Movement Lag on Client
« Reply #3 on: March 05, 2013, 08:39:39 am »
It doesn't seem to be lagging, movement starts and stops exactly at the same moment on both sides. You should try to send the position (or offset) rather than just a direction, so that each side executes exactly the same moves.
Laurent Gomila - SFML developer

io

  • Jr. Member
  • **
  • Posts: 52
  • z/OS by day, SFML by night
    • View Profile
Re: Movement Lag on Client
« Reply #4 on: March 05, 2013, 08:48:13 am »
Thanks Laurent for taking the time to reply. 

By lag I meant what you see @ 22 seconds (the client is at a different position then the server) on the latest video.

I will take your suggestion and use positions/offsets instead of just direction.  I'll work up an example and see how it goes.

Thanks again (=
« Last Edit: March 05, 2013, 08:59:45 am by io »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Movement Lag on Client
« Reply #5 on: March 05, 2013, 09:17:48 am »
Quote
By lag I meant what you see @ 22 seconds (the client is at a different position then the server) on the latest video.
Yes, but what I mean is that it's probably not a network issue. Both rectangles start and stop at the same time, and they seem to do the same number of moves. So I strongly suspect that what's different is the amount of pixels that each rectangle moves by, which produces a significant difference at the end, even though they both executed the exact same set of commands.
Laurent Gomila - SFML developer

io

  • Jr. Member
  • **
  • Posts: 52
  • z/OS by day, SFML by night
    • View Profile
Re: Movement Lag on Client
« Reply #6 on: March 09, 2013, 11:04:02 am »
(Updated code 3/10/2013)

Well, I think I am getting a lot closer!





Updated code is below.  Video is more choppy then when running and I am not screen recording... but I am getting very close to what I want to achieve.

I think client end is choppy because it is making bigger moves then server... maybe I have to break this down somehow for a smoother move?

Am I taking the correct approach now?  Thanks (=.. I think after some more work I'll finally get this how I want.


Here is the updated code
main.cpp
#include "tcp_issue.hpp"


int main( int argc, char* argv[])
{

    if( argc > 2 )
    {
        //tcp/udp issue
        issueServer( argv[1], argv[2] ); //[server,client] [tcp,udp]
    }


    return EXIT_SUCCESS;
}
 

tcp_issue.hpp
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <iostream>
#include <string>
#include <queue>
#include <cmath>


const float MOVE_SPEED = 70;
const int PORT = 7777;

sf::TcpSocket socket;
sf::Mutex globalMutex;
sf::Packet serverPacket;


bool quit = false;
std::string sendString = "";

std::string v_command;
float v_offset_x = 0;
float v_offset_y = 0;


void serverListener();
void serverSend();
void clientListener();



void issueServer( std::string mode, std::string method )
{
    std::cout << "Incoming mode: " << mode << std::endl;
    std::cout << "Incoming method: " << method << std::endl;


    sf::Thread serverListenerThread(&serverListener);
    sf::Thread clientListenerThread(&clientListener);



    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Playground");
    window.setFramerateLimit(60);

    sf::Clock Clock;
    sf::Clock PacketClock;
    int packet_counter = 0;

    sf::Time time;

    sf::RectangleShape rectangle;
    rectangle.setSize(sf::Vector2f(100, 50));
    rectangle.setOutlineColor(sf::Color::Red);
    rectangle.setOutlineThickness(5);
    rectangle.setPosition(10, 20);



    if( mode.compare("server") == 0 )
        serverListenerThread.launch();
    else
    {
        socket.connect("127.0.0.1",7777);
        clientListenerThread.launch();
    }


    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                quit = true;

                if( mode.compare("server") == 0 )
                    serverListenerThread.terminate();
                else
                    clientListenerThread.terminate();

                window.close();
            }
        }
        if( mode.compare("server") == 0 )
        {
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                rectangle.move(-1*MOVE_SPEED*time.asSeconds(),0);

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                rectangle.move(0,1*MOVE_SPEED*time.asSeconds());

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                rectangle.move(1*MOVE_SPEED*time.asSeconds(),0);

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                rectangle.move(0,-1*MOVE_SPEED*time.asSeconds());

        }
        else //client mode
        {
            float offset_x = 0;
            float offset_y = 0;
            std::string command = "";


            if( v_command.compare("move") == 0 )
            {
                sf::Clock test_clock;
                sf::Time test_time;
                globalMutex.lock();
                command = v_command;
                offset_x = v_offset_x - rectangle.getPosition().x;
                offset_y = v_offset_y - rectangle.getPosition().y;
                v_command = "";
                v_offset_x = 0;
                v_offset_y = 0;
                globalMutex.unlock();

                rectangle.move(offset_x,offset_y);
            }

            window.draw( rectangle );
            window.display();
            window.clear();

        }


        if( mode.compare("server") == 0 )
        {
            window.draw( rectangle );
            window.display();
            window.clear();

            if( PacketClock.getElapsedTime().asSeconds() >= 1 )
            {
                packet_counter = 0;
                PacketClock.restart();
            }
            else if( (PacketClock.getElapsedTime().asMilliseconds()/30) > packet_counter )
            {
                globalMutex.lock();
                serverPacket << "move" << rectangle.getPosition().x << rectangle.getPosition().y;
                globalMutex.unlock();

                serverSend();
                packet_counter++;
            }
        }

        time = Clock.restart();
    }
}

void serverListener()
{
    std::cout << "Listening for clients." << std::endl;
    sf::TcpListener listener;
    listener.listen(PORT);
    listener.accept(socket);
    std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
}

void clientListener()
{
    std::string command;
    float offset_x;
    float offset_y;

    while( !quit )
    {
        socket.receive(serverPacket);

        while( !serverPacket.endOfPacket() )
        {
            globalMutex.lock();
            serverPacket >> command >> offset_x >> offset_y;
            v_command = command;
            v_offset_x = offset_x;
            v_offset_y = offset_y;
            globalMutex.unlock();
        }

        serverPacket.clear();
    }
}


void serverSend()
{
    if( serverPacket.getDataSize() > 0 )
    {
        globalMutex.lock();
        socket.send(serverPacket);
        serverPacket.clear();
        globalMutex.unlock();
    }
}
 
« Last Edit: March 10, 2013, 10:01:33 am by io »

io

  • Jr. Member
  • **
  • Posts: 52
  • z/OS by day, SFML by night
    • View Profile
Re: [Updated] Movement Lag on Client
« Reply #7 on: March 10, 2013, 10:00:01 am »
So I've cleaned up the code a touch...


I'm sending a packet with x y coord that will be used as a move offset every 1/3 of a second. 

I've identified that the movement was choppy in my previous post's code on the client end because the move distance offset is larger than compared to the server between window draws. 

The more packets I send per second, the smoother movement is on the client end because the movement offset between draws are smaller -- but this is not a solution... we want to keep @ about 30 packets a second.

I've added interpolation, and this has seemed to help the smoothness a lot -- although you can still notice the client side is slightly sluggish and very very slightly jumpy.  Still trying to figure out how to fix this.

One thing I am really confused about is this:


The black line is the server box movement.  At snap two, we send to the client pos x, pos y (grey line)... because the client doesn't know about the move left and move right of the server he will just go straight down with his interpolation...  If the server sends more data, then our packet size gets bigger and I'm guessing that's bad?  I think I could always send more data and not render it... just use it for any extra calculations and render based on how I am doing it now (the green line)



Current Result



Some Articles I read for reference:
https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking  <-- very good article
http://en.wikipedia.org/wiki/Client-side_prediction
http://www.mindcontrol.org/~hplus/epic/
http://www.racer.nl/tech/multiplayer.html

I've also attached the below code incase you want to grab it and don't want to copy paste
updated tcp_issue.hpp
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <iostream>
#include <string>
#include <cmath>


const float MOVE_SPEED = 70;
const int PORT = 7777;

sf::TcpSocket socket;
sf::Mutex globalMutex;
sf::Packet serverPacket;


bool quit = false;

std::string v_command = "";

float v_offset_x = 0;
float v_offset_y = 0;


void serverListener();
void serverSend();
void clientListener();



void issueServer( std::string mode, std::string method )
{
    std::cout << "Incoming mode: " << mode << std::endl;
    std::cout << "Incoming method: " << method << std::endl;


    sf::Thread serverListenerThread(&serverListener);
    sf::Thread clientListenerThread(&clientListener);



    sf::RenderWindow window(sf::VideoMode(800, 600), "SFML Playground");
    window.setFramerateLimit(60);

    sf::Clock Clock;
    sf::Clock PacketClock;
    int packet_counter = 0;

    sf::Time time;

    sf::RectangleShape rectangle;
    rectangle.setSize(sf::Vector2f(100, 50));
    rectangle.setOutlineColor(sf::Color::Red);
    rectangle.setOutlineThickness(5);
    rectangle.setPosition(10, 20);


    int left_over_x = 0;
    int left_over_y = 0;
    float offset_x = 0;
    float offset_y = 0;
    std::string command = "";

    if( mode.compare("server") == 0 )
        serverListenerThread.launch();
    else
    {
        socket.connect("127.0.0.1",7777);
        clientListenerThread.launch();
    }


    while (window.isOpen())
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                quit = true;

                if( mode.compare("server") == 0 )
                    serverListenerThread.terminate();
                else
                    clientListenerThread.terminate();

                window.close();
            }
        }
        if( mode.compare("server") == 0 )
        {
            if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
                rectangle.move(-1*MOVE_SPEED*time.asSeconds(),0);

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
                rectangle.move(0,1*MOVE_SPEED*time.asSeconds());

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
                rectangle.move(1*MOVE_SPEED*time.asSeconds(),0);

            if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
                rectangle.move(0,-1*MOVE_SPEED*time.asSeconds());

        }
        else //client mode
        {
            if( v_command.compare("move") == 0 )
            {
                globalMutex.lock();
                command = v_command;

                offset_x = v_offset_x - rectangle.getPosition().x;
                offset_y = v_offset_y - rectangle.getPosition().y;

                v_command = "";
                v_offset_x = 0;
                v_offset_y = 0;
                globalMutex.unlock();

                left_over_x = offset_x;
                left_over_y = offset_y;

            } //end of if v_command is "move"

            float move_offset = MOVE_SPEED*time.asSeconds();
            //interpolation
            if( left_over_x != 0 )
            {
                if( left_over_x < 0 )
                {
                    if( (left_over_x + move_offset) < 0 )
                    {
                        rectangle.move(-1*move_offset,0);
                        left_over_x += move_offset;
                    }
                    else
                    {
                        rectangle.move(left_over_x,0);
                        left_over_x = 0;
                    }
                }
                else if( left_over_x > 0 )
                {
                    if( (left_over_x - move_offset) > 0 )
                    {
                        rectangle.move(move_offset,0);
                        left_over_x -= move_offset;
                    }
                    else
                    {
                        rectangle.move(left_over_x,0);
                        left_over_x = 0;
                    }
                }
            }
            if( left_over_y != 0 )
            {
                if( left_over_y < 0 )
                {
                    if( (left_over_y + move_offset) < 0 )
                    {
                        rectangle.move(0,-1*move_offset);
                        left_over_y += move_offset;
                    }
                    else
                    {
                        rectangle.move(0,left_over_y);
                        left_over_y = 0;
                    }
                }
                else if( left_over_y > 0 )
                {
                    if( (left_over_y - move_offset) > 0 )
                    {
                        rectangle.move(0,move_offset);
                        left_over_y -= move_offset;
                    }
                    else
                    {
                        rectangle.move(0,left_over_y);
                        left_over_y = 0;
                    }
                }
            }
            //end of interpolation

            window.draw( rectangle );
            window.display();
            window.clear();

        } //end of client mode if


        if( mode.compare("server") == 0 )
        {
            window.draw( rectangle );
            window.display();
            window.clear();

            if( PacketClock.getElapsedTime().asSeconds() >= 1 )
            {
                packet_counter = 0;
                PacketClock.restart();
            }
            else if( (PacketClock.getElapsedTime().asMilliseconds()/23) > packet_counter )
            {
                serverPacket << "move" << rectangle.getPosition().x << rectangle.getPosition().y;
                serverSend();
                packet_counter++;
            }
        }

        time = Clock.restart();
    }
}

void serverListener()
{
    std::cout << "Listening for clients." << std::endl;
    sf::TcpListener listener;
    listener.listen(PORT);
    listener.accept(socket);
    std::cout << "New client connected: " << socket.getRemoteAddress() << std::endl;
}

void clientListener()
{
    std::string command;
    float offset_x;
    float offset_y;

    while( !quit )
    {
        socket.receive(serverPacket);

        while( !serverPacket.endOfPacket() )
        {
            globalMutex.lock();
            serverPacket >> command >> offset_x >> offset_y;
            v_command = command;
            v_offset_x = offset_x;
            v_offset_y = offset_y;
            globalMutex.unlock();
        }

        serverPacket.clear();
    }
}


void serverSend()
{
    if( serverPacket.getDataSize() > 0 )
    {
        globalMutex.lock();
        socket.send(serverPacket);
        serverPacket.clear();
        globalMutex.unlock();
    }
}
 

[attachment deleted by admin]
« Last Edit: March 11, 2013, 07:39:28 am by io »