#include "stdafx.h"
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#include <iostream>
using namespace std;
using sf::SocketUDP;
using sf::IPAddress;
using sf::Packet;
class Input
{
public:
Input():
left(false), right(false), up(false), down(false)
{}
bool left;
bool right;
bool up;
bool down;
void update(const sf::Input& input);
};
void Input::update(const sf::Input& input)
{
left = input.IsKeyDown(sf::Key::Left);
right = input.IsKeyDown(sf::Key::Right);
up = input.IsKeyDown(sf::Key::Up);
down = input.IsKeyDown(sf::Key::Down);
}
class Player
{
public:
Player(float x, float y, float width, float height, float xSpeed, float ySpeed):
xPos(x), yPos(y), width(width), height(height), xSpeed(xSpeed), ySpeed(ySpeed)
{}
Input input;
float xPos;
float yPos;
float height;
float width;
float xSpeed;
float ySpeed;
void move(float delta);
void draw(sf::RenderWindow & app);
};
void Player::draw(sf::RenderWindow & app)
{
glBegin(GL_QUADS);
glVertex2f(xPos, yPos);
glVertex2f(xPos + width, yPos);
glVertex2f(xPos + width, yPos + height);
glVertex2f(xPos, yPos + height);
glEnd();
}
void Player::move(float delta)
{
int xDir = 0;
int yDir = 0;
if(input.left ^ input.right)
{
if(input.left)
xDir = -1;
else
xDir = 1;
}
if(input.up ^ input.down)
{
if(input.up)
yDir = 1;
else
yDir = -1;
}
xPos += xDir * xSpeed * delta;
yPos += yDir * ySpeed * delta;
}
sf::Packet& operator>>(sf::Packet& packet, Input& inp)
{
packet >> inp.left >> inp.right >> inp.up >> inp.down;
return packet;
}
sf::Packet& operator<<(sf::Packet& packet, const Input& inp)
{
packet << inp.left << inp.right << inp.up << inp.down;
return packet;
}
class Game
{
public:
Game();
int run();
private:
void handleEvents();
void update(float delta);
void updateGameState(float delta);
void initNetwork();
void receiveClientInput();
void sendClientInput();
void sendGameState();
void receiveAndSyncGameState();
Player myServerPlayer;
Player myClientPlayer;
bool myIsServer;
bool myIsConnected;
sf::IPAddress myIPAddress;
sf::SocketUDP mySocket;
sf::RenderWindow * myWindow;
static const unsigned short PORT;
static const float UPDATE_RATE;
};
const unsigned short Game::PORT = 3456;
const float Game::UPDATE_RATE = 1.f/100; //TODO different rates for update and networking
Game::Game():
myServerPlayer(-1, -1, 0.2f, 0.2f, 0.35f, 0.35f),
myClientPlayer(0.5f, 0.5f, 0.2f, 0.2f, 0.35f, 0.35f),
myIsServer(false),
myWindow(0),
myIsConnected(false)
{
}
void Game::initNetwork()
{
while(true)
{
cout << "Server mode(s) or Client mode (c)? ";
string str;
cin >> str;
if(str == "s")
{
myIsServer = true;
break;
}
else if(str == "c")
{
myIsServer = false;
break;
}
}
if(!mySocket.Bind(PORT))
{
cerr << "Error binding socket to port << PORT";
}
cout << "Enter ip: ";
string line;
cin >> line;
myIPAddress = IPAddress(line);
mySocket.SetBlocking(false);
myIsConnected = true;
}
void Game::handleEvents()
{
sf::Event event;
while (myWindow->GetEvent(event))
{
switch(event.Type)
{
case sf::Event::Closed:
myWindow->Close();
break;
case sf::Event::Resized:
glViewport(0, 0, event.Size.Width, event.Size.Height);
break;
default:
break;
}
}
}
int Game::run()
{
initNetwork();
myWindow = new sf::RenderWindow(sf::VideoMode(800, 600, 32), "SFML Window");
float restTime = 0;
while(myWindow->IsOpened())
{
handleEvents();
restTime += myWindow->GetFrameTime();
while(restTime > UPDATE_RATE)
{
restTime -= UPDATE_RATE;
update(UPDATE_RATE);
}
glClear(GL_COLOR_BUFFER_BIT);
myClientPlayer.draw(*myWindow);
myServerPlayer.draw(*myWindow);
myWindow->Display();
}
return 0;
}
void Game::sendClientInput()
{
sf::Packet toSend;
toSend << myClientPlayer.input;
unsigned short port = PORT;
sf::Socket::Status status = mySocket.Send(toSend, myIPAddress, port);
switch(status)
{
case sf::Socket::Disconnected:
cout << "Disconnected" << endl;
myIsConnected = false;
break;
case sf::Socket::Error:
cout << "Error sending input" << endl;
break;
case sf::Socket::Done:
break;
case sf::Socket::NotReady:
//try again next time;
break;
}
}
void Game::receiveClientInput()
{
sf::Packet toReceive;
unsigned short port = PORT;
sf::Socket::Status status = mySocket.Receive(toReceive, myIPAddress, port);
switch(status)
{
case sf::Socket::Disconnected:
cout << "Disconnected" << endl;
myIsConnected = false;
break;
case sf::Socket::Error:
cout << "Error receiving" << endl;
break;
case sf::Socket::Done:
toReceive >> myClientPlayer.input;
break;
case sf::Socket::NotReady:
//try again next time;
break;
}
}
void Game::sendGameState()
{
sf::Packet toSend;
toSend << myServerPlayer.xPos << myServerPlayer.yPos << myServerPlayer.input
<< myClientPlayer.xPos << myClientPlayer.yPos;
sf::Socket::Status status = mySocket.Send(toSend, myIPAddress, PORT);
switch(status)
{
case sf::Socket::Disconnected:
cout << "Disconnected" << endl;
myIsConnected = false;
break;
case sf::Socket::Error:
cout << "Error sending" << endl;
break;
case sf::Socket::Done:
break;
case sf::Socket::NotReady:
//try again next time;
break;
}
}
void Game::receiveAndSyncGameState()
{
sf::Packet toReceive;
unsigned short port = PORT;
sf::Socket::Status status = mySocket.Receive(toReceive, myIPAddress, port);
switch(status)
{
case sf::Socket::Disconnected:
cout << "Disconnected" << endl;
myIsConnected = false;
break;
case sf::Socket::Error:
cout << "Error receiving game state" << endl;
break;
case sf::Socket::Done:
toReceive >> myServerPlayer.xPos >> myServerPlayer.yPos >> myServerPlayer.input
>> myClientPlayer.xPos >> myClientPlayer.yPos;
//no interpolation yet
break;
case sf::Socket::NotReady:
//try again next time;
break;
}
}
void Game::updateGameState(float delta)
{
myClientPlayer.move(delta);
myServerPlayer.move(delta);
}
void Game::update(float delta)
{
if(myIsServer)
{
myServerPlayer.input.update(myWindow->GetInput());
if(myIsConnected)
{
receiveClientInput();
updateGameState(delta);
sendGameState();
}
}
else
{
myClientPlayer.input.update(myWindow->GetInput());
if(myIsConnected)
{
sendClientInput();
receiveAndSyncGameState();
}
}
}
int main()
{
Game game;
return game.run();
}