PDA

Ver la versión completa : SDL: Dudas Existenciales con Surfaces (eficiencia)



D_Skywalk
15/09/2005, 21:16
Hola de nuevo, vengo con ganas de guerra y con algunas dudas existenciales que he tenido empezando a trabajar con SDL que espero que me podais ayudar ;)

La cuestion es que tengo una estructura de animaciones que antes usando el SDK oficial, q tenia un array de unsigned chars y claro ahora al pasar a SDL lo mejor es usar Surfaces en lugar de mis socorridos "u8" xD

La cuestion es que antes tenia:



struct bitmap{
unsigned char contenido;
unsigned char ancho;
unsigned char alto;
}


Y ahora uso directamente un SDL_Surface que basicamente es:



struct bitmap{
void * pixels;
int w;
int h;
...
}


Y bueno algunos mas... da igual, la cuestion es que ahora usando SDL_Surface me vienen dudas de como usarlo con mas eficiencia, os cuento:

Lo primero que hago es cargar un BMP con los frames del keko y luego crear una estructura con cada frame, recortando del grafico principal (BMP original) a una nueva SDL_Surface (que creo especificamente para ese frame).
Una vez he recortado todos los frames de la animacion; libero el BMP y fin... al menos esa es la teoria pero me saltan dudas...

¿Es mejor hacer tener directamente todo el BMP en memoria sin recortar y luego "blitear" el rectangulo del frame a visionar?

¿Ocupan demasiada memoria tantos SDL_Surfaces (uno por cada frame) ? ¿Seria mejor tener solo uno (BMP) y "blitear" desde alli?

¿Es mas rapido volcar todo el frame a pantalla que blitear un "trozo" a pantalla?

Espero que podais darme una pistilla y si tenemos la suerte que Chui anda por ahi, quien mejor para resolver estas dudillas ;)

Tengo ademas una duda mas, no se bien como tengo que usar:

SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 32,
rmask, gmask, bmask, amask);


¿Para que exacmente se usan rmask, gmask...? Hay alguna forma mejor de crear una Surface a partir de ese BMP que antes os he nombrado?

Un Saludo

Eskema
16/09/2005, 14:28
Pues la verdad no se hasta q punto sera mejor o peor pero en mi caso por razones de comodidad tengo un bmp con las animaciones y como dices las voy bliteando y mostrandolas por pantalla.
Segun varios tutoriales q he visto por la red parece mas una cuestion de gustos del programador q de eficiencia, pero parece q la mayoria usan solo un bmp y van recortando los trozos q necesitan ;)

anibarro
16/09/2005, 15:01
A mi me pasa lo mismo, tengo una cabecera con funciones para colisiones y hay q pasarle una SDL_Surface para que trabaje, por lo que se supone que cada fotograma de una animacion va a estar en una SDL_Surface distinta. Tuve que adaptarla pq yo hago como eskema, recorto el trozo de imagen que uso en cada fotograma de la animacion, pero al ver esa funcion me entro la duda de si lo estaba haciendo mal :rolleyes:
Luego la funcion que pones para crear una superficie vacia, no la he usado nunca y no se en que casos vendria bien usarla, de momento solo defino las variables de tipo SDL_Surface, por ejemplo
SDL_Surface *sprite;
y luego cargo ahi una imagen, que principalmente es algo como:
IMG_Load(fichero_imagen);
Supongo que IMG_Load llamara primero a SDL_CreateRGBSurface, pero vamos que ni idea...a ver si chui nos echa un cable :brindis:

EDIT:

Se me olvidaba que yo tb tenia una pregunta para CHUI, ¿tienen activado de alguna manera la sincronia con el refresco de la pantalla las SDL? Es que yo volviendome loco pq sin pintar practicamente nada no me pasaba de 50 o 60 fps sin limitar la velocidad, y es que aunque pinte mas o menos, no me pasa de unos 50 o 60 fps :?

Gammenon
16/09/2005, 20:08
Saludos
Respecto al tema de la sincronicacion, segun la documentacion de las SDL hacer flip hace que tu aplicacion se sincronice con el retrazo vertical, por lo que es normal que no pases de 60 Hz (que sera la velocidad que fijaria chui, creo que se puede fijar el refresco de pantalla de la gp32).

En cuanto a lo de si tener una surface por frame o un surface para todos los frames, no creo que haya demasiada diferencia, ya que no se cachean datos ni nada, simplemente es una porcion de memoria donde estan los datos y listo (en DirectDraw por ejemplo es posible que se guarde una cache por surface, por lo que en ese caso seria mejor, respecto a memoria, guardar los frames en una unica surface). Por lo tanto supongo que usar una surface para todos los frames (bueno, uno por todos los frames del personaje, por ejemplo) usa menos memoria que con la otra alternativa (cada frame en una surface), mas que nada porque no tienes que guardar tantos punteros XD. La contrapartida a esto es que necesitas andarte, como se ha comentado, pillando cachos de la surface gorda, mientras que con una surface por frame haces un blit de la surface entera y listos.

Concluyendo, es cuestion de gustos o herramientas que tengas :shock:

Perdonad el tochazo XD

EDIT: Ejem, usando una unica surface no tienes que guardar tantos punteros, pero si SDL_Rects, pero basicamente creo que la conclusion sigue siendo la misma, a no ser que tengas una cantidad ingente de frames en el juego (sizeof(SDL_Rect) contra sizeof(SDL_Surface *)).

D_Skywalk
19/09/2005, 09:42
Al final me he puesto a hacer lo mas complicado para mi, y lo mas directo para la GP, y es crear surfaces por frame. ¿Por que? de esta forma la gp no tendra que hacer desplazamientos en ambas capas, sino que de una copiara directamente byte a byte y en la otra pues, ya calculara la posicion cuando toque ;)

El problema que tengo ahora es bastante chungo y no le encuentro salida despues de 3 dias de pruebas... os lo paso a contar a ver si veis algo que a mi se me pasara :(

El problema que me he encontrado es que cuando quiero reservar memoria para un nuevo frame SIEMPRE me da el mismo, quiere decir que todos los frames estan usando el mismo espacio de memoria y por lo tanto cuando cambio algo en uno, se cambia tambien en todos los demas... No se si me habeis entendido bien, es como si todos intentaramos hacer un dibujo en el mismo "papel" si alguno hace un cambio en el papel, nos lo cambia (claro) a todos. ¿Como podria darle un "papel" a cada uno?

Para ello uso:


[...]
typedef struct{
SDL_Surface *contenido;
u8 bitFlags;
}cBaldosa;


[...]

miBaldosa->contenido = QuickSurface( zona.w, zona.h, 8);
blitSprite_EX( miTextura, &zona, miBaldosa->contenido, NULL );
miBaldosa->bitFlags=posicion; //solo para saber que son baldosas distintas :?

[...]

Y la funcion QuickSurface es:


SDL_Surface *QuickSurface(int width, int height, int depth)
{
SDL_Surface *temp, *final; //espacio temporal

temp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, depth, 0x0, 0x0, 0x0, 0x0);

//Transparente
SDL_SetColorKey(temp, SDL_SRCCOLORKEY | SDL_RLEACCEL, F_TRANSPARENTE(temp->format) );
//aplica los colores de pantalla a la nueva superficie
SDL_SetColors(temp, pantalla->format->palette->colors, 0, pantalla->format->palette->ncolors);

final = SDL_DisplayFormat(temp);

if(final == NULL) {
final = temp;
fprintf(stderr, "CreateRGBSurface ha fallado? %s\n", SDL_GetError());
return NULL;
}else{
fprintf(stderr, "SurfaceCreada: miSurface -> F: %p T: %p \n", *final, *temp);
SDL_FreeSurface(temp);
}

fprintf(stderr, "SurfaceCreada: miSurface -> H: %p \n", *final);

return final;
}

Y Esta es la salida del DEBUG:


SurfaceCreada: miSurface -> F: 00003000 T: 00A6CED8
SurfaceCreada: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 0...
SurfaceCreada: miSurface -> F: 00003000 T: 00A6CF98
SurfaceCreada: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 1...
SurfaceCreada: miSurface -> F: 00003000 T: 00A683C8
SurfaceCreada: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 2...
SurfaceCreada: miSurface -> F: 00003000 T: 00A68488
SurfaceCreada: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 3...
SurfaceCreada: miSurface -> F: 00003000 T: 00A68548
SurfaceCreada: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 4...
DBG-TILE_C: 2 NumCapa: 0 | Columna: 0 | BitFlags: 0 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 1 | BitFlags: 1 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 2 | BitFlags: 2 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 3 | BitFlags: 3 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 4 | BitFlags: 4 | SurfaceH: 00003000

Como veis a todos les da la direccion de memoria: 0x3000 y claro, cambio en una y cambia en todas... espero que podais ayudarme por que yo desde luego no se que mas puedo hacer :(

Un Saludo

Loren
19/09/2005, 11:12
Respecto a la función SDL_Surface *SDL_CreateRGBSurface(Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)

Esta function devuelve un puntero a una superficie, igual que hace la función SDL_SetVideoMode.
Los parámetros width y height tienen el mismo significado que en SDL_SetVideoMode, y depth es lo mismo que bpp (o sea la profundidad de color, 8, 16, 24).
Los posibles valores para flags son:
SDL_SWSURFACE crea la superficie en la memoria principal.
SDL_HWSURFACE crea la superficie en la memoria de video.
SDL_SRCCOLORKEY permite el uso de transparencias (color key).
SDL_SRCALPHA Activa el alpha-blending.

En cuanto a Rmask, Gmask, Bmask y Amask se refieren a unas estructuras de datos internas de SDL, en concreto la estructura SDL_PixelFormat. Red, Green, Blue y Alpha.
Rmask por ejemplo es la mascara de bits que representa al color rojo puro; por lo tanto Rmask serían los bits que es necesario activar para conseguir el color que tiene un 100% de rojo, un 0% de verde y un 0% de azul.

D_Skywalk
19/09/2005, 12:06
Gracias por el intento Loren, pero mi problema sobretodo es que no se si estoy usando mal SDL_CreateRGBSurface, por que como veis por mucho que hago las llamadas para reservar memoria siempre me da la misma para todas las llamadas que le hago :/

¿Alguien se ha peleado con SDL?

La verdad que yo no doy con el problema :(

Un Saludo

anibarro
19/09/2005, 12:47
Puedes probar a añadir otro parametro "nombre_imagen" a la funcion quicksurface que sea el nombre de una imagen, y cambiar la linea en q reservas el espacio:

if ((temp =temp = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, depth, 0x0, 0x0, 0x0, 0x0))==NULL)
return NULL;
por:

if ((temp = IMG_Load(nombre_imagen))==NULL)
return NULL;
a ver si cargando una imagen te sigue pasando lo mismo..es q nunca he usado el SDL_CreateRGBSurface y no se bien como funciona :s Pero de la forma que te digo no he tenido problemas de momento

D_Skywalk
19/09/2005, 13:10
if ((temp = IMG_Load(nombre_imagen))==NULL)
return NULL;
a ver si cargando una imagen te sigue pasando lo mismo..es q nunca he usado el SDL_CreateRGBSurface y no se bien como funciona :s Pero de la forma que te digo no he tenido problemas de momento

Y que hago por cada tile un bmp?

Si ademas IMG_Load como LoadBMP llaman a SDL_CreateRGBSurface, pero a ellos le reserva un nuevo "sitio" y a mi siempre me da el mismo o_O

Y lo he depurado todo, como veis el debug que os he pegado se ve muy claro que reservo la memoria y siempre me da la 0x3000 ¿sera un error de la version? del SDL? que la uso mal??

DIOS MIO CHUIIII AYUDAMEEE :*

Un Saludo

anibarro
19/09/2005, 13:24
D_Skywalk q no digo q lo hagas asi xD Solo te estoy diciendo que pruebes a hacer eso, para asegurarte de que todo esta bien y el problema es de esa funcion, q o mismo se le ha colado a chui o vete a saber

D_Skywalk
19/09/2005, 15:41
Pues pasa exactamente lo mismo, copio el code:



SDL_Surface * CrearSurfaceIMG( int width, int height, int depth )
{
SDL_Surface *temp = NULL, *final = NULL; //espacio temporal

temp = IMG_Load("datas/32x32_c.bmp");

//Transparente
SDL_SetColorKey(temp, SDL_SRCCOLORKEY | SDL_RLEACCEL, F_TRANSPARENTE(temp->format) );
//aplica los colores de pantalla a la nueva superficie
SDL_SetColors(temp, pantalla->format->palette->colors, 0, pantalla->format->palette->ncolors);

final = SDL_DisplayFormat(temp);

if(final == NULL) {
final = temp;
fprintf(stderr, "CreateRGBSurface ha fallado? %s\n", SDL_GetError());
return NULL;
}else{
fprintf(stderr, "SurfaceIMG: miSurface -> F: %p T: %p \n", *final, *temp);
SDL_FreeSurface(temp);
}

fprintf(stderr, "SurfaceIMG: miSurface -> H: %p \n", *final);

return final;
}


Debug:

DBG: Inicializamos el mapa...
DBG: Cargando Tiles...
DBG-TILE_C: Cargando Tiles (datas/32x32.bmp)...
DBG-TEXTURA_C: Cargando BMP || TEMP: W(160) H(32) M(00003000)
DBG-TEXTURA_C: Textura Cargada: W(160) H(32)...
DBG-TILE_C: Columnas: 5...
SurfaceIMG: miSurface -> F: 00003000 T: 012BEE58
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 0...
SurfaceIMG: miSurface -> F: 00003000 T: 012BEF18
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 1...
SurfaceIMG: miSurface -> F: 00003000 T: 012BEFD8
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 2...
SurfaceIMG: miSurface -> F: 00003000 T: 00A68F30
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 3...
SurfaceIMG: miSurface -> F: 00003000 T: 00A68FE0
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 4...
DBG-TILE_C: 2 NumCapa: 0 | Columna: 0 | BitFlags: 0 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 1 | BitFlags: 1 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 2 | BitFlags: 2 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 3 | BitFlags: 3 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 4 | BitFlags: 4 | SurfaceH: 00003000
DBG: Tiles cargados...
DBG: Mapa cargado correctamente...
DBG: Comienza el programa...
DBG: Cerramos el programa...

¿alguna idea? me estoy volviendo tarumba xD :loco:

[UPDATE]

Sigo depurando ahora estaba mirando que direccion de memoria le daba al BMP con todos los "tiles" y resulta que tambien es el 3000 oO_

Y por si os vale, asi cargo una imagen:

SDL_Surface * cTexturas_loadIMG(char * Filename, u16 Transparent)
{
SDL_Surface *temp; /* Surface temporal para cargar la imagen */
SDL_Surface *final; /* Surface donde quedar�la imagen optimizada */

/*Miramos la extension y seleccionamos el tipo de fichero a cargar*/

/*Cargamos usando SDL_Image*/
if ((temp = IMG_Load(Filename))==NULL)
return NULL;

/* SDL_SetColorKey india a SDL que no debe copiar el color indicado
al hacer un Blit, de esa manera ese color ser�trasparente.
La bandera SDL_RLEACCEL hace que SDL utiliza optimizaci� para
mayor velocidad al momento de hacer el Blit */
SDL_SetColorKey(temp, SDL_SRCCOLORKEY | SDL_RLEACCEL, F_TRANSPARENTE(temp->format) );
//SDL_SetColorKey(temp,SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(pantalla->format, 0x80, 0x80, 0x80));

/* Mete la paleta de la imagen en PANTALLA */
if ( temp->format->palette ) {
ChangePalette(temp->format->palette->colors, temp->format->palette->ncolors);
}

/* Ahora optimizamos la imagen convirtiendola al fotmato que se
est�utilizando actualmente, as�SDL no tendr�que ocupar tiempo
convirti�dola cada vez que hagamos un Blit */
final = SDL_DisplayFormat(temp);

fprintf(stderr, "DBG-TEXTURA_C: Cargando BMP || TEMP: W(%i) H(%i) M(%x) - FINAL: W(%i) H(%i) M(%x)...\n", temp->w, temp->h, *temp, final->w, final->h, *final);

if (final == NULL){
/* Si la imagen, por alguna raz�, no se pudo optimizar,
simplemente devolveremos el puntero a la imagen original,
Esta se podr�utilizar, no t� r�ido pero se podr�utilizar. */
final = temp;
}else{
/* Liberamos la imagen temporal ya que la fina est�bien*/
SDL_FreeSurface(temp);
}

fprintf(stderr, "DBG-TEXTURA_C: Cargando BMP || FINAL: W(%i) H(%i) M(%p) \n", final->w, final->h, *final);

/* Devolvemos el puntero a la imagen cargada */
return final;
}

Como veis es la de Chui, con el debug y un par de cambios para el SDL_Image :-

Ahora en el debug fijaros el tamaño que tiene la surface FINAL despues de haber hecho el " SDL_DisplayFormat", aqui algo falla :rolleyes:

Debug:

DBG: Inicializamos el mapa...
DBG: Cargando Tiles...
DBG-TILE_C: Cargando Tiles (datas/32x32.bmp)...
DBG-TEXTURA_C: Cargando BMP || TEMP: W(160) H(32) M(3000) - FINAL: W(19692944) H(160) M(20)...
DBG-TEXTURA_C: Cargando BMP || FINAL: W(160) H(32) M(00003000)
DBG-TEXTURA_C: Textura Cargada: W(160) H(32)...
DBG-TILE_C: Columnas: 5...
SurfaceIMG: miSurface -> F: 00003000 T: 012BE930
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 0...
SurfaceIMG: miSurface -> F: 00003000 T: 012BE9F0
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 1...
SurfaceIMG: miSurface -> F: 00003000 T: 012BEAB0
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 2...
SurfaceIMG: miSurface -> F: 00003000 T: 012BEB70
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 3...
SurfaceIMG: miSurface -> F: 00003000 T: 012BEC30
SurfaceIMG: miSurface -> H: 00003000
DBG-TILE_C: NumCapa: 0 | Columna: 4...
DBG-TILE_C: 2 NumCapa: 0 | Columna: 0 | BitFlags: 0 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 1 | BitFlags: 1 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 2 | BitFlags: 2 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 3 | BitFlags: 3 | SurfaceH: 00003000
DBG-TILE_C: 2 NumCapa: 0 | Columna: 4 | BitFlags: 4 | SurfaceH: 00003000
DBG: Tiles cargados...
DBG: Mapa cargado correctamente...
DBG: Comienza el programa...
DBG: Cerramos el programa...

Fijaos una cosa mas, si yo hago:

final = SDL_DisplayFormat(temp);
En ese momento tenemos: TEMP: W(160) H(32) M(3000) - FINAL: W(19692944) H(160) M(20)...

Luego llegamos abajo y hago:
SDL_FreeSurface(temp);

Como es posible que: DBG-TEXTURA_C: Cargando BMP || FINAL: W(160) H(32) M(00003000)

¿Ahora FINAL apunta a donde apuntaba TEMP? pero si TEMP lo hemos liberado!??!

Un Saludo :shock:

Eskema
19/09/2005, 18:34
Perdona mi ignorancia skywalk pero, ¿que es lo que pretendes conseguir exactamente con esa funcion? es decir si cambias algo en un frame se cambia en todos. ¿Que es lo q cambias exactamente que afecta al resto?
La verdad hace tiempo yo cargaba cada tile en un bmp distinto y por tanto una surface, pero tampoco llegue a hacer cambios en los tiles para ver si cambiaban.
Perdona pero como ya te digo soy muy burro y sin explicaciones claras......... (no es por robarte el codigo hombre XDDDD)

oankali
20/09/2005, 08:18
La verdad, es que a primera vista parece muy sospechoso.
¿Porqué no intentas pasar el debuger por el código fuente del SDL? Sobretodo por la función SDL_DisplayFormat, que parece ser la que da el resultado más extraño.

Zheo
20/09/2005, 21:12
SDL lleva un contador de referencias de superficies, por eso has de eliminarlo con sdl_freesurface:

typedef struct SDL_Surface {
Uint32 flags; /* Read-only */
SDL_PixelFormat *format; /* Read-only */
int w, h; /* Read-only */
Uint16 pitch; /* Read-only */
void *pixels; /* Read-write */
int offset; /* Private */

// bla bla bla

/* Reference count -- used when freeing surface */
int refcount; /* Read-mostly */
} SDL_Surface;

Más cosas, es mejor usar una sóla imagen donde guardes todos los frames, no por cuestión de gustos de progamación, sino por cuestión de eficiencia: todas las imágenes necesitan una serie de datos, y las superficies de SDL también (como puedes ver arriba) Ocupa más espacio en memoria cargar una imagen partida a trozos que una completa. Y la estructura SDL_Rects que puedes necesitar es mínima en comparación, por no hablar que NO necesitas un Rect por cada frame, sólo necesitas el número de frames y el tamaño de estos, al menos para cosas no muy complicadas.

anibarro
21/09/2005, 01:45
Zheo una pregunta, en una SDL_Surface:
typedef struct SDL_Surface {

Uint32 flags; /* Read-only */
SDL_PixelFormat *format; /* Read-only */
int w, h; /* Read-only */
Uint16 pitch; /* Read-only */
void *pixels; /* Read-write */

/* clipping information */
SDL_Rect clip_rect; /* Read-only */

/* Reference count -- used when freeing surface */
int refcount; /* Read-mostly */

/* This structure also contains private fields not shown here */
} SDL_Surface;

¿Para que sirve o como se usa "clip_rect"? Yo lo definia asi:

SDL_Rect *rect;
rect=malloc(sizeof(SDL_Rect));
rect->w=16;
rect->h=16;
rect->x=0;
rect->y=0;
SDL_SetClipRect(video_disco, rect);

poniendo en w y h la anchura y altura del recorte de la surface que uso, igual que cuando hago un blit, pero resulta que en una funcion tenia que bloquear la surface apra acceder al campo pixels, y solo con bloquear y desbloquear, aunque no hiceise nada en medio, se me corrompia de alguna manera la transparencia, y aparecia basura donde tenia que aparecer transparente.
Probe a quitar a no usar SDL_SetClipRect(video_disco, rect); y ya va todo bien otra vez, pero me he queado sin saber para que sirve o como se usa :S
Y mi otra cosa es, para que existe una funcion que "setea" eso, si pone read only :s

D_Skywalk
21/09/2005, 01:50
Ok, Zheo entonces voy a empezar de nuevo desde el principio, pero necesitare cargar al menos 2 bmps uno kekos y otro para tiles, y aun tengo la duda por que no se si luego no me dejara cargar 2 bmps diferentes... bueno ya veremos sino me ire a lokigames y asesinare a mas de uno xD

Un Saludo y gracias por la indicacion Zheo ;)

Zheo
21/09/2005, 02:24
Estoy bajando el código de la SDL y le echaré un vistazo, pero la utilidad básica que le veo para usar una función "setter" sería comprobar que no te pasas de dimensiones de la superficie, y que al hacer un blit no pete.
Problemas de bloquear y desbloquear y se que fastidie, se me ocurre de momento que podría ser que no tienes habilitada la transparencia en la superficie, pero sin mirar código no se porqué puede ser.
Además hace como 6 meses que no toco la SDL :(

Edito: efectivamente, SDL_SetClipRect comprueba, primero que existe superficie a la que aplicar un rectángulo de clip, y luego interseca el rectángulo de la superficie con el que pasas como parámetro para obtener el rectángulo de clip y así evitar problemas.

Por el otro lado, SDL_GetClipRect() es tan simple como

void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect)
{
if ( surface && rect ) {
*rect = surface->clip_rect;
}
}

oankali
21/09/2005, 15:31
[...]

¿Para que sirve o como se usa "clip_rect"? Yo lo definia asi:

SDL_Rect *rect;
rect=malloc(sizeof(SDL_Rect));
rect->w=16;
rect->h=16;
rect->x=0;
rect->y=0;
SDL_SetClipRect(video_disco, rect);

poniendo en w y h la anchura y altura del recorte de la surface que uso, igual que cuando hago un blit, pero resulta que en una funcion tenia que bloquear la surface apra acceder al campo pixels, y solo con bloquear y desbloquear, aunque no hiceise nada en medio, se me corrompia de alguna manera la transparencia, y aparecia basura donde tenia que aparecer transparente.
Probe a quitar a no usar SDL_SetClipRect(video_disco, rect); y ya va todo bien otra vez, pero me he queado sin saber para que sirve o como se usa :S
Y mi otra cosa es, para que existe una funcion que "setea" eso, si pone read only :s

Te complicas demasiado la vida, ya que no hace falta hacer una alocación dinámica de memória.
Si te fijas, en la estructura SDL_Surface, clip_rect no es un puntero, sino la estructura completa.
Luego, en tu ejemplo hay un error ya que no vuelves a liberar la memória reservada al finalizar el proceso.

Yo haría así:



SDL_Rect rect;

rect.w=16;
rect.h=16;
rect.x=0;
rect.y=0;
SDL_SetClipRect(video_disco, &rect);


La estructura clip_rect define la zona de la surface que es de lectura/escritutra. Es como una ventana dentro de la surface. Todo lo que esté fuera de la ventana no queda afectado por los cambios.
Equivale al parámetro gptag del SDK oficial de la GP32.

Oankali.

D_Skywalk
22/09/2005, 18:27
Finalmente despues de incontables debugs he conseguido que SDL haga lo que debe de hacer xD

Bien, como creo que nadie por aqui sabia que ocurria, quiero relatar las soluciones a los problemas que tenia :)

Lo primero: El problema de la memoria con los Surfaces



fprintf(stderr, "DBG-CORE_C: CREANDO SURFACE || TEMP: W(%i) H(%i) M(%p) - FINAL: W(%d) H(%d) M(%p)...\n", temp->w, temp->h, *temp, final->w ,final->h, *final);


¿que pasaba que estaba mirando el contenido a donde apuntaba el puntero y este era siempre el mismo, claro por que todas mis surfaces tenian los mismos datos (al ser tiles iguales). Vamos que yo creia que eran punteros que apuntaban a punteros, y ahi mi error :_)

¿solucion? Simple:


fprintf(stderr, "DBG-CORE_C: CREANDO SURFACE || TEMP: W(%i) H(%i) M(%p) - FINAL: W(%d) H(%d) M(%p)...\n", temp->w, temp->h, temp, final->w ,final->h, final);


Es decir, si quiero saber donde esta la surface solo tengo que mirar donde apunta el puntero (sin la * que quiere decir "el contenido de") y ahora con ese cambio se podia ver que todas las surfaces eran diferentes :D

El siguiente problema que tenia era que copiaba los datos del BMP a mi nueva surface y esta cambiaba siempre... ¿que pasaba?

Bueno que uno es tan merluzo que habia puesto:


__inline void blitSprite_EX( SDL_Surface * origen, SDL_Rect *srcrect, SDL_Surface * destino, SDL_Rect *desrect )
{

SDL_BlitSurface(origen,srcrect,pantalla, desrect);

}


Como veis mi error es que copiaba a la pantalla y no al destino xD

Y claro ahora con poner:

__inline void blitSprite_EX( SDL_Surface * origen, SDL_Rect *srcrect, SDL_Surface * destino, SDL_Rect *desrect )
{

SDL_BlitSurface(origen,srcrect,destino, desrect);

}

Pues todo arreglado, lo dicho pa matarme :shock:
Menudos despistes, bien al final mi mapeador ahora funciona con SDL como podeis observar ^^_

Un Saludo y larga vida a los mendrugos xDDD

Eskema
22/09/2005, 21:44
¿Puedo preguntar ese mapeador para que es? es decir ¿forma parte de algun juego tuyo o es un mapeador al estilo mappy?

Saludos,

D_Skywalk
22/09/2005, 22:44
¿Puedo preguntar ese mapeador para que es? es decir ¿forma parte de algun juego tuyo o es un mapeador al estilo mappy?

Saludos,

Es parte del engine que estoy haciendo para mi RPG, ya tengo mucho avanzado internamente, pero la parte grafica aun la tengo abandonada, a ver si hoy me curro un smooth scroll para el engine isometrico ;)

Pero vamos si quereis que hablemos de mi proyectillo, mejor abrid un temilla nuevo ;D

Un Saludop