Hoppa till innehållet

Programmera spel i C++ för nybörjare/Nätverksprogrammering 3

Från Wikibooks


OBS!!!

Exemplet i botten fungerar inte, structen skickas aldrig eftersom kontakt inte uppnås mellan sändande och mottagande socket. Om någon som är bättre än jag på nätverksprogrammering hittar felet och ändrar koden vore ingen gladare än jag :)

Mycket av informationen grundar sig på:

http://www.sfml-dev.org/tutorials/1.6/network-packets.php

För att spelexemplen skall fungera föresätts det att du använder SFML 1.6 samt Visual C++ 2010 express.

Problemen

[redigera]

De två föregående kapitlen visade hur man kan skapa enkel kontakt mellan datorer i ett nätverk. Redan med de enkla programmen kan det uppstå problem och det finns främst tre olika felkällor:

1: Värsta problemet kallas "endianism" på engelska. Enkelt beskrivet har det att göra med hur olika processorer tolkar heltal. Skall man säga att 48 = fyrtio och åtta, eller åtta och fyrtio (som t.ex. danskar och tyskar säger)? En enkel processor som driver Windows XP i en 32 bitars miljö hanterar t.ex. 16 bitars talet 48 som: 00000000 00110000 medan en Apple PowerPC som tar emot talet mycket väl kan se samma 16 bitars heltal som 00000011 00000000 (talet 768) eftersom de olika processorfamiljerna hanterar heltal helt olika. Flyttal är normalt sett mycket svårare att skicka och då kan man t.ex. skicka flyttalet i två olika heltalsvärden, heltalet som ett värde och decimalerna som ett annat "heltalsvärde" och programeringsmässigt slå ihop dem vid framkomsten. Läs mer om: flyttal och endianism. Observera att problem med endianism inte uppstår om programmet körs på en enda dator utan bara när samma kod körs på olika datorer med olika processorfamiljer som risken t.ex. är i ett nätverksspel.

2: Olika processorer ger primitiverna olika mycket bits. En long int variabel kan vara 16 bitar på din dator medan en annan dator kan tycka att samma variabel skall vara en 32 bitars long int och då blir siffrorna vid överföringen över nätverket fel.

Lösningen på bägge dessa problemen är att alltid använda SFML:s egna primitiver (se nedan) när du hanterar heltal.

3: Slutligen blir det lätt fel när man skickar- och tar emot större bitar information än enstaka bokstäver och siffror. I standard C++ programmering användes ofta länkade listor (så nu vet du varför du bör lära dig mer om det) där man skickar struct-instanser med information mellan datorerna. SFML använder en egen class som heter sf::Packet som du bör använda när du skapar spel i SFML.

Primitiva typer

[redigera]

Som du vet (eller borde veta) som C++ programmerare kallas alla grundtyperna för primitiva typer. Det inkluderar int, unsigned int, short int, long int osv. Problemet är att dessa typer är generella och kan vara av olika storlek i minnet beroende på vilket system programmet körs på. Eftersom vi måste veta med 100% säkerhet exakt hur mycket minne som en primitiv använder, så kan vi inte skicka meddelanden baserade på generella primitiver mellan datorer i ett nätverk.

Lösningen är att använda SFML:s inbyggda primitiver:

sf::Int8       = 8 bitar heltal 
sf::Uint8      = 8 bitar positivt heltal
sf::Int16      = 16 bitar heltal 
sf::Uint16     = 16 bitar positivt heltal 
sf::Int32      = 32 bitar heltal 
sf::Uint32     = 32 bitar positivt heltal 
(Uint, förkortning för unsigned int = heltal utan signatur som talar om ifall det är positivt eller negativt så det är altid ett värde från 0 och uppåt).

Om du t.ex. definierar

int iEttHeltal = 48; 

kan det alltså bli fel, då är det bättre att skriva

sf::Int8 iEttHeltal = 48;

Enkelt exempel

[redigera]

Hur skickar man då information mellan datorer? Här följer ett superenkelt exempel. Vi använder oss av << och >> symbolerna, precis som när man skall få ut och in information på skärmen, men istället är den överlagrad för att skicka- eller ta emot information över nätverket. Det finns ett "float" värde med så att du skall kunna testa om det förändras mellan datorerna.

// Information som skall skickas

sf::Int8      x = 24;
std::string   s = "hej";
float         f = 59864.265f;

sf::Packet ToSend;
ToSend << x << s << f;

När man sedan skall läsa av informationen skriver man:

// Information som tas emot

sf::Packet Received;

sf::Int8    x;
std::string s;
float       f;
Received >> x >> s >> f;

UDP och TCP

[redigera]

Man skickar, och tar emot, paketet litet olika beroende på om man använder UDP eller TCP protokollet.

// Med TCP sockets

Socket.Send(Packet);
Socket.Receive(Packet);
// Med UDP sockets

Socket.Send(Packet, Address, Port);
Socket.Receive(Packet, Address);


Exempel med en struct

[redigera]

Rent praktiskt nu då, hur gör man för att skicka en information om en struct (eller klass) från en dator till en annan? Vi börjar med att skapa en struct som heter Character:

struct Character
{
    sf::Uint8   Age;
    std::string Name;
    float       Height;
};

Därefter skall vi skapa en ny instans av Character som vi döper till C. Med hjälp av den instansen skall vi kunna skicka och lämna information över nätverket.

sf::Packet& operator <<(sf::Packet& Packet, const Character& C)
{
    return Packet << C.Age << C.Name << C.Height;
}

sf::Packet& operator >>(sf::Packet& Packet, Character& C)
{
    return Packet >> C.Age >> C.Name >> C.Height;
}


I praktiken

[redigera]

Nu skall vi kunna läsa och skicka information, då skapar vi karaktären Bob. Till Bob har vi paketet Packet. Bob innehåller namn, ålder och storlek. När vi skickar information om Bob kopplar vi bara ihop Bob Med paketet:

Character Bob; //Bob skapas
sf::Packet Packet; //Paketet skapas 

//Redigera informationen i paketet

Packet << Bob; //Fyll paketet med information från Bob
Packet >> Bob; //Fyll Bob med information från paketet


Struct eller class?

[redigera]

Du får hela tiden uppmaningen om att skicka information över nätverket i form av en struct, samtidigt som en van C++ programmerare helst jobbar med klasser/class för en ren Objekt Orienterad Programmering. Så varför struct?

Förklaringen är enkel, du kan inte skicka värden som är private eller protected över nätverket, bara värden som är public. Eftersom en struct har samtliga värden satta som public när den skapas minskar risken att göra fel. Du kan naturligtvis använda klasser istället så länge som du kommer ihåg att det bara är public värdena som kommer att kunna användas.

Pojke och ko

[redigera]

Kommer du ihåg övningen där du skulle få en ko att jaga en pojke? Det står i kapitlet: Sprites och spelpjäser 2. I det exemplet styrdes pojken och kon med samma tangentbord, nu är det dags att göra om det till ett nätverksspel där den ena styr kon och den andra styr pojken. För enkelhetens skull låter vi datorn som har pojken agera server. Det vi behöver veta är: Vilken spelare är det (ID), hastigheten i X- och Y-led samt vilken bild som skall visas upp.

class spelare 
{
 public:
   sf::Uint8   ID; //0=pojke, 1=ko
   sf::int32 hastighetX; //Hastighet i X-led, kan vara negativ
   sf::int32 hastighetY; //Hastighet i Y-led, kan vara negativ
   sf::Sprite sprite; //Bilden som representerar pojken eller kon
};


Komplett programkod till enkelt nätverksspel

[redigera]
 //Originalkod från SFML hemsida.
//Bearbetad för att driva ett enkelt spel och inte bara skicka ett ord fram och tillbaka
#include <iostream>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Network.hpp> 
#include <vector> //Måste vara med, vet ej varför

// using namespace std;

#define SFML_STATIC //Se till så att det inte behövs extra DLL-filer

//Skapa en struct som är "budbäraren" mellan datorerna
//Det är den som skickas mellan så att spelarna fr tillgång till varandras värden

/*
struct Position
{
  sf::Uint8   spelarID;
  sf::Int32   xfart;
  sf::Int32   yfart;
};
*/

//Skapa den klass som spelarna pojken och kon kommer från

class spelare 
{
public:
 sf::Uint8   ID; //0=pojke, 1=ko
 sf::Int32 hastighetX; //Hastighet i X-led, kan vara negativ
 sf::Int32 hastighetY; //Hastighet i Y-led, kan vara negativ
 sf::Sprite sprite; //Bilden som representerar pojken eller kon
};

 // Server = styr pojken
 // Client = styr ko

//--------------------------------------------------------------
//Skapa paketen som skall skickas mellan datorerna
//--------------------------------------------------------------

sf::Packet &operator <<(sf::Packet &Packet, const spelare &C)
{
   return Packet << C.ID << C.hastighetX << C.hastighetY;
}

sf::Packet &operator >>(sf::Packet &Packet, spelare &C)
{
   return Packet >> C.ID >> C.hastighetX >> C.hastighetY;
}

 //Funktioner för att köra programmet som en server eller som en klient
 void RunClient(unsigned short Port);
 void RunServer(unsigned short Port);

//---------------------------------------------------------
// Programstart
//---------------------------------------------------------
int main (int argc, char **argv)

{  //Början av programkörningen
char Who = 'Z'; //Avgör om man skall vara klient eller server
float ElapsedTime = 0.0f; //Skapar en konstant för att hålla hastigheten likvärdig på olika datorer

//--------------------------------------------------------
// Visa upp lokal adress, troligen 192.168.x.x eller 10.100.x.x eller 169.254.x.x
//-------------------------------------------
 sf::IPAddress Address1 = sf::IPAddress::GetLocalAddress();
 std::string IP1 = Address1.ToString();
 std::cout<<"Din egen lokala IP-adress = " << IP1 << std::endl << std::endl;

//Skapa paket
sf::Packet ToSend;//Paketet skapas för att skicak uppgifter
sf::Packet Received; //Paket att ta emot uppgifter skapas

//Skapa en port som vi skall använda till vår socket
//(portarna < 1024 är reserverade)
   const unsigned short Port = 2435;


   // Client eller server ?------------------------------------------------
   std::cout << "Vill du vara server ('s') eller en klient ('c') ? ";
   std::cin  >> Who;

   if (Who == 's')
       RunServer(Port);
   else
       RunClient(Port);

//Skapa inte spelfönstret innan anslutning skett
sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Test - nätverksspel"); 

//Skapa en pojke
spelare pojke; //pojke blir en kopia av klassen spelare
pojke.hastighetX = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”.
pojke.hastighetY = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”.
pojke.ID=0;

//Skapa en ko
spelare ko; //ko blir en kopia av klassen spelare
ko.hastighetX = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”.
ko.hastighetY = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”.
ko.ID=1;

//Skapa bildhållarna
sf::Image pojkbild; 
sf::Image kobild;

//Ladda in bildfilerna
pojkbild.LoadFromFile("boy.png");
kobild.LoadFromFile("cow.png");

//Dela ut bild till ko
ko.sprite.SetImage(kobild);
ko.sprite.SetPosition(500,500);

//Dela ut bild till pojke
pojke.sprite.SetImage(pojkbild);
pojke.sprite.SetPosition(100,100);

while(App.IsOpened())
{ //Gameloop
ElapsedTime=App.GetFrameTime(); //Skapar en konstant för att hålla hastigheten likvärdig på olika datorer
sf::Event Event; 
      
while (App.GetEvent(Event)) // Ta hand om händelser 
 { //while 2

    if (Event.Type == sf::Event::Closed) //kryssat på [x] symbolen? stäng programmet
       App.Close(); 

    if (Event.Type == sf::Event::KeyPressed) // En tangent har tryckts ner
           { //if 1
             if (Event.Key.Code == sf::Key::Escape) // ESC tangenten = stäng programmet
                  App.Close(); 


             } //slut if 1

} //slut, while 2

if (Who == 's')
{ //Du är en server
//X-led värden
if (App.GetInput().IsKeyDown(sf::Key::Left)) 
 pojke.hastighetX= -100;
               
if (App.GetInput().IsKeyDown(sf::Key::Right)) 
pojke.hastighetX= 100;
 //Spring ingenstans om inte knapparna är nedtryckta
if (!App.GetInput().IsKeyDown(sf::Key::Left) && !App.GetInput().IsKeyDown(sf::Key::Right)) 
pojke.hastighetX= 0;

if (App.GetInput().IsKeyDown(sf::Key::Up)) 
pojke.hastighetY= -100;
                                        
if (App.GetInput().IsKeyDown(sf::Key::Down)) 
pojke.hastighetY= 100;

  //Spring ingenstans om inte knapparna är nedtryckta
if (!App.GetInput().IsKeyDown(sf::Key::Up) && !App.GetInput().IsKeyDown(sf::Key::Down)) 
pojke.hastighetY= 0;
} //Du är en server

 if ( Who != 's')
{ //Du är en klient
//X-led värden
if (App.GetInput().IsKeyDown(sf::Key::Left)) 
 ko.hastighetX= -100;
               
if (App.GetInput().IsKeyDown(sf::Key::Right)) 
ko.hastighetX= 100;
 //Spring ingenstans om inte knapparna är nedtryckta
if (!App.GetInput().IsKeyDown(sf::Key::Left) && !App.GetInput().IsKeyDown(sf::Key::Right)) 
ko.hastighetX= 0;

if (App.GetInput().IsKeyDown(sf::Key::Up)) 
ko.hastighetY= -100;
                                        
if (App.GetInput().IsKeyDown(sf::Key::Down)) 
ko.hastighetY= 100;

  //Spring ingenstans om inte knapparna är nedtryckta
if (!App.GetInput().IsKeyDown(sf::Key::Up) && !App.GetInput().IsKeyDown(sf::Key::Down)) 
ko.hastighetY= 0;
} //Du är en klient


//Flytta spelpjäserna
pojke.sprite.Move(pojke.hastighetX * ElapsedTime,pojke.hastighetY * ElapsedTime);
ko.sprite.Move(ko.hastighetX * ElapsedTime,ko.hastighetY* ElapsedTime);

//Rita ut ändringarna på skärmen
App.Clear();    
App.Draw(pojke.sprite);
App.Draw(ko.sprite);

App.Display();
} //Gameloop
return 0;

} //slut på programkörningen

void RunClient(unsigned short Port)
{
   // Fråga efter serveradressen
   sf::IPAddress ServerAddress;
   do
   {
       std::cout << "Skriv in IP adress eller namn att ansluta till : ";
       std::cin  >> ServerAddress;
   }
   while (!ServerAddress.IsValid());

   // Skapa en TCP socket för att samarbeta med servern
   sf::SocketTCP Client;

   // Anslut till servern
   if (Client.Connect(Port, ServerAddress) != sf::Socket::Done)
       return;
   std::cout << "Ansluten till server " << ServerAddress << std::endl;

	  sf::Packet RegularPacket;
   if (Client.Receive(RegularPacket) != sf::Socket::Done)
       return;

   spelare C1;
   if (RegularPacket >> C1)
   {
       std::cout << "Character received from the server (regular packet) : " << std::endl;
       std::cout << C1.ID << "ID, " << C1.hastighetX << " hastighet x, " << C1.hastighetY << " hastighet y" << std::endl;
   }

}
//Serverfunktionerna

 void RunServer(unsigned short Port)
{
   // Skapa en TCP socket för att kommunicera med klienterna
   sf::SocketTCP Server;

   // Lyssna på en port för inkommande anrop
   if (!Server.Listen(Port))
       return;
   std::cout << "Servern lyssnar på port " << Port << ", väntar på anslutning... " << std::endl;

   // Väntar på kontakt
   sf::IPAddress ClientAddress;
   sf::SocketTCP Client;
   Server.Accept(Client, &ClientAddress);
   std::cout << "Klient ansluten : " << ClientAddress << std::endl;
 
   spelare C1 = {1, 100, 100};
   sf::Packet RegularPacket;
   RegularPacket << C1;
   if (Client.Send(RegularPacket) != sf::Socket::Done)
       return;

   std::cout << "Spelare skickad till klienten: " << std::endl;
   std::cout << C1.ID << "ID, " << C1.hastighetX  << " hastighet x, " << C1.hastighetY << " hastighet y," << std::endl;

}

Skrotkod här nedanför!

[redigera]
//Originalkod från SFML hemsida.
//Bearbetad för att driva ett enkelt spel och inte bara skicka ett ord fram och tillbaka
#include <iostream>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Network.hpp> 
#include <vector>

// using namespace std;

#define SFML_STATIC //Se till så att det inte behövs extra DLL-filer


//Skapa den klass som spelarna pojken och kon kommer från

class spelare 
{
public:
 sf::Uint8   ID; //0=pojke, 1=ko
 sf::Int32 hastighetX; //Hastighet i X-led, kan vara negativ
 sf::Int32 hastighetY; //Hastighet i Y-led, kan vara negativ
 sf::Sprite sprite; //Bilden som representerar pojken eller kon
};

 // Server = styr pojken
 // Client = styr ko

//--------------------------------------------------------------
//Skapa paketen som skall skickas mellan datorerna
//--------------------------------------------------------------

sf::Packet &operator <<(sf::Packet &Packet, const spelare &C)
{
   return Packet << C.ID << C.hastighetX << C.hastighetY;
}

sf::Packet &operator >>(sf::Packet &Packet, spelare &C)
{
   return Packet >> C.ID >> C.hastighetX >> C.hastighetY;
}


// Skapa en global TCP socket 
sf::SocketTCP spelsocket;

 //Funktioner för att köra programmet som en server eller som en klient
 void RunClient(unsigned short Port);
 void RunServer(unsigned short Port);

 void PlayerSend(class spelare &s);
 void PlayerRecieve( class spelare &s);

//---------------------------------------------------------
// Programstart
//---------------------------------------------------------
int main (int argc, char **argv)
{  //Början av programkörningen

char Who = 'Z'; //Avgör om man skall vara klient eller server
float ElapsedTime = 0.0f; //Skapar en konstant för att hålla hastigheten likvärdig på olika datorer
spelsocket.SetBlocking(false); //Tar emot utan avbrott


//--------------------------------------------------------
// Visa upp lokal adress, troligen 192.168.x.x eller 10.100.x.x eller 169.254.x.x
//-------------------------------------------
 sf::IPAddress Address1 = sf::IPAddress::GetLocalAddress();
 std::string IP1 = Address1.ToString();
 std::cout<<"Din egen lokala IP-adress = " << IP1 << std::endl << std::endl;


 
//Skapa en port som vi skall använda till vår socket
//(portarna < 1024 är reserverade)
   const unsigned short Port = 2435;



   // Client eller server ?------------------------------------------------
   std::cout << "Vill du vara server ('s') eller en klient ('c') ? ";
   std::cin  >> Who;

   if (Who == 's')
       RunServer(Port); //Vänta
   else
       RunClient(Port); //Anslut till server

//Skapa inte spelfönstret innan anslutning skett
sf::RenderWindow App(sf::VideoMode(800, 600, 32), "Test - nätverksspel"); 

//Skapa en pojke
spelare pojke; //pojke blir en kopia av klassen spelare
pojke.hastighetX = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”.
pojke.hastighetY = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”.
pojke.ID=0;

//Skapa en ko
spelare ko; //ko blir en kopia av klassen spelare
ko.hastighetX = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”.
ko.hastighetY = 0; //grundhastighet, skall multipliceras med ”ElapsedTime ”.
ko.ID=1;

//Skapa bildhållarna
sf::Image pojkbild; 
sf::Image kobild;

//Ladda in bildfilerna
pojkbild.LoadFromFile("boy.png");
kobild.LoadFromFile("cow.png");

//Dela ut bild till ko
ko.sprite.SetImage(kobild);
ko.sprite.SetPosition(500,500);

//Dela ut bild till pojke
pojke.sprite.SetImage(pojkbild);
pojke.sprite.SetPosition(100,100);

while(App.IsOpened())
{ //Gameloop
ElapsedTime=App.GetFrameTime(); //Skapar en konstant för att hålla hastigheten likvärdig på olika datorer
sf::Event Event; 
      
while (App.GetEvent(Event)) // Ta hand om händelser 
 { //while 2

    if (Event.Type == sf::Event::Closed) //kryssat på [x] symbolen? stäng programmet
       App.Close(); 

    if (Event.Type == sf::Event::KeyPressed) // En tangent har tryckts ner
           { //if 1
             if (Event.Key.Code == sf::Key::Escape) // ESC tangenten = stäng programmet
                  App.Close(); 


             } //slut if 1

} //slut, while 2

if (Who == 's')
{ //Du är en server
  //X-led värden
  if (App.GetInput().IsKeyDown(sf::Key::Left)) 
  {
  pojke.hastighetX= -100;
  PlayerSend(pojke); //Skicka ut var pojken är
  }
               
  if (App.GetInput().IsKeyDown(sf::Key::Right)) 
  {
  pojke.hastighetX= 100;
  PlayerSend(pojke); //Skicka ut var pojken är
  }

  //Spring ingenstans om inte knapparna är nedtryckta
  if (!App.GetInput().IsKeyDown(sf::Key::Left) && !App.GetInput().IsKeyDown(sf::Key::Right)) 
  {
  pojke.hastighetX= 0;
  PlayerSend(pojke); //Skicka ut var pojken är
  }

  if (App.GetInput().IsKeyDown(sf::Key::Up)) 
  {
  pojke.hastighetY= -100;
  PlayerSend(pojke); //Skicka ut var pojken är
  }
                                        
  if (App.GetInput().IsKeyDown(sf::Key::Down))
  {
  pojke.hastighetY= 100;
  PlayerSend(pojke); //Skicka ut var pojken är
  }

  //Spring ingenstans om inte knapparna är nedtryckta
  if (!App.GetInput().IsKeyDown(sf::Key::Up) && !App.GetInput().IsKeyDown(sf::Key::Down)) 
  {
  pojke.hastighetY= 0;
  PlayerSend(pojke); //Skicka ut var pojken är
  }

  //Ta emot motspelarens värde
  PlayerRecieve(ko);

} //Du är en server

 if ( Who != 's')
{ //Du är en klient
//X-led värden
  if (App.GetInput().IsKeyDown(sf::Key::Left)) 
  {
  ko.hastighetX= -100;
  PlayerSend(ko); //Skicka ut var kon är
  }
               
  if (App.GetInput().IsKeyDown(sf::Key::Right)) 
  {
  ko.hastighetX= 100;
  PlayerSend(ko); //Skicka ut var kon är
  }

  //Spring ingenstans om inte knapparna är nedtryckta
  if (!App.GetInput().IsKeyDown(sf::Key::Left) && !App.GetInput().IsKeyDown(sf::Key::Right)) 
  {
  ko.hastighetX= 0;
  PlayerSend(ko); //Skicka ut var kon är
  }

  if (App.GetInput().IsKeyDown(sf::Key::Up)) 
  {
  ko.hastighetY= -100; 
  PlayerSend(ko); //Skicka ut var kon är
  }
                                        
  if (App.GetInput().IsKeyDown(sf::Key::Down)) 
  {
  ko.hastighetY= 100;
  PlayerSend(ko); //Skicka ut var kon är
  }

  //Spring ingenstans om inte knapparna är nedtryckta
  if (!App.GetInput().IsKeyDown(sf::Key::Up) && !App.GetInput().IsKeyDown(sf::Key::Down))
  {
  ko.hastighetY= 0;
  PlayerSend(ko); //Skicka ut var kon är
  }

 PlayerRecieve(pojke);

} //Du är en klient


//Flytta spelpjäserna
pojke.sprite.Move(pojke.hastighetX * ElapsedTime,pojke.hastighetY * ElapsedTime);
ko.sprite.Move(ko.hastighetX * ElapsedTime,ko.hastighetY* ElapsedTime);


//Rita ut ändringarna på skärmen
App.Clear();    
App.Draw(pojke.sprite);
App.Draw(ko.sprite);

App.Display();
} //Gameloop
return 0;

} //slut på programkörningen

void RunClient(unsigned short Port)
{ 
   // Fråga efter serveradressen
   sf::IPAddress ServerAddress;
   do
   {
       std::cout << "Skriv in IP adress eller namn att ansluta till : ";
       std::cin  >> ServerAddress;
   }
   while (!ServerAddress.IsValid());

	//Socket spelsocket skapas som global variabel

   // Anslut till servern
   if (spelsocket.Connect(Port, ServerAddress) != sf::Socket::Done)
       return;
   std::cout << "Ansluten till server " << ServerAddress << std::endl;

}
//Serverfunktionerna

 void RunServer(unsigned short Port)
{

	 //Socket spelsocket skapas som global variabel

   // Lyssna på en port för inkommande anrop
   if (!spelsocket.Listen(Port))
       return;
   std::cout << "Servern lyssnar på port " << Port << ", väntar på anslutning... " << std::endl;

   // Väntar på kontakt
   sf::IPAddress ClientAddress;
   sf::SocketTCP Client;
   spelsocket.Accept(Client, &ClientAddress);
   std::cout << "Klient ansluten : " << ClientAddress << std::endl;

}

 //Skicka iväg informationen om spelaren till mottagaren
 void PlayerSend(class spelare &s)
{
sf::Packet ToSend; //Skapa paket
ToSend << s.ID << s.hastighetX << s.hastighetY; //Fyll paketet

	   if (spelsocket.Send(ToSend) != sf::Socket::Done) //Paketet skickas
       return;
}

 void PlayerRecieve(class spelare &s)

 {
	
	sf::Packet Received;
	spelare R;
	if (spelsocket.Receive(Received) != sf::Socket::Done)
	return;

	if (Received >> R)
   {
		//Kopiera över värdena till angiven spelare
	    s.hastighetX = R.hastighetX;
	    s.hastighetY = R.hastighetY;
	}
			else 
   {std::cout << "Nothing recieved: " << std::endl;}
		  
 }