Duda con SDL: movimiento raro de imagen

Consulte acerca de programas, técnicas, algoritmos etc.

Duda con SDL: movimiento raro de imagen

Notapor endaramiz » Vie Ago 29, 2008 4:52 pm

Hola llevo un tiempo leyendo cosas de c++ y SDL, tengo conocimientos de pygame y al estar basado en SDL me he sentido bastante cómodo. Pero al intentar hacer unas pruebas me han comenzado a surgir comportamientos inesperados:
1. La prueba consiste en una imagen que se mueve con las teclas, pero por la izquierda y por arriba no se sale de la pantalla. Se supone que el rectángulo tiene las variables x e y con signo así que no comprendo por que me da este problema. ¿Puede ser que lo modifica el blit? por que se desplaza lo de ese ciclo pero no mas.
2. Tenía problemas con los eventos pero ahora ya no me salen y creo que no he tocado nada de la parte esa :?.

Como no es muy largo el código lo pego a continuación:
MakeFile
Código: Seleccionar todo
CXX = g++
OBJS = main.o personaje.o
CXXFLAGS = -g -Wall
BIN = personaje

all: $(BIN)

$(BIN): $(OBJS)
   g++ -o personaje $(OBJS) -lSDL -ggdb3

main.cpp
Código: Seleccionar todo
#include <stdio.h>
#include "personaje.h"

int main (void)
{
   bool salir = false;
   class personaje personaje;
   SDL_Event event;
   SDL_Surface *screen;
   if (SDL_Init(SDL_INIT_VIDEO) == -1)
   {
      printf("Error al ejecutar SDL_Init: %s\n", SDL_GetError());
      return 1;
   }
   
   screen = SDL_SetVideoMode(320, 240, 16, SDL_DOUBLEBUF | SDL_HWSURFACE);

   if ( screen == NULL )
   {
      printf("Error al ejecutar SDL_SetVideoMode: %s\n", \
            SDL_GetError());
      return 1;
   }
   
   SDL_WM_SetCaption("Prueba sprite", NULL);
   while (salir == false)
   {
/*      while (SDL_PollEvent(&event))
      {
         switch (event.type)
         {
            case SDL_QUIT:
               salir = true;
               break;

            case SDL_KEYDOWN:
               switch (event.key.keysym.sym)
               {
                  case SDLK_q:
                  case SDLK_ESCAPE:
                     salir = true;
                     break;

                  default:
                     break;
               }

            default:
               break;
         }
      } */
      while (SDL_PollEvent(&event))
      {
         if(event.type == SDL_QUIT)
            salir = true;
      }
      SDL_FillRect(screen, NULL, 0);
      personaje.actualizar();
      personaje.imprimir(screen);
      SDL_Flip(screen);
   }
   SDL_Quit();
   return 0;
}

personaje.cpp
Código: Seleccionar todo
#include "personaje.h"

personaje :: personaje ()
{
   image = SDL_LoadBMP("ima/personaje.bmp");
   if (image == NULL)
   {
      printf("Error al cargar la imágen: %s\n", SDL_GetError());
   }
   rect.x = 50;
   rect.y = 60;
   rect.w = image->w;
   rect.h = image->h;
}

personaje :: ~personaje ()
{
   if (image == NULL)
      SDL_FreeSurface(image);
}

void personaje :: actualizar (void)
{
   key = SDL_GetKeyState(NULL);
   if (key[SDLK_UP])
      rect.y = rect.y - 10;
   if (key[SDLK_DOWN])
      rect.y = rect.y + 10;
   if (key[SDLK_LEFT])
      rect.x = rect.x - 10;
   if (key[SDLK_RIGHT])
      rect.x = rect.x + 10;
}

void personaje :: imprimir (SDL_Surface *screen)
{
   SDL_BlitSurface(image, NULL, screen, &rect);
}

personaje.h
Código: Seleccionar todo
#ifndef _JUGADOR
#define _JUGADOR

#include "SDL/SDL.h"

class personaje
{
   public:
      personaje();
      ~personaje();
      void actualizar (void);
      void imprimir (SDL_Surface *screen);
      
   private:
      SDL_Surface *image;
      SDL_Rect rect;
      Uint8 *key;
};


#endif


¿Alguna idea de por que pasa esto? Si es un fallo bastante tonto acordaros que es mi primera prueba con SDL.

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

Notapor Juan Carlos » Vie Ago 29, 2008 8:26 pm

Hola,

Fijate que en el destructor de la clase personaje (en el archivo personaje.cpp) el condicional "if" esta al revez.

Deberia decir

Código: Seleccionar todo
if(image!=NULL){ /* */ }


Respecto al error de la imagen, ¿que sistema operativo estas usando?. Si no me falla la memoria, en mi Ubuntu, cuando yo intentaba hacer un blit en una posicion negativa (o sea que la imagen se desplaze por encima de la pantalla, o por la izquierda) se cerraba mi programa.

Saludos
Juan Carlos
 
Mensajes: 97
Registrado: Sab Jul 07, 2007 1:05 pm

Re: Duda con SDL: movimiento raro de imagen

Notapor hugoruscitti » Vie Ago 29, 2008 8:45 pm

dvd escribió:... pero por la izquierda y por arriba no se sale de la pantalla. Se supone que el rectángulo tiene las variables x e y con signo así que no comprendo por que me da este problema. ¿Puede ser que lo modifica el blit? por que se desplaza lo de ese ciclo pero no mas.


Sí, exactamente ahí se produce la anomalía. La función
SDL_BlitSurface modifica el parámetro "dstrect" para informar
al programador la region de pantalla que efectivamente se
dibujó. La documentación oficial [1] de la función dice algo como:

"The final blit rectangle is saved in dstrect after all clipping is performed ( srcrect is not modified)."

Por lo tanto, una forma de solucionarlo es crear un rectángulo
auxiliar antes de imprimir:

Código: Seleccionar todo
void personaje :: imprimir (SDL_Surface *screen)
{
    SDL_Rect dst = {rect.x, rect.y, 0, 0};
    SDL_BlitSurface(image, NULL, screen, &dst);
}


Notas:

[1] - http://docs.mandragor.org/files/Common_ ... rface.html
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina

Notapor endaramiz » Dom Ago 31, 2008 10:19 pm

Juan Carlos escribió:Fijate que en el destructor de la clase personaje (en el archivo personaje.cpp) el condicional "if" esta al revez.
Gracias, aún no comprendo del todo el código, sólo hice un copy/paste de fragmentos de otros archivos y adaptándolos a mi gusto, deduciendo como funcionaba.


Juan Carlos escribió:Respecto al error de la imagen, ¿que sistema operativo estas usando?. Si no me falla la memoria, en mi Ubuntu, cuando yo intentaba hacer un blit en una posicion negativa (o sea que la imagen se desplaze por encima de la pantalla, o por la izquierda) se cerraba mi programa.
Yo también utilizo ubuntu, a lo mejor era por algún fallo del código o porque utilizamos versiones distintas :? Si te pasas por Ubuntu, siempre puedes probar si este código funciona...

hugoruscitti escribió:"The final blit rectangle is saved in dstrect after all clipping is performed ( srcrect is not modified)."

Por lo tanto, una forma de solucionarlo es crear un rectángulo
auxiliar antes de imprimir
Muchas gracias, había leído eso, pero entre que no acababa de entender la frase y que al intentar utilizar variables auxiliares me daba segmentantion fault... Creo que seremos buenos amigos ese error y yo... xD Espero que al empezar la facultad lo pierda de vista :lol:
Un comportamiento algo extraño lo de guardar el dstrect, supongo que para usos más avanzado será útil :? Igualmente con lo que me has dicho va de perlas.

Saludos y perdón por mi tardanza, he estado fuera unos días.
Avatar de Usuario
endaramiz
 
Mensajes: 283
Registrado: Vie Ago 31, 2007 9:25 am
Ubicación: Barcelona

Notapor endaramiz » Mar Sep 02, 2008 1:20 pm

Hola, ¿el MakeFile está bien? lo digo porque me ha vuelto a pasar que se me arregla "solo" un fallo bastante raro: en el archivo personaje añadí unas variables de ángulos y esas cosas y se ponían a valores que no les decía. Después de buscar el error con printfs, decidí disminuir una variable de fps para leerlos mejor (solamente modifiqué eso). Al compilar, el error había desaparecido. Volví a colocar la variable fps a su estado anterior y seguía funcionando perfectamente :? ¿A alguien más le ha pasado algún "fenómeno paranormal" de estos y sabe como solucionarlos?

Creo que puede ser del MakeFile porque lo modifiqué sin tener mucha idea (porque tenía no se qué de generar documentación o algo así)(era el del ejemplo colmap, de la tortuga)

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

Otra vez el error de antes

Notapor endaramiz » Mar Sep 02, 2008 9:25 pm

Me ha vuelto a pasar lo mismo: al cambiar el archivo personaje.cpp y personaje.h, he visto que se comportaba muy raro el programa pero que el código parecía correcto (ya estoy acostumbrado a pygame). Entonces solamente he cambiado la variable fps de main.cpp y al compilar todo funcionaba correctamente, luego he podido dejar la variable como estaba sin ningún problema. La próxima vez que me pase, pruebo a compilar a mano. A ver si realmente es del MakeFile.

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

Re: Otra vez el error de antes

Notapor hugoruscitti » Mié Sep 03, 2008 2:16 pm

dvd escribió:al cambiar el archivo personaje.cpp y personaje.h, he visto que se comportaba muy raro el programa pero que el código parecía correcto ...


Saludos, muchas veces los problemas que presentan los programas
escritos con C o C++ son difíciles de encontrar. Esto es así porque
el programa generado por el compilador no hace controles
sobre el estado inicial de las variables, el desborde de vectores e
incluso muchas veces ignora si un acceso a memoria es válido
o no.

Posiblemente el problema del programa se deba a algo como eso,
por ejemplo una variable sin inicializar... por lo tanto una de las
mejores medidas que puedes tomar es usar un programa como
valgrind:

http://valgrind.org/

para que este verifique con detalle si tu programa lee o escribe
alguna variable de manera incorrecta.
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina


Volver a General

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados

cron