1
Network / [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:
http://www.youtube.com/watch?v=7LNnuwdrHUw
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
tcp_issue.hpp
[attachment deleted by admin]
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:
http://www.youtube.com/watch?v=7LNnuwdrHUw
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;
}
#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();
}
}
}
#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]