My Code (There are some German Comments in it but I think you will understand it):
Client:
//Moving Cubes 2 Client
//Includes
#include "stdafx.h"
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#include <iomanip>
#include <iostream>
#include <irrlicht.h>
#include <IrrIni.h>
//Libaries
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(lib, "IrrIni.lib")
//Namcespaces
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace gui;
using namespace io;
//Classes
#include "cCube.h"
//Variables
int iClientNumber;
char name[256];
char input[256];
bool binput = false;
bool bThreadRunning = false;
//Functions
void Input(void* UserData)
{
std::cin.getline(input,256);
binput = true;
bThreadRunning = false;
}
;
int main()
{
printf("--------------------Chat--------------------\n\n");
printf("Please enter your Nickname...\n");
std::cin.getline(name,256);
sf::SocketTCP Socket;
printf("\nPlease enter the ip of the Server.\n");
sf::IPAddress ip;
std::cin >> ip;
std::cin.sync();
printf("Connecting to Server...\n");
if(Socket.Connect(12345, ip) != sf::Socket::Done)
{
//Error
printf("Error during connecting!\nProgramm will close in 2 seconds!\n");
Sleep(2000);
Socket.Close();
return 0;
}
printf("Connected to the Server!\n\nChat started!\n\n");
Socket.SetBlocking(false);
sf::Thread Thread(&Input);
sf::Packet Packet;
sf::SelectorTCP Selector;
Selector.Add(Socket);
while(true)
{
if(bThreadRunning == false)
{
bThreadRunning = true;
Thread.Launch();
}
int iSocketReady = Selector.Wait(0.1f);
if(iSocketReady == 1) //Data can be recieved
{
if(Socket.Receive(Packet) == sf::Socket::Done)
{
//Recive Data
bool bGameStarted;
char message[256];
Packet >> bGameStarted;
if(bGameStarted == true)
{
goto Game;
}
Packet >> message; //der Boolwert ist ja schon raus!!!
printf("%s\n",message);
}
else
{
//Eorror during Reciving
//printf("Error during receiving the message...\nThe Server is probably down...\nExit with Enter...\n");
//return 0;
}
}
if(binput == true)
{
binput = false;
char message[256] = "";
strcat(message,name);
strcat(message," : ");
strcat(message,input);
sf::Packet Packet;
Packet << message; //Messsage ins Packet schreiben
if(Socket.Send(Packet) == sf::Socket::Done)
{
//Data Sended
}
}
}
Game:;
//Create Cubes
cCube Cube[4];
//Read used Clients and Client number
Packet >> Cube[0].bUsed >> Cube[1].bUsed >> Cube[2].bUsed >> Cube[3].bUsed >> iClientNumber;
//Socket auf non-blocking stellen
Socket.SetBlocking(false);
//Device erstellen
IrrlichtDevice* device = createDevice(EDT_DIRECT3D9, dimension2d<s32>(640, 480), 32, false, false, false, 0);
if(device == 0)
{
printf("\nError while creating Device! Programm will close in 2 seconds!\n");
Sleep(2000);
return 1;
}
//Pointer erstellen
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* gui = device->getGUIEnvironment();
//Cubes einstellen
for(int i = 0;i < 4; ++i)
{
if(Cube[i].bUsed == true)
{
Cube[i].Startup();
Cube[i].Mesh = smgr->getMesh("Cube.3ds");
Cube[i].Node = smgr->addOctTreeSceneNode(Cube[i].Mesh->getMesh(0));
if(iClientNumber == i)//Wenn man selbst Client i ist
{
Cube[i].Camera = smgr->addCameraSceneNode();
Cube[i].Camera->setPosition(vector3df(0,8,6));
Cube[i].Camera->setTarget(Cube[i].Node->getPosition() + vector3df(0,4,0));
}
}
}
sf::Clock Clock;
while(device->run())//Hauptschleife
{
//Timer
float fElapsedTime = Clock.GetElapsedTime();
Clock.Reset();
//starte Scene
driver->beginScene(true, true, SColor(255,100,100,140));
//Daten empfangen
if(Socket.Receive(Packet) == sf::Socket::Done)
{
int iCube;
int iKeycode;
Packet >> iCube >> iKeycode;
if(iKeycode >= 16)
{
Cube[iCube].bForward = !Cube[iCube].bForward;
iKeycode = iKeycode - 16;
}
if(iKeycode >= 8)
{
Cube[iCube].bBackward = !Cube[iCube].bBackward;
iKeycode = iKeycode - 8;
}
if(iKeycode >= 4)
{
Cube[iCube].bLeft = !Cube[iCube].bLeft;
iKeycode = iKeycode - 4;
}
if(iKeycode >= 2)
{
Cube[iCube].bRight = !Cube[iCube].bRight;
iKeycode = iKeycode - 2;
}
//printf("Recived Data fromClient %i!\n", iCube);
}
//Eigenen Keycode akualisieren
if(device->isWindowFocused() == true)
{
if(Cube[iClientNumber].UpdateKeyStates() == true) //Wenn sich was geändert hat
{
//Daten senden
Packet.Clear();
Packet << iClientNumber << Cube[iClientNumber].iKeycode;
Socket.Send(Packet);
}
}
//Cubes Bewegen
for(int i = 0;i < 4; ++i)
{
if(Cube[i].bUsed == true)
{
Cube[i].Move(fElapsedTime);
}
}
//printf("frame completed!\n");
//Rendern
smgr->drawAll();
gui->drawAll();
driver->endScene();
}
device->drop();
return 0;
}
The Class cCube.h:
#include <windows.h>
#include <IrrIni.h>
class cCube
{
//Private Area
private:
//Variables
float fSpeed;
float fRotSpeed;
char kForward;
char kBackward;
char kLeft;
char kRight;
//Methods
//...
//Puplic Area
public:
//Variables
scene::ICameraSceneNode* Camera;
scene::IAnimatedMesh* Mesh;
scene::ISceneNode* Node;
bool bUsed;
bool bForward;
bool bBackward;
bool bLeft;
bool bRight;
int iKeycode;
//Methods
bool UpdateKeyStates()
{
bool bChanged = false;
iKeycode = 0;
if(GetAsyncKeyState(kForward) & 0x8000)
{
if(bForward == false)
{
bChanged = true;
iKeycode = iKeycode + 16;
}
bForward = true;
}
else
{
if(bForward == true)
{
bChanged = true;
iKeycode = iKeycode + 16;
}
bForward = false;
}
if(GetAsyncKeyState(kBackward) & 0x8000)
{
if(bBackward == false)
{
bChanged = true;
iKeycode = iKeycode + 8;
}
bBackward = true;
}
else
{
if(bBackward == true)
{
bChanged = true;
iKeycode = iKeycode + 8;
}
bBackward = false;
}
if(GetAsyncKeyState(kLeft) & 0x8000)
{
if(bLeft == false)
{
bChanged = true;
iKeycode = iKeycode + 4;
}
bLeft = true;
}
else
{
if(bLeft == true)
{
bChanged = true;
iKeycode = iKeycode + 4;
}
bLeft = false;
}
if(GetAsyncKeyState(kRight) & 0x8000)
{
if(bRight == false)
{
bChanged = true;
iKeycode = iKeycode + 2;
}
bRight = true;
}
else
{
if(bRight == true)
{
bChanged = true;
iKeycode = iKeycode + 2;
}
bRight = false;
}
return bChanged;
}
void Move(float fElapsedTime)
{
vector3df vMovement;
vector3df vNewPos = Node->getPosition();
matrix4 mTransformation;
if(bForward == true)
{
mTransformation = Node->getAbsoluteTransformation();
vMovement = vector3df(0,0,-fSpeed);
mTransformation.rotateVect(vMovement);
vNewPos = vNewPos + vMovement * fElapsedTime;
}
if(bBackward == true)
{
mTransformation = Node->getAbsoluteTransformation();
vMovement = vector3df(0,0,fSpeed);
mTransformation.rotateVect(vMovement);
vNewPos = vNewPos + vMovement * fElapsedTime;
}
if(bLeft == true)
{
mTransformation = Node->getAbsoluteTransformation();
vMovement = vector3df(fSpeed,0,0);
mTransformation.rotateVect(vMovement);
vNewPos = vNewPos + vMovement * fElapsedTime;
}
if(bRight == true)
{
mTransformation = Node->getAbsoluteTransformation();
vMovement = vector3df(-fSpeed,0,0);
mTransformation.rotateVect(vMovement);
vNewPos = vNewPos + vMovement * fElapsedTime;
}
Node->setPosition(vNewPos);
}
void Startup()
{
//Open Ini
IrrIni* ini = createIniFile("config.ini");
//Load Ini and close if error
if(!ini->load())
{
ini->drop();
}
//Read Data
fSpeed = ini->getValueF("cCube","fSpeed");
fRotSpeed = ini->getValueF("cCube","fRotSpeed");
kForward = ini->getValueK("cCube","kForward");
kBackward = ini->getValueK("cCube","kBackward");
kLeft = ini->getValueK("cCube","kLeft");
kRight = ini->getValueK("cCube","kRight");
//Close Ini
ini->drop();
bForward = false;
bBackward = false;
bLeft = false;
bRight = false;
}
};
The Server:
//Moving Cubes 2 Server
//Includes
#include "stdafx.h"
#include <SFML/System.hpp>
#include <SFML/Network.hpp>
#include <iomanip>
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <string>
//Libaries
//Klassen
#include "cClient.h"
int main()
{
sf::SocketTCP Listener;
if(!Listener.Listen(12345))
{
//Error
printf("Error during listening!\nProgramm will close in 2 seconds!\n");
Sleep(2000);
Listener.Close();
return 0;
}
printf("Listening...\n");
cClient Client[4];
for(int i = 0;i < 4; ++i)
{
Client[i].bUsed = false;
}
sf::Packet Packet;
sf::SelectorTCP Selector;
Selector.Add(Listener);
while(true)
{
int iReadableSockets = Selector.Wait(0.01);
for(int i = 0;i < iReadableSockets; ++i)
{
sf::SocketTCP Socket = Selector.GetSocketReady(i);
if(Socket == Listener)
{
//New Connection
for(int i = 0;i < 4; ++i)
{
if(Client[i].bUsed == false)
{
Client[i].bUsed = true;
Listener.Accept(Client[i].Socket);
Selector.Add(Client[i].Socket);
printf("New Client connected (%i)!\n",i);
break; //for schleife verlassen;
}
}
}
else //Socket ist ein Client
{
if(Socket.Receive(Packet) == sf::Socket::Done)
{
char message[256];
Packet >> message;
printf("%s\n",message);
Packet.Clear();
Packet << false << message;
//Message an alle Clients Schicken
for(int i = 0;i < 4; ++i)
{
if(Client[i].bUsed == true)
{
if(Client[i].Socket.Send(Packet) != sf::Socket::Done)
{
//Error
printf("Error while sending the Packet to Client %i!\nClient %i was removed.\n",i,i);
Client[i].bUsed = false;
Selector.Remove(Client[i].Socket);
}
}
}
}
else
{
// Error : we better remove the socket from the selector
//Selector.Remove(Socket); */
}
}
}
//Auf Spielstart überprüfen
if(GetAsyncKeyState('Q') & 0x8000)
{
printf("\nGame started!\n\n");
//Welche Spieler und Clientnummer senden
for(int i = 0;i < 4; ++i)
{
if(Client[i].bUsed == true)
{
Packet.Clear();
Packet << true << Client[0].bUsed << Client[1].bUsed << Client[2].bUsed << Client[3].bUsed << i;
Client[i].Socket.Send(Packet);
}
}
while(true) //Hauptschleife
{
int iReadableSockets = Selector.Wait();
for(int i = 0;i < iReadableSockets; ++i) //Für jeden gesendet Client
{
sf::SocketTCP Socket = Selector.GetSocketReady(i);
Socket.Receive(Packet);
int iClient;
int iKeycode;
Packet >> iClient >> iKeycode;
Packet.Clear();
Packet << iClient << iKeycode;
for(int i = 0;i < 4; ++i)
{
if(Client[i].bUsed == true && i != iClient) //Nicht and den Sender zurücksenden
{
Client[i].Socket.Send(Packet);
}
}
printf("Data from Client %i sended!\n", iClient);
}
}
}
}
return 0;
}
The Class cClient included in the Server only contains the Socket "Socket" and the bolean "bUsed".
Im using Irrlicht as 3d Engine.
This Code works almost fine.
The only Problem is that the Position of the Cubes on each Client is a bit different.