Problemas con Sprites

Tratamos sobre el manejo de APIs frecuentemente utilizadas en el desarrollo de videojuegos, como SDL, pygame o SFML.

Problemas con Sprites

Notapor pablo9891 » Mar Ene 05, 2010 3:12 am

Estoy haciendo un Pong, y tengo un problema cuando quiero mover las barras

Asi es como son las barritas:

Imagen

Asi es como quedan despues de ejecutarse el evento para mover sprites:

Imagen

pueden ver que se alargan, yo creo que es porque no actualizo la pantalla, el problema es que no se cual es el mejor metodo para hacerlo, estuve probando con varios pero no llegue a nada

les dejo las partes del codigo que tienen que ver con este problema

Este es el metodo para mover las barras:

Código: Seleccionar todo
void CBarra::movimiento(int y,SDL_Surface *screen)
{
  SDL_Rect dest, rectV;
  int color = 0;

   dest.x = x;
   dest.y = gety();
   dest.w = sprite[cont].img->w;
   dest.h = sprite[cont].img->h;
   SDL_FillRect(screen,&dest,NULL);

//SE ACTUALIZA AL FRAME CON SU NUEVA POSICION
  dest.x = x;
  dest.y = y;
  dest.w = sprite[cont].img->w;
  dest.h = sprite[cont].img->h;
  color = SDL_MapRGB(sprite[cont].img->format,0,0,0);
/*  SDL_SetColorKey(sprite[cont].img,SDL_SRCCOLORKEY|SDL_RLEACCEL,color);*/
  SDL_BlitSurface(sprite[cont].img, NULL, screen, &dest);
  SDL_UpdateRect(screen,dest.x,dest.y,dest.w,dest.h);
}
};


Desde aca se llama al metodo que mueve a las barras:

Código: Seleccionar todo
  while(SDL_PollEvent(&evento))
  {
    if(key[SDLK_UP])
    {
     if(barra1.gety() > 0)
     {
      SDL_FillRect(screen,NULL,NULL);     
      y = barra1.gety()-8;
      barra1.sety(y);
      barra1.movimiento(y,screen);
      barra2.movimiento(barra2.gety(),screen);
      red.movimiento(red.gety(),screen);
      pel.movimiento(pel.gety(),screen);
     }
    }


Espero que me puedan solucinar el problema

SALUDOS
pablo9891
 
Mensajes: 32
Registrado: Lun Dic 28, 2009 2:48 am

Notapor Geo » Mar Ene 05, 2010 9:10 am

Lo más simple y que te recomendaría hacer en un principio: borra la pantalla antes de iniciar las rutinas de dibujado de los objetos. Este borrado puede ser poner toda la pantalla en negro o copiar alguna imagen de fondo a la pantalla.

Luego puedes probar optimizando, por ejemplo, no borrar toda la pantalla, sino solamente las zonas donde hubo cambios, por ejemplo, donde dibujaste la barra en el ciclo anterior.
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor endaramiz » Mar Ene 05, 2010 12:51 pm

Código: Seleccionar todo
void CBarra::movimiento(int y,SDL_Surface *screen)

  [...]
  SDL_UpdateRect(screen,dest.x,dest.y,dest.w,dest.h);
  [...]
}


Esto no te lo aconsejo. Ahora puede que no se note diferencia, pero si dibujas muchas cosas en pantalla y cada vez que dibujas una haces un SDL_UpdateRect, pueden verse cosas extrañas. Esta función lo que hace es decir que se actualice la pantalla con lo que has dibujado. Así que si, por ejemplo, hay un scroll, se verá como una parte del terreno se ha desplazado y la otra no. Así que lo mejor es borrar todo, dibujar todo y, por último, actualizar la pantalla (lo que se conoce como un fotograma o frame).

Aunque si lo que querías era hacer el pong de forma muy optimizada, quizás no estés mal encaminado, pero recuerda hacer un update también de la posición que estaba en el ciclo anterior.

Saludos, ya comentarás si al final das con el problema.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor pablo9891 » Mar Ene 05, 2010 3:04 pm

me podrian decir cual es la mejor funcion para borrar la pantalla??

yo estuve usando SDL_UpdateRect, pero mucho resultado no me esta dando

porque sigo con el mismo error de antes.
pablo9891
 
Mensajes: 32
Registrado: Lun Dic 28, 2009 2:48 am

Notapor Geo » Mié Ene 06, 2010 4:01 am

No mencionas cómo inicializaste el modo de video, sobretodo si estás utilizando doble búfer (que supongo que si, por las actualizaciones que haces con UpdateRect).

Checando las porciones de código que pusiste (hubiera sido mejor algo que se pudiera copiar y compilar para hacer pruebas), veo que si haces una llamada para borrar la pantalla (ponerla en negro):

Código: Seleccionar todo
      SDL_FillRect(screen,NULL,NULL);


pero nunca llamas a la función para actualizar la pantalla y que se observe lo que has dibujado. Así como llamas a UpdateRect para actualizar donde dibujaste la barra, también deberías hacerlo para actualizar cuando dibujaste sobre la pantalla. Esto lo puedes hacer tanto con UpdateRect como con la función SDL_Flip, los dos ejemplos de código a continuación son equivalentes:

Código: Seleccionar todo
      SDL_FillRect(screen,NULL,NULL);
      SDL_UpdateRect( screen, 0, 0, 0, 0 );

Código: Seleccionar todo
      SDL_FillRect(screen,NULL,NULL);
      SDL_Flip( screen );


En realidad, si vas a hacer una llamada para actualizar toda la pantalla, podrías realizar todo el dibujado y olvidarte de actualizar cada porción (por ejemplo, la barra), y simplemente llamar al final a SDL_Flip( screen );

Si deseas actualizar solo las porciones que se han modificado (por motivos de rendimiento, por ejemplo), deberías también actualizar la porción donde estuvo antes la barra, que es lo que al parecer está fallando y por eso ocurre el efecto que te está dando problemas.

Suerte :).
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor pablo9891 » Mié Ene 06, 2010 7:02 pm

Bueno, segui el consejo de Geo, y solucione el problema, ahora me enfrento a otro cuano muevo las barras, tanto la barra central como la pelotita que esta en el medio me parpadean,yo pensaba que con ya tener un doble buffer ese problema se solucionaba, pero evidentemente no

aca les dejo el codigo para que lo vean:

http://rapidshare.com/files/331325953/Movimiento_de_sprites.rar.html

tambien me gustaria que me explicasen bien los siguientes comandos SDL_FillRect y SDL_UpdateRect, porque veo que mi problema esta ahi

saludos!
pablo9891
 
Mensajes: 32
Registrado: Lun Dic 28, 2009 2:48 am

Notapor endaramiz » Jue Ene 07, 2010 9:05 pm

SDL_FillRect(...) lo que hace es dibujar un rectángulo en una superficie. Si la superficie es la denominada screen, cuando se actualice la pantalla (!), pasará a dibujarse en la ventana.
SDL_UpdateRect(...) lo que hace es actualizar un rectángulo de la pantalla con nuevos datos. Si se ha dibujado algo en ese rectángulo de la screen (por ejemplo con SDL_FillRect) ahora pasará a verse por la ventana. Sin embargo, todo lo que no esté dentro del rectángulo, seguirá dibujándose como antes (creo que era por eso por lo que se alargaban las barras).
SDL_Flip(...) hace algo parecido a un SDL_UpdateRect con un rectángulo que ocupa toda la ventana y se puede usar incluso si no activas DoubleBuffer.

El problema de antes es que ponías toda la pantalla a negro con SDL_FillRect y luego actualizabas con SDL_Flip() por lo tanto la ventana se veía todo en negro durante un instante porque luego dibujabas lo demás y lo actualizabas con SDL_UpdateRect.


Yo lo que te aconsejo es que borres el SDL_UpdateRect de la clase barra y comenzar con lo básico:
Código: Seleccionar todo
bucle principal:
    eventos, updates...
    pintar toda la screen a negro (con SDL_FillRect)
    dibujar
    SDL_Flip


Si no acabas de entender mi explicación (no me explico muy bien jeje) ya lo comentarás y pongo tu código con los cambios. Y si funciona ya lo comentarás también que así me quedo más tranquilo. Y no te preocupes, que es normal que al principio se atraviese algún concepto, pero estamos aquí para ayudarte ;-)


Saludos.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor pablo9891 » Vie Ene 08, 2010 9:03 pm

Bueno, finalmente solucione el problema, el tema era que estaba actualizando la posicion del sprite antes de borrar esa zona, lo que hacia que borrrara la posicion nueva del sprite y no la anterior (tendrian que ver el codigo para entender).

Ahora estoy afrontanto el problema de que ante tantos moviemientos, el movimiento de la pelota y de las barras se alentece. es decir si no muevo las barras la pelotita va a una cierta velocidad pero si muevo la barra se alentece

Aca tienen el coodigo para que lo vean:

Código: Seleccionar todo
while(done == 0)
{
  pel.movimiento(pel.getx()-1,pel.gety()+1,screen); 
  key = SDL_GetKeyState(NULL);
  while(SDL_PollEvent(&evento))
  {
   if(key[SDLK_UP])
   {
    if(barra1.gety() > 0)
    {
     y = barra1.gety()-10;//TOMO LA POSICION SOBRE Y EN LA QUE SE ENCUENTRA LA BARRA
     barra1.movimiento(barra1.getx(),y,screen);
     barra2.movimiento(barra2.getx(),barra2.gety(),screen);
     red.movimiento(red.getx(),red.gety(),screen);
     pel.movimiento(pel.getx()-1,pel.gety()+1,screen); 
    }
   }
   if(key[SDLK_DOWN])
   {
    if(barra1.gety()+barra1.geth() <700> 0)
    {
     y = barra2.gety()-10;
     barra1.movimiento(barra1.getx(),barra1.gety(),screen);
     barra2.movimiento(barra2.getx(),y,screen);
     red.movimiento(red.getx(),red.gety(),screen);
     pel.movimiento(pel.getx()-1,pel.gety()+1,screen); 
    }
   }
   if(key[SDLK_z])
   {
    if(barra2.gety()+barra2.geth() < 700)
    {
     y = barra2.gety()+10;
     barra1.movimiento(barra1.getx(),barra1.gety(),screen);
     barra2.movimiento(barra2.getx(),y,screen);
     red.movimiento(red.getx(),red.gety(),screen);
     pel.movimiento(pel.getx()-1,pel.gety()+1,screen); 
    }
   }


Saludos
pablo9891
 
Mensajes: 32
Registrado: Lun Dic 28, 2009 2:48 am

Notapor Juanxo » Sab Ene 09, 2010 1:37 am

No se cual es exactamente el problema del ralentizamiento, pero dejame que te de un par de consejos a ver si arregla algo:

obtienes el estado del teclado luego, para que quieres ver si se ha producido un evento? Si la tecla ha sido pulsada es porque ya hubo un evento, luego puedes quitar lo del while (SDL_PollEvent)

segundo, fijate que tienes mucho código repetido en cada if (no ralentiza nada, pero dificulta leer el codigo y hace más facil fallar

fijate que tienes muchas llamadas repetidas. Quita todas y pon solo una de cada despues de todos los if, ya que no son necesarias para ninguno de ellos

No creo que esto te acelere demasiado, pero igual te da claridad
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Notapor Metalero » Sab Ene 09, 2010 2:17 am

Con el tema de la ralentizacion hay dos factores importantes:

1º si estas usando sprites cargados desde disco, por ninguna razon debes cargarlos directamente, sino, cargarlos en una superficie temporal y luego psarlas a la lsuperficie definitva con SDL_DisplayFormat:

Código: Seleccionar todo
SDL_Surface tmp = IMG_Load("sprite.png");
SDL_Surface MiSprite = SDL_DisplayFormat(tmp);
SDL_FreeSurface(tmp);


Si es un sprite con canal Alpha, usa SDL_DisplayFormatAlpha();

Esto hace que la superficie se convierta al mismo formato que el de la pantalla, y entonces te ahorras que tenga que convertirlo en cada blitting (cosa que es muy costosa a nivel procesador)

El otro tema, es que tal vez estas corriendo el juego a quichicientas FPS (lo que da el CPU), entonces, cuando tiene que realizar un procese, no le da el cuero, si hace mas lento.

Por ejemplo, puede ser que estes moviendo un sprote pixel por pixel a 200 FPS, cuando seria lo mismo, moverlo de a 10 pixeles a 20 FPS.

Para esto tenes que usar una funcion de SDL llamada:

SDL_GetTicks(); uqe devuelve la cantidad de ms que trascurrieron desde que se inicio el juego.

Luego simplemente es cuestion de llamarlo antes de todo el bucle del juego, guardar el valor, y volverlo a llamar antes de dibujar la pantalla, si pasaron 40 ms (para tener 25 FPS), refrescaas la pantalla, con eso mantenes constante la velocidad del juego en cualquier circunstancia de procesamiento y en cualquier PC
Metalero
 
Mensajes: 14
Registrado: Sab Oct 24, 2009 3:47 pm

Notapor Geo » Dom Ene 10, 2010 12:34 am

En primer lugar ¿por qué mueves la pelota respondiendo a las pulsaciones de teclas? Esta debe ser la razón de tu problema, ya que mientras no presionas ninguna tecla el código se está ejecutando a cierta velocidad, al presionar una tecla, se ejecutan más instruccione s y seguramente estarás aplicando las funciones de movimiento de la pelota más de las veces deseadas por ciclo. Las teclas son para mover las barras, no el resto del juego, así que saca el código para mover la pelota de las condiciones de las teclas.

Después, toma en cuenta los comentarios que ya te hicieron :).
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor Juanxo » Dom Ene 10, 2010 1:46 am

Ves pablo, problemas como el que ha tenido Geo son los causantes de tener tanto codigo innecesario. Geo, la pelota no se mueve solo cuando hay eventos, sino que tambien se mueve al principio de cada iteracion, lo que hace que se pueda mover, hasta 5 veces por iteracion!!!

Pablo si subes el código entero, me lo bajo e intento ayudarte en lo que sea, que ayudar a otros mola más que hacer cosas aburridas (como estudiar algoritmica de los cojo..... xD)
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)

Notapor Geo » Lun Ene 11, 2010 2:37 am

Juanxo escribió:Geo, la pelota no se mueve solo cuando hay eventos, sino que tambien se mueve al principio de cada iteracion, lo que hace que se pueda mover, hasta 5 veces por iteracion!!!

Si, se que no se mueve solo cuando hay eventos, lo que le dije es que no debería haber código para mover la pelota en respuesta a esos eventos.
La imaginación es el límite.
Visita mi blog en inglés o en español.
Geo
 
Mensajes: 244
Registrado: Jue Ago 10, 2006 3:51 am
Ubicación: México

Notapor pablo9891 » Lun Ene 11, 2010 4:04 am

Pablo si subes el código entero, me lo bajo e intento ayudarte en lo que sea, que ayudar a otros mola más que hacer cosas aburridas (como estudiar algoritmica de los cojo..... xD)


Te agradezco la ayuda..

http://www.mediafire.com/?qmtgjjlook2

Aca dejo el codigo con los cambios

El problema que estoy teniendo ahora es el de las colisiones, intente varias formas pero no quedaro bien, o sea, colisionaba, pero por como estaban planteadas la pelotita no picaba como queria, fijate si me podes ayudar con eso

gracias..
pablo9891
 
Mensajes: 32
Registrado: Lun Dic 28, 2009 2:48 am

Notapor Juanxo » Mié Ene 13, 2010 10:01 pm

pablo mira tus mensajes privados cuando puedas
Avatar de Usuario
Juanxo
 
Mensajes: 437
Registrado: Sab Ene 31, 2009 2:34 am
Ubicación: Madrid(España)


Volver a Sobre las bibliotecas multimedia

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 1 invitado

cron