|
|
Este documento está disponible en los siguientes idiomas: English Castellano Deutsch Francais Nederlands Turkce |
por Leonardo Giordani <leo.giordani(at)libero.it> Sobre el autor: He obtenido mi diploma por parte de la Facultad de Ingenier�a en Telecomunicaciones del Polit�cnico de Mil�n. Estoy interesado en la programaci�n, principalmente en ensamblador y C/C++. Trabajo desde 1999 con Linux y Unix solamente. Traducido al español por: Edgar Hern�ndez Z��iga <edgar(at)linuxfocus.org> Contenidos: |
Implementando un desplazador de texto en gr�ficos SDLResumen: Esta serie de art�culos tiene el prop�sito de introducir al lector en el mundo de las producciones multimedia, tambi�n conocidas como "demos". Toda la Internet est� llena de informaci�n en la materia, pero algunas personas han conseguido grandes cosas en Linux: my meta es describir la teor�a de algunos efectos gr�ficos y de audio y su implementaci�n utilizando la biblioteca SDL. Podr�n encontrar m�s informaci�n en:
Los requisitos para el entendimiento del art�culo son:
|
Un desplazador o voluta, es parte de un "demo" que permite escribir una sentencia o texto en movimiento en la panatalla o monitor: este es uno de los efectos b�sicos que puedes encontrar en cualquier producci�n multimedia al cual es posible a�adirle un poco de din�mica al mostr�rsele al usuario. En �ste art�culo veremos como construir un desplazador b�sico que permitir� mover texto de derecha a izquierda.
La idea b�sica de un desplazador, es copiar una parte de la pantalla uno o m�s pixeles hacia la izquierda o en alguna otra direcci�n. Ejecutando esta operaci�n con una buena velocidad obtendr�s la ilusi�n de un movimiento continuo, eso es todo.
La teor�a b�sica no es nada complicada; vamos a traducir todo esto en c�digo: nos referiremos en adelante al concepto de superficie, dado que tenemos ya los conocimientos b�sicos de programaci�n con SDL. Mientras trabajemos con la biblioteca SDL, debemos recordar siempre que podemos usar el poder�o de la funci�n
SDL_BlitSurface() la cual nos permite hacer una copia de una parte de una SDL_Surface identificada por una SDL_Rect en otra SDL_Surface identificada por otra SDL_Rect .Por ejemplo, imaginemos que hemos definido e inicializado dos superficies y dos rect�ngulos
#define WIDTH 800 #define HEIGHT 600 SDL_Surface *Src; SDL_Surface *Dst; Src = SDL_CreateRGBSurface(SDL_HWSURFACE, WIDTH, HEIGHT, 8, r_mask, g_mask, b_mask, a_mask); Dst = SDL_CreateRGBSurface(SDL_HWSURFACE, WIDTH, HEIGHT, 8, r_mask, g_mask, b_mask, a_mask); SDL_Rect BigArea = {0, 0, (WIDTH / 2), HEIGHT}; SDL_Rect SmallArea = {(WIDTH / 2) + 1, 0, (WIDTH / 2), (HEIGHT / 2)};Suponiendo que el color de la m�scara se encuentra correctamente inicializado. Copiar las dos superficies completas implica solo un peque�o esfuerzo.
SDL_BlitSurface(Src, 0, Dst, 0);Nota que en el destino de la superficie solo las coordenadas del rect�ngulo est�n consideradas y no su dimensi�n, esto significa que la operaci�n
SDL_BlitSurface(Src, &BigArea, Dst, &SmallArea);es perfectamente legal y copia la mitad izquierda de Src la superficie en la mitad derecha de la Dst superficie.
Ahora ejecutar el desplazado de una superficie no es m�s un misterio: es suficiente copiar una parte de la superficie en un rect�ngulo cambiado en la misma superficie; es obvio que esto tendremos que crearlo como un ciclo, con esto, el programa resultante ser� un poco m�s complejo, pero el concepto b�sico se mantiene simple. A cada instante del ciclo usaremos dos rect�ngulos, el segundo cambio se refiere al primero en la direcci�n en la que se ha determinado el desplazamiento, y copiaremos la superficie a s� misma del primero al segundo rect�ngulo.
SDL_Surface *temp; SDL_Rect From = {1, 0, WIDTH, HEIGHT}; SDL_Rect First = {0, 0, 1, HEIGHT}; SDL_Rect Last = {WIDTH-1, 0, 1, HEIGHT}; temp = SDL_CreateRGBSurface(SDL_HWSURFACE, 1, HEIGHT, 8, r_mask, g_mask, b_mask, a_mask); while(1){ SDL_BlitSurface(Src, &First, temp, 0); SDL_BlitSurface(Src, &From, Src, 0); SDL_BlitSurface(temp, &First, Src, &Last); SDL_BlitSurface(Src, 0, Screen, 0); }Como puedes ver, esto no es suficiente para desplazar la superficie hacia la izquierda: tenemos que reinsertar desde la derecha los pixeles que han salido de la pantalla, o la superficie de desplazamiento estar� detr�s de las copias generando un peque�o efecto de "deslizamiento". Con esto suponemos que est� lista una superficie vinculada en la pantalla. Ahora veamos un programa completo que abre una ventana de 480x200 pixeles y muestra el desplazamiento continuo de una imagen en ella.
#include "SDL/SDL.h" #include "SDL/SDL_image.h" #define SCREEN_WIDTH 480 #define SCREEN_HEIGHT 200 #if SDL_BYTEORDER == SDL_BIG_ENDIAN static const Uint32 r_mask = 0xFF000000; static const Uint32 g_mask = 0x00FF0000; static const Uint32 b_mask = 0x0000FF00; static const Uint32 a_mask = 0x000000FF; #else static const Uint32 r_mask = 0x000000FF; static const Uint32 g_mask = 0x0000FF00; static const Uint32 b_mask = 0x00FF0000; static const Uint32 a_mask = 0xFF000000; #endifEste grupo de definiciones es est�ndar en la mayor�a de las producciones multimedia.
static SDL_Surface* img_surface; static SDL_Surface* scroll_surface; static SDL_Surface* temp_surface;Aqu� est�n las tres superficies que usaremos: img_surface contendr� la imagen obtenida de un archivo, scroll_surface la imagen cambiada y, temp_surface los pixeles que hemos obtenido nuevamente de la derecha.
static const SDL_VideoInfo* info = 0; SDL_Surface* screen;Una SDL_VideoInfo estructura, contiene informaci�n acerca de la tarjeta de video, con la cual screen la superficie permite apuntar hacia la pantalla o monitor.
int init_video() { if( SDL_Init( SDL_INIT_VIDEO) < 0 ) { fprintf( stderr, "Video initialization failed: %s\n", SDL_GetError( ) ); return 0; } info = SDL_GetVideoInfo( ); if( !info ) { fprintf( stderr, "Video query failed: %s\n", SDL_GetError( ) ); return 0; } return 1; } int set_video( Uint16 width, Uint16 height, int bpp, int flags) { if (init_video()) { if((screen = SDL_SetVideoMode(width,height,bpp,flags))==0) { fprintf( stderr, "Video mode set failed: %s\n", SDL_GetError( ) ); return 0; } } return 1; }La funci�n init_video() inicializa el subsistema de video SDL y llena completamente la info estructura. La funci set_video() intenta establecer la proporci�n o modo de video que fue establecido, tama�o y profundidad de color.
void quit( int code ) { SDL_FreeSurface(scroll_surface); SDL_FreeSurface(img_surface); SDL_Quit( ); exit( code ); }Esta es la funci�n esencial de terminaci�n, la cual libera todos los recursos que utilizamos as� como las llamadas SDL_Quit .
void handle_key_down( SDL_keysym* keysym ) { switch( keysym->sym ) { case SDLK_ESCAPE: quit( 0 ); break; default: break; } }Un evento "Presionar tecla": en este caso la tecla ESC.
void process_events( void ) { SDL_Event event; while( SDL_PollEvent( &event ) ) { switch( event.type ) { case SDL_KEYDOWN: handle_key_down( &event.key.keysym ); break; case SDL_QUIT: quit( 0 ); break; } } }La funci�n para el control de un evento no menor.
void init() { SDL_Surface* tmp; Uint16 i; tmp = SDL_CreateRGBSurface(SDL_HWSURFACE, SCREEN_WIDTH, SCREEN_HEIGHT, 8, r_mask, g_mask, b_mask, a_mask); scroll_surface = SDL_DisplayFormat(tmp); SDL_FreeSurface(tmp);Vamos a trabajar con tmp una superficie para inicializar scroll_surface y temp_surface Ambas son convertidas en formato de video framebuffer por la funci SDL_DisplayFormat
img_surface = IMG_Load("img.pcx");Aqu� cargaremos dentro de img_surface la imagen guardada en el archivo.
for (i = 0; i < SDL_NUMEVENTS; ++i) { if (i != SDL_KEYDOWN && i != SDL_QUIT) { SDL_EventState(i, SDL_IGNORE); } } SDL_ShowCursor(SDL_DISABLE); }Todos los eventos son ignorados, a excepci�n de la tecla ESC que teminar� el programa; adem�s de eso, desactivaremos el puntero. All events are ignored except for the pressure of a key and the exit from the program; moreover we disable the cursor.
int main( int argc, char* argv[] ) { SDL_Rect ScrollFrom = {1, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; SDL_Rect First = {0, 0, 1, SCREEN_HEIGHT}; SDL_Rect Last = {SCREEN_WIDTH - 1, 0, 1, SCREEN_HEIGHT};Estos son los tres rect�ngulos descritos en el art�culo.cle.
if (!set_video(SCREEN_WIDTH, SCREEN_HEIGHT, 8, SDL_HWSURFACE | SDL_HWACCEL | SDL_HWPALETTE /*| SDL_FULLSCREEN*/)) quit(1); SDL_WM_SetCaption("Demo", ""); init(); SDL_BlitSurface(img_surface, 0, scroll_surface, 0);Este c�digo inicializa todo lo necesario: establece el modo de video escribe el t�tulo de la ventana, llama a init() y prepara scroll_surface .
while( 1 ) { process_events(); SDL_BlitSurface(scroll_surface, &First, temp_surface, 0); SDL_BlitSurface(scroll_surface, &ScrollFrom, scroll_surface, 0); SDL_BlitSurface(temp_surface, &First, scroll_surface, &Last); SDL_BlitSurface(scroll_surface, 0, screen, 0); SDL_Flip(screen); } return 0; }Este es el ciclo descrito en el art�culo: solo el evento para controlar las funciones y el regreso de la superficie en la pantalla han sido a�adidos.
Como puedes ver, el trabajo de inicializaci�n de la biblioteca no es peque�o, pero la ventaja es que es com�n para todo el "demo", as�, cuando el c�digo incrementa, la inicializaci�n continua siendo una peque�a parte de todo el programa, esto lo hace portable y reutilizable.
PD: Puedes hacerme llegar cualquier comentario, correcci�n o pregunta a mi direcci�n de correo o a trav�s de la p�gina de Retroalimentaci�n, Talback. Escr�beme en ingl�s, alem�n o italiano.
Contactar con el equipo de LinuFocus
© Leonardo Giordani, FDL LinuxFocus.org |
Información sobre la traducción:
|
2003-07-02, generated by lfparser version 2.40