Está en la página 1de 20

ESTRUCTURA DE DATOS Y ANALISIS DE ALGORITMOS PRACTICA 1

OBJETIVOS
Que el estudiante conozca que es SDL aprenda cuales son las principales estructuras de datos y de control de SDL establezca similitudes entre SRGP y SDL que faciliten su aprendizaje. comprenda como manejar eventos del teclado y del ratn. compile y pruebe sus primeros programas en SDL utilizando un editor multifuncional integrado. practique algunas primitivas de figuras geomtricas

DESCRIPCIN

En esta primera prctica aprenderemos algunos de los fundamentos bsicos de SDL (Simple DirectMedia Layer), una API (Aplication Program Interface) de desarrollo multimedia y multiplataforma libre, usada para desarrollar juegos, SDK (Software Development Kit) para juegos, emuladores, demos y cualquier otra aplicacin multimedia. Dado que est diseada principalmente para juegos, su implementacin es optimizada en hardware para obtener buenos tiempos de respuesta, lo que nos ser particularmente til en esta materia donde nos interesa siempre darle prioridad a algoritmos y estructuras de datos que garanticen eficiencia. Tal como lo ir descubriendo el lector de esta gua, esta librera nos ofrecer mucha ms versatilidad y control sobre el hardware de la computadora que la librera grfica SRGP estudiada en el curso previo. Pero este incremento del poder en un programa tendr un costo: un incremento de la complejidad. Consciente de ello, intentaremos aprovechar el conocimiento y la experiencia del estudiante en SRGP haciendo analogas (siempre que sea posible), de lo que haca antes (con SRGP) y de lo que har ahora (con SDL). ANTES DE COMENZAR Para sta y las prximas guas de la materia supondremos que el lector cuenta con una mquina con el sistema operativo OpenSUSE 11.2 instalado (el estudiante puede solicitar una copia con el profesor), con todos los paquetes de desarrollo necesarias para compilar y enlazar programas en lenguaje C, as como los paquetes necesarios para manejar el escritorio en ambiente grfico. Para ayudar a ubicar al lector, hay que recordar que una librera tiene dos componentes: Un conjunto de declaraciones de constantes, tipos de datos y prototipos de funcin, generalmente ubicados en uno o ms archivos de cabecera, los cuales se encuentran dentro del directorio de prototipos del sistema: "/usr/include", o en algn subdirectorio de este. En el caso de SDL, estos archivos se encuentran ubicados dentro del directorio "/usr/include/SDL". Un conjunto de uno o ms archivos de cdigo objeto que contiene los cdigos de funcin de la librera. La mayora de las libreras en Linux tienen el prefijo "lib" como parte del nombre, y estn ubicadas dentro del directorio de libreras del sistema: "/usr/lib" o en algn subdirectorio de este. En el caso de SDL, el archivo principal de la librera se llama "libSDL.so", pero pueden existir otras libreras complementarias para extender el poder de SDL. Los dos componentes de cada librera son colocados en la mquina mediante un proceso de instalacin (usualmente al instalar el sistema operativo). Sin embargo, muchas libreras, tal como SDL, deben ser instaladas en un proceso separado, posterior a la instalacin del sistema operativo, ya que no forman parte del sistema bsico que viene con el DVD de instalacin. 1

Las computadoras de los talleres del Departamento de Electrnica e Informtica de la UCA ya tienen instalada dicha librera, pero es probable que el lector desee hacer una instalacin en la mquina de su casa u oficina. Dicha librera puede ser obtenida desde los repositorios de OpenSUSE, en el sitio, "http://software.opensuse.org/112/es" En la caja de texto que aparece en la parte superior (a la derecha de la cajita), ingrese lo siguiente, "libSDL-devel" Entre las diferentes alternativas de versin de esta librera, instale desde, "games/openSUSE_11.2" Use el link, "1-Click Install" Como toda instalacin, tendr que aceptar y confirmar algunos parmetros, as como proporcionar la contrasea del usuario root. Cuando la instalacin termine, estar listo para programar en SDL. Debe recordar agregar en el encabezado del programa en lenguaje C, los archivos de cabecera de la correspondiente librera (ya que all se encuentran las definiciones que garantizan que la compilacin no fall), y al crear el archivo ejecutable debe agregarse en el enlazamiento la correspondiente librera (ya que esto garantiza que el ejecutable estar completo con todo el cdigo binario necesario). En este punto, es recomendable emplear algn editor multifuncional tal como Geany, que entre otras opciones, cuenta con un entorno integrado desde donde el programador puede hacer lo siguiente: Editar el programa con un embellecedor grfico similar al disponible en otros editores como kate o kwrite, el cual permite editar mltiples archivos a la vez, y para cada archivo muestra el conjunto de funciones y/o prototipos que tiene definido, as como el conjunto de macros, con opcin de moverse directamente hacia ellos. Tambin tiene una opcin para ver los directorios y archivos de una determinada carpeta de su rea de trabajo. Compilar el programa con reas donde se muestran los errores de sintaxis que el programa puede tener, o un mensaje de xito si el cdigo no posee errores. La compilacin puede seleccionarse con un cono o con una tecla de acceso directo. En caso de error puede moverse directamente de un error al siguiente o al anterior. Crear el programa ejecutable, el cual enlaza el programa objeto con la librera estndar de C y cualquier otra librera u opcin que el programador especifique, con lo que pueden verificarse los posibles errores de enlazamiento. La creacin del ejecutable se puede obtener mediante un cono o mediante una tecla de acceso directo. Ejecutar el programa, opcin que permite ejecutar un programa con parmetros (los parmetros de la lnea de comandos del sistema operativo). Nuevamente esta opcin se puede seleccionar mediante un cono o una tecla de acceso directo, lo que da al programador un ambiente ms verstil. Este editor puede bajarse desde los repositorios de OpenSUSE, simplemente busque "geany", e instlelo desde, "GNOME:Apps/openSUSE_11.2" 2

El editor geany se carga igual que cualquiera de los otros editores que usted ha utilizado, y siempre puede utilizar sus editores preferidos, pero en esta prctica se espera que el alumno conozca y use este editor para que evalu sus ventajas. ACCESO BASICO Para utilizar en un programa la librera SDL se deben seguir en concreto los siguientes pasos: PASO 1: agregar en el encabezado del programa la siguiente directiva de compilacin,
#include "SDL/SDL.h"

Por lo general, todos los archivos de cabecera de esta librera se agregan por defecto en el directorio "/usr/include/SDL". Sin embargo, es probable que en algunos sistemas operativos el directorio pudiera cambiar (v.g. Windows), esto es algo que el programador deber verificar. PASO 2: inicializar y finalizar la librera. La librera SDL est compuesta por ocho sub-sistemas: Manejadores de audio (Audio) Control de unidades pticas (CDROM) Manejador de eventos (Event Handling): ratn y teclado Operaciones de entrada y salida por archivo (File I/O) Manejador de mandos de juego (Joystick Handling) Control de hilos (Threading) Control de temporizadores (Timer) Control de video (Video) Para que pueda utilizarse dentro de un programa cualquier utilidad de alguno de estos ocho subsistemas, la librera de SDL debe ser inicializada. La inicializacin se realiza ejecutando la funcin SDL_Init(), cuyo prototipo es, int SDL_Init(Uint32 flags); La funcin SDL_Init() utiliza un parmetro de tipo Uint32 que no es ms que un entero de 32 bits sin signo. Otros tipos de datos similares a este, utilizados por SDL son los siguientes: TIPO Uint8 Sint8 Uint16 Sint16 Sint32 DESCRIPCION Entero de 8 bits sin signo Entero de 8 bits con signo Entero de 16 bits sin signo Entero de 16 bits con signo Entero de 32 bits con signo

La funcin SDL_Init() inicializa automticamente los sistemas Event Handling, File I/O y Threading. Para inicializar a los otros cinco subsistemas, se debe colocar como parmetro de la funcin SDL_Init(), uno o ms de los siguientes valores, unidos por un o-lgico a nivel de bits, dependiendo del o los subsistema(s) que se desea(n) tener activo(s): 3

SUBSISTEMA SDL_INIT_AUDIO SDL_INIT_CDROM SDL_INIT_JOYSTICK SDL_INIT_TIMER SDL_INIT_VIDEO SDL_INIT_EVERYTHING

USO Inicializa Inicializa Inicializa Inicializa Inicializa Inicializa

al subsistema de Audio al subsistema de CDROM al subsistema de Joystick al subsistema de Timer al subsistema de Video a todos los subsistemas

Tabla 1. Algunos subsistemas de SDL

Por ejemplo, Para inicializar los subsistemas de Audio y Video, se escribe una instruccin como la siguiente, SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO); La funcin SDL_Init() devuelve -1 si no tiene xito, o 0 en caso de xito. Si la librera no se pudo inicializar, por lo general el programa tendr que terminar su ejecucin, a no ser que la causa del problema pueda corregirse. En SDL, para conocer la causa por la cual una determinada funcin que acaba de ejecutarse fall, puede invocarse a la funcin SDL_GetError(), cuyo prototipo es el siguiente, char *SDL_GetError(void); Esta funcin devuelve una cadena de caracteres que informa el tipo de error que ha ocurrido. Esta cadena se puede copiar y/o mostrar al usuario para su correspondiente evaluacin. Por esta razn, el programador debe escribir la instruccin anterior de la siguiente manera, if(SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO)<0){ fprintf(stderr,"SDL_Init: %s\n", SDL_GetError()); exit(1); } Una vez inicializada la librera, el programador puede hacer uso de las funciones que estn definidas en los subsistemas que fueron inicializados. Los subsistemas que no fueron inicializados no se podrn usar, hasta que stos se inicialicen. Si la funcin SDL_Init() ya fue ejecutada, un programa puede inicializar un subsistema no inicializado invocando a la funcin SDL_InitSubSystem(), cuyo prototipo es, int SDL_InitSubSystem(Uint32 flags); Esta funcin usa el mismo tipo de argumento de SDL_Init(), para inicializar subsistemas no inicializados, y retorna -1 si falla, o 0 si tiene xito. Por ejemplo, se puede escribir el siguiente cdigo en un programa, if(SDL_Init(SDL_INIT_VIDEO)<0){ fprintf(stderr,"SDL_Init: %s\n", SDL_GetError()); exit(1); } if(SDL_InitSubSystem(SDL_INIT_AUDIO|SDL_INIT_CDROM)<0){ fprintf(stderr,"SDL_InitSubSystem: %s\n", SDL_GetError()); exit(1); } 4

Para conocer que subsistemas han sido inicializados se puede invocar a la funcin SDL_WasInit(), cuyo prototipo es, Uint32 SDL_WasInit(Uint32 flags); Esta funcin devuelve los subsistemas indicados en flags que estn inicializados. Los argumentos usan el mismo formato que la funcin SDL_Init(). Si un subsistema ya no va a utilizarse en un programa este puede cerrarse utilizando la funcin SDL_QuitSubSystem(), cuyo prototipo es, void SDL_QuitSubSystem(Uint32 flags); Despus de invocar a dicha funcin, la funcionalidad de los subsistemas indicados quedar inactiva hasta que se vuelvan a inicializar mediante SDL_InitSubSystem(). Antes de finalizar el programa debe invocar a la funcin SDL_Quit(), cuyo prototipo es, void SDL_Quit(void); Para finalizar todos los subsistemas. Dado que los programadores con frecuencia ejecutan una llamada a la funcin exit() para terminar un programa, olvidando ejecutar a SDL_Quit(), es conveniente que luego de inicializar la librera, se ejecute la siguiente instruccin, atexit(SDL_Quit); Al ejecutar esta funcin, el sistema operativo se encarga de invocar a la funcin indicada entre parntesis, luego de una terminacin normal del programa. En este sentido la inicializacin de la librera debera lucir de la siguiente manera. if(SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO)<0){ fprintf(stderr,"No se pudo inicializar SDL: %s\n", SDL_GetError()); exit(1); } atexit(SDL_Quit); En otras palabras, con el cdigo anterior, la funcin SDL_Quit() se ejecutar implcitamente cuando el programa termine. PASO 3: inicializar el modo de video. Es importante comprender que la inicializacin de la librera planteada en el ejemplo anterior, habilita al programador a cierta funcionalidad relacionada tanto con el manejo de audio como del video, pero no crea una ventana grfica. Para crear una ventana grfica (una superficie grfica), debe inicializarse el video mediante la funcin SDL_SetVideoMode(), cuyo prototipo es el siguiente, SDL_Surface *SDL_SetVideoMode(int width,int height, int bpp,Uint32 flags); Esta funcin devuelve un puntero de tipo SDL_Surface. Todas las funciones que manipularn dicha ventana grfica requerirn la direccin devuelta por esta funcin como uno de sus parmetros, por lo que el programador deber guardar el valor devuelto por SDL_SetVideoMode(). 5

El primero y segundo parmetro de SDL_SetVideoMode() especifican las dimensiones de la ventana deseada, es decir, la resolucin. El tercer parmetro indica el nmero de bits que se tendrn por cada pixel. En tal sentido, este parmetro especifica la profundidad de la ventana grfica. El cuarto parmetro determina la forma en cmo se crear la ventana, y se pueden usar uno o ms de los siguientes valores separados entre s por un o-lgico a nivel de bits, aunque no todos estos valores pueden combinarse, VALOR SDL_SWSURFACE SDL_HWSURFACE DESCRIPCION Crea la superficie del video en la memoria principal del sistema, este sera el uso ms comn. Crea la superficie del video en la memoria de video, ms eficiente pero no todas las superficie deben crearse all y en algunas computadoras la memoria de video se comparte de la memoria del sistema. Habilita el uso asncrono del despliegue en la superficie lo que produce un incremento de velocidad en mquinas con mltiples procesadores (SMP), pero deprecia el rendimiento de mquinas con un solo procesador (SSP). Cuando cierta profundidad (tercer parmetro) no es soportado por un sistema de video, se busca automticamente la mejor profundidad posible para la resolucin indicada por el programador (primeros dos parmetros). Proporciona acceso exclusivo a la paleta de color, lo que permite personalizar los colores a discrecin del programador. Habilita doble manejo de espacio de memoria, slo disponible con SDL_HWSURFACE, til al crear animaciones. Puede permitir a SDL utilizar modo de pantalla completa Crea una ventana cuyo tamao puede ser cambiada a voluntad del usuario. Si es posible, hace que SDL cree la ventana sin barra de ttulo o marco. Este es un valor implcito si se usa SDL_FULLSCREEN.
Tabla 2. Algunas banderas vlidas al crear una ventana grfica

SDL_ASYNCBLIT

SDL_ANYFORMAT

SDL_HWPALETTE SDL_DOUBLEBUF SDL_FULLSCREEN SDL_RESIZABLE SDL_NOFRAME

Si la funcin SDL_SetVideoMode() no tiene xito en crear la ventana grfica retornar un valor NULL. Es importante que el programador recuerde hacer esta validacin. En SRGP se trabajaba con lienzos. En SDL se trabaja con superficies. En tal sentido, la superficie creada con SDL_SetVideoMode() constituye el lienzo principal, el que ser visualizado en pantalla. Muchas operaciones de escritura en pantalla, tal como la colocacin de imgenes se realizan en superficies adicionales, y cuando se desea que stas sean visibles el programador debe migrar el contenido de estas superficies a la superficie principal. Esto ser explicado en prximas guas. Ntese que al iniciar el modo de video no se especifica el ttulo de la barra de ttulo. Si se desea colocar texto en dicha barra debe invocarse a la funcin SDL_WM_SetCaption(), cuyo prototipo es, void SDL_WM_SetCaption(const char *title, const char *icon); El primer parmetro es el ttulo que se quiere para la ventana, mientras que el segundo es el nombre del cono de dicha ventana. En consecuencia, para iniciar una ventana grfica de 640x480 con 8 bits por pixel, usando memoria del sistema, con una barra de ttulo que diga "Mi primer ventana grfica", tendra que escribirse lo siguiente, 6

SDL_Surface *screen=NULL; screen=SDL_SetVideoMode(640,480,8,SDL_SWSURFACE); if(screen==NULL){ fprintf(stderr,"Error al crear ventana de 640x480x8: %s\n", SDL_GetError()); exit(0); } SDL_WM_SetCaption("Mi primer ventana grfica",""); Podemos presentar al lector la siguiente analoga entre la librera SRGP y la librera SDL, En SRGP
SRGP_begin("Mi primer ventana grfica", 640,480,8,FALSE);

En SDL
SDL_Surface *screen=NULL; if(SDL_Init(SDL_INIT_VIDEO)<0){ fprintf(stderr, "No se pudo inicializar la librera %s\n", SDL_GetError()); exit(0); } atexit(SDL_Quit); screen=SDL_SetVideoMode(640,480,8,SDL_SWSURFACE); if(screen==NULL){ fprintf(stderr,"No se pudo crear ventana 640x480x8: %s\n", SDL_GetError()); exit(0); } SDL_WM_SetCaption("Mi primer ventana grfica",""); SDL_Quit();

SRGP_end();

Tabla 3. Comparacin en inicio y fin entre SRGP y SDL

Por supuesto, lo anterior puede que deje mal parada a nuestra nueva amiga SDL, pero ella nos lo compensar mas tarde. PASO 4: crear un ciclo de deteccin y manejo de eventos Para el manejo de eventos, SDL emplea la unin SDL_Event, cuya definicin es como sigue, typedef union{ Uint8 type; // tipo de evento SDL_ActiveEvent active; // evento activo SDL_KeyboardEvent key; // evento del teclado SDL_MouseMotionEvent motion; // Movimiento del ratn SDL_MouseButtonEvent button; // Evento de botones del ratn SDL_JoyAxisEvent jaxis; // Movimiento del Joystick SDL_JoyBallEvent jball; // Trackball del Joystick SDL_JoyHatEvent jhat; // Movimiento hat del joystick SDL_JoyButtonEvent jbutton; // Botones del Joystick SDL_ResizeEvent resize; // Redimensionamiento de la ventana SDL_QuitEvent quit; // Cierre de la ventana SDL_UserEvent user; // Evento definido por el usuario SDL_SywWMEvent syswm; // Evento no definido, manejado por la ventana } SDL_Event; La union SDL_Event es, despus de SDL_Surface, la estructura de datos ms importante de SDL. Dado su complejidad, discutiremos algunos detalles de SDL_Surface solo cuando sea necesario. Todo programa que quiera manejar eventos debe incluir una declaracin como la siguiente, 7

SDL_Event event; Para detectar un evento se puede invocar a la funcin SDL_WaitEvent(), cuyo prototipo es, int SDL_WaitEvent(SDL_Event *event); Esta funcin espera un tiempo indefinido hasta que se produzca un evento, retornando 1 al producirse el evento, en cuyo caso ste queda almacenado en el argumento event. La funcin retorna 0 en caso de producirse un error al leer el evento. Una vez que el evento es detectado, es fundamental darle el tratamiento adecuado, segn el tipo de evento que se haya producido. El campo type de la union SDL_Event sirve para este propsito, y se pueden presentar los siguientes tipos de eventos, Tipo de evento SDL_ACTIVEEVENT SDL_KEYDOWN SDL_KEYUP SDL_MOUSEBUTTONDOWN SDL_MOUSEBUTTONUP SDL_MOUSEMOTION SDL_JOYAXISMOTION SDL_JOYBALLMOTION SDL_JOYHATMOTION SDL_JOYBUTTONDOWN SDL_JOYBUTTONUP SDL_QUIT SDL_SYSWMEVENT SDL_VIDEORESIZE SDL_USEREVENT Estructura que maneja el evento SDL_ActiveEvent SDL_KeyboardEvent SDL_MouseButtonEvent SDL_MouseMotionEvent SDL_JoyAxisEvent SDL_JoyBallEvent SDL_JoyHatEvent SDL_JoyButtonEvent SDL_QuitEvent SDL_SysWMEvent SDL_ResizeEvent SDL_UserEvent
Tabla 4. Evento en SDL

CONTROL DEL TECLADO En el caso del teclado, por ejemplo, los eventos ocurren cuando se presiona una tecla (evento SDL_KEYDOWN) o cuando se suelta una tecla (evento SDL_KEYUP), en cuyo caso el evento queda almacenado dentro del campo key que es de tipo SDL_KeyboardEvent (vese la union SDL_Event). La estructura SDL_KeyboardEvent est definida de la siguiente manera, typedef struct{ Uint8 type; Uint8 state; SDL_keysym keysym; } SDL_KeyboardEvent; // Contiene SDL_KEYDOWN o SDL_KEYUP // Contiene SDL_PRESSED o SDL_RELEASED // Contiene la informacin de la tecla presionada

Los campos type y state son redundantes, pero son necesarios para lograr congruencia con la definicin de la unin SDL_Event. Ntese que no almacenan los mismos valores. Para poder conocer cul es la tecla que se ha presionado, se examina el campo keysym de la estructura SDL_KeyboardEvent, el cual es de tipo SDL_keysym que es una estructura definida como, 8

typedef struct{ Uint8 scancode; SDLKey sym; SDLMod mod; Uint16 unicode; } SDL_keysym;

// // // //

Valor determinado por el hardware, identifica a la tecla Nombre simblico de la tecla presionada Modificadores usados junto con la tecla presionada Caracter segn la tabla de codificacin UNICODE

El campo scancode de esta estructura identifica a la tecla en el teclado. Es determinado por el hardware. Casi no se usa ya que puede cambiar de un teclado a otro. El campo sym es probablemente el ms utilizado, ya que determina la representacin simblica de la tecla que ha sido presionada. En SDL se tienen definidas las siguientes macros para identificar a las diferentes teclas del teclado,
SDLKey SDLK_BACKSPACE SDLK_TAB SDLK_CLEAR SDLK_RETURN SDLK_PAUSE SDLK_ESCAPE SDLK_SPACE SDLK_EXCLAIM SDLK_QUOTEDBL SDLK_HASH SDLK_DOLLAR SDLK_AMPERSAND SDLK_QUOTE SDLK_LEFTPAREN SDLK_RIGHTPAREN SDLK_ASTERISK SDLK_PLUS SDLK_COMMA SDLK_MINUS SDLK_PERIOD SDLK_SLASH SDLK_0 SDLK_1 SDLK_2 SDLK_3 SDLK_4 SDLK_5 SDLK_6 SDLK_7 SDLK_8 SDLK_9 SDLK_COLON SDLK_SEMICOLON SDLK_LESS SDLK_EQUALS SDLK_GREATER SDLK_QUESTION SDLK_AT Valor ASCII '\b' '\t' '\r' '^[' ' ' '!' '"' '#' '$' '&' ''' '(' ')' '*' '+' ',' '-' '.' '/' '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' ':' ';' '<' '=' '>' '?' '@' Nombre "backspace" "tab" "clear" "return" "pause" "escape" "space" "exclaim" "quotedbl" "hash" "dollar" "ampersand" "quote" "left parenthesis" "right parenthesis" "asterisk" "plus sign" "comma" "minus sign" "period" "forward slash" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "colon" "semicolon" "less-than sign" "equals sign" "greater-than sign" "question mark" "at" SDLKey SDLK_LEFTBRACKET SDLK_BACKSLASH SDLK_RIGHTBRACKET SDLK_CARET SDLK_UNDERSCORE SDLK_BACKQUOTE SDLK_a SDLK_b SDLK_c SDLK_d SDLK_e SDLK_f SDLK_g SDLK_h SDLK_i SDLK_j SDLK_k SDLK_l SDLK_m SDLK_n SDLK_o SDLK_p SDLK_q SDLK_r SDLK_s SDLK_t SDLK_u SDLK_v SDLK_w SDLK_x SDLK_y SDLK_z SDLK_DELETE SDLK_KP0 SDLK_KP1 SDLK_KP2 SDLK_KP3 SDLK_KP4 Valor ASCII '[' '\' ']' '^' '_' '`' 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' '^?' Nombre "left bracket" "backslash" "right bracket" "caret" "underscore" "grave" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "delete" "keypad 0" "keypad 1" "keypad 2" "keypad 3" "keypad 4"

SDLKey SDLK_KP5 SDLK_KP6 SDLK_KP7 SDLK_KP8 SDLK_KP9 SDLK_KP_PERIOD SDLK_KP_DIVIDE SDLK_KP_MULTIPLY SDLK_KP_MINUS SDLK_KP_PLUS SDLK_KP_ENTER SDLK_KP_EQUALS SDLK_UP SDLK_DOWN SDLK_RIGHT SDLK_LEFT SDLK_INSERT SDLK_HOME SDLK_END SDLK_PAGEUP SDLK_PAGEDOWN SDLK_F1 SDLK_F2 SDLK_F3 SDLK_F4 SDLK_F5 SDLK_F6 SDLK_F7 SDLK_F8

Valor ASCII

Nombre "keypad 5" "keypad 6" "keypad 7" "keypad 8" "keypad 9" "keypad period" "keypad divide" "keypad multiply" "keypad minus" "keypad plus" "keypad enter" "keypad equals" "up arrow" "down arrow" "right arrow" "left arrow" "insert" "home" "end" "page up" "page down" "F1" "F2" "F3" "F4" "F5" "F6" "F7" "F8"

SDLKey SDLK_F9 SDLK_F10 SDLK_F11 SDLK_F12 SDLK_F13 SDLK_F14 SDLK_F15 SDLK_NUMLOCK SDLK_CAPSLOCK SDLK_SCROLLOCK SDLK_RSHIFT SDLK_LSHIFT SDLK_RCTRL SDLK_LCTRL SDLK_RALT SDLK_LALT SDLK_RMETA SDLK_LMETA SDLK_LSUPER SDLK_RSUPER SDLK_MODE SDLK_HELP SDLK_PRINT SDLK_SYSREQ SDLK_BREAK SDLK_MENU SDLK_POWER SDLK_EURO

Valor ASCII

Nombre "F9" "F10" "F11" "F12" "F13" "F14" "F15" "numlock" "capslock" "scrollock" "right shift" "left shift" "right ctrl" "left ctrl" "right alt" "left alt" "right meta" "left meta" "left windows key" "right windows key" "mode shift" "help" "print-screen" "SysRq" "break" "menu" "power" "euro"

'.' '/' '*' '-' '+' '\r' '='

Tabla 5. Macros para el manejo del teclado

Puede obtenerse el nombre simblico de la tecla presionada ejecutando la funcin SDL_GetKeyName(), cuyo prototipo es el siguiente, char *SDL_GetKeyName(SDLKey key); El campo mod identifica cual o cuales teclas especiales (modificadores) estaban presionadas cuando se presiono la tecla en cuestin, proporcionndose las siguientes macros, SDLMod
KMOD_NONE KMOD_NUM KMOD_CAPS KMOD_LCTRL KMOD_RCTRL KMOD_RSHIFT

Descripcin
No se aplico modificador Numlock est abajo Capslock est abajo Left Control est abajo Right Control est abajo Right Shift est abajo

SDLMod
KMOD_LSHIFT KMOD_RALT KMOD_LALT KMOD_CTRL KMOD_SHIFT KMOD_ALT

Descripcin
Left Shift est abajo Right Alt est abajo Left Alt est abajo Una tecla de Control est abajo Una tecla Shift est abajo Una tecla Alt key esta abajo

Tabla 6. Macros para modificadores en el teclado

El campo unicode slo tiene un valor til si previamente se ha ejecutado la funcin SDL_EnableUNICODE(), la cual habilita la transicin entre el caracter ASCII de la tecla y su representacin en UNICODE. 10

Ejemplo: manejo de eventos por teclado A continuacin se muestra un programa completo "teclado1.c" que permite obtener los nombres simblicos de las teclas del teclado, sobre una ventana grfica de 640x480x16. Se muestran tanto el evento SDL_KEYDOWN como el evento SDL_KEYUP. Siga el siguiente procedimiento para probar este programa, 1. Usando el editor geany, edite el siguiente cdigo,
#include #include #include #define #define "stdio.h" "stdlib.h" "SDL/SDL.h" ANCHO 640 ALTO 480

void iniciar(SDL_Surface **screen,char *titulo,int ancho,int alto,int p,int m); int main(void){ SDL_Surface *screen=NULL; SDL_Event event; iniciar(&screen,"Eventos-Teclado en SDL",ANCHO,ALTO,16,SDL_SWSURFACE); while(1){ SDL_WaitEvent(&event); switch(event.type){ case SDL_KEYDOWN: printf("Se puls la tecla %s!\n", SDL_GetKeyName(event.key.keysym.sym)); break; case SDL_KEYUP: printf("Se solt la tecla: %s!\n", SDL_GetKeyName(event.key.keysym.sym)); if(event.key.keysym.sym==SDLK_q){ printf("Terminando el programa..."); exit(0); } break; case SDL_QUIT: printf("El usuario cerr la aplicacin...\n"); exit(0); } } return 0; } void iniciar(SDL_Surface **screen,char *titulo,int ancho,int alto,int p,int m){ if(SDL_Init(SDL_INIT_VIDEO)<0){ fprintf(stderr,"No se puede iniciar SDL: %s\n",SDL_GetError()); exit(1); } atexit(SDL_Quit); *screen = SDL_SetVideoMode(ancho,alto,p,m); if(*screen==NULL){ fprintf(stderr,"No se puede establecer el modo de video a %dx%dx%d: %s\n", ancho,alto,p,SDL_GetError()); exit(1); } SDL_WM_SetCaption(titulo,""); }

11

2. Luego de editar el programa anterior, antes de compilarlo, usted debe seleccionar en la barra de mens la opcin, "Construir/Selecciona Inclusiones y Argumentos" Lo que har que se presente una pantalla como la siguiente, en la que usted deber agregar la librera SDL, usando "-lSDL" (que se lee "menos ele SDL"), tal como se muestra en la figura,

Luego para compilar y ejecutar su programa usted dispone de dos botones en la parte media superior del programa geany,

Ejecutar (F5) Compilar (F9)

12

Como puede observar, el programa ofrece dos mecanismos de salida: al soltar la tecla q (luego de haberla presionado), y al dar clic izquierdo sobre el botn de cierre de la ventana (esquina superior derecha de la ventana). Ahora resulta ms evidente el poder superior de SDL sobre SRGP, ya que SDL nos proporciona acceso total a las teclas del teclado, pudiendo detectar tanto el evento "tecla hacia abajo" como el evento "tecla hacia arriba" (cuando se suelta), dos cosas que estaban ausentes en nuestra vieja amiga SRGP. Ntese adems el uso de tildes y caracteres especiales al imprimir que son interpretados y usados sin problemas. CONTROL DEL RATON En el caso del ratn existen tres tipos de eventos: SDL_MOUSEBUTTONDOWN, SDL_MOUSEBUTTONUP y SDL_MOUSEMOTION. Los tres eventos slo pueden ocurrir cuando el puntero del ratn se encuentra sobre la parte interna de la ventana grfica. El evento SDL_MOUSEBUTTONDOWN se da siempre que, en el ratn, se presiona un botn. El evento SDL_MOUSEBUTTONUP ocurre cuando un botn del ratn, que se encuentra presionado, se suelta. El evento SDL_MOUSEMOTION ocurre cada vez que el puntero del ratn se mueve. Dado que cuando se presiona o suelta un botn del ratn casi siempre el puntero del ratn se mueve, es conveniente que el evento SDL_MOUSEMOTION se verifique luego de los otros dos eventos del ratn. Cuando se produce un evento SDL_MOUSEBUTTONDOWN o SDL_MOUSEBUTTONUP, el evento queda almacenado en el campo button de la union SDL_Event. Cuando el evento es de tipo SDL_MOUSEMOTION este queda almacenado en el campo motion de esa misma union. El campo button es de tipo SDL_MouseButtonEvent, que es una estructura de datos definida de la siguiente manera, typedef struct{ Uint8 type; // Contiene SDL_MOUSEBUTTONDOWN o SDL_MOUSEBUTTONUP Uint8 button; // Un ndice que identifica al botn Uint8 state; // Contiene SDL_PRESSED or SDL_RELEASED Uint16 x, y; // Contienen las coordenadas del puntero del ratn } SDL_MouseButtonEvent; El ndice que identifica al botn es un entero entre 1 y 255. Para los primeros tres botones se disponen de las macros SDL_BUTTON_LEFT (ndice igual a 1) , SDL_BUTTON_MIDDLE (ndice igual a 2), SDL_BUTTON_RIGHT (con ndice igual a 3, pero si no existe botn central se le asigna 2). Para un botn con ruedita de ventana deslizante (scroll), el giro en una direccin tomar el valor de 4, mientras que el giro en la direccin contraria tomar el valor de 5, etc. Esta es otra gran diferencia con nuestra inseparable SRGP que slo era capaz de controlar tres botones. El campo motion es de tipo SDL_MouseMotionEvent, que es una estructura de datos definida de la siguiente manera, 13

typedef struct{ Uint8 type; Uint8 state; Uint16 x, y; Sint16 xrel, yrel; } SDL_MouseMotionEvent;

// // // //

Contiene Contiene Contiene Contiene

el el la la

valor SDL_MOUSEMOTION estado actual de los botones coordenada actual del puntero del ratn coordenada previa del puntero del ratn

Tener control total sobre el ratn es especialmente til cuando se trabaja en una ventana grfica ya que es posible seleccionar, segn su posicin, a los diversos objetos que se colocan en ella. Por desgracia, SDL es una librera grfica con escasa capacidad para colocar objetos en la ventana, ya que no cuenta con primitivas para el trazo de figuras geomtricas (tales como puntos, lneas, crculos, polgonos, etc.), para el despliegue de texto o el manejo de imgenes en otro formato que no sea BMP (Bit Map Pixel). En su lugar, proporciona unas cuantas primitivas bsicas para el manejo directo de la memoria empleada en las superficies de las ventanas grficas, y con ayuda de algo de conocimiento sobre hardware y de geometra computacional el programador puede construir l mismo sus propias primitivas. Escapa a los objetivos del curso de Estructura de Datos y Anlisis de Algoritmos explorar esta rea de las ciencias de la computacin, ms propia de cursos como grficos por computadora, geometra computacional, o de cursos avanzados sobre arquitectura o hardware de computadoras. En su lugar, ac trabajaremos con complementos de SDL. COMPLEMENTOS DE SDL Un complemento de SDL es una librera que trabaja junto a SDL, proporcionndole funcionalidades adicionales en forma de primitivas. Esto significa que los programas que usen a SDL y sus complementos debern enlazar dos o ms libreras, dependiendo de los complementos utilizados. En este curso usaremos la siguiente lista de complementos que el lector deber buscar e instalar desde los repositorios de OpenSUSE en caso de que desee usarlos en la mquina de su casa u oficina. LIBRERIA ARCHIVO A INSTALAR gfx "libSDL_gfx_devel" image ttf net sound mixer "libSDL_image-devel" "libSDL_ttf-devel" "libSDL_net-devel" "libSDL_sound-devel" "libSDL_mixer-devel" UTILIDAD Proporcionar primitivas bsicas de trazo para superficies, tales como lneas, crculos y polgonos Carga de imgenes en superficies en formatos BMP, PPM, PCX, GIF, JPEG, PNG y TIFF Permite el uso de fuente TrueType dentro de las superficies Librera para aplicaciones en red de diferentes plataformas Manejo de sonido en formato wav, ogg mp3 y midi Mezclador de sonido multicanal que soporta cuatro canales de audio estreo de 16 bits, ms un canal simple de msica

Yo recomiendo bajarlos todos desde el mismo lugar. Todas las computadoras de los Talleres de Electrnica e Informtica ya tienen instalados todos estos complementos desde el enlace, "games/OpenSUSE_11.2" En todas las funciones de la librera gfx se incluye el color de trazo como argumento, pero se presentan dos modalidades para especificar dicho color: 14

Se escribe un nmero hexadecimal de la forma 0xRRGGBBAA, para indicar la intensidad de color Rojo (Red), Verde (Green) y Azul (Blue) con valores entre 00 y FF, esto es, 256 intensidades de color; as como el Ajuste Alpha (valores entre 00 y FF), que dar brillantes al color indicado. Se escriben cuatro nmeros enteros de 8 bits para indicar cada componente de color (Rojo, Verde, Azul y el Ajuste).

A continuacin se presentan los prototipos de las funciones incluidas en gfx, de uso ms comn, que se encuentran incluidas dentro del archivo de cabecera "SDL_gfxPrimitives.h". Se recomienda que el lector practique elaborando programas que hagan uso de estas funciones.
// Dibujar un punto int pixelColor(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color); int pixelRGBA(SDL_Surface *dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar lnea horizontal int hlineColor(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color); int hlineRGBA(SDL_Surface *dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a); //Dibujar lnea vertical int vlineColor(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color); int vlineRGBA(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); //Dibujar una lnea cualquiera int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un tringulo int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color); int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint8 r, Uint8 g, Uint8 b, Uint8 a); int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color); int aatrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un tringulo relleno int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color); int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar rectngulo int rectangleColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); int rectangleRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a);

15

// Dibujar rectngulo relleno int boxColor(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color); int boxRGBA(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un circulo int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color); int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color); int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un circulo relleno int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color); int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un arco int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Sint16 start, Sint16 end, Uint32 color); int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un arco cerrado int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r,Sint16 start, Sint16 end, Uint32 color); int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un arco cerrado relleno int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color); int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar una ellipse int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color); int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); int aaellipseColor(SDL_Surface * dst, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color); int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar una ellipse rellena int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color); int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un polgono int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a);

16

int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); // Dibujar un polgono relleno int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color); int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a); int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface * texture,int texture_dx,int texture_dy); // Dibuja un caracter o cadena int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color); int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a); int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, const char *c, Uint32 color); int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, const char *c, Uint8 r, Uint8 g, Uint8 b, Uint8 a);

Ntese que en las ventanas grficas, el origen est en la esquina superior izquierda, es decir, dicha esquina tiene como coordenada la posicin (0,0). Siempre que coloque algn objeto sobre una superficie debe recordar ejecutar la funcin SDL_UpdateRect(), cuyo prototipo se muestra a continuacin, void SDL_UpdateRect(SDL_Surface *screen, Sint32 xIni, Sint32 yIni, Sint32 width, Sint32 Height); Slo los objetos viejos que ya se visualizaban en la ventana grfica, y aquellos objetos nuevos (o una seccin de ellos) que se encuentren dentro de la seccin de la superficie que sea abarcada por esta llamada sern visibles. Este efecto asncrono entre lo que escribes y lo que ves es deseable para lograr la mayor eficiencia posible, que como lo hemos dicho antes, es un objetivo en esta asignatura. Por supuesto, el lector rpidamente puede encontrar la analoga con SRGP: la funcin SRGP_refresh(), pero hay una diferencia fundamental, SDL s trabaja con memoria, por lo que no se requiere el refresco constante para evitar el oscurecimiento de la ventana. Ejemplo: manejo de eventos por ratn En este ejemplo elaboramos un programa que coloca lneas en pantalla. La lnea comienza donde el usuario presione el botn izquierdo del ratn y finaliza cuando el usuario suelta dicho botn, en cuyo caso la lnea se dibuja en pantalla, en color rojo. Cuando se presiona el botn izquierdo se coloca un punto rojo para indicar donde inicia la lnea. Para terminar el programa se ofrecen dos opciones: el cierre de la ventana grfica o la presin del botn derecho del ratn.
#include #include #include #include #define #define #define "stdio.h" "sdtdlib.h" "SDL/SDL.h" "SDL/SDL_gfxPrimitives.h" ANCHO 640 ALTO 480 ROJO 0xFF0000FF

17

void iniciar(SDL_Surface **screen,char *titulo,int ancho,int alto,int p,int m); void procesarRaton(SDL_Surface *screen,SDL_Event *e); int main(void){ SDL_Surface *screen=NULL; SDL_Event event; iniciar(&screen,"Eventos-Raton en SDL",ANCHO,ALTO,16,SDL_SWSURFACE); while(1){ SDL_WaitEvent(&event); switch(event.type){ case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: procesarRaton(screen,&event); break; case SDL_QUIT: printf("El usuario cerr la aplicacin...\n"); exit(0); } } return 0; } void iniciar(SDL_Surface **screen,char *titulo,int ancho,int alto,int p,int m){ if(SDL_Init(SDL_INIT_VIDEO)<0){ fprintf(stderr,"No se puede iniciar SDL: %s\n",SDL_GetError()); exit(1); } atexit(SDL_Quit); *screen = SDL_SetVideoMode(ancho,alto,p,m); if(*screen==NULL){ fprintf(stderr,"No se puede establecer el modo de video a %dx%dx%d: %s\n", ancho,alto,p,SDL_GetError()); exit(1); } SDL_WM_SetCaption(titulo,""); } void procesarRaton(SDL_Surface *screen, SDL_Event *e){ static Uint16 xant,yant; Uint16 x=e->button.x, y=e->button.y; switch(e->type){ case SDL_MOUSEBUTTONDOWN: if(e->button.button==SDL_BUTTON_LEFT){ xant=x; yant=y; pixelColor(screen,x,y,ROJO); SDL_UpdateRect(screen,x,y,1,1); // Refresca un punto } if(e->button.button==SDL_BUTTON_RIGHT){ printf("Saliendo del programa...\n"); exit(0); } break; case SDL_MOUSEBUTTONUP: lineColor(screen,xant,yant,x,y,ROJO); //Refrescar toda la pantalla SDL_UpdateRect(screen,0,0,ANCHO,ALTO); // Refresca todo break; } }

18

EJERCICIO 1 Modifique el programa anterior para que incluya los siguientes eventos SDL_KEYDOWN con el teclado: TECLA SDLK_r SDLK_g SDLK_b SDLK_w SDLK_F1 SDLK_F3 SDLK_F6 SDLK_F9 SDLK_ESCAPE EVENTO Establece el color como ROJO Establece el color como VERDE Establece el color como AZUL Establece el color como BLANCO Muestra en la consola el color y figura activa. El punto inicial se une con el final mediante una lnea El punto inicial y el final definen las esquinas de un rectngulo hueco El punto inicial y final definen las esquinas de un rectngulo relleno Hace que el programa termine

Ejemplo: colocar texto en una posicin indicada por el puntero del ratn. El siguiente programa muestra una forma muy simple de colocar texto en pantalla en diferentes colores. El color se elige secuencialmente entre 16 valores posibles, identificados por valores enteros entre 0 y 15, comenzando con 0. Cada vez que se hace clic derecho se toma el siguiente color. Al llegar a 16 se reinicia el color a cero. El texto se coloca en una posicin indicada por el botn izquierdo del ratn. Se puede consultar el color actual usando F1, o terminar la aplicacin pulsando la tecla ESC.
#include #include #include #include #define #define #define "stdio.h" "stdlib.h" "SDL/SDL.h" "SDL/SDL_gfxPrimitives.h" ANCHO 640 ALTO 480 NC 16

int COLOR[NC]={0x000000FF,0x0000A0FF,0x00A000FF,0x00A0A0FF, 0xA00000FF,0xA000A0FF,0xA0A000FF,0xA0A0A0FF, 0xFFFFFF80,0x0000FFFF,0x00FF00FF,0x00FFFFFF, 0xFF0000FF,0xFF00FFFF,0xFFFF00FF,0xFFFFFFFF}; int c,color; void iniciar(SDL_Surface **screen,char *titulo,int ancho,int alto,int p,int m); void procesarRaton(SDL_Surface *screen,SDL_Event *e); void procesarTeclado(SDL_Event *e); int main(void){ SDL_Surface *screen=NULL; SDL_Event event; iniciar(&screen,"Eventos-Raton en SDL",ANCHO,ALTO,16,SDL_SWSURFACE); while(1){ SDL_WaitEvent(&event); switch(event.type){ case SDL_KEYDOWN: procesarTeclado(&event); break; case SDL_MOUSEBUTTONDOWN: procesarRaton(screen,&event); break; case SDL_QUIT: printf("El usuario cerr la aplicacin...\n"); exit(0); }

19

} return 0; } void iniciar(SDL_Surface **screen,char *titulo,int ancho,int alto,int p,int m){ if(SDL_Init(SDL_INIT_VIDEO)<0){ fprintf(stderr,"No se puede iniciar SDL: %s\n",SDL_GetError()); exit(1); } atexit(SDL_Quit); *screen = SDL_SetVideoMode(ancho,alto,p,m); if(*screen==NULL){ fprintf(stderr,"No se puede establecer el modo de video a %dx%dx%d: %s\n", ancho,alto,p,SDL_GetError()); exit(1); } SDL_WM_SetCaption(titulo,""); c=0; color=COLOR[c]; } void procesarRaton(SDL_Surface *screen, SDL_Event *e){ Uint16 x=e->button.x, y=e->button.y; if(e->button.button==SDL_BUTTON_LEFT){ // Se dibuja una cadena en el lugar donde se hizo clic izquierdo stringColor(screen,x,y,"Hola Mundo",color); SDL_UpdateRect(screen,0,0,ANCHO,ALTO); // Refresca todo return; } if(e->button.button==SDL_BUTTON_RIGHT){ c++; if(c==NC) c=0; color=COLOR[c]; return; } } void procesarTeclado(SDL_Event *e){ if(e->key.keysym.sym==SDLK_F1){ printf("Color actual: 0x%08X\n",color); return; } if(e->key.keysym.sym==SDLK_ESCAPE){ printf("Saliendo del programa...\n"); exit(0); } }

EJERCICIO 2 Construya un programa (tipo Paint) con una ventana grfica igual a la del ejemplo anterior, que contenga una paleta de colores (digamos de dos columnas y ocho filas), en la parte izquierda de la pantalla (con los 16 colores del ejemplo anterior), que consuma un rea de 100x480 pixeles, en la que el usuario pueda seleccionar con el botn izquierdo del ratn el color de trazo deseado, y en el que manteniendo presionado el botn izquierdo del ratn, le permita al usuario trazar una lnea de puntos continua, usando el color actual. Obviamente debe restringir el rea de trazo a toda posicin x mayor que 100. Si lo desea puede agregar un rea de seleccin de forma o tamaos, y todo lo que se ocurra en este momento. 20

También podría gustarte