No es mi intención explicar concienzudamente cada función de las librerias "SDL", para esos asuntos consultar la página oficial. La idea es ir creando una librería personalizada de fácil manejo en español. Esta librería se llamará "Mi_Libreria.h" como encabezado y "Mi_Libreria.cpp" donde estarán contenidas las funciones.
Usaremos unas definiciones estandares incluidas en "Mi_Libreria.h":
#define Pantalla_X 640 // Pixels ancho pantalla. #define Pantalla_Y 480 // Pixels alto pantalla. #define Pantalla_bpp 16 // Bits por Pixels. #define Pantalla_Ventana SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE #define Pantalla_Completa SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN #define Volumen_Musica 64 // Valores de 0 a 128. #define Volumen_Sonido 64 // Valores de 0 a 128. #define Frames_Segundo 20 // Son los fotogramas por segundo.
Y estas variables Externas:
extern SDL_Surface *pantalla; // Es la superficie principal o pantalla. extern SDL_Event evento; // Eventos del Teclado y Ratón. extern int terminar; // Variable para bucle principal.
Todas las funciones explicadas a continuación son a modo de ejemplo e instrucción, las verdaderas funciones son las contenidas en "Mi_Libreria.cpp", al final de este tutorial veremos un pequeño ejemplo de su uso.
Estos son los tipos de datos que usaremos normalmente, los primeros son definidos por SDL y los últimos son nativos del "C". Además hay una serie de estructuras también definidas por SDL.
#define Pantalla_X 640 // Pixels ancho pantalla. #define Pantalla_Y 480 // Pixels alto pantalla. #define Pantalla_bpp 16 // Bits por Pixels. #define Pantalla_Ventana SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE #define Pantalla_Completa SDL_SWSURFACE | SDL_DOUBLEBUF | SDL_FULLSCREEN #define Frames_Segundo 20 // Son los fotogramas por segundo. void Inicia_SDL( const char *nombre_ventana ) { atexit( SDL_Quit ); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) == -1) { printf("No se pudo iniciar la libreria SDL: %s\n", SDL_GetError()); exit(1); } pantalla = SDL_SetVideoMode( Pantalla_X, Pantalla_Y, Pantalla_bpp, Pantalla_Ventana ); if (!pantalla) { printf("No se pudo iniciar el modo de pantalla: %s\n", SDL_GetError()); exit(1); } SDL_WM_SetCaption( nombre_ventana, NULL ); // Pone nombre a la ventana. }
typedef struct { Uint8 r; // Intensidad de la componente roja. ( 0 <-> 255 ) Uint8 g; // Intensidad de la componente verde.( 0 <-> 255 ) Uint8 b; // Intensidad de la componente azul. ( 0 <-> 255 ) Uint8 unused; // Utilizado para el canal Alpha. ( 0 <-> 255 ) } SDL_Color;
El rango de valores de r, g y b comprende desde 0 hasta 255, donde 0 es la menor intensidad de color y 255 la mayor posible. Si quisiéramos, por ejemplo, mostrar el color verde puro deberíamos inicializar estos valores con (0, 255, 0) con lo que estaríamos indicando que la intensidad de color para el rojo sería 0, 255 para el verde y 0 para el azul. El miembro que no se usa es libre para almacenar la información que queramos, como puede ser el canal alpha, o bien cualquier otra cosa que consideremos oportuna.
Ejemplos:
SDL_Color verde = { 0, 255, 0 }; SDL_Color rojo; rojo.r = 255; rojo.g = 0; rojo.b = 0; SDL_Color azul_trans = { 0, 0, 255, 127 }; SDL_Color Amarillo_trans; Amarillo_trans.r = 255; Amarillo_trans.g = 255; Amarillo_trans.b = 0; Amarillo_trans.unused = 127;
No la vamos a utilizar puesto que sólo sirve para 256 colores, pero la veremos brevemente.
typedef struct { int ncolors; // número de colores usados en la paleta. SDL_Color *colors; // puntero a la estructura COLOR. } SDL_Palette;
La definición de este tipo de datos es bastante lógica ya que vamos a guardar una colección de colores. La paleta es solo usada en los modos de 8 bits por pixel, es decir los modos que funcionan a 256 colores. Una paleta de color no es mas que un subconjunto o agrupación de colores de los que podemos mostrar por pantalla que van a ser de uso común en el desarrollo de la aplicación. Por ejemplo si disponemos de 256 colores y vamos a desarrollar un videojuego o una aplicación en el que vamos a usar sólo 16 podemos crear una paleta con estos 16 colores y utilizarla para no tener que hacer referencia cada vez a la cantidad de colores en RGB. Es decir, cada vez que quiera utilizar el color azul no tendremos que especificar el (0,0,255) por componentes RGB si no acceder a, por ejemplo, la primera posición de nuestra paleta donde lo hemos almacenado previamente.
Por desgracia un Pixel no usa el formato SDL_Color que vimos anteriormente, es más nisiquiera usa el mismo formato en un mismo ordenador. El color de un pixel depende de los "bpp" bit por píxel, de la máscara, del desplazamiento de color y de la pérdida de precisión. Vamos un auténtico lío en el cual no pienso entrar a fondo.
Cada uno de estos píxeles tendrá asociado un color para los que se destinará un determinado número de bits (bits por píxel o bpp) que determinaran la calidad, medida en profundida de color, de la imagen. Los valores más comunes para el bpp son:
typedef struct { SDL_Palette *palette; Uint8 BitsPerPixel; Uint8 BytesPerPixel; Uint32 Rmask, Gmask, Bmask, Amask; Uint8 Rshift, Gshift, Bshift, Ashift; Uint8 Rloss, Gloss, Bloss, Aloss; Uint32 colorkey; Uint8 alpha; } SDL_PixelFormat;
El manejo del color en hexadecimal puede ser engorroso. Es conveniente utilizar funciones que nos transformen del tipo de color que vamos a usar "SDL_Color" a "Color Hexadecimal Puro y Duro Uint32".
Estas funciones son:
SDL_MapRGB:
Según el formato del píxel (bpp) la representación de un color puede variar. Estas funciones se encarga que a partir del formato de píxel y la cantidad de cada color RGB que queramos establecer devuelva el color en dicho formato de píxel. La función necesita un puntero al formato del pixel, por lo que utilizaremos normalmente el campo format de SDL_Surface además de la intensidad de color rojo, verde y azul. La función devuelve un número que contiene el color demandado en un formato manejable por SDL. Si el bpp es de 16 bits el valor retornado será del tipo Uint16 y si es de 8 bits el tipo devuelto será de tipo Uint8. Existe una variante de esta función con un parámetro más añadido que nos permite trabajar con canales alpha.
SDL_GetRGB:
Estas funciones reciben como parámetro de entrada el color y el formato del píxel y devuelve por referencia en r, g y b las componentes del píxel en cuestión. En la segunda función además devuelve la componente del canal alpha.
Ejemplo de Funciones:
// Crea un Color_RGB usando un Color_SDL
Uint32 Crea_Color_RGB( SDL_Surface *imagen, SDL_Color color ) { return SDL_MapRGBA( imagen->format, color.r, color.g, color.b, color.unused ); }
// Crea un Color_SDL usando un Color_RGB
SDL_Color Crea_SDL_Color( SDL_Surface *imagen, Uint32 color_rgb ) { SDL_Color color = { 0, 0, 0, 0 }; SDL_GetRGBA( color_rgb, imagen->format, &color.r, &color.g, &color.b, &color.unused ); return color; }
El sistema de coordenadas que utiliza SDL es diferente al sistema cartesiano de coordenadas que estamos acostumbrados a utilizar. La posición (0,0) se establece en la esquina superior izquierda de la superficie o pantalla principal. Cualquier valor positivo sobre x o y supone un desplazamiento hacia la derecha, en el caso de x, o hacia abajo, en el caso de y en la superficie en cuestión. Un valor negativo representa una posición fuera de la pantalla.
typedef struct { Sint16 x, y; // x,y posicion en pantalla Uint16 w, h; // w - Ancho h - Alto } SDL_Rect;
Un rectángulo abarca la superficie comprendida desde la posición (x,y) hasta la (x + w, y + h). Las otras dos esquinas vienen dadas por (x, y + h) la esquina que se encuentra abajo a la izquierda y (x + w,y) la que se corresponde con la esquina superior derecha.
typedef struct SDL_Surface { Uint32 flags; // solo lectura SDL_PixelFormat *format; // solo lectura int w, h; // solo lectura Uint16 pitch; // solo lectura void *pixels; // lectura y escritura clipping information SDL_Rect clip_rect; // solo lectura int refcount; // Read-mostly } SDL_Surface;
Básicamente hay dos formas de crear una nueva Superficie o Imagen, la primera y más evidente es cargar una imagen "BMP", "PNG" o "JPG" con cualquiera de las funciones encargadas para esto como ejemplo: "SDL_Surface *imagen = IMG_Load( const char *nombre_archivo );". Y la que vamos a ver ahora que es creando una superficie nueva vacía. La manera de crear una nueva superficie es utilizando la función SDL_CreateRGBSurface(). Esta función nos permite crear una nueva superficie RGB vacía lista para ser usada. El prototipo de la función es:
SDL_Surface *SDL_CreateRGBSurface( Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask );
Puedes observar como la función devuelve un puntero a una superficie que es, al fin y al cabo, lo que queremos obtener. Los parámetros que recibe la función están íntimamente relacionados con los de la estructura SDL y tienen prácticamente la misma semántica que estos. Es lógico ya que van a crear una estructura de este tipo. Pasamos a estudiar estos parámetros:
Para comprender los parámetros Rmask, Gmask, Bmask y Amask debemos estudiar las estructuras internas de SDL. Estos parámetros pertenecen a la estructura SDL_PixelFormat. Cada parámetro de los comentados representa a la cantidad de color correspondiente que queremos añadir como si de una mezcla RGB se tratase. Los valores que puede tomar el campo flags de esta estructura son los siguientes:
A la hora de elegir en que memoria crear la superficie debemos de tener en cuenta los siguientes aspectos. En la memoria del sistema tenemos un acceso más rápido a los píxeles pero conseguimos una menor rapidez en el blitting. En la memoria de vídeo ocurre lo contrario, tenemos un acceso lento a los píxeles pero un mayor rendimiento a la hora de realizar blitting.
Ejemplo de Función:
SDL_Surface *Crea_Imagen_Color( int ancho, int alto, SDL_Color color ) { const SDL_VideoInfo *vi = SDL_GetVideoInfo(); SDL_Surface *surface=SDL_CreateRGBSurface( SDL_SWSURFACE | SDL_SRCALPHA | SDL_SRCCOLORKEY, ancho, alto, vi->vfmt->BitsPerPixel, vi->vfmt->Rmask, vi->vfmt->Gmask, vi->vfmt->Bmask, vi->vfmt->Amask ); SDL_SetColorKey( surface, SDL_SRCCOLORKEY|SDL_RLEACCEL, SDL_MapRGB( surface->format, color.r, color.g, color.b)); return surface; }
SDL_SetColorKey es una función que define un color transparente en la imagen. Al crear los tiles para un juego se define un color que será el que se colocará como transparente. Por ejemplo una nave se le coloca el fondo verde y con esta función se elimina ese color. La estructura de la función es la siguiente:
int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
El primer parámetro es la superficie a la cual queremos aplicar el color transparente, el segundo son los flags, y el tercer es el color. Para ello utilizaremos la función SDL_MapRGB que nos devuelve un valor Uint32 con el valor de un color RGB.
A continuación vemos un ejemplo:
Uint32 color; // Especificamos el verde como color para transparente color = SDL_MapRGB( imagen->format, 0,255,0 ); SDL_SetColorKey( imagen, SDL_SRCCOLORKEY | SDL_RLEACCEL, color );
// Carga una imagen con un color transparente
// Puede manejar ficheros en formato BMP, PNM, XPM, LBM, PCX, GIF, JPG, PNG y TGA. SDL_Surface *Carga_Imagen_Color( const char *nombre_archivo, SDL_Color color ) { SDL_Surface *tmp, *bmp; tmp = IMG_Load( nombre_archivo ); if( !tmp ) { printf("No se pudo cargar %s \n", nombre_archivo); exit(1); } SDL_SetColorKey( tmp, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB( tmp->format, color.r, color.g, color.b ) ); bmp = SDL_DisplayFormat( tmp ); SDL_FreeSurface( tmp ); if( !bmp ) { printf("No se pudo DisplayFormat %s \n", nombre_archivo); exit(1); } return bmp; }
int SDL_SetAlpha( SDL_Surface *surface, Uint32 flag, Unit8 alpha );
Puedes observar que la función es muy parecida a SDL_SetColorKey() ya que no deja de tener un cometido parecido. En este caso el parámetro flag puede tomar los valores 0, para desactivar el alpha o SDL_SRCALPHA para indicar que el tercer parámetro de la función es el alpha o transparencia que queremos aplicar a la superfice surface. Junto a SDL_SRCALPHA podemos activar SDL_RLEACCEL para la aceleración comentada en el subaparatado anterior. Los niveles de transparencia son 0 para totalmente opaco y 255 para totalmente transparente. Como las demás funciones devuelve 0 si se realizó la tarea con éxito y -1 en caso de error.
int SDL_FillRect( SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color ); // Pinta un Rectángulo void Pinta_Rectangulo_Lleno( SDL_Surface *imagen, int x, int y, int ancho, int alto, SDL_Color color ) { SDL_Rect dest = { x, y, ancho, alto }; SDL_FillRect( imagen, &dest, SDL_MapRGBA( imagen->format, color.r, color.g, color.b, color.unused ) ); } // Limpia la superficie con un color void Limpia_Imagen( SDL_Surface *imagen, SDL_Color color ) { SDL_Rect dest = {0, 0, imagen->w, imagen->h}; SDL_FillRect( imagen, &dest, SDL_MapRGBA( imagen->format, color.r, color.g, color.b, color.unused ) ); }
Blitting es el proceso de hacer blit. Blit proviene de las palabras "block transfer" o en castellano, transferencia de bloques. Antiguamente la transferencia de bloques era abreviada como BLT. Como BLT no era pronunciable heredó una 'i' y de ahí surgió el término blit. Conceptualmente hacer blit puede ser equivalente al conocidísimo copy-paste aunque realmente hace más cosas que simplemente mover datos de una superficie a otra. Llamaremos blitter a la unidad de hardware o software que se encarga del blit y blitting a la acción de transferir bloques.
Para realizar un blit necesitas dos superficies, una de origen y una de destino, y dos rectángulos, también uno de origen y otro de destino. Una vez tengas esta información puedes realizar la llamada a la función de blitting entre superficies de SDL:
int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
Como puedes observar esta función recibe como parámetros toda la información que demandábamos antes, pasando todas las estructuras como punteros a las originales. Si los parámetros que definen los rectángulos de origen y de destino se inicializan con el valor NULL indicará que las superficies serán utilizadas enteras, ya que no se especifica rectángulo alguno. Debes saber que los rectángulos de origen y destino no tienen que coincidir ni en altura ni anchura, es más, el valor que tenga el rectángulo destino no influye en absoluto en la tarea de blitting, sólo importa las coordenadas donde queremos copiar la región. Esto es debido a que no es posible redimensionar una superficie al hacer blitting con la librería básica de SDL.
Esta función devuelve un entero. Si el valor de este entero es 0 todo habrá ido bien mientras qe si el valor devuelto es -1 indica que existe un error. Esta función devuelve un valor especial para describir una situación específica. Si la función devuelve el valor -2 indica que al menos una de las superficies están almacenadas en la memoria de vídeo por lo que necesitaremos refrescar para mostrar la imagen.
En el caso de realizar blitting entre dos superficies con formato de píxel diferentes la unidad de blitter de SDL se encarga de "traducir" un formato de píxel en otro. Este proceso es transparente al usuario pero supone una sobrecarga del sistema. Hay que tener en cuenta que ciertas operaciones de este estilo pueden afectar al rendimiento. La regla a tener en cuenta es bastante sencilla, a cuánto más complejidad, más lentitud. Cuantas más cosas obliguemos al blitter a realizar más tardará en realizarlas, así de simple. Una buena práctica es tener todas nuestras superficies en el mismo formato de píxel por lo que ahorraremos al blitter hacer traducciones.
// Muestra la Pantalla y espera el tiempo sobrante
#define Frames_Segundo 20 // Son los fotogramas por segundo. void Muestra_Pantalla_Frame( void ) { SDL_Flip( pantalla ); static const Uint32 frames = Uint32( 1000 / Frames_Segundo ); // Son los fotogramas por segundo. static Uint32 tiempo = SDL_GetTicks() + frames ; // Se inicia la cuenta de tiempo. Uint32 t_espera = tiempo - SDL_GetTicks(); if ( t_espera > 0 && t_espera <= frames ) SDL_Delay( t_espera ); tiempo += frames; }
// Elimina de la Memoria una Imagen
void Elimina_Imagen( SDL_Surface *imagen ) { SDL_FreeSurface( imagen ); }
// Cierra la libreria SDL
void Cierra_SDL( void ) { SDL_FreeSurface( pantalla ); // Liberar memoria pantalla SDL_Quit(); // Cerrar SDL printf( "\nTodo ha salido bien.\n" ); }
#include <cstdlib> #include <iostream> using namespace std; #include "Mi_Libreria.h" // ----------------------------------------------------------------------------- // Mis Clases, Programación Orientada a Objetos ( POO ) ------------------------ // ----------------------------------------------------------------------------- class sprite { private: // Variables y funciones privadas SDL_Surface *imagen; SDL_Rect rect; int mas_x; int mas_y; public: // Variables y funciones públicas sprite( const char *nombre_archivo ); // Constructor mismo nombre que la clase sprite( const char *nombre_archivo, SDL_Color color ); ~sprite( void ); // Destructor void mostrar( void ); // Mostrar Sprite }; sprite::sprite( const char *nombre_archivo ) // Constructor { imagen = Carga_Imagen_Alpha( nombre_archivo ); rect.x = rand() % ( Pantalla_X - 75 ); rect.y = rand() % ( Pantalla_Y - 75 ); rect.w = imagen->w; rect.h = imagen->h; do { mas_x = ( rand() % 12 ) - 6; mas_y = ( rand() % 12 ) - 6; } while ( mas_x == 0 || mas_y == 0 ); } sprite::sprite( const char *nombre_archivo, SDL_Color color ) // Constructor { imagen = Carga_Imagen_Color( nombre_archivo, color ); rect.x = rand() % ( Pantalla_X - 50 ); rect.y = rand() % ( Pantalla_Y - 50 ); rect.w = imagen->w; rect.h = imagen->h; do { mas_x = ( rand() % 12 ) - 6; mas_y = ( rand() % 12 ) - 6; } while ( mas_x == 0 || mas_y == 0 ); } sprite::~sprite( void ) // Destructor { Elimina_Imagen( imagen ); } void sprite::mostrar(void) // Dibujamos el cursor del ratón { rect.x += mas_x; rect.y += mas_y; if ( rect.x < 0 || rect.x > Pantalla_X - imagen->w ) mas_x *= -1; if ( rect.y < 0 || rect.y > Pantalla_Y - imagen->h ) mas_y *= -1; SDL_BlitSurface( imagen, NULL, pantalla, &rect ); }; // ----------------------------------------------------------------------------- // MAIN FUNCION PRINCIPAL ------------------------------------------------------ // ----------------------------------------------------------------------------- int main(int argc, char *argv[]) { // Inicimamos la Librerias SDL. ---------------------------------------------- Inicia_SDL( "Mi curso SDL Graficos." ); Icono_Ventana( ".\\Imagen\\mi_icono.png", (SDL_Color){255, 0, 255} ); // SDL_ShowCursor( SDL_DISABLE ); // No mostrar el cursor genérico windows. SDL_ShowCursor( SDL_ENABLE ); // Mostrar el cursor genérico windows. // Creamos colores. ---------------------------------------------------------- SDL_Color blanco = { 255, 255, 255 }; SDL_Color rojo = { 255, 0, 0 }; SDL_Color negro = { 0, 0, 0 }; SDL_Color verde = { 0, 255, 0 }; SDL_Color azul = { 0, 0, 255 }; // Inicializa la semilla de numeros aleatorios. ------------------------------ srand(time(0)); // Cargamos la imágen de fondo ----------------------------------------------- SDL_Surface *imagen_fondo = Carga_Imagen( ".\\Imagen\\fondo.png" ); SDL_Rect rect_fondo = { 0, 0, 100, 100 }; Sint16 fondo_mas_x = 4; Sint16 fondo_mas_y = 4; // Cargamos los Sprites ------------------------------------------------------ sprite cursor( ".\\Imagen\\cursor.png" ); sprite cursor_color( ".\\Imagen\\cursor.png", (SDL_Color){ 255, 0, 255} ); sprite copo( ".\\Imagen\\sprite.png" ); sprite copo_color( ".\\Imagen\\sprite.png", (SDL_Color){ 255, 0, 255} ); // Cargamos una Imagen para Rotar. ------------------------------------------- SDL_Surface *imagen_a_rotar = Carga_Imagen_Alpha( ".\\Imagen\\mail.png" ); SDL_Surface *imagen_rotada; SDL_Rect rect_rotar; float angulo = 0, zoom = 0; // Creamos mi imagen --------------------------------------------------------- SDL_Surface *mi_imagen = Crea_Imagen_Color( 50, 50, verde ); Limpia_Imagen( mi_imagen, verde ); // Pintamos Pixels en la imagen con color RGB. Uint32 azul_RGB = Crea_Color_RGB( mi_imagen, (SDL_Color){ 0, 0, 255 } ); Bloquea_Imagen( mi_imagen ); // Bloquear Imagen para pintar Pixels. for ( Sint16 p_x = 0; p_x < 50; p_x+= 2 ) { for ( Sint16 p_y = 0; p_y < 50; p_y+= 2 ) { Pinta_Pixel_Color_RGB( mi_imagen, p_x, p_y, azul_RGB ); } } Desbloquea_Imagen( mi_imagen ); // Desbloquear Imagen al terminar Pixels. // Bucle Principal, usa variable externa llamada "terminar" ------------------ while( !terminar ) { // Dibujamos el fondo ------------------------------------------------------ Limpia_Imagen( pantalla, negro ); SDL_SetAlpha( imagen_fondo, SDL_SRCALPHA|SDL_RLEACCEL, 127 ); SDL_BlitSurface( imagen_fondo, NULL, pantalla, &(SDL_Rect){0,0,0,0} ); rect_fondo.x += fondo_mas_x; rect_fondo.y += fondo_mas_y; rect_fondo.w = 100; rect_fondo.h = 100; if ( rect_fondo.x < 0 || rect_fondo.x > Pantalla_X - 100 ) fondo_mas_x *= -1; if ( rect_fondo.y < 0 || rect_fondo.y > Pantalla_Y - 100 ) fondo_mas_y *= -1; SDL_SetAlpha( imagen_fondo, SDL_SRCALPHA|SDL_RLEACCEL, 255 ); SDL_BlitSurface( imagen_fondo, &rect_fondo, pantalla, &rect_fondo ); // Pintamos Pixels --------------------------------------------------------- Bloquea_Imagen( pantalla ); for ( Sint16 p_x = 0; p_x < Pantalla_X; p_x++ ) { Pinta_Pixel_SDL_Color( pantalla, p_x, ( p_x * Pantalla_Y ) / Pantalla_X, azul ); } Desbloquea_Imagen( pantalla ); // Pintamos unas primitivas. ----------------------------------------------- Pinta_Linea( pantalla, 0, 480, 640, 0, rojo ); Pinta_Rectangulo( pantalla, 100, 50, 200, 150, verde ); Pinta_Rectangulo_Lleno( pantalla, 500, 100, 50, 50, rojo ); Pinta_Circulo( pantalla, 320, 240, 110, rojo ); // Pintamos una Imagen Rotando y con Zoom. --------------------------------- imagen_rotada = rotozoomSurface( imagen_a_rotar , angulo, zoom, 0); ++angulo; zoom += 0.005; if ( angulo >= 360 ) angulo = 0; if ( zoom >= 2 ) zoom = 0; rect_rotar.x = 200 - (imagen_rotada->w >> 1 ); rect_rotar.y = 300 - (imagen_rotada->h >> 1 ); rect_rotar.w = 0; rect_rotar.h = 0; SDL_BlitSurface( imagen_rotada, NULL, pantalla, &rect_rotar ); // Pintamos Mi imagen. ----------------------------------------------------- SDL_BlitSurface( mi_imagen, NULL, pantalla, &(SDL_Rect){ 500, 200, 0, 0} ); // Pintamos los Sprites. --------------------------------------------------- cursor.mostrar(); cursor_color.mostrar(); copo.mostrar(); copo_color.mostrar(); // Esperamos Eventos y Mostramos la Pantalla con Frames_Segundo.------------ Espera_Eventos(); Muestra_Pantalla_Frame(); } Elimina_Imagen( imagen_fondo ); // Liberar memoria. Elimina_Imagen( mi_imagen ); // Liberar memoria. Elimina_Imagen( imagen_a_rotar); // Liberar memoria. Elimina_Imagen( imagen_rotada ); // Liberar memoria. Cierra_SDL(); // Cierra las Librerias SDL. return EXIT_SUCCESS; }
Descargar Ejemplo de Graficos (Sólo usuarios registrados)
Descargar Ejemplo de Graficos mas los Alpha (Sólo usuarios registrados)
Comentarios
muchisimas gracias no sabes
muchisimas gracias no sabes cuanto me has ayudado en esto del C
yo programo en Basic pero habia estado buscando como empezar en C
y todo esto me esta ayudando bastante gracias...
Oye, tengo un problema. Me
Oye, tengo un problema.
Me podrias decir donde esta la pestaña argum..?? No la encuentro.
A ser posible con una captura.
Saludos
¡Iníciate en Linux fácilmente! Sólo entra aquí y comprueba que distribución se adapta mejor a tí.
Mi review: iPod Touch 4G
Vaya lujo
tener este tipo de tutoriales. Estoy seguro de que el dia de mañana daran sus frutos, como los han dado los de PSP (aunque han tenido que pasar meses para que "cuajen" de verdad).
Tienes mis 5 estrellas, como casi siempre pipa.
Un saludo compañero, y gracias por aportar tu granito de arena para difundir el arte de la programacion.
Para recibir ayuda más rápidamente, recomendamos que pongas títulos descriptivos y no utilices abreviaturas (estilo MSN) en tus post de los foros. Recuerda revisar el Manual del perfecto forero y las Normas de la Comunidad.
Gracias...
La programación en C++ es mucho más compleja que en LUA pero merece la pena por la versatilidad y la potencia.
Yo me he dado 6 meses para estudiar C++ y las Librerias SDL, así que es normal que mis tutoriales en LUA tarden en dar resultados, nadie se lee un tutorial y hace un juego a la primera. Gracias Unicorn...
¿Tienes idea de hacer algo
¿Tienes idea de hacer algo en la psp con el c++?, lo digo mas q nada por "mantenerte" dentro de los limites de psp, usar la resolucion 480x272, tratar de evitar los png con canal alpha 32bits, evitar en la medida de lo posible sdl_alpha y evitar cualquier libreria como la sdl_gfx pues tiene una gran perdida de rendimiento.
A ver si un dia de estos me animo yo a poner mi codigo en c++, saludos