我对SFML网络很陌生,并且已经有很长一段时间用于pong克隆了。我写了两个程序:客户端和服务器。我的问题是两者似乎没有在彼此之间正确地发送/接收数据。我检查过,我的端口正确绑定,我的数据包不大于最大数据报大小。但是,当我检查socket.send(...)
对Socket::Done
的状态时,它会发现数据未发送。有什么我做错了吗?
客户端:
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <ctime>
#include <iostream>
#include <sstream>
using namespace sf;
using namespace std;
template <typename T>
string NumberToString ( T Number )
{
stringstream ss;
ss << Number;
return ss.str();
}
int main()
{
cout << "Enter an IP address: ";
string address;
cin >> address;
IpAddress other = address;
//window
RenderWindow window(VideoMode(800, 600), "Pong");
//player 1
RectangleShape rect(Vector2f(40, 130));
rect.setPosition(40, 50);
rect.setFillColor(Color::Blue);
rect.setOutlineThickness(4);
rect.setOutlineColor(Color::Black);
//player 2
RectangleShape player2(Vector2f(40, 130));
player2.setPosition(520,50);
player2.setFillColor(Color(255, 0, 208));
player2.setOutlineThickness(4);
player2.setOutlineColor(Color::Black);
//ball
CircleShape ball(50, 50);
ball.setOrigin(ball.getRadius(), ball.getRadius());
ball.setPosition(400, 300);
ball.setFillColor(Color(255, 255, 0));
ball.setOutlineThickness(4);
ball.setOutlineColor(Color::Black);
//score
Uint16 score1;
Uint16 score2;
//socket
short unsigned int port = 54000;
UdpSocket socket;
if (socket.bind(port) != Socket::Done)
{
cout << "Error\n";
}
socket.setBlocking(false);
//text
Font font;
font.loadFromFile("SF Electrotome.ttf");
Text score;
score.setFont(font);
score.setColor(Color::Black);
score.setString("0 0");
score.setCharacterSize(16);
score.setPosition(300, 50);
//loop
bool running = true;
while (running) //game loop
{
Event ev;
while (window.pollEvent(ev)) //event loop
{
switch (ev.type)
{
case Event::Closed: //quit on click x
running = false;
break;
case Event::KeyPressed:
if (ev.key.code == Keyboard::Escape) //quit on escape
{
running = false;
}
break;
}
}
//get that sweet info
Packet received;
socket.receive(received, other, port);
float player1pos[2];
float player2pos[2];
float ballpos[2];
received >> player1pos[0] >> player1pos[1] >> player2pos[0] >> player2pos[1] >>
ballpos[0] >> ballpos[1] >> score1 >> score2;
rect.setPosition(player1pos[0], player1pos[1]);
player2.setPosition(player2pos[0], player2pos[1]);
ball.setPosition(ballpos[0], ballpos[1]);
//scores
score.setString(NumberToString(score1) + " " + NumberToString(score2));
//handle player input
if (Keyboard::isKeyPressed(Keyboard::Up))
{
if (rect.getPosition().y >= 0) //keep in bounds
{
Packet p;
Uint16 direction = 1;
p << direction;
socket.send(p, other, port);
}
} else if (Keyboard::isKeyPressed(Keyboard::Down)){
if (player2.getPosition().y + player2.getSize().y <= 600) //keep in bounds
{
Packet p;
Uint16 direction = 2;
p << direction;
socket.send(p, other, port);
}
}
//draw everything
window.clear(Color::White);
window.draw(rect);
window.draw(player2);
window.draw(ball);
window.draw(score);
window.display();
}
return 0;
}
服务器:
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <cstdlib>
#include <ctime>
#include <sstream>
#include <iostream>
using namespace sf;
using namespace std;
template <typename T>
string NumberToString ( T Number )
{
stringstream ss;
ss << Number;
return ss.str();
}
int main()
{
cout << "Enter an IP address: ";
string address;
cin >> address;
IpAddress other(address);
if (other == IpAddress::None)
{
cout << "Error loading ip";
}
srand(time(NULL));
//window
RenderWindow window(VideoMode(800, 600), "Pong");
//player 1
RectangleShape rect(Vector2f(40, 130));
rect.setPosition(40, 50);
rect.setFillColor(Color::Blue);
rect.setOutlineThickness(4);
rect.setOutlineColor(Color::Black);
//player 2
RectangleShape player2(Vector2f(40, 130));
player2.setPosition(720, 50);
player2.setFillColor(Color(255, 0, 208));
player2.setOutlineThickness(4);
player2.setOutlineColor(Color::Black);
//ball
CircleShape ball(50, 50);
ball.setOrigin(ball.getRadius(), ball.getRadius());
ball.setPosition(400, 300);
ball.setFillColor(Color(255, 255, 0));
ball.setOutlineThickness(4);
ball.setOutlineColor(Color::Black);
float randX = (rand() % 5 + 1);
float randY = (rand() % 5 + 1);
Vector2f ballVelocity(randX/15, randY/15);
//score
Uint16 score1 = 0;
Uint16 score2 = 0;
//text
Font font;
font.loadFromFile("SF Electrotome.ttf");
Text score;
score.setFont(font);
score.setColor(Color::Black);
score.setString("0 0");
score.setCharacterSize(16);
score.setPosition(350, 50);
//network socket
UdpSocket socket;
short unsigned int sendPort = 54000;
if (!(socket.bind(sendPort) == Socket::Done))
{
cout << "Error";
}
socket.setBlocking(false);
//loop
bool running = true;
while (running) //game loop
{
Event ev;
while (window.pollEvent(ev)) //event loop
{
switch (ev.type)
{
case Event::Closed: //quit on click x
running = false;
break;
case Event::KeyPressed:
if (ev.key.code == Keyboard::Escape) //quit on escape
{
running = false;
}
break;
}
}
//handle player input
if (Keyboard::isKeyPressed(Keyboard::Up))
{
if (rect.getPosition().y >= 0) //keep in bounds
{
rect.move(0, -0.2);
}
} else if (Keyboard::isKeyPressed(Keyboard::Down)){
if (rect.getPosition().y + rect.getSize().y <= 600) //keep in bounds
{
rect.move(0, 0.2);
}
}
//handle player 2 input
Uint16 direction;
IpAddress sender;
Packet received;
if ((socket.receive(received, other, sendPort)) != Socket::Done)
{
cout << "Error receiving data";
}
received >> direction;
if (sender == other)
{
switch (direction)
{
case 1:
player2.move(0, -0.2);
break;
case 2:
player2.move(0, 0.2);
break;
}
}
//handle ball direction changes
if ((ball.getPosition().y - ball.getRadius() <= 0) || (ball.getPosition().y + ball.getRadius() >= 600)) { //top or bottom
ballVelocity.y *= -1;
} else if ((ball.getPosition().x + ball.getRadius() >= 800)) { //right edge
ballVelocity.x *= -1;
score1 += 1;
} else if (ball.getPosition().x - ball.getRadius() <= 0) { //left edge
ballVelocity.x *= -1;
score2 += 1;
}
ball.move(ballVelocity);
//handle player/ball collisions
FloatRect player1Box = rect.getGlobalBounds();
FloatRect ballBox = ball.getGlobalBounds();
FloatRect player2Box = player2.getGlobalBounds();
if (player1Box.intersects(ballBox) || player2Box.intersects(ballBox))
{
ballVelocity.x *= -1;
}
//set score
score.setString(NumberToString(score1) + " " + NumberToString(score2));
//send everything over
Packet p;
p << rect.getPosition().x << rect.getPosition().y << player2.getPosition().x << player2.getPosition().y <<
ball.getPosition().x << ball.getPosition().y << score1 << score2;
socket.send(p, other, sendPort);
//draw everything
window.clear(Color::White);
window.draw(rect);
window.draw(player2);
window.draw(ball);
window.draw(score);
window.display();
}
return 0;
}