kreezii escribió:No sé si me explicado bien, mi problema es que mientras escribo estoy pensando maneras de solucionarlo y se me ocurre una pero lo mismo es una burrada, una función que compruebe la coordenada y del enemigo y del personaje y en función de donde esté hacer un Blit_surface de uno y después de otro pero la cosa es que cuando haya más enemigos será un caos.
Sí, ha quedado claro. Lo que me temo es que SDL no cuenta con una función que realice lo que necesitas. Dado
que ese requisito es muy propio del juego que buscas conseguir.
Aún así, existen varias formas de lograr este efecto en SDL. Lo que puedes
hacer es almacenar todos tus personajes en una estructura de datos en memoria
como un vector o una lista. De cada personaje puedes almacenar su posición
junto con la superficie que lo representa en pantalla.
Al momento de mostrar los personajes en pantalla puedes comenzar a imprimirlos
siguiendo un orden de profundidad, primero imprimes aquellos que "están mas
alejados de la pantalla" y luego aquellos que "están mas cerca". Una forma de
lograr esto es reordenar todos los elementos de tu estructura justo antes de
comenzar a imprimir (puedes ordenarlos en base al valor de su coordenada "y").
Una vez que están todos ordenados los imprimes.
Aquí te dejo un pequeño ejemplo de ello utilizando objetos en C++, si programas
en otro lenguaje como C será un poco mas complicado de hacer, pero de todas
maneras se le parecerá, consulta nuevamente si quieres.
Una vez que compiles el programa verás en pantalla algo así:
los cuadrados de color azul representan a los enemigos del juego (hay que tener
imaginación ...) mientras que el cuadrado blanco representa el personaje
protagonista que se puede mover en pantalla utilizando los direccionales del
teclado. Al mover los cuadrados todos se imprimen "ordenados por profundidad",
como se esperaría de un juego como Final Fight.
A continuación te dejo el código fuente de este programa, ten en cuenta que
las estructuras de datos se manejan mediante STL, una biblioteca que nos
facilita el manejo e implementación de listas, vectores etc...
- Código: Seleccionar todo
/*
* Ordenar elementos en pantalla al imprimir
*
* Este programa muestra varios rectángulos en pantalla y simula
* como deberían imprimirse en pantalla si estuvieran sobre un
* plano con profundidad, similar al que se encuentra en videojuegos
* como Final Fight.
*
* Puede encontrar una discusión acerca de este programa en el
* foro:
* www.losersjuegos.com.ar/foro
*
*/
#include "SDL.h"
#include <list>
/* Representa las características mas elementales
* de un personaje que se debe imprimir en pantalla
*/
class Sprite
{
public:
Sprite (int x, int y);
virtual void actualizar () = 0;
void imprimir (SDL_Surface * screen);
int get_y (void);
protected:
SDL_Rect rect;
Uint32 color;
};
/* define la posición y tamaño inicial del sprite */
Sprite :: Sprite (int x, int y)
{
this->rect = (SDL_Rect) {x, y, 40, 40};
}
/* informa la coodenada "y" en donde se deberían
* encontrar los `pies` de un personaje
*/
int Sprite :: get_y (void)
{
return this->rect.y + this->rect.h;
}
/* muestra el objeto en pantalla */
void Sprite :: imprimir (SDL_Surface * screen)
{
SDL_Rect rect = this->rect; /* nota: se realiza una copia
dado que SDL_FillRect puede
modificar este rectángulo si
no cabe en pantalla */
/* TODO: utilizar superficies en lugar de rectángulos
* para que "parezca" un juego */
SDL_FillRect (screen, & rect, this->color);
}
/* Representa un personaje que se maneja mediante del teclado.
* hereda el comportamiento y estructura de todo Sprite.
*/
class Protagonista : public Sprite
{
public:
Protagonista (int x, int y);
void actualizar ();
};
/* método invocado al crear un nuevo protagonista */
Protagonista :: Protagonista (int x, int y) : Sprite (x, y)
{
this->color = 0xffffff;
}
/* actualiza la posición del personaje atendiendo la
* pulsación de teclas */
void Protagonista :: actualizar (void)
{
Uint8 * teclas = SDL_GetKeyState (NULL);
int velocidad = 2;
if (teclas [SDLK_UP])
this->rect.y -= velocidad;
else
if (teclas [SDLK_DOWN])
this->rect.y += velocidad;
if (teclas [SDLK_LEFT])
this->rect.x -= velocidad;
else
if (teclas [SDLK_RIGHT])
this->rect.x += velocidad;
}
/* representa un enemigo (¡ un malvado cuadrado azul !)
* que se mueve de izquierda a derecha por la pantalla.
* hereda de Sprite, al igual que el protagonista.
*/
class Enemigo : public Sprite
{
public:
Enemigo (int x, int y);
void actualizar ();
public:
int direccion;
};
/* construye al Enemigo asignándole el color azul */
Enemigo :: Enemigo (int x, int y) : Sprite (x, y)
{
this->color = 0x0000F5;
this->direccion = 1;
}
/* realiza el movimiento del enemigo en pantalla */
void Enemigo :: actualizar ()
{
/* el comportamiento de un enemigo es ir de un lado a otro en
* la pantalla */
if (direccion == 1)
{
this->rect.x ++;
if (rect.x + rect.w > 320)
direccion = 0;
}
else
{
this->rect.x --;
if (rect.x < 0)
direccion = 1;
}
}
/* informa "true" si el primer argumento "a" está mas alejado de la pantalla
* que el argumento "b"
* esta función se utiliza para re-ordenar la lista de personajes (ver
* función main)
*/
bool es_menor (Sprite * a, Sprite * b)
{
return (a->get_y () < b->get_y ());
}
/*
* programa principal
*/
int main (int argc, char * argv [])
{
std :: list <Sprite *> sprites;
SDL_Surface * screen;
SDL_Event event;
bool salir = false;
/* TODO: verificar errores */
SDL_Init (0);
screen = SDL_SetVideoMode (320, 240, 16, 0);
/* Genera los personajes y los almanena en una lista */
sprites.push_front (new Protagonista (30, 30));
sprites.push_front (new Enemigo (130, 10));
sprites.push_front (new Enemigo (220, 50));
sprites.push_front (new Enemigo (170, 130));
while (! salir)
{
while (SDL_PollEvent (&event))
{
if (event.type == SDL_QUIT)
salir = true;
}
SDL_FillRect (screen, NULL,
SDL_MapRGB (screen->format, 200, 200, 200));
/* actualiza todos los elementos */
std :: list <Sprite *> :: iterator iter;
for (iter = sprites.begin (); iter != sprites.end (); iter ++)
(* iter) -> actualizar ();
/* IMPORTANTE: ordena los personajes antes de imprimirlos
* llamando a la función "es_menor" para realizar
* comparaciones */
sprites.sort (es_menor);
/* imprime a todos los personajes en pantalla */
for (iter = sprites.begin (); iter != sprites.end (); iter ++)
(* iter) -> imprimir (screen);
SDL_Flip (screen);
SDL_Delay (1);
}
SDL_Quit ();
return 0;
}
y si archivo Makefile para compilarlo en GNU/Linux:
- Código: Seleccionar todo
CC = g++
CXXFLAGS = `sdl-config --cflags`
LDFLAGS = `sdl-config --libs`
ejemplo: ejemplo.o
Saludos.
PD: creo que "Requeteguay" estaba trabajando en una idea similar
a la del juego que buscas hacer, buscalo en este foro, puede que
también te de una mano en tu proyecto.