[LinuxFocus-icon]
<--  | Hogar  | Mapa  | Indice  | Busqueda

Noticias | Arca | Enlaces | Sobre LF
Este documento está disponible en los siguientes idiomas: English  Castellano  Deutsch  Francais  Nederlands  Turkce  

[Leonardo]
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 SDL

[sdl]

Resumen:

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:

  • Simple DirectMedia Layer: leer el c�digo de las muestras y los juegos es la mejor manera de aprender nuevas soluciones.
  • lnxscene: un sitio nuevo, pero un gran lugar para el intercambio de conocimiento; podr�s encontrarme algunas veces como "muaddib"

Los requisitos para el entendimiento del art�culo son:

  • Conocimiento b�sico del lenguaje C, sint�xis, ciclos, bibliotecas.
  • Conocimiento b�sico de la biblioteca SDL, funciones b�sucas e inicializaci�n., te servir� consultar www.libsdl.org

_________________ _________________ _________________

 

El desplazador o voluta

Agradezco ampliamente a Sam Lantinga por la biblioteca SDL.

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;
#endif
Este 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.

 

Una peque�a demostraci�n

Aqu� est� una captura de pantalla en diferentes momentos:
state1 state2

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.


<--, regresar al índice de este número

Contactar con el equipo de LinuFocus
© Leonardo Giordani, FDL
LinuxFocus.org
Información sobre la traducción:
it --> -- : Leonardo Giordani <leo.giordani(at)libero.it>
it --> en: Leonardo Giordani <leo.giordani(at)libero.it>
en --> es: Edgar Hern�ndez Z��iga <edgar(at)linuxfocus.org>

2003-07-02, generated by lfparser version 2.40