-- 17/01/2010 javier07b9@hotmail.com -- Versión para WINDOWS 32 BITS -- En este capítulo vamos a introducir la libreria SDL, para lo cual -- obtendremos de www.libsdl.org Runtime Libraries el archivo -- SDL-1.2.14-win32.zip o cualquier version existente, fundamental es -- que obtengamos del zip la libreria de enlace dinámico llamada SDL.dll -- y la incluyamos en la carpeta /system32 del sistema operativo además -- debemos colocar el archivo SDL_Wrap.ew en la carpeta /include de Euphoria. -- ¿ Por qué es necesario la libreria SDL ? -- Pues básicamente Euphoria no posee libreria gráfica, si bien el intérprete EX.EXE -- para DOS32 posee el CauseWay DOS EXTENDER que nos provee de ciertas -- interrupciones de video y memoria, en Windows y Linux esto no es posible. -- Hoy en dia todo programa se apoya en librerias dinámicas para de un modo ahorrar -- código de un programa, asi como un desarrollo de este más rápido, con funciones -- preparadas y optimizadas. ------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------ include SDL_Wrap.ew integer der, escape, space, adr, esi, edi atom key, eax, ebx, ecx, edx, t1 atom virtual, surface, dummy constant st=3.14159265/180 constant hx= 640 constant hy= 480 constant bytes = 1 constant size_video=hy*hx*bytes constant depth = hx*bytes constant midx = hx /2 constant midy = hy/2 ------------------------------------------------------------ puts(1,"Press space for reset \n\n") puts(1,"Press escape for exit ") t1=time() while time()-t1<4 do end while free_console() ------------------------------------------------------------------------ dummy = SDL_Init(SDL_INIT_VIDEO) if dummy = -1 then puts(1, "SDL_Init falló en el intento!\n") end if surface = SDL_SetVideoMode(hx, hy, 8*bytes, SDL_DOUBLEBUF+SDL_SWSURFACE+SDL_HWPALETTE+SDL_NOFRAME) virtual=peek4u(surface+20) constant pal1=allocate(1024) for m=0 to 255 do poke(pal1+(m*4),m) poke(pal1+(m*4)+1,m) poke(pal1+(m*4)+2,m) poke(pal1+(m*4)+3,m) end for dummy=SDL_SetPalette(surface,SDL_PHYSPAL,pal1,0,256) --------------------------------------------------------------der=0 constant num_v=360*5*10 sequence vec vec={} vec=repeat(vec,num_v) procedure set_vect() integer rd atom grd grd=0 rd=1 for m=0 to num_v-5 by 5 do grd+=1/10 if grd=360 then grd=0 end if rd=rand(63) ebx=sin(grd*st*rd*6 )*rd+midy eax=cos(grd*st*rd*6 )*rd+midx vec[1+m]=eax vec[2+m]=ebx vec[3+m]=sin( grd*st ) vec[4+m]=cos( grd*st ) vec[5+m]={rd*4} end for end procedure ------------------------------------------------------------- set_vect() -- BUCLE PRINCIPAL der=0 while der=0 do SDL_PumpEvents() key=SDL_GetKeyState(NULL) escape=peek(key+SDLK_ESCAPE) if escape>0 then der=1 end if space=peek(key+SDLK_SPACE) if space>0 then set_vect() end if for m=0 to num_v-5 by 5 do eax=vec[1+m] ebx=vec[2+m] ecx=vec[3+m] edx=vec[4+m] eax+=ecx if eax>hx-2 or eax<2 then ecx*=-1 end if ebx+=edx if ebx>hy-2 or ebx<2 then edx*=-1 end if edi=floor(ebx) if edi>-2 or edi-2 or esi {0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,...} el primer byte corresponde al -- valor rojo el segundo al verde, el tercero al azul y el cuarto al número de color, asi obtenemos la -- tipica paleta escala de grises. -- dummy=SDL_SetPalette(surface,SDL_PHYSPAL,pal,0,256) -- Ahora ya podemos llamar a SDL_SetPalette() dándole como primer dato (surface) la dirección de memoria -- donde se aloja los datos de la pantalla, el segundo valor pertenece a la definición del tipo de paleta, -- como lo queremos es modificar la paleta de la pantalla , entonces es la paleta fisica ( SDL_PHYSPAL ) -- en contra si fuera una imagen cargada que posee paleta propia entonces seria SDL_LOGPAL ( paleta logica ). -- Recordemos que para que esto sea posible tuvimos que introducir en SDL_SetVideoMode() la constante -- SDL_HWPALETTE, asi le decimos a SDL que queremos trabajar con la paleta del hardware de video. -- Ahora vamos a crear unos vectores. -- ¿Qué es un vector? -- Bueno sin entrar demasiado en matemáticas diremos que nuestro vector consta de : -- origen, que en este caso serán dos atom correspondientes a la posición X e Y en la pantalla. -- dirección, son dos atom que si los sumamos al origen podemos modificar este, para que el movimiento del -- pixel sea suave los dos atom directivos seran siempre valores entre 0 y 1. -- Además nuestro vector poseerá color que se almacenará como un valor entero entre 0 y 255. -- Resumiendo nuestro vector poseerá 5 datos que desglosados son : -- 1 atom correspondiente a la posición de X -- 1 atom correspondiente a la posición de Y -- 1 atom correspondiente a la variación de X -- 1 atom correspondiente a la variación de Y -- 1 integer correspondiente al número de color. -- constant num_v=3600*5 -- creamos entonces el número de datos total. -- En este caso creamos 3600 vectores y los multiplicamos por 5 datos que posee cada vector. -- sequence vec -- Designamos el nombre de la secuencia donde se alojarán los datos. -- vec={} -- Establecemos vec como secuencia. Ahora vec es secuencia nula. Pero ya forma 1 dato. -- vec=repeat(vec,num_v) -- Repetimos la secuencia vec el número de veces deseado. Con esto tenemos la estructura necesaria -- para ir alojando los datos de los vectores. -- procedure set_vect() -- Creamos un proceso que posteriormente llamaremos como set_vect(), es en definitiva una subrutina. -- integer rd -- En el proceso usaremos un integer para determinar el radio ( rd ) polar del vector. -- ¿Por qué definimos ahora estas variables aqui y no al principio ? -- Porque estas variables se usan en el proceso y no fuera de él. También se las podría haber definido -- al principio pero sería crear un cúmulo total de variables innecesarias. -- atom grd -- grd=0 -- Así creamos también un atom para establecer el ángulo polar en grados ( grd ) que tomará como -- dirección ese vector. -- for m=0 to num_v-5 by 5 do -- rd=rand(63) -- ebx=sin(grd*st*rd*6 )*rd+midy -- eax=cos(grd*st*rd*6 )*rd+midx -- vec[1+m]=eax -- vec[2+m]=ebx -- vec[3+m]=sin( grd*st ) -- vec[4+m]=cos( grd*st ) -- vec[5+m]={rd*4} -- grd+=1/10 if grd=360 then grd=0 end if -- end for -- Este bucle recorre ls estructura vec depositando consecutivamente en avances de 5 en 5 datos por -- iteración los valores correspondientes al vector. ------------------------------------------------------------------------------------------------------------ -- Los datos de posición del vector ( eax, ebx ) se construyen con la transformación de coordenadas -- polares a cartesianas. -- Para los que esten solo acostumbrados a las coordenadas cartesianas, en donde un punto bidimensional -- esta representado por una coordenada horizontal ( X ) y otra vertical ( Y ), diremos que las -- coordenadas polares basan su posicionamiento en una coordenada angular que suele adoptar valores -- de 0 a 360 grados y otra coordenada radial cuyo valor positivo designa el radio. -- Para transformar entonces coordenadas polares a cartesianas diremos sencillamente sin demostrar que -- la coordenada horizontal ( X ) es igual al seno del angulo de la coordenada polar multiplicado por el -- radio y la coordenada vertical hace lo mismo con el coseno. -- Resumiendo si tenemos las coordenadas polares {59.9º,100} entonces: -- x = sin( 59.9 ) * 100 = 86.515 -- y = cos( 59.9 ) * 100 = 50.151 -- La función Euphoria sin() y cos() trabajan con radianes y no con grados por ello utilizo la constante st -- Las coordenadas polares sirven en este programa para crear posiciones equidistantes del centro (midx, midy) -------------------------------------------------------------------------------------------------------------- -- Continuando dentro del proceso, -- rd obtiene con la función rad() un valor entero aleatorio comprendido entre 1 y 63. Será el radio del vector -- en esa iteración. -- ebx obtiene la coordenada cartesiana Y a la que se suma el centro vertical de pantalla. -- eax obtiene la coordenada cartesiana X a la que se suma el centro horizontal de pantalla. -- luego introducimos eax y ebx en las posiciones X e Y del vector -- para las variaciones de X e Y usamos también el sin() y cos() para que los vectores salgan radialmente. -- grd se incrementa de tal manera que para 3600 vectores habrá 3600 angulos en donde el primer vector poseerá -- el valor 0º y el último 360º. -- finalizamos el proceso con end procedure -- Una vez tenemos todo listo, solo nos queda centrarnos en el bucle principal -- Para ello seteamos los valores de los vectores con, -- set_vect() -- der=0 -- while der=0 do -- Pues eso, mientras der = 0 el bucle continuará -- SDL_PumpEvents() -- necesario para cualquier evento ( mouse, teclado, joystick, etc...) -- key=SDL_GetKeyState(NULL) -- key obtiene la dirección de memoria donde se hallan los valores de las teclas. -- escape=peek(key+SDLK_ESCAPE) if escape>0 then der=1 end if -- recoge el valor de la tecla escape y si es mayor que cero termina el programa -- space=peek(key+SDLK_SPACE) if space>0 then set_vect() end if -- recoge el valor de la tecla space y si fue pulsada resetea la posición de los vectores. -- for m=0 to num_v-5 by 5 do -- Abrimos un bucle para los vectores ya que vamos a leer todos sus valores -- eax=vec[1+m] -- ebx=vec[2+m] -- ecx=vec[3+m] -- edx=vec[4+m] -- Recogemos los valores posición y dirección del vector en esa iteración -- eax+=ecx if eax>hx-2 or eax<2 then ecx*=-1 end if -- ebx+=edx if ebx>hy-2 or ebx<2 then edx*=-1 end if -- Sumamos los valores de dirección a los de posición y comprobamos que no exceden de los -- limites deseados ( que practicamente coinciden con la pantalla ) y si exceden pues multiplicamos -- por -1, es decir invertimos la dirección. -- edi=floor(ebx) -- Redondeamos Y para trabajar con direcciones de pantalla. -- if edi>-1 or edi-1 or esi