Artículo
|
Librerias Euphoria |
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 all_lib.ew
integer der, escape, space, adr, esi, edi, flags
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
flags= SDL_DOUBLEBUF+SDL_SWSURFACE+SDL_HWPALETTE+SDL_NOFRAME
surface = SDL_SetVideoMode(hx, hy, 8*bytes, flags)
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=3600*5
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+=0.1 if grd=360 then grd=0 end if
rd=rand(63)
ebx=sin(grd*st*rd )*rd+midy
eax=cos(grd*st*rd )*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<hy-2 then
esi=floor(eax)
if esi>-2 or esi<hx-2 then
adr=(edi*depth)+(esi*bytes)
poke(virtual+adr,vec[5+m])
end if
end if
vec[1+m]=eax
vec[2+m]=ebx
vec[3+m]=ecx
vec[4+m]=edx
end for
dummy=SDL_Flip(surface)
mem_set(virtual,0,size_video)
end while
SDL_Quit()
include SDL_Wrap.ew
Empezamos por incluir el archivo SDL_Wrap.ew en nuestro programa Con este archivo abrimos la libreria SDL.dll y la cargamos en memoria además creamos todos los enlaces para llamar a las funciones.
integer der, escape, space, adr, esi, edi, flags definimos seis variables enteras que más tarde usaremos, es conveniente definir las variables todas al principio para una mejor optimización de la memoria.
La variable der nos servirá de testigo para el bucle principal asi contendrá en principio el valor 0 y solo cuando la tecla escape sea pulsada se activará a 1 rompiendo el bucle y terminando el programa. Las variables escape y space obtienen el valor depositado en la dirección de memoria de la variable key más el desfase de esa tecla, ejemplo:
escape=peek(key+SDLK_ESCAPE)
lee el valor de la dirección de memoria que hay en key y le añade a esta dirección un "offset " o desplazamiento designado por la constante SDLK_ESCAPE.
adr almacenará un calculo entero correspondiente a la dirección del pixel en la pantalla. esi nos servirá para determinar si el pixel está dentro del rango {0,hx},
es decir si el pixel está dentro del eje X y no fuera de la pantalla. edi hace lo mismo con el eje Y.
¿ Por qué definimos estas variables como integer y no como atom ?
Pués depende del valor que recibirán, en estos casos los valores que deben almacenar son enteros entre {-1073741824, 1073741823} por lo tanto integer es el tipo de variable más optimizado.
atom key, eax, ebx, ecx, edx, t1
Definimos varios atom a la vez:
key almacenará la dirección de memoria donde estarán todos los valores de las teclas.
eax, almacenará en formato decimal el valor posición en el eje X del pixel.
ebx, almacenará en formato decimal el valor posición en el eje Y del pixel.
ecx, almacenará en formato decimal el valor de incremento en el eje X del pixel.
eax, almcenará en formato decimal el valor de incremento en el eje Y del pixel.
t1 nos servirá para el valor decimal que la funcion time() devuelve.
atom virtual, surface, dummy
virtual será la dirección de memoria de la pantalla ( en C se llamaria puntero ). -- Todas las direcciones de memoria necesitan definirse como atom ya que este maneja 4 bytes, que es el formato utilizado en todos los sistemas de 32 bits para direccionar memoria.
surface posee la dirección de memoria en donde se halla ciertos valores entre ellos el mismo que poseerá la variable virtual, devueltos todos ellos por la función SetVideoMode().
dummy será usada tanto para valores enteros como direcciones. Se usa para necesidad de ciertas funciones que devuelven valores ( SDL_Init(), SDL_Flip(), SDL_GetError(), ...)
constant st=3.14159265/180 , constante que nos convierte los grados en
radianes.
constant hx= 640 , valor de la resolución X de la pantalla.
constant hy= 480 , valor de la resolución Y de la pantalla.
constant bytes = 1 , número de bytes del pixel ( 1 byte = 8 bits ,
3 = 24 bits RGB ).
constant size_video=hy*hx*bytes, será el número de bytes que posee la pantalla.
constant depth = hx*bytes, el número de bytes del ancho de pantalla.
constant midx = hx/2 , punto central en el eje X de la pantalla.
constant midy = hy/2 , punto central en el eje Y de la pantalla.
puts(1,"Press space for reset \n\n")
puts(1,"Press escape for exit ")
Informamos sobre las funciones de las teclas posibles a usar.
t1=time() while time()-t1<4 do end while free_console()
time() devuelve sobre un atom el valor decimal del tiempo transcurrido
en el reloj interno.
Con este bucle conseguimos un retardo de 4 segundos para que el usuario tenga tiempo suficiente para leer la información previamente escrita.
Con free_console() eliminamos la consola de texto creada por puts(1,"").
dummy = SDL_Init(SDL_INIT_VIDEO) if dummy = -1 then puts(1, "SDL_Init
falló en el intento!\n") end if
Inicia el subsistema SDL de video y nos avisa si fallara al llamar.
flags = SDL_DOUBLEBUF+SDL_SWSURFACE+SDL_HWPALETTE+SDL_NOFRAME
surface = SDL_SetVideoMode(hx, hy, 8*bytes, flags)
SDL_SetVideoMode() devuelve una dirección de memoria donde se hallan
números interesantes. para ello previamente hay que darle cuatro datos :
hx es la resolución horizontal de la ventana o pantalla en pixels.
hy es la resolución vertical. el tercer dato es el número de bits que contendrá un pixel ( 8,16,24 o 32 ) dependiendo de la cantidad de colores deseados ( 256, 65536, 16 millones, 16 millones + Alpha ) respectivamente. flags es una suma de constantes establecidas en all_lib.ew .
virtual=peek4u(surface+20)
Una vez obtenemos esa dirección de memoria cogemos un número de 32 bits posicionado en el veinteavo byte de esta. Ese número de 32 bits es la dirección de memoria de pantalla. Tambi´´en llamada LFB ( Linear Frame Buffer ). Ahora solo hay que pokearla para obtener los pixels.
constant pal=allocate(1024)
Con esto estamos creando una variable de 32 bits, la cual posee la dirección de memoria donde se alojan 1024 bytes, ahi pokearemos ( meteremos valores en memoria con la instrucción poke ) los valores RGB y número de color de los 256 colores que la resolución previa nos permite.
for m=0 to 255 do
poke(pal+(m*4)+0,m)
poke(pal+(m*4)+1,m)
poke(pal+(m*4)+2,m)
poke(pal+(m*4)+3,m)
end for
Creamos un bucle para rellenar los 1024 bytes de valores crecientes desde 0 a 255. En la memoria se alojan de esta manera :
{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 poriteració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<hy-2 then
esi=floor(eax)
if esi>-1 or esi<hx-2 then
adr=(edi*depth)+(esi*bytes)
poke(virtual+adr,vec[5+m])
end if
end if
Si Y esta dentro de la pantalla entonces redondea X y si X esta dentro de la pantalla entonces calcula la dirección de pantalla del pixel en la forma (y*ancho_pantalla_en_bytes)+(x_bytes_por_pixel) , lo pokea en pantalla con el color del vector vec[5+m] y termina los ifs propuestos .
end for
terminamos la iteración y volvemos a la siguiente si todavia quedan vectores.
dummy=SDL_Flip(surface)
SDL_Flip() vuelca la memoria de video a la pantalla .
mem_set(virtual,0,size_video)
y borramos la pantalla para una nueva imagen .
end while
finaliza si der=1 sino vuelta a empezar.
SDL_Quit()
Finaliza el sistema SDL y termina el programa
Autor: Vicente Expósito
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 all_lib.ew
integer der, escape, space, adr, esi, edi, flags
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
flags= SDL_DOUBLEBUF+SDL_SWSURFACE+SDL_HWPALETTE+SDL_NOFRAME
surface = SDL_SetVideoMode(hx, hy, 8*bytes, flags)
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=3600*5
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+=0.1 if grd=360 then grd=0 end if
rd=rand(63)
ebx=sin(grd*st*rd )*rd+midy
eax=cos(grd*st*rd )*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<hy-2 then
esi=floor(eax)
if esi>-2 or esi<hx-2 then
adr=(edi*depth)+(esi*bytes)
poke(virtual+adr,vec[5+m])
end if
end if
vec[1+m]=eax
vec[2+m]=ebx
vec[3+m]=ecx
vec[4+m]=edx
end for
dummy=SDL_Flip(surface)
mem_set(virtual,0,size_video)
end while
SDL_Quit()
include SDL_Wrap.ew
Empezamos por incluir el archivo SDL_Wrap.ew en nuestro programa Con este archivo abrimos la libreria SDL.dll y la cargamos en memoria además creamos todos los enlaces para llamar a las funciones.
integer der, escape, space, adr, esi, edi, flags definimos seis variables enteras que más tarde usaremos, es conveniente definir las variables todas al principio para una mejor optimización de la memoria.
La variable der nos servirá de testigo para el bucle principal asi contendrá en principio el valor 0 y solo cuando la tecla escape sea pulsada se activará a 1 rompiendo el bucle y terminando el programa. Las variables escape y space obtienen el valor depositado en la dirección de memoria de la variable key más el desfase de esa tecla, ejemplo:
escape=peek(key+SDLK_ESCAPE)
lee el valor de la dirección de memoria que hay en key y le añade a esta dirección un "offset " o desplazamiento designado por la constante SDLK_ESCAPE.
adr almacenará un calculo entero correspondiente a la dirección del pixel en la pantalla. esi nos servirá para determinar si el pixel está dentro del rango {0,hx},
es decir si el pixel está dentro del eje X y no fuera de la pantalla. edi hace lo mismo con el eje Y.
¿ Por qué definimos estas variables como integer y no como atom ?
Pués depende del valor que recibirán, en estos casos los valores que deben almacenar son enteros entre {-1073741824, 1073741823} por lo tanto integer es el tipo de variable más optimizado.
atom key, eax, ebx, ecx, edx, t1
Definimos varios atom a la vez:
key almacenará la dirección de memoria donde estarán todos los valores de las teclas.
eax, almacenará en formato decimal el valor posición en el eje X del pixel.
ebx, almacenará en formato decimal el valor posición en el eje Y del pixel.
ecx, almacenará en formato decimal el valor de incremento en el eje X del pixel.
eax, almcenará en formato decimal el valor de incremento en el eje Y del pixel.
t1 nos servirá para el valor decimal que la funcion time() devuelve.
atom virtual, surface, dummy
virtual será la dirección de memoria de la pantalla ( en C se llamaria puntero ). -- Todas las direcciones de memoria necesitan definirse como atom ya que este maneja 4 bytes, que es el formato utilizado en todos los sistemas de 32 bits para direccionar memoria.
surface posee la dirección de memoria en donde se halla ciertos valores entre ellos el mismo que poseerá la variable virtual, devueltos todos ellos por la función SetVideoMode().
dummy será usada tanto para valores enteros como direcciones. Se usa para necesidad de ciertas funciones que devuelven valores ( SDL_Init(), SDL_Flip(), SDL_GetError(), ...)
constant st=3.14159265/180 , constante que nos convierte los grados en
radianes.
constant hx= 640 , valor de la resolución X de la pantalla.
constant hy= 480 , valor de la resolución Y de la pantalla.
constant bytes = 1 , número de bytes del pixel ( 1 byte = 8 bits ,
3 = 24 bits RGB ).
constant size_video=hy*hx*bytes, será el número de bytes que posee la pantalla.
constant depth = hx*bytes, el número de bytes del ancho de pantalla.
constant midx = hx/2 , punto central en el eje X de la pantalla.
constant midy = hy/2 , punto central en el eje Y de la pantalla.
puts(1,"Press space for reset \n\n")
puts(1,"Press escape for exit ")
Informamos sobre las funciones de las teclas posibles a usar.
t1=time() while time()-t1<4 do end while free_console()
time() devuelve sobre un atom el valor decimal del tiempo transcurrido
en el reloj interno.
Con este bucle conseguimos un retardo de 4 segundos para que el usuario tenga tiempo suficiente para leer la información previamente escrita.
Con free_console() eliminamos la consola de texto creada por puts(1,"").
dummy = SDL_Init(SDL_INIT_VIDEO) if dummy = -1 then puts(1, "SDL_Init
falló en el intento!\n") end if
Inicia el subsistema SDL de video y nos avisa si fallara al llamar.
flags = SDL_DOUBLEBUF+SDL_SWSURFACE+SDL_HWPALETTE+SDL_NOFRAME
surface = SDL_SetVideoMode(hx, hy, 8*bytes, flags)
SDL_SetVideoMode() devuelve una dirección de memoria donde se hallan
números interesantes. para ello previamente hay que darle cuatro datos :
hx es la resolución horizontal de la ventana o pantalla en pixels.
hy es la resolución vertical. el tercer dato es el número de bits que contendrá un pixel ( 8,16,24 o 32 ) dependiendo de la cantidad de colores deseados ( 256, 65536, 16 millones, 16 millones + Alpha ) respectivamente. flags es una suma de constantes establecidas en all_lib.ew .
virtual=peek4u(surface+20)
Una vez obtenemos esa dirección de memoria cogemos un número de 32 bits posicionado en el veinteavo byte de esta. Ese número de 32 bits es la dirección de memoria de pantalla. Tambi´´en llamada LFB ( Linear Frame Buffer ). Ahora solo hay que pokearla para obtener los pixels.
constant pal=allocate(1024)
Con esto estamos creando una variable de 32 bits, la cual posee la dirección de memoria donde se alojan 1024 bytes, ahi pokearemos ( meteremos valores en memoria con la instrucción poke ) los valores RGB y número de color de los 256 colores que la resolución previa nos permite.
for m=0 to 255 do
poke(pal+(m*4)+0,m)
poke(pal+(m*4)+1,m)
poke(pal+(m*4)+2,m)
poke(pal+(m*4)+3,m)
end for
Creamos un bucle para rellenar los 1024 bytes de valores crecientes desde 0 a 255. En la memoria se alojan de esta manera :
{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 poriteració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<hy-2 then
esi=floor(eax)
if esi>-1 or esi<hx-2 then
adr=(edi*depth)+(esi*bytes)
poke(virtual+adr,vec[5+m])
end if
end if
Si Y esta dentro de la pantalla entonces redondea X y si X esta dentro de la pantalla entonces calcula la dirección de pantalla del pixel en la forma (y*ancho_pantalla_en_bytes)+(x_bytes_por_pixel) , lo pokea en pantalla con el color del vector vec[5+m] y termina los ifs propuestos .
end for
terminamos la iteración y volvemos a la siguiente si todavia quedan vectores.
dummy=SDL_Flip(surface)
SDL_Flip() vuelca la memoria de video a la pantalla .
mem_set(virtual,0,size_video)
y borramos la pantalla para una nueva imagen .
end while
finaliza si der=1 sino vuelta a empezar.
SDL_Quit()
Finaliza el sistema SDL y termina el programa
Autor: Vicente Expósito
![]() |
Publicado por: angel carrero |
|
|
Comentarios
Últimas noticias
· factura
Últimos artículos














































