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
http://www.youtube.com/watch?v=8IaDKJr2fJASome Articles I read for reference:
https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking <-- very good article
http://en.wikipedia.org/wiki/Client-side_predictionhttp://www.mindcontrol.org/~hplus/epic/http://www.racer.nl/tech/multiplayer.htmlI'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]