Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Reducir el tiempo de respuesta

Iniciado por StarAD, 23 de Junio de 2007, 05:07:50 PM

« anterior - próximo »

StarAD

Hola:

Hace poco abri un post para preguntar que libreria podia utilizar para un juego de 2 players donde uno hacia de servidor y otro de cliente:

http://www.stratos-ad.com/forums3/viewtopic.php?t=8791

Después de pelearme con la libreria SDL_Net he conseguido implementarlo. El jugador que hace de servidor hace los calculos de la posicion y la envia al cliente, y el cliente envia los inputs de teclado y mouse. He conseguido que funcione, pero el problema es que desde que envias la peticion desde el cliente para moverte hasta que llega la posicion y se mueve el personaje puede pasar hasta 5-10 seg. Supongo que el error sera de codigo o diseño ya que lo he probado en mi red local de casa conectandome por la direccion interna de la red y tarda la mismo. Otro problema que he notado es que cuando se mueve no se mueve fluido , se mueve como a trompicones. Hay algun método para hacer el movimiento más fluido.

En cuanto al diseño he creado dos clases (Singletons), una para el cliente y otra para el servidor donde tienen guardado los sockets, las direcciones ip y  los datos compartidos de las posiciones e inputs. Esta dos clases crean un nuevo thread uno para el cliente y otro para el servidor y pasan como parametros ellos mismos. Mediante un semaforo van actualizando los datos compartidos y el juego va leyendo las posiciones. Os pongo el codigo de los threads para ver si sabeis donde puede estar el problema o, si no es problema de implementacion, alguna idea para reducir el tiempo de respuesta.


int listenServer(void* punt)
{
NetServer* net = static_cast<NetServer*>(punt);
UDPpacket* ini;
UDPpacket* outi;
tcFloatSend tc;
tcFloatSend* tcfs;
IPaddress ip;
char datos[sizeof(tcFloatSend)];
if(!(ini=SDLNet_AllocPacket(sizeof(tcFloatSend))))
{
net->setError();
Ogre::LogManager::getSingletonPtr()->logMessage("Error al crear el paquete de entrada");
}
if(!(outi=SDLNet_AllocPacket(sizeof(tcFloatSend))))
{
net->setError();
Ogre::LogManager::getSingletonPtr()->logMessage("Error al crear el paquete de salida");
}
outi->channel=-1;
SDLNet_ResolveHost(&ip,SDLNet_ResolveIP(net->getRemoteIP()),5426);
outi->address.host = ip.host;
outi->address.port = ip.port;
outi->len=sizeof(tcFloatSend);
ini->len=sizeof(tcFloatSend);
while(!net->getStop())
{
SDL_Delay(50);
if(0<SDLNet_UDP_Recv(net->getSockUDPR(),ini))
{
memcpy(datos,ini->data,ini->len);
tcfs=(tcFloatSend*)datos;
Ogre::LogManager::getSingletonPtr()->logMessage("Recibo algo "+Ogre::StringConverter::toString(tcfs->tip));
if(tcfs->tip==TRANS2){
Ogre::LogManager::getSingletonPtr()->logMessage("Recibo TRANS2");
while(net->getDatos()->getSemaforo())
{
SDL_Delay(1);
}
net->getDatos()->setSemaforo(true);
net->getDatos()->setTrans2(tcfs->x1,tcfs->y1,tcfs->z1);
net->getDatos()->setOrient2(tcfs->x2,tcfs->y2,tcfs->z2,tcfs->w2);
net->getDatos()->setSemaforo(false);
}
}
while(net->getDatos()->getSemaforo())
{
SDL_Delay(1);
}
net->getDatos()->setSemaforo(true);
tc.tip = POS1;
tc.x1 = net->getDatos()->getPos1()->x;
tc.y1 = net->getDatos()->getPos1()->y;
tc.z1 = net->getDatos()->getPos1()->z;
tc.x2 = net->getDatos()->getOrient1()->x;
tc.y2 = net->getDatos()->getOrient1()->y;
tc.z2 = net->getDatos()->getOrient1()->z;
tc.w2 = net->getDatos()->getOrient1()->w;
memcpy(outi->data,(Uint8*)&tc,outi->len);
SDLNet_UDP_Send(net->getSockUDPS(),-1,outi);

tc.tip = POS2;
tc.x1 = net->getDatos()->getPos2()->x;
tc.y1 = net->getDatos()->getPos2()->y;
tc.z1 = net->getDatos()->getPos2()->z;
tc.x2 = net->getDatos()->getOrient2()->x;
tc.y2 = net->getDatos()->getOrient2()->y;
tc.z2 = net->getDatos()->getOrient2()->z;
tc.w2 = net->getDatos()->getOrient2()->w;
memcpy(outi->data,(Uint8*)&tc,outi->len);
SDLNet_UDP_Send(net->getSockUDPS(),-1,outi);
net->getDatos()->setSemaforo(false);
}
SDLNet_FreePacket(ini);
SDLNet_FreePacket(outi);
Ogre::LogManager::getSingletonPtr()->logMessage("Acabando el thread de comunicacion.");
return 0;
};

int listenClient(void* punt)
{
NetClient* net = static_cast<NetClient*>(punt);
UDPpacket* ini;
UDPpacket* outi;
tcFloatSend tc;
tcFloatSend* tcfs;
IPaddress ip;
char datos[sizeof(tcFloatSend)];
if(!(ini=SDLNet_AllocPacket(sizeof(tcFloatSend))))
{
net->setError();
Ogre::LogManager::getSingletonPtr()->logMessage("Error al crear el paquete de entrada");
}
if(!(outi=SDLNet_AllocPacket(sizeof(tcFloatSend))))
{
net->setError();
Ogre::LogManager::getSingletonPtr()->logMessage("Error al crear el paquete de salida");
}
outi->channel=-1;
SDLNet_ResolveHost(&ip,SDLNet_ResolveIP(net->getRemoteIP()),5426);
outi->address.host = ip.host;
outi->address.port = ip.port;
outi->len=sizeof(tcFloatSend);
ini->len=sizeof(tcFloatSend);
while(!net->getStop())
{
SDL_Delay(50);
if(0<SDLNet_UDP_Recv(net->getSockUDPR(),ini))
{
memcpy(datos,ini->data,ini->len);
tcfs=(tcFloatSend*)datos;
Ogre::LogManager::getSingletonPtr()->logMessage("Recibo algo "+Ogre::StringConverter::toString(tcfs->tip));
if(tcfs->tip==POS1){
Ogre::LogManager::getSingletonPtr()->logMessage("Recibo POS1");
while(net->getDatos()->getSemaforo())
{
SDL_Delay(1);
}
net->getDatos()->setSemaforo(true);
net->getDatos()->setPos1(tcfs->x1,tcfs->y1,tcfs->z1);
net->getDatos()->setOrient1(tcfs->x2,tcfs->y2,tcfs->z2,tcfs->w2);
net->getDatos()->setSemaforo(false);
}else if(tcfs->tip==POS2){
Ogre::LogManager::getSingletonPtr()->logMessage("Recibo POS2");
while(net->getDatos()->getSemaforo())
{
SDL_Delay(1);
}
net->getDatos()->setSemaforo(true);
net->getDatos()->setPos2(tcfs->x1,tcfs->y1,tcfs->z1);
}
}
while(net->getDatos()->getSemaforo())
{
SDL_Delay(1);
}
net->getDatos()->setSemaforo(true);
tc.tip = TRANS2;
tc.x1 = net->getDatos()->getTrans2()->x;
tc.y1 = net->getDatos()->getTrans2()->y;
tc.z1 = net->getDatos()->getTrans2()->z;
tc.x2 = net->getDatos()->getOrient2()->x;
tc.y2 = net->getDatos()->getOrient2()->y;
tc.z2 = net->getDatos()->getOrient2()->z;
tc.w2 = net->getDatos()->getOrient2()->w;
outi->len=sizeof(tcFloatSend);
memcpy(outi->data,(Uint8*)&tc,outi->len);
SDLNet_UDP_Send(net->getSockUDPS(),-1,outi);
net->getDatos()->setSemaforo(false);
}
Ogre::LogManager::getSingletonPtr()->logMessage("Acabando el thread de comunicacion.");
return 0;
};


Aqui os pongo el struct que utilizo para enviar los datos:

struct tcFloatSend{
int tip;
float x1,y1,z1;
float x2,y2,z2,w2;
};


Muchas gracias.

StarAD

Hola:

Soy yo otra vez. Despues de buscar en el foro y en otras pgs he visto sistemas de predicion de posicion. Supongo que me tendre que currar mas el sistema. Aunque todavia me sigue pareciendo excesivo el tiempo en que tarda en recivir la respueta el cliente. Es normal que tarde tanto? o es devido a que se pierden paquetes?

Gracias otra vez.

Titonus

He visto que usas SDL_Delay antes de envío/recepción de datos y quizás no sea buena idea y tenga algo que ver con los problemas que comentas.

Deberías mirar las funciones de SocketSets de la SDL_Net, así dicho por encima, cada socketset puede ser un conjunto de sockets (que tu indicas) y que permite comprobar si algún soket del conjunto tiene actividad, es decir se ha enviado o recibido algo por el socket. Y entonces según la actividad del socketset actúas en consecuencia, por ejemplo haciendo la llamada de recibir datos, esto te permite evitar el bloqueo que provoca la llamada de la función recibir datos, pues antes te aseguras que tiene actividad (datos por recibir) el socket, porque aunque sea UDP creo recordar que se bloquea el proceso si no tiene nada que recibir.

Sobre el sistema de predicción pues sí, la idea es buscarte o crear un método para que si algunos mensajes UDP se pierden o llegan desordenados, con la información hasta ese momento recibida por el cliente, puedas estimar (mediante porcentajes, u otras técnicas) cual es probablemente el movimiento que el cliente está realizando, y aunque sea erróneo no se quedará parado el movimiento que estuviera haciendo y si es erróneo luego lo puedes arreglar/corregir con los siguiente mensajes que recibas.






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.