[SDL] Problemas con SDL_FreeSurface() y/o SDL_SetColorKey()

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

[SDL] Problemas con SDL_FreeSurface() y/o SDL_SetColorKey()

Notapor j4xl » Mar Sep 16, 2008 10:11 am

Hola a todos los integrantes del foro, mi nombre es Jairo tengo 20 años y soy estudiante de Ingeniería Informática de Sistemas. (Una pequeña presentación para ser/parecer un poco formal).
Estoy haciendo un juego estilo Mario con SDL, empece en Junio se puso peleón y lo dejé ahora lo he retomado, siempre que he buscado algo referente a SDL (desde como instalarlo para Devc++, hasta algunas dudas) el resultado estaba en esta pagina por eso he decidido formar parte de ella.

Bien ahora mi duda/trauma/frustración (porque me frustra... en serio) el Juego gráficamente consta de tres capas (SDL_Surface) una es el fondo, la segunda es el "nivel", que se construye a partir de un fichero de texto con tiles de 16*16px, y la tercera son los "objetos", es decir aquello con lo que interactuas también construida de la misma forma que el nivel.
El fondo es una imagen cargada directamente con IMG_Load().
Para el Nivel y los Objetos creo dos superficies con SDL_CreateRGBSurface() sobre las cuales voy poniendo las tiles.

El Nivel una vez creado no cambia para nada, pero en cambio los objetos si lo hacen y ademas resulta que es la capa de mas al frente (la puedo poner detras del nivel pero no detrás del fondo) para cambiarlo lo borro con SDL_FillRect() con un color negro puro y después vuelvo a dibujar las tiles con los cambios realizados, así una vez hecho esto hago SDL_SetColorKey() con el mismo negro, la misma profundidad... y se supone que debería hacerlo transparente, pero no, lo deja negro así que no veo el fondo ni el nivel.
Con la desesperación he intentado copiar la superficie, crearla de nuevo y después liberar la copia (no es copia profunda sino la copia de la dirección mediante los punteros) pero al hacer SDL_FreeSurface() me peta (en windows... en linux no aunque en linux tengo otros problemas.... XD)

Para ayudar un poco hago un "croquis" del codigo:
Código: Seleccionar todo
void CNivel::CargarObjetos(char *ObjFile){
     //....
     //leo un fichero y lo cargo en memoria TxtObjetos[y][x]
     //....
     //Creo la Superficie de los objetos
     ImgObjetos = SDL_CreateRGBSurface(SDL_SWSURFACE, 16*ANivel, 272, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
     DibujarObjetos();
}

void CNivel::DibujarObjetos(){
    int i, j;
    SDL_FillRect(ImgObjetos, NULL,  SDL_MapRGB(ImgObjetos->format,0,0,0));
    for(i=0;i<17;i++){//Doble bucle for que se encarga de leer TxtObjetos de memoria y dibujar en ImgObjetos
        for(j=0;j<ANivel;j++){
            switch(TxtObjetos[i][j]){
                case 'a':
                    Objetos[0].SetX(j*16);
                    Objetos[0].SetY(i*16);
                    Objetos[0].Mostrar(ImgObjetos);
                    break;
                case 'b':
                    Objetos[1].SetX(j*16);
                    Objetos[1].SetY(i*16);
                    Objetos[1].Mostrar(ImgObjetos);
                    break;
                case 'c':
                    Objetos[2].SetX(j*16);
                    Objetos[2].SetY(i*16);
                    Objetos[2].Mostrar(ImgObjetos);
                    break;
                case 'd':
                    Objetos[3].SetX(j*16);
                    Objetos[3].SetY(i*16);
                    Objetos[3].Mostrar(ImgObjetos);
                    break;
                case 'e':
                    Objetos[4].SetX(j*16);
                    Objetos[4].SetY(i*16);
                    Objetos[4].Mostrar(ImgObjetos);
                    break;
                default:
                    break;
            }
        }
    }
    if(SDL_SetColorKey(ImgObjetos, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB(ImgObjetos->format,0,0,0))==-1){
        printf("Error al aplicar Transparencias.\n");
    }
}

//Funcion que se llama cada vez que se toca un objeto y se tiene que "quitar"
void CNivel::QuitarObjeto(int x, int y){
    TxtObjetos[y][x]=0; //Pone a 0 el punto donde a partir de ahora no se dibujara nada
    DibujarObjetos(x, y); //Vuelvo a redibujar la superficie

}


¿Hay algun tipo de incompatibilidad entre SDL_CreateRGBSurface() y SDL_SetColorKey()?

Todas las superficies tienen una profundidad de 32bpp ya que uso png's por tanto no creo que sea problema de la profundidad del color...

¿Me proponeis alguna alternativa?

Gracias.

DEW
j4xl
 
Mensajes: 2
Registrado: Dom Sep 14, 2008 5:12 pm

Re: [SDL] Problemas con SDL_FreeSurface() y/o SDL_SetColorKe

Notapor hugoruscitti » Mié Sep 17, 2008 12:59 am

Por lo visto no hay problemas ahí, si tengo la posibilidad de
tiempo voy a hacer un ejemplo pequeño a ver si me ocurre
lo mismo (solo si tengo tiempo).

j4xl escribió:¿Me proponeis alguna alternativa?


Sí, en general no se imprimen los personajes (animados) de
un juego en otra superficie que no sea la pantalla. Debido a
que un nivel puede tener un tamaño muy grande, y no es
necesario imprimir y limpiar una superficie del tamaño del
nivel completo, si es que la pantalla es mas pequeña.

En su lugar, se suele almacenar en una variable la posición de
la cámara, alcanza con una sola variable que indique cuanto se
ha desplazado el nivel. Luego imprimes el fondo, la capa que le
sigue y por último lees uno a uno los elementos animados del
juego y los imprimes desplazados tanto como te indique la
variable que tiene el desplazamiento de la cámara.

De esta forma, no es necesario limpiar una superficie, todo lo
que haces sobre la pantalla se limpia cuando imprimes
nuevamente el fondo del escenario.

El juego Chanta Clauss tiene un desplazamiento con cámara
que te puede servir, cualquier cosa nos avisas.

Un saludo.
Avatar de Usuario
hugoruscitti
Site Admin
 
Mensajes: 1242
Registrado: Dom Jul 30, 2006 3:57 am
Ubicación: Buenos Aires, Argentina

Notapor j4xl » Mié Sep 17, 2008 6:44 pm

Hugo, permiteme que te diga que eres un crack... yo estaba desesperado porque no podía hacerlo y vas tu y me iluminas. Yo creía que esos dos bucles, con tanto volcado de superficies, en cada una de las iteraciones del "bucle principal" seria un desparramo de CPU pero resulta que después de implementar lo que me sugerías, el consumo tanto de RAM como de CPU a bajado, de forma bastante significativa de un 18-20% de CPU a un 10% y de 20.500kB de RAM a tan solo 8.000kB. :shock: tengo que mirar porqué, pero supongo que una superficie de unos 272 * 1000 px será muy pesada de hay lo de la RAM...

Explico un poco lo que he hecho, yo antes dibujaba en dos superficies "Grandes" el Nivel y los Objetos y dependiendo de una variable "Pos" que me indica en que posición del nivel se encuentra el personaje la imprimía en Pantalla (ya tenia implementado el scroll del nivel y del fondo, uno mas rápido que el otro de esta forma parece que hay perspectiva). Después de leer este consejo he eliminado la superficie de los Objetos y ahora Dibujo en cada iteración los objetos, pero solo lo que se encuentran a la vista del Jugador el resto no. Y todo va mucho mejor, ahora miraré si es plausible hacer lo mismo con el nivel... por probar, no pasa nada, si veo que los recursos vuelven a bajar... todo ira mejor, sino pues lo dejaré tal cual.


PD:Una cosa que no había comentado es que mi idea es hacer este Juego para portarlo después a PSP, y, teniendo en cuenta la bajada de consumo, ahora estoy un poco menos preocupado...

Pues lo dicho Gracias por el consejo.
DW
j4xl
 
Mensajes: 2
Registrado: Dom Sep 14, 2008 5:12 pm


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