I'm currently making a P2P two-person co-op game. This is my first experience with network programming.
I started with a simple example where two remote clients each move a square around onscreen, and are updated on the other's movements.
My question pertains to this code in my game loop:
// GAME LOOP
{
...
// Has the player moved?
bool moved = false;
// Handle controls
// Time since last frame
float deltaTime = window.GetFrameTime();
if (window.GetInput().IsKeyDown(sf::Key::Left))
{
mySquare.Move(-MOVE_SPEED * deltaTime, 0.f);
moved = true;
}
else if (window.GetInput().IsKeyDown(sf::Key::Right))
{
mySquare.Move(MOVE_SPEED * deltaTime, 0.f);
moved = true;
}
if (window.GetInput().IsKeyDown(sf::Key::Up))
{
mySquare.Move(0.f, -MOVE_SPEED * deltaTime);
moved = true;
}
else if (window.GetInput().IsKeyDown(sf::Key::Down))
{
mySquare.Move(0.f, MOVE_SPEED * deltaTime);
moved = true;
}
// SEND INFORMATION
sf::Packet outPacket;
outPacket << mySquare.GetPosition().x << mySquare.GetPosition().y;
// Only send packets to the other player if I've updated my square's position.
// NOTE: if I set this to "if (true)", the program works fine.
if (moved)
{
std::stringstream ss;
ss << "Moved";
writeError(ss);
if (socket.Send(outPacket, theirIP, port) != sf::Socket::Done)
{
std::stringstream ss;
ss << "Couldn't send packet";
writeError(ss);
}
}
// GET INFORMATION
sf::Packet inPacket;
if (socket.Receive(inPacket, theirIP, port) != sf::Socket::Done)
{
std::stringstream ss;
ss << "Couldn't send packet";
writeError(ss);
}
else
{
// Received a packet
std::stringstream ss;
ss << "Received a packet";
writeError(ss);
}
float theirX = theirSquare.GetPosition().x;
float theirY = theirSquare.GetPosition().y;
if (!(inPacket >> theirX >> theirY))
{
std::stringstream ss;
ss << "Invalid packet read";
writeError(ss);
}
else
{
// Update the remote player's position
theirSquare.SetPosition(theirX, theirY);
}
...
}
If I set moved to always be "true" (i.e., I'm sending a packet at each iteration of the game loop regardless of whether or not there's a need to) the program works fine. Otherwise, the other player's square never moves at all. I know I'm sending packets, but it's as if the other client is never receiving them.
The single UDP socket I'm using is non-blocking. My thought is the problem is caused because I'm calling Receive() more often than Send(). How does Receive() behave in this scenario? And if I do have to match each Receive() call to a Send() call, how can I determine how often the other client is calling Send()? Would it be better to use a blocking socket in a separate thread instead?