20-10-2009 21:47:38
- nabouill
- Membres

- Date d'inscription:
- Messages: 242
- IP: 77.195.53.232
- Courriel
[intro]
: 
RakNet est un moteur de réseau multiplateforme écrit en C++ et pensé pour le domaine du jeu vidéo principalement. Je vous laisse le soin de lire la licence
/i\\Licence RakNet/i\\
RakNet à l’avantage d’être assez simple à utiliser et est relativement rapide. En plus les fichiers sources sont très très bien commentés.
Ici, je ne vais pas faire un tuto très détaillé de toutes les fonctions de RakNet, mais simplement utiliser les notions de base, qui seront déjà suffisantes pour créer une petite application en réseaux. Pour les détails, n’hésiter pas a faire un tour dans la
/i\\documentation RakNet./i\\
Le déroulement du tuto :
ancres->set(Les préparatifs, Ma vision de l’utilisation de RakNet dans mes applications, Introduction rapide au réseau, Un paquet !, Les fonctions principal que l’on va utiliser, 1er application : une petite console pour comprendre, 2e application : RakNet et Irrlicht – Ninja !);
[/intro]
ancres->create(Les préparatifs);
Commençons par télécharger RakNet
Download RakNet
Compilez le avec votre IDE favoris (les projets sont créent et configuré pour les IDE les plus courant, juste a lancer la compilation et c’est réglé). Récupérez la DLL pour vos projets.
On peut utiliser RakNet de 2 façons :
- Replica : Un système qui permet de répliquer la même chose sur tous les clients connectés au serveur automatiquement. (Le système replica utilise le système BitStream)
- BitStream : Une autre façon, celle de tout faire a la main. A nous d’écrire les données à envoyer, et de les lire. Il faut une bonne organisation pour ne pas lire n’importe quoi à la réception.
Nous allons nous utiliser le BlitStream. D’abord parce que je préfère bien contrôler les paquets, savoir ce que j’envoie et quand je l’envoie. Mais aussi, parce que je ne sais pas encore très bien utiliser le Replica
ancres->create( Ma vision de l’utilisation de RakNet dans mes applications);
Personnellement, je préfère créer une application « serveur » et une application « client ».
On peut très bien faire une application qui fait les deux, mais sur une application assez lourde, on a vite fait de s’emmêler les pédales sur la gestion des paquets. Chacun son rôle !
ancres->create( Introduction rapide au réseau);
Les machines doivent être toutes reliées sur un réseau (qu’il soit local ou internet) évidement.
Pour que les machines communiquent entre elle, elle utilise une adresse IP et un numéro de port.
- L’adresse IP :
Il faut donc impérativement connaitre l’adresse IP du serveur pour pouvoir si connecter.
Si on veut utiliser le même PC pour faire tourner à la fois le client et le serveur, on utilisera l’adresse 127.0.0.1, c’est une adresse réservé à l’ordinateur lui-même.
- Le port :
Le port est un numéro utilisé par le PC pour en quelque sorte savoir sur quelle application on se connecte. Imaginer que vous avez 2 application serveur sur le même PC et qu’il passe tout les 2 sur le port 5000 (par exemple) Il y aurait vite un conflit entre le client et le/les serveurs.
On préféra donc lancer un serveur sur le port 5000 et l’autre sur le port 5001.
ancres->create( Un paquet !);
On peut imaginer un tube avec des cases. Case 1, case 2, case 3…
C’est à nous de mettre ce qu’on veut dans les cases, des variables de n’importe quels types.
Du moment qu’on sait les relire a l’autre bout.

ancres->create( Les fonctions principal que l’on va utiliser);
Voici en gros les chose que l’on va utiliser pendant le tuto.
Vous retrouverez tout cela bien en détail dans la doc de RakNet bien sûr.
Code c++ :
//creation de l’interface client ou serveur
RakPeerInterface *client = RakNetworkFactory::GetRakPeerInterface();Code c++ :
// creation d’un paquet
Packet *packet;Code c++ :
//Demarrage du client
Startup (unsigned short maxConnections,
int _threadSleepTimer,
SocketDescriptor *socketDescriptors,
unsigned socketDescriptorCount)
//exemple
client->Startup( unsigned short maxConnections, int _threadSleepTimer, SocketDescriptor *socketDescriptors, unsigned socketDescriptorCount )Code c++ :
// definie le nombre de client maxi ( reserver au serveur bien sur)
SetMaximumIncomingConnections (unsigned short numberAllowed)
//exemple
server->SetMaximumIncomingConnections(int nbClientMaxi);Code c++ :
//Connection du client
Connect (const char *host,
unsigned short remotePort,
const char *passwordData,
int passwordDataLength,
unsigned connectionSocketIndex=0,
unsigned sendConnectionAttemptCount=7,
unsigned timeBetweenSendConnectionAttemptsMS=500,
RakNetTime timeoutTime=0)
//exemple
client->Connect(ipServer, portServer, 0,0);Code c++ :
// le système BitStream
BitStream (unsigned char *_data,
const unsigned int lengthInBytes,
bool _copyData)
//exemple
RakNet::BitStream dataStream(packet->data, packet->length, false);Code c++ :
//ecriture d’une case dans le paquet
Write (templateType var)
//exemple
int nombre = 10;
dataStream.Write(nombre);Code c++ :
//lecture d’une case dans le paquet
Read (templateType &var)
//exemple
int nombre;
dataStream.Read(nombre);Code c++ :
//on supprime le packet
DeallocatePacket (Packet *packet)
//exemple
client->DeallocatePacket(packet);Code c++ :
//envoie d’un packet
Send (const RakNet::BitStream *bitStream,
PacketPriority priority,
PacketReliability reliability,
char orderingChannel,
SystemAddress systemAddress,
bool broadcast)=0
//exemple :
client->Send(&dataStream, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
//on notera ici la prioriter du paquet (LOW_PRIORITY, MEDIUM_PRIORITY, HIGH_PRIORITY)
//ainsi que le SystemAddress qui correspond au client a qui on n'envoie PAS le paquet, dans cette exemple on l'envoie a tous
Code c++ :
//suppression du client ou du serveur
RakNetworkFactory::DestroyRakPeerInterface(client);Avec ça, on devrait déjà en faire pas mal
/i\\Je vous conseil quand même d'allez faire un petit tour dans la doc pour voir ça de plus prêt documentation RakNet./i\\
ancres->create( 1er application : une petite console pour comprendre);
Une petite application pour tester la connexion a un serveur et l'envoie de paquet/réception de données.
Ce programme va simplement lancer un serveur, puis un client qui va envoyer sont nom au serveur si ça connexion est accepté.
Puis le serveur va avertir tous les clients déjà connecté qu'un nouveau client est arrivé.
LE SERVEUR
Créez une application console appelé "serveur"et linker les lib.
Code c++ :
#include "RakNetworkFactory.h"
#include "RakPeerInterface.h"
#include "MessageIdentifiers.h"
#include <BitStream.h>
#include <RakNetTypes.h>
#include <conio.h>// for getch()
// creation de nos propre ID
const unsigned char PACKET_ID_MESSAGE_DIT = 100;
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// MES FONCTIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////
// une fonction qui va nous servir a envoyer un message au clients
void sendAMessage(RakPeerInterface *serveur, Packet* packet, char name[])
{
char message[100];// on creer de quoi ecrire un message
//on met ça en forme
sprintf(message, "Le client <%s> vient de se connecter\
", name);
RakNet::BitStream data;// creation de nos data a envoyer
data.Write(PACKET_ID_MESSAGE_DIT);// on ecrit l'ID de notre packet
data.Write(message);// on ecrit notre message
// et on ça a nos client //envoie a tout le monde sauf a celui qui nous avait envoyer le paquet "packet->systemAddress"
serveur->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, true);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// LA FONCTIONS MAIN
///////////////////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
int maxClient = 10;
int portServeur = 10000;
// création de l'interface serveur
RakPeerInterface *serveur = RakNetworkFactory::GetRakPeerInterface();
// creation d'un packet
Packet * packet = NULL;
// demarrage du serveur
serveur->Startup(maxClient, 10, &SocketDescriptor(portServeur,0), 1);
//OBLIGATOIRE, sinnon on n'accepte aucun client
serveur->SetMaximumIncomingConnections(maxClient);
printf("Demarrage du serveur sur le port %d\
", portServeur);
printf("Avec %d client maxi\
", maxClient);
//la grande boucle
bool continuer = true;
while(continuer)
{
//on verifie si on a reçu un packet
packet = serveur->Receive();
if(packet != NULL)// si oui
{
unsigned char packetID;
//creation de data que l'on est pret a recevoir
RakNet::BitStream dataStream(packet->data, packet->length, false);
dataStream.Read(packetID);// on commence par lire l'ID du paquet que l'on vient de recevoir
char charTempo[50];// on creer un tableau de char pour nous permette d'y ecrrire quelque chose
switch(packetID)
{
case ID_NEW_INCOMING_CONNECTION:
break;
case PACKET_ID_MESSAGE_DIT:
// on sait que l'on va receptionner un message envoyer par notre client^^
dataStream.Read(charTempo);// on lis les données que l'on vient de recevoir
//on les stocks directement dans notre tableau de char
printf("Bienvenue a %s .\
", charTempo);
// on utilise notre fonction pour dire a tous les clients ce qu'on vient de recevoir
sendAMessage(serveur, packet, charTempo);
break;
case ID_NO_FREE_INCOMING_CONNECTIONS:
// ID automatiquement reçu si on client tente de se connecter mais que le nombre de client maxi est atteint
printf("le serveur est plein.\
");
break;
case ID_CONNECTION_LOST:
//ID automatiquement reçu si on client perd la connection
printf("Un client a perdu la connection.\
");
break;
default:
// si on l'ID d'un paquet que l'on a pas referencer on le dit
//ceci n'est pas forcement un probleme !
printf("Reception d'un packet avec un ID inconnue: %i\
", int(packetID));
}
serveur->DeallocatePacket(packet);
}
// la gestion des touche au clavier, ici on va juste gerer la touche echap pour quitter
if (kbhit())
{
int key = getch();
if (key == 27)// 27 est egale a la touche echap
{
continuer = false;
}
}
}// fin de la boucle principale du programme
// destruction de l'interface serveur
RakNetworkFactory::DestroyRakPeerInterface(serveur);
return 0;
}LE CLIENT
Créez une application console appelé "client"et linker les lib.
Code c++ :
#include "RakNetworkFactory.h"
#include "RakPeerInterface.h"
#include "MessageIdentifiers.h"
#include <BitStream.h>
#include <RakNetTypes.h>
#include <conio.h>// for getch()
// creation de nos propre ID
const unsigned char PACKET_ID_MESSAGE_DIT = 100;
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// MES FONCTIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////
// une fonction qui va nous servir a envoyer un message au serveur
void sendMyName(RakPeerInterface *client, char name[])
{
RakNet::BitStream data;// creation de nos data a envoyer
data.Write(PACKET_ID_MESSAGE_DIT);// on ecrit l'ID du packet
data.Write(name);// on ecrit notre nom
// et on envoie le tout au serveur //envoie a tout le monde
client->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// LA FONCTIONS MAIN
///////////////////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
int portServeur = 10000;
char IP_serveur[20];
char myName[50];
// on commence par entrez l'adresse du serveur
printf("Entrez l'adresse IP su serveur :");
scanf("%s", IP_serveur);
printf("Entrez votre nom :");
scanf("%s", myName);
// création de l'interface serveur
RakPeerInterface *client = RakNetworkFactory::GetRakPeerInterface();
// creation d'un packet
Packet * packet = NULL;
// demarrage du client
client->Startup(1,10,&SocketDescriptor(), 1);
client->Connect(IP_serveur, portServeur, 0,0);
//la grande boucle
bool continuer = true;
while(continuer)
{
//on verifie si on a reçu un packet
packet = client->Receive();
if(packet != NULL)// si oui
{
unsigned char packetID;
//creation de data que l'on est pret a recevoir
RakNet::BitStream dataStream(packet->data, packet->length, false);
// on commence par lire l'ID du paquet que l'on vient de recevoir
dataStream.Read(packetID);
char charTempo[100];// on creer un tableau de char pour nous permette d'y ecrire quelque chose
switch(packetID)
{
case ID_CONNECTION_REQUEST_ACCEPTED:
//on reçois cet ID automatiquement du serveur si il a accepter notre connection
printf("La connection au serveur a bien ete accepter\
");
//on envoie notre nom au serveur
sendMyName(client, myName);
break;
case ID_CONNECTION_ATTEMPT_FAILED:
//on reçois cet ID automatiquement si on arrive pas a ce connecter au serveur
printf("La connection au serveur a echouer !!!\
");
break;
case PACKET_ID_MESSAGE_DIT:
// on sait que l'on va receptionner un message envoyer par notre serveur
dataStream.Read(charTempo);// on lis les données que l'on vient de recevoir
//on les stocks directement dans notre tableau de char
printf("%s", charTempo);
break;
default:
// si on l'ID d'un paquet que l'on a pas referencer on le dit
//ceci n'est pas forcement un probleme !
printf("Reception d'un packet avec un ID inconnue: %i\
", int(packetID));
}
client->DeallocatePacket(packet);
}
// la gestion des touche au clavier, ici on va juste gerer la touche echap pour quitter
if (kbhit())
{
int key = getch();
if (key == 27)// 27 est egale a la touche echap
{
continuer = false;
}
}
}// fin de la boucle principale du programme
// destruction de l'interface serveur
RakNetworkFactory::DestroyRakPeerInterface(client);
return 0;
}COMPILEZ !
OK : Vous pouvez donc maintenant lancer le serveur, puis lancer plusieurs clients en même temps pour testé ça.
/i\\Comme vous avez pu le remarquez, un certain nombre de paquets avec un ID bien précis sont déjà envoyé automatiquement par RakNet. Vous retrouverez tous ces ID dans le fichier "MessageIdentifiers.h" des sources/i\\
Donc pour résumer un peu, comme vous avez sans doute pu le remarquer, l'idée c'est quoi ?(pas la mienne hein, celle de RakNet
On créer un paquet, ( pour reprendre le schéma du paquet plus haut) dans la première case on écrit l'ID du paquet, ce qui va nous servir à savoir à quoi ce paquet va nous servir. Puis on écrit les valeurs (dans les cases) que l'on a besoin.
De l'autre côté, le client reçoit un paquet. Il commence par lire l'ID de ce paquet, (je me répète) ce qui va lui servir à savoir à quoi ce paquet va nous servir. Puis on lie les données ( dans les cases) qui suivent.
Cette première application est très juste une petite approche de ce qu'il possible de faire, c'est que ici, l'utilisateur ne rentre pas vraiment en jeu.
Mais attendez de voir la suite...
ancres->create( 2e application : RakNet et Irrlicht – Ninja !);
On va ici, créer un serveur (toujours en console) et un client qui lui va être un peu plus jolie.
Le serveur:
- Doit être capable d'accepter 2 connections client.
- Il doit réceptionner la position des 2 joueurs et la renvoyer au client.
Le client :
- dans une application Irrlicht, création d'un sol, de 2 nodes animés (on va prendre le Ninja fournie par Irrlicht), une camera qui suit notre node.
- On doit envoyer notre position régulièrement au serveur.
- On doit être capable de réceptionner la position de l’autre joueur envoyé par le serveur.
- On va aussi joueur une animation lorsque les ninja se déplace. (Idle, lorsqu'il sont sur place et Walk quand il se déplace)
- On va utiliser les models et textures fournie par Irrlicht :
- le terrain : terrain-heightmap.bmp, terrain-texture.jpg, detailmap3.jpg.
- les modèles : ninja.b3d, nskinbl.jpg, nskinrd.jpg. (pour avoir 1 ninja rouge et un bleu)
Mais avant : Un problème de la vitesse de l'envoi/lecture des paquets.
Il existe un vrai problème sur la vitesse d'envoi et de réception des paquet suivant l'application que vous voulez mettre en réseau.
Exemple :
- Un jeu de morpion : le joueur 1 coche un case, il envoie directement au serveur quel case il a cocher, le serveur dit au joueur 2 quel case le joueur 1 a cocher, et tout roule pas de problème.
- Un FPS : Le joueur 1 se déplace, il dit au serveur ou il est, le serveur envoie la position du joueur 1 au joueur 2.
/!\\Mais !/!\\ A quel moment doit-on envoyer notre position ? quand est-ce que le serveur renvoie la position de tout les joueurs a tout le monde ?
Imaginons que à chaque frame on envoie notre position au serveur, cela est-il suffisant, sachant que l'on sait que pour une animation fluide, il faut au minimum 25 frames par seconde. Mais imaginons que sur notre premier client on tourne à 50 fps. On envoie donc 50 fois par seconde notre position au serveur, qui lui, dès qu'il la reçois, il la renvoie au autre client. Seulement, imaginons que le 2em client tourne a 30 fps. Ce client va donc vite se retrouver déborder, il va donc avoir plus de paquet à lire qu'il n'est capable de le faire (on part bien-sûr avec le code exemple de la console au dessus, ou notre client ne sait lire que 1 paquet par frame). Bien des solutions existe pour remédier a ce genre de problème :
1= On envoie notre position au serveur toutes les 40 millisecondes (ce qui correspond à 25 fois par seconde). Et le serveur renvoie la position à tout les client toutes les 40 ms à sont tour. En théorie ça marche bien, à condition que le client et le serveur tourne à plus de 25fps.(en général le serveur tourne largement plus vite, surtout si on ne l'utilise que en console)
Personnellement, j'ai pour habitude de gérer le temps avec clock(). exemple :
Code c++ :
#include <ctime>
int main(void)
{
clock_t tempsActuel = clock();
clock_t tempsEcouler = clock();
while(1)
{
tempsEcouler = clock();
if(tempsEcouler - tempsActuel > 40)
{
//on fait tous les trucs que l'on a envie de faire toute les 40ms
tempsActuel = clock(); //et on remet a jour "tempsActuel"
}
}
}Mais vous pouvez très bien utiliser ce qu'il vous plait.
2=On fait une boucle qui li tout les paquets reçus avant d'afficher le rendu. ça marche aussi pas mal, sauf si on reçois d'un coup énormément de paquets et là, on va ramer un gros coup.
3=On fait un mélange des 2 premières solution, on essaye d'optimiser au maximum pour envoyer le moins de paquet possible. On envoi notre position toutes les 40 ms mais seulement si on a bouger depuis la dernière fois.
4=Pour encore plus de rapidité pour les clients, on sait que bien souvent les perte de FPS sont en partie a cause des collisions (notamment avec Irrlicht) Alors, même si c'est un peut plus compliquer, on peut très bien ne gérer aucune collision sur le programme client, mais plutôt laisser le serveur s'en charger. Si on fait un serveur sans interface graphique, il ne perd quasiment rien en rapidité même avec une gestion des collisions. Cela implique que le personnage du client ne bouge pas directement pour ensuite envoyer sa position au serveur, mais fait une demande au serveur de bouger, et c'est le serveur qui place le personnage.
Il y a encore un bon nombre de chose pouvant être réaliser, avec un peu d'imagination, on peut réaliser de très belle chose...
/i\\NINJA !!/i\\ c'est partie !
Bon, nous dans notre exemple du Ninja nous allons codé en utilisant la première solution, ce n'est pas la plus optimisée mais pour faire tourner une api composée seulement de 2 ninjas et 1 terrain, ça devrais suffire.
Je vais mettre un maximum de commentaire dans le code plutôt que de faire un long chapitre explicatif
/!\\depuis la version 1.5.1 de Irrlicht, il n'est plus possible de lancer 2 clients simultanément utilisant une caméra FPS, il vous faudra donc au moins 2 ordinateurs pour testé ce programme (1 serveur et client et 1 client)/!\\
LE SERVEUR
Code c++ :
#include <irrlicht.h>
#include "RakNetworkFactory.h"
#include "RakPeerInterface.h"
#include "MessageIdentifiers.h"
#include <BitStream.h>
#include <RakNetTypes.h>
#include <conio.h>// for getch()
#include <ctime>//for clock()
using namespace std;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace gui;
// creation de nos propre ID
const unsigned char PACKET_ID_DEPLACEMENT = 101;
const unsigned char PACKET_ID_ANIMATION = 102;
const unsigned char PACKET_ID_ID_JOUEUR = 103;
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// MES FONCTIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////
//pour envoyer un ID a notre joueur qui vient de se connecter
void send_a_ID_joueur(RakPeerInterface *serveur, int ID_joueur)
{
RakNet::BitStream data;// creation de nos data a envoyer
data.Write(PACKET_ID_ID_JOUEUR);// on ecrit l'ID de notre packet
data.Write(ID_joueur);// l'ID du joueur a envoyer
serveur->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
}
//**un fonction pour envoyer l'animation de notre ninja au client
//on notera que ici on n'envoie pas le paquet au client nous nous
//l'avait envoyer (packet->systemAddress)
void send_animation(RakPeerInterface *serveur, Packet *packet, int ID_joueur, bool il_marche)
{
RakNet::BitStream data;
data.Write(PACKET_ID_ANIMATION);
data.Write(ID_joueur);
data.Write(il_marche);
serveur->Send(&data, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, packet->systemAddress, true);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// LA FONCTIONS MAIN
///////////////////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
int maxClient = 2;
int portServeur = 10000;
// création de l'interface serveur
RakPeerInterface *serveur = RakNetworkFactory::GetRakPeerInterface();
// creation d'un packet
Packet * packet = NULL;
// demarrage du serveur
serveur->Startup(maxClient, 10, &SocketDescriptor(portServeur,0), 1);
/// OBLIGATOIRE, sinnon on n'accepte aucun client
serveur->SetMaximumIncomingConnections(maxClient);
printf("Demarrage du serveur sur le port %d\
", portServeur);
printf("Avec %d client maxi\
", maxClient);
//une variable pour gerer l'ID du client, cette ID seras envoyer au client a sa connection
//Cette ID lui seras envoyer a lui seul et attribuer tous le long de sa connection
//C'est qui qui serviras a l'identifier et a se faire identifier
int ID_joueur = 0;
bool il_marche = false;//servira a gerer si le ninja du client marche ou pas pour le dire au autre
// servira a enregistrer la position et la rotation des ninja
vector3df positionJoueur[2];
vector3df rotationJoueur[2];
//initialisation
positionJoueur[0].X = 0;
positionJoueur[0].Y = 0;
positionJoueur[0].Z = 0;
positionJoueur[1].X = 0;
positionJoueur[1].Y = 0;
positionJoueur[1].Z = 0;
//pour gerer le temps
clock_t tempsActuel = clock();
clock_t tempsEcouler = clock();
//la grande boucle
bool continuer = true;
while(continuer)
{
//on verifie si on a reçu un packet
packet = serveur->Receive();
if(packet != NULL)// si oui
{
unsigned char packetID;
//creation de data que l'on est pret a recevoir
RakNet::BitStream dataStream(packet->data, packet->length, false);
dataStream.Read(packetID);// on commence par lire l'ID du paquet que l'on vient de recevoir
int un_ID_Joueur;//servira a identifier quelle client a envoyer un paquet
switch(packetID)
{
case ID_NEW_INCOMING_CONNECTION:
//Un nouveau client vient de se connecter, on lui envoie un ID
//qui lui servira à s'autentifier
send_a_ID_joueur(serveur, ID_joueur);
ID_joueur++;
break;
case PACKET_ID_DEPLACEMENT:
//on reçois la position et la rotation d'un client
//on l'enregistre
dataStream.Read(un_ID_Joueur);
dataStream.Read(positionJoueur[un_ID_Joueur]);
dataStream.Read(rotationJoueur[un_ID_Joueur]);
break;
case PACKET_ID_ANIMATION:
//on reçoit l'animation d'un client, on l'envoie a l'autre client
dataStream.Read(un_ID_Joueur);
dataStream.Read(il_marche);
send_animation(serveur, packet, un_ID_Joueur, il_marche);
break;
case ID_NO_FREE_INCOMING_CONNECTIONS:
// ID automatiquement reçu si on client tente de se connecter mais que le nombre de client maxi est atteint
printf("le serveur est plein.\
");
break;
case ID_CONNECTION_LOST:
//ID automatiquement reçu si on client perd la connection
printf("Un client a perdu la connection.\
");
break;
default:
// si on l'ID d'un paquet que l'on a pas referencer on le dit
//ceci n'est pas forcement un probleme !
printf("Reception d'un packet avec un ID inconnue: %i\
", int(packetID));
}
serveur->DeallocatePacket(packet);
}
//envoie la position des joueurs a tout le monde toute les 40 ms
tempsEcouler = clock();
if(tempsEcouler - tempsActuel > 40)
{
for(int i = 0; i < 2; i++)
{
RakNet::BitStream data;
data.Write(PACKET_ID_DEPLACEMENT);
data.Write(i);
data.Write(positionJoueur[i]);
data.Write(rotationJoueur[i]);
serveur->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
}
tempsActuel = clock();
}
// la gestion des touche au clavier, ici on va juste gerer la touche echap pour quitter
if (kbhit())
{
int key = getch();
if (key == 27)// 27 est egale a la touche echap
{
continuer = false;
}
}
}// fin de la boucle principale du programme
// destruction de l'interface serveur
RakNetworkFactory::DestroyRakPeerInterface(serveur);
return 0;
}
LE CLIENT
Code c++ :
#include <irrlicht.h>
#include "RakNetworkFactory.h"
#include "RakPeerInterface.h"
#include "MessageIdentifiers.h"
#include <BitStream.h>
#include <RakNetTypes.h>
#include <iostream>
#include <conio.h>// for getch()
using namespace std;
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace gui;
// creation de nos propre ID
const unsigned char PACKET_ID_DEPLACEMENT = 101;
const unsigned char PACKET_ID_ANIMATION = 102;
const unsigned char PACKET_ID_ID_JOUEUR = 103;
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// MES CLASS
///////////////////////////////////////////////////////////////////////////////////////////////////////
class MyEventReceiver : public IEventReceiver
{
public:
// This is the one method that we have to implement
virtual bool OnEvent(const SEvent& event)
{
// Remember whether each key is down or up
if (event.EventType == irr::EET_KEY_INPUT_EVENT)
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
return false;
}
// This is used to check whether a key is being held down
virtual bool IsKeyDown(EKEY_CODE keyCode) const
{
return KeyIsDown[keyCode];
}
MyEventReceiver()
{
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
KeyIsDown[i] = false;
}
private:
// We use this array to store the current state of each key
bool KeyIsDown[KEY_KEY_CODES_COUNT];
};
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// LA FONCTIONS MAIN
///////////////////////////////////////////////////////////////////////////////////////////////////////
int main(void)
{
int portServeur = 10000;
char IP_serveur[20];
// on commence par entrez l'adresse du serveur
printf("Entrez l'adresse IP su serveur :");
scanf("%s", IP_serveur);
// création de l'interface serveur
RakPeerInterface *client = RakNetworkFactory::GetRakPeerInterface();
// creation d'un packet
Packet * packet = NULL;
// demarrage du client
client->Startup(1,10,&SocketDescriptor(), 1);
client->Connect(IP_serveur, portServeur, 0,0);
MyEventReceiver myReceiver;
IrrlichtDevice *device = createDevice(EDT_DIRECT3D9, dimension2d<u32>(800,600),32,false,false,false);
IVideoDriver* driver = device->getVideoDriver ();
ISceneManager* sceneMgr = device->getSceneManager ();
device->setEventReceiver(&myReceiver);
device->getCursorControl()->setVisible(false);
//creation de notre camera
ICameraSceneNode* myCamera = sceneMgr->addCameraSceneNodeFPS(0, 100.0f, 0.50f);
myCamera->setPosition(vector3df(500,100,500));
//création du terrain
scene::ITerrainSceneNode* terrain = sceneMgr->addTerrainSceneNode(
"terrain-heightmap.bmp",
0,
-1,
core::vector3df(0.f, 0.f, 0.f),
core::vector3df(0.f, 0.f, 0.f),
core::vector3df(10.f, 0.3f, 10.f),
video::SColor ( 255, 255, 255, 255 ),
5,
scene::ETPS_17,
4
);
terrain->setMaterialFlag(video::EMF_LIGHTING, false);
terrain->setMaterialTexture(0,driver->getTexture("terrain-texture.jpg"));
terrain->setMaterialTexture(1,driver->getTexture("detailmap3.jpg"));
terrain->setMaterialType(video::EMT_DETAIL_MAP);
terrain->scaleTexture(1.0f, 20.0f);
// create triangle selector for the terrain
ITriangleSelector* selector = sceneMgr->createTerrainTriangleSelector(terrain, 0);
terrain->setTriangleSelector(selector);
// terrain->setVisible(false);
// create collision response animator and attach it to the camera
ISceneNodeAnimator* anim = sceneMgr->createCollisionResponseAnimator(
selector, myCamera,
vector3df(60,100,60),
vector3df(0,-5,0),
vector3df(0,100,0));
selector->drop();
myCamera->addAnimator(anim);
anim->drop();
//on creer 2 ninja, un rouge et un bleu
IAnimatedMeshSceneNode* ninja[2];
ninja[0] = sceneMgr->addAnimatedMeshSceneNode(sceneMgr->getMesh("ninja.b3d"));
ninja[0]->setMaterialFlag(video::EMF_LIGHTING, false);
ninja[0]->setScale(vector3df(30,30,30));
ninja[0]->setFrameLoop(184,205);// on les mes sur une animation IDLE pour commencer
ninja[0]->setAnimationSpeed(10);
ninja[1] = sceneMgr->addAnimatedMeshSceneNode(sceneMgr->getMesh("ninja.b3d"));
ninja[1]->setMaterialTexture(0, driver->getTexture("nskinrd.jpg"));
ninja[1]->setMaterialFlag(video::EMF_LIGHTING, false);
ninja[1]->setScale(vector3df(30,30,30));
ninja[1]->setFrameLoop(184,205);
ninja[1]->setAnimationSpeed(10);
//on defini une variable qui va nous servir a nous identifier
int my_ID_Joueur = -1;
//et une autre pour identifier le/les autre(s)
int un_ID_Joueur = 0;
//servira a recuperer les positions et rotation des joueur envoyer par le serveur
vector3df une_position;
vector3df une_rotation;
bool je_marche = false;//pour dire au serveur si on est entrain de marcher ou pas
//cela sert au autre pour joueur l'animation
bool il_marche = false;//nous sert pour joueur l'animation des autres joueurs
//pour la gestion du temps
clock_t tempsActuel = clock();
clock_t tempsEcouler = clock();
/// On fait une boucle pour la connection, ici on va attendre de savoir si la connection
/// au serveur est OK ou non et attendre de recevoir un ID envoyer par le serveur
///on continue cette boucle temps que notre ID est inferieur à 0.
do
{
packet = client->Receive();
if(packet != NULL)// si oui
{
unsigned char packetID;
//creation de data que l'on est pret a recevoir
RakNet::BitStream dataStream(packet->data, packet->length, false);
// on commence par lire l'ID du paquet que l'on vient de recevoir
dataStream.Read(packetID);
switch(packetID)
{
case ID_CONNECTION_REQUEST_ACCEPTED:
printf("La connection au serveur a bien ete accepter\
");
break;
case ID_CONNECTION_ATTEMPT_FAILED:
//on reçois cet ID automatiquement si on arrive pas a ce connecter au serveur
printf("La connection au serveur a echouer !!!\
");
break;
//le packet qui nous donne notre ID joueur
case PACKET_ID_ID_JOUEUR:
dataStream.Read(my_ID_Joueur);
printf("recetion de l'ID: %d\
", my_ID_Joueur);
ninja[my_ID_Joueur]->setParent(myCamera);
ninja[my_ID_Joueur]->setPosition(vector3df(000,-210,-30));
break;
}
}
}while(my_ID_Joueur < 0);//c'est que l'on a bien reçu notre ID
///****************************************************
/// LA GRANDE BOUCLE
///****************************************************
while (device->run())
{
//on verifie si on a reçu un packet
packet = client->Receive();
if(packet != NULL)// si oui
{
unsigned char packetID;
//creation de data que l'on est pret a recevoir
RakNet::BitStream dataStream(packet->data, packet->length, false);
// on commence par lire l'ID du paquet que l'on vient de recevoir
dataStream.Read(packetID);
switch(packetID)
{
//un packet qui indique la position des joueurs
case PACKET_ID_DEPLACEMENT:
dataStream.Read(un_ID_Joueur);//on li l'ID du joueur a qui correspond cette position
dataStream.Read(une_position);//on li la position
dataStream.Read(une_rotation);//puis la rotation
//bien sur on n'effectue un changement sur la position du joueur
//seulement si c'est pas le notre
if(un_ID_Joueur != my_ID_Joueur)
{ //on place le joueur et on le tourne par rapport au valeur reçu precedement
ninja[un_ID_Joueur]->setPosition(une_position);
ninja[un_ID_Joueur]->setRotation(une_rotation);
}
break;
//un packet qui indique l'animation des autres joueurs
case PACKET_ID_ANIMATION:
dataStream.Read(un_ID_Joueur);//on li l'ID du joueur a qui correspond cette position
dataStream.Read(il_marche);//on li si il marche
if(il_marche)
{
ninja[un_ID_Joueur]->setFrameLoop(1,14);
}
else
{
ninja[un_ID_Joueur]->setFrameLoop(184,205);
}
break;
default:
// si on l'ID d'un paquet que l'on a pas referencer on le dit
//ceci n'est pas forcement un probleme !
printf("Reception d'un packet avec un ID inconnue: %i\
", int(packetID));
}
client->DeallocatePacket(packet);//on vide le packet
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// GESTION DES EVENEMENTS AU CLAVIER
///////////////////////////////////////////////////////////////////////////////////////////////////////
// pour quittez le programme
if(myReceiver.IsKeyDown(irr::KEY_ESCAPE))
{
device->closeDevice();
}
//si on avance on bouge on envoie dit au serveur que l'on est entrain de marcher
//pour que lui le dise au autres et qu'il joue l'animation
if(myReceiver.IsKeyDown(irr::KEY_UP) || myReceiver.IsKeyDown(irr::KEY_DOWN)
||myReceiver.IsKeyDown(irr::KEY_LEFT) || myReceiver.IsKeyDown(irr::KEY_RIGHT))
{
if(!je_marche)//on verifie si on ne marchait pas deja avant
{ //car si c'est le cas, on l'a deja dit au serveur
je_marche = true;
// on envoie notre statue au serveur
RakNet::BitStream data;
data.Write(PACKET_ID_ANIMATION);
data.Write(my_ID_Joueur);//on ecrit notre ID_joueur pour que le serveur sait de qui il s'agit
data.Write(je_marche);//on dit si on est entrain de marcher
//et on envoie ça au serveur
client->Send(&data, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
}
}
else//c'est que l'on appuie ni sur haut/bas/gauche ou droite
{
//on verifie si on etait entrain de marcher, si oui, on dit au
//serveur que l'on a arreté.
if(je_marche)
{
je_marche = false;
RakNet::BitStream data;
data.Write(PACKET_ID_ANIMATION);
data.Write(my_ID_Joueur);//on ecrit notre ID_joueur pour que le serveur sait de qui il s'agit
data.Write(je_marche);//on dit si on est entrain de marcher
//et on envoie ça au serveur
client->Send(&data, MEDIUM_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// ENVOIE NOTRE POSTION AU SERVEUR TOUTE LES 30 MS
///////////////////////////////////////////////////////////////////////////////////////////////////////
tempsEcouler = clock();//mise a jour du temps ecouler
if(tempsEcouler - tempsActuel > 30)//si ça fait plus de 30 ms qui se sont ecoulé
{
RakNet::BitStream data;
data.Write(PACKET_ID_DEPLACEMENT);//on ecrit l'ID du packet
data.Write(my_ID_Joueur);//on ecrit notre ID_joueur pour que le serveur sait de qui il s'agit
une_position = ninja[my_ID_Joueur]->getAbsolutePosition();//on recupere notre position
data.Write(une_position);//on l'ecrit dans notre packet
une_rotation = myCamera->getRotation();//on recupere notre rotation
//on remet la rotation des axe X et Z a zéro, sinon il est fort posible que les autres
//vous retrouve dans des positions qui ne parraissent pas possible (en effet, car quand
//on regarde vers le bas par exemple, du faite que notre ninja est attacher a notre camera
//il se trouve completement coucher) essayer d'enlever ça si vous vouler pour tester
une_rotation.X = 0;
une_rotation.Z = 0;
data.Write(une_rotation);//on ecrit notre rotation dans notre packet
//et on envoie tout ça
client->Send(&data, HIGH_PRIORITY, RELIABLE_ORDERED, 0, UNASSIGNED_SYSTEM_ADDRESS, true);
tempsActuel = clock();//on remet le temps a jour
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
/// MISE A JOUR DE LA SCENE
///////////////////////////////////////////////////////////////////////////////////////////////////////
driver->beginScene(true, true, video::SColor(0,200,200,200));
sceneMgr->drawAll ();
driver->endScene ();
}// fin de la boucle principale du programme
device->drop();
// destruction de l'interface serveur
RakNetworkFactory::DestroyRakPeerInterface(client);
return 0;
}
Bien-sûr il y a énormément de chose qu'on pourrait rajouté ici pour rendre ce petit programme un peu prêt correct, je vous suggère même de le faire. Créer une class pour les personnages, enregistrer le nom des ninjas, leurs rajouter des animations.... lâchés-vous
Toutes les remarques sur ce tutoriel sont les bienvenue afin de le rendre le plus complet et compréhensible possible.
Hors ligne
22-10-2009 16:46:22
- nico
- Administrateurs

- Date d'inscription:
- Messages: 563
- IP: 82.232.128.163
- Courriel
Super le tuto
il me sera utile dans quelques temps ![]()
Hors ligne
22-10-2009 19:32:16
- tmyke
- Administrateurs

- Date d'inscription:
- Messages: 1025
- IP: 90.56.122.125
- Courriel
Je vais lire cela de près, la partie réseau est vraiment un domaine ou j'ai de forte lacune, voilà une occasion de bien progresser ![]()
Force et sagesse...
Hors ligne
23-10-2009 09:05:55
- TUpac
- Membres

- Date d'inscription:
- Messages: 387
- IP: 90.27.93.13
- Courriel
Je ne te dirais pas merci même si ton tuto est génial. C'est juste que j'ai fait tout ça à la mimine y'a un ptit bout de temp. Donc pas merci mais bravo :p
"Si vous ne partagez pas votre stabilité avec les pauvres, les pauvres partageront leur instabilité avec vous."
Hors ligne
16-12-2009 10:06:03
- nabouill
- Membres

- Date d'inscription:
- Messages: 242
- IP: 82.127.58.127
- Courriel
OK, je pense avoir un peu prêt fini ce tutoriel.
Si vous avez des suggestions, n'hésiter pas.
Hors ligne
14-01-2010 18:21:29
- nico
- Administrateurs

- Date d'inscription:
- Messages: 563
- IP: 82.232.128.163
- Courriel
Merci nabouill, ton tuto m'aide beaucoup ![]()
Hors ligne
02-03-2010 12:34:01
- jonath313
- Membres
- Date d'inscription:
- Messages: 240
- IP: 195.221.123.215
- Courriel
Vrément intéréssant tout cela je suis impatient de voir ce que çà donne! Vraiment merci j'ai à peine vu le titre de ce tuto et je me suis laisser envahir par l'envie d'essayer !!
Très bon travail !
Hors ligne
02-03-2010 12:51:44
- nabouill
- Membres

- Date d'inscription:
- Messages: 242
- IP: 82.127.58.127
- Courriel
Merci bien,
Je vous suggère aussi d'aller faire un tour dans les dossier "DependentExtensions" du dossier RakNet ou il y a un projet Irrlicht de réaliser. et dans le dossier "Samples" qui contient un nombre énorme d'exemple de projet pouvant être réalisé (autopatch, voice, mail...)
Hors ligne
01-04-2010 12:31:03
- jonath313
- Membres
- Date d'inscription:
- Messages: 240
- IP: 195.221.123.215
- Courriel
Je ne trouve pas les .lib et la Dll de RakNet dans les fichiers est-ce normal ???
Hors ligne
03-04-2010 06:28:33
- nabouill
- Membres

- Date d'inscription:
- Messages: 242
- IP: 79.92.237.64
- Courriel
pour ceux a qui ça arriverais solution ici: http://irrlicht-fr.org/viewtopic.php?pid=8160#p8160
Hors ligne
06-02-2011 16:01:49
- hitmax
- Membres

- Date d'inscription:
- Messages: 9
- IP: 78.241.245.53
- Courriel
Bonjour, j'ai un problème, avec ce tuto des ninjas, quand je test avec 2 pc, le pc qui n'héberge pas le serveur envoie au bout de 1 ou 2 minutes :
ENDING SLOW START
Initial SND=0.042959 Megabytes per second
Et là il n'envoie plus rien au serveur et le serveur affiche aussi ENDING ... Initital ...
Je voudrai savoir pourquoi ça fait ça.
Merci
Hors ligne
06-02-2011 16:04:59
- tmyke
- Administrateurs

- Date d'inscription:
- Messages: 1025
- IP: 90.56.197.149
- Courriel
Perso, je ne suis pas doué pour le reseau, plus qu'a attendre que nabouill passe par là ![]()
Force et sagesse...
Hors ligne
21-02-2011 16:37:33
- hitmax
- Membres

- Date d'inscription:
- Messages: 9
- IP: 78.241.245.53
- Courriel
Vous ne savez toujours pas pourquoi j'ai cette erreur ?
Hors ligne
26-02-2011 23:52:42
- nabouill
- Membres

- Date d'inscription:
- Messages: 242
- IP: 77.195.183.134
- Courriel
salut, tu utilise quel version de RakNet ?
Il semblerais qu'il y ai eu un bug dans des version de RakNet mais qui serais corrigé dans les dernière version.
Aussi, il dise que cela peut être du a un problème mémoire sur le PC, a voir, peut etre essayer avec un autre pc du coup.
A+
Hors ligne
05-05-2011 12:00:05
- Oelth
- Membres

- Date d'inscription:
- Messages: 8
- IP: 90.42.143.240
- Courriel
Hello !
Desolé de remonter le topic,
mais je souhaitais d'une part te féliciter pour
ce tutoriel fort abouti, et d'autre part poser une question.
Ayant actuellement un projet à réaliser sous Irrlicht,
je souhaitais m'occuper de la partie réseau via Raknet.
J'ai donc chargé les fichiers à compiler pour créer la dll,
mais petit soucis, j'utilise Visual Studio 10. Et comme
les sources pour ce dernier ne sont pas disponibles
j'ai essayé de compiler avec le source pour visual 2008.
J'ai donc mis à jour le projet, mais la compilation ne veut pas s'effectuer.
J'obtiens lors de la compilation des warning :
1>------ Début de la génération : Projet : DLL, Configuration : Debug Win32 ------
1>La génération a démarré 05/05/2011 13:51:43.
1>InitializeBuildStatus:
1> Création de "Debug\\DLL.unsuccessfulbuild", car "AlwaysCreate" a été spécifié.
1>ClCompile:
1> Ignoré... (aucune modification pertinente détectée)
1> WSAStartupSingleton.cpp
1> VariadicSQLParser.cpp
1> VariableListDeltaTracker.cpp
1> VariableDeltaSerializer.cpp
1> UDPProxyServer.cpp
1> UDPProxyCoordinator.cpp
1> UDPProxyClient.cpp
1> UDPForwarder.cpp
1> TwoWayAuthentication.cpp
1> ThreadsafePacketLogger.cpp
1> TelnetTransport.cpp
1> TeamBalancer.cpp
1> TCPInterface.cpp
1> TableSerializer.cpp
1> SuperFastHash.cpp
1> StringTable.cpp
1> StringCompressor.cpp
1> SocketLayer.cpp
1> SimpleMutex.cpp
1> SignaledEvent.cpp
1> SHA1.cpp
1> SendToThread.cpp
1> SecureHandshake.cpp
1> RPC4Plugin.cpp
1> Router2.cpp
1> ReplicaManager3.cpp
1> ReliabilityLayer.cpp
1> ReadyEvent.cpp
1> rdlmalloc.cpp
1> Rand.cpp
1> RakWString.cpp
1> RakThread.cpp
1> RakString.cpp
1> RakSleep.cpp
1> RakPeer.cpp
1> RakNetTypes.cpp
1> RakNetTransport2.cpp
1> RakNetStatistics.cpp
1> RakNetSocket.cpp
1> RakNetCommandParser.cpp
1> RakMemoryOverride.cpp
1> Rackspace.cpp
1> PluginInterface2.cpp
1> PacketOutputWindowLogger.cpp
1> PacketLogger.cpp
1> PacketizedTCP.cpp
1> PacketFileLogger.cpp
1> PacketConsoleLogger.cpp
1> NetworkIDObject.cpp
1> NetworkIDManager.cpp
1> NatTypeDetectionServer.cpp
1> NatTypeDetectionCommon.cpp
1> NatTypeDetectionClient.cpp
1> NatPunchthroughServer.cpp
1> NatPunchthroughClient.cpp
1> MessageFilter.cpp
1> LogCommandParser.cpp
1> LocklessTypes.cpp
1> LinuxStrings.cpp
1> Itoa.cpp
1> IncrementalReadInterface.cpp
1> HTTPConnection.cpp
1> GridSectorizer.cpp
1> gettimeofday.cpp
1> GetTime.cpp
1> Gets.cpp
1> Getche.cpp
1> FullyConnectedMesh2.cpp
1> FormatString.cpp
1> FileOperations.cpp
1> FileListTransfer.cpp
1> FileList.cpp
1> EpochTimeToString.cpp
1> EncodeClassName.cpp
1> EmailSender.cpp
1> DynDNS.cpp
1> DS_Table.cpp
1> DS_HuffmanEncodingTree.cpp
1> DS_ByteQueue.cpp
1> DS_BytePool.cpp
1> DirectoryDeltaTransfer.cpp
1> DataCompressor.cpp
1> ConsoleServer.cpp
1> ConnectionGraph2.cpp
1> CommandParserInterface.cpp
1> CloudServer.cpp
1> CloudCommon.cpp
1> CloudClient.cpp
1> CheckSum.cpp
1> CCRakNetUDT.cpp
1> CCRakNetSlidingWindow.cpp
1> BitStream.cpp
1> _FindFirst.cpp
1>ManifestResourceCompile:
1> Toutes les sorties sont à jour.
1>C:\\Program Files\\MSBuild\\Microsoft.Cpp\\v4.0\\Microsoft.CppBuild.targets(990,5): warning MSB8012: TargetPath(D:\\Documents\\Utilitaires\
aknet\\Lib\\DLL\\Debug\\DLL.dll) ne correspond pas à la valeur de la propriété OutputFile (D:\\Documents\\Utilitaires\
aknet\\Lib\\RakNetDebug.dll) de Linker. Cela peut entraîner une génération incorrecte de votre projet. Pour corriger ce problème, vérifiez que les valeurs des propriétés $(OutDir), $(TargetName) et $(TargetExt) correspondent à la valeur spécifiée dans %(Link.OutputFile).
1>C:\\Program Files\\MSBuild\\Microsoft.Cpp\\v4.0\\Microsoft.CppBuild.targets(992,5): warning MSB8012: TargetName(DLL) ne correspond pas à la valeur de la propriété OutputFile (RakNetDebug) de Linker. Cela peut entraîner une génération incorrecte de votre projet. Pour corriger ce problème, vérifiez que les valeurs des propriétés $(OutDir), $(TargetName) et $(TargetExt) correspondent à la valeur spécifiée dans %(Link.OutputFile).
1>Link:
1> Création de la bibliothèque Debug\\../../RakNetDLLDebug.lib et de l'objet Debug\\../../RakNetDLLDebug.exp
1>Manifest:
1> Toutes les sorties sont à jour.
1>LinkEmbedManifest:
1> Toutes les sorties sont à jour.
1> DLL_vc8.vcxproj -> D:\\Documents\\Utilitaires\
aknet\\Lib\\DLL\\Debug\\DLL.dll
1>FinalizeBuildStatus:
1> Suppression du fichier "Debug\\DLL.unsuccessfulbuild".
1> Mise à jour de l'horodatage "Debug\\DLL.lastbuildstate".
1>
1>La génération a réussi.
1>
1>Temps écoulé 00:00:04.95
========== Génération : 1 a réussi, 0 a échoué, 0 mis à jour, 0 a été ignoré ==========Donc il m'indique que la génération à réussie mais j'ai tout de même une fenêtre qui m'affiche le message suivant :
Impossible de démarrer le programme
'D:\\Documents\\Utilitaires\
aknet\\Lib\\DLL\\Debug\\DLL.dll'.
Le fichier spécifié est introuvable.
Ma question est donc, ai je fait quelque chose de travers ? Ou alors manqué une étape (sachant que j'essaye de compiler DLL.vc8_vcxproj qui est dans le dossier ./Lib/DLL de Raknet)? Quelqu'un serait il déjà parvenu à faire fonctionner Raknet sous VS10 ? Si oui comment ? ^^"
Merci beaucoup par avance pour vos réponses.
EDIT : Probleme résolu !
En fait il suffit d'inclure les sources dans le projet, j'ai suivi ce tuto : http://www.jenkinssoftware.com/raknet/manual/compilersetup.html
fais pour visual c++ 2005 et ça marche pour visual c++ 2010, merci tout de même !
Hors ligne
02-02-2012 13:49:48
- Kirk
- Membres
- Date d'inscription:
- Messages: 14
- IP: 82.123.174.99
- Courriel
Super tuto, merci beaucoup !!!
wofwar.olympe.in
Hors ligne



