Versión HTML por Nacho Cabanes
Por los mensajes que nos llegan, mucha gente tiene el CPV, pero la mayor parte del tiempo está metido en un cajón, la verdad es que lo entendemos y quizás sea culpa nuestra por lanzar el programa en tan mala fecha (Enero-Febrero 95), pero por otro lado ha sido una buena elección. A los 15 días de distribuir la primera lección (45 de empezar con el proyecto) comenzó la fiebre de los videojuegos, todas las revistas están abriendo nuevas secciones sobre juegos, salen revistas enteramente dedicadas a la programación de estas aplicaciones, e incluso se han publicado Enciclopedias enteras que cubren este área (por el escalofriante precio de más de 10000 pesetas), con esto no queremos decir que hayamos provocado nosotros la estampida, todo lo contrario, JASM y BMP somos meros continuadores de una tendencia formativa que ha comenzado en distintos lugares del mundo y que en el momento de crear el CPV no había llegado a España de manera notable. Como se ve vamos a tener una fuerte competencia, pero al precio de cero pesetas con el que han salido las dos primeras lecciones, de momento, no vamos a tener competidores, a menos que haya un loco que regale su producto y encima dé dinero.
Respecto al tironcillo de orejas que os hemos dado antes con lo de encajonar un poco el CPV, no hay problema, estamos seguros de que cuando estéis desagobiados os meteréis de lleno con el curso. Además en nuestras filas también se han producido cambios importantes, BMP está hasta el cuello de trabajo al andar metido en proyectos de desarrollo de aplicaciones tele-informáticas, además de continuar con sus estudios superiores, yo por mi parte acabo de ser becado por una multinacional y durante dos meses me van a 'poner a prueba' metiéndome toda la caña habida y por haber, así que la cantidad de tiempo que dedicábamos al curso se van a ver reducidas drásticamente y por consiguiente el lanzamiento de nuevas lecciones se verá retrasado.....
Pero no abandonamos, NO ME SIENTO LAS PIERNAS, pero no podrán con nosotros, el CPV sigue en pie y que lo paremos un poco no significa que se vaya a eternizar, además con estas dos lecciones ya tenéis carnaza para una buena temporada.
Una manera de paliar los efectos de nuestra nueva situación, sería mediante vuestras colaboraciones, si os sentís capaces, ahora vais a poder hacer constar vuestros nombres junto a JASM-BMP en nuestras lecciones. En la primera lección os dijimos que podíamos abrir nuestro CPV a colaboraciones externas, pues ya es una realidad y necesitamos vuestra colaboración más que nunca, nos gustaría recibir artículos, programas, gráficos, melodías y todo lo que consideréis relacionado con la programación de sistemas, nosotros entendemos el trabajo que cuesta realizar un único artículo, así que hemos pensado una forma de gratificar a nuestros colaboradores. En el apartado de Colaboraciones y Condiciones, os explicamos más detalladamente nuestra idea, remito allí a todo el mundo. :)
Ya acabo la introducción tranquilos. He incluido una sección dedicada a los bugs del CPV-01 y a responder las consultas que nos han llegado, respecto a abrir nuevas secciones, no puedo, no puedo, decidirme ya que ... Hoy 20 días después del lanzamiento del CPV, no me ha llegado ni un solo cuestionario de la primera lección. Sí, sí, esas 10 preguntitas de nada que os hicimos, como veo le tenéis mucha rabia a todo lo que sean cuestionarios y tests. Espero que no sea por lo incomunicados que estamos con la gente que no tiene modem, ni cuenta en Internet, para ellos proporcionaremos nuestras direcciones de correo tortuga (lento pero seguro) para que podáis escribir al que más rabia os de.
Bueno estaréis impacientes por empezar con la lección
pues veamos ... Pre-parados..... Listos..... (PUUUUUM)
Ya........
Algunos pensaréis que no podéis aportar nada, (eso me dijo un profesor de 'C' y aficionado el Autodesk 3D), pero todo el mundo puede. En muchos de los mensajes recibidos vemos que hay mucha gente 'puesta' en el mundo de la programación, otras personas me dicen que son unos virgueros con los gráficos pero que no salen de ahí, pues ya esta, si lo tenéis todo. Mucho de vosotros no estaréis en la misma situación que el profesor de 'C' pero quizás podéis colaborar con programas, con gráficos, melodías.... :) Pues ¿ a qué esperáis para participar? Quizás os falte una motivación, pues aquí está:
Entre todas las personas que nos mande cualquier tipo de colaboración, (gráficos, sonidos, programas, artículos, correcciones) se realizará un sorteo en cada lección y al ganador de éste, se le mandará gratuitamente por correo (en 3 1/2) la lección en la que haya resultado ganador. Entre el resto de participaciones, seleccionaremos los mejores trabajos para que aparezcan en las lecciones del CPV y sus autores serán debidamente mencionados y figuraran con honores en los créditos de la lección.
Para la gente que vaya un poquito más lejos y nos mande programas y/o artículos, seremos más generosos. A toda persona que se le publique un artículo en el CPV, se le mandará por correo la lección donde se incluya su trabajo y si envía y son publicados más de tres artículos recibirá todo el CPV gratuitamente.
En un principio esto último era para nosotros impensable, pero ya hemos recibido un mensaje de cierta persona que podría hacer varios artículos sobre el tema de las 3 dimensiones (área que habréis notado no incluimos en el CPV por nuestra inmadurez en ella) y parece que su propuesta podría llegar a buen puerto. Ni que decir tiene que los autores mantendrán todos sus derechos sobre los programas/artículos y que serán mencionados y figuraran con enormes méritos en los créditos de la lección y del CPV. :)
Espero que con estas ofertas os animéis a participar y nos
echéis
una mano que necesitamos.
** IMPORTANTE ** *** IMPORTANTE ***
*** IMPORTANTE **** ** IMPORTANTE **
Si eres responsable de alguna BBS y te gustaría recibir el CPV, ponte en contacto con nosotros ....
** IMPORTANTE ** *** IMPORTANTE *** *** IMPORTANTE **** ** IMPORTANTE **
Por el momento Sakery Fox BBS 'es nuestra casa' y podéis contactar con nosotros allí, seguimos sin saber si se abrirá un área especial para el curso, luego dejad un mensaje en el área de programación o en 'mi' dirección. Cualquier duda, consulta, petición, sugerencia, ofrecimiento, aviso, ideas, vítores, insultos, alabanzas, teléfonos de tías buenas, besos, abrazos, saludos, cortes de manga, y sobre todo CUESTIONARIOS DE LA PRIMERA LECCION, podéis dejarlos en dicha zona. :)
Sakery Fox BBS 91- 413 98 55
También se puede obtener el CPV en el servidor de FTP del nodo de INTERNET, asterix.fi.upm.es, las lecciones se situarán en el directorio /pub/facultad/alumnos/juegos, para ponerte en contacto con nosotros en esta red, consulta los créditos.
Para los que no tengan ni modem, ni cuenta en Internet o prefieran la comunicación de toda la vida, aquí tenéis nuestras direcciones de correo. Si os habéis decidido a colaborar podéis mandarnos también vuestras creaciones a estas direcciones:
Jesús
Angel
Sánchez Mena Benjamín
Moreno Palacios
c\ Berlín
1
c\ Estocolmo 1
28850
Torrejón
de Ardoz 28850
Torrejón
de Ardoz
Madrid
Madrid
** NECESARIO ** *** NECESARIO *** *** NECESARIO **** ** NECESARIO **
Bueno llega el momento de cubrirse las espaldas, sé que es un poco pesado pero, queremos que sepáis que:
- Manda un mensaje de
espera mientras se cargan las lecciones.
- Permite la
visualización
de artículo de más de 199 líneas.
- Mejora en la
impresión
de artículos.
- Evita parpadeo de las
cabeceras.
- Permite la
visualización
e impresión de los fuentes.
- Presenta los banner
correctamente
como ya os explique antes.
- Permite desactivar/activar
el color para monitores monocromos.
- Evita bloqueos del
teclado.
- Mantiene en el menú
el cursor sobre la última lección consultada.
Podéis consultar la ayuda para ver cómo acceder a las
nuevas funciones. Como he comentado, respeto el formato de los
artículos
en la nueva versión así que podéis machacar
tranquilamente
el VCPV de la primera lección y poner el nuevo. Un problema
de esta versión del VCPV es la visualización de colores
que
a lo mejor se produce con parpadeos, pero ya estoy agotado y he
decidido
dejarlo ahí. En cualquier caso si es muy tedioso el parpadeo
desactivar el color y sin problemas. :)
Otras sugerencias curiosas que he recibido son:
Para cerrar este artículo voy a publicar algunos mensajes que
me han llegado y que considero proponen cuestiones que pueden interesar
a más personas:
De :Sergio Cruz Moral
Para :Jesús Angel Sánchez Mena
Tema :Un problemilla.
------------------------------------------------------------------------------
Hola Jesús, ¿Cómo andamos? ;-)
Mira, tengo un problemilla referente a los gráficos .PIC.
Yo los hago con el ANIMATOR PRO. Como bien dijiste en el artículo correspondiente del curso los ficheros .PIC contienen un gráfico en formato semibruto. Normalmente (el .PIC que mandabas dentro del curso) suelen tener una longitud de 64800 o 64748 bytes. Pues el ANIMATOR PRO los graba en el directorio \PAAT como ficheros .PIC pero de una longitud de 64846 bytes. He intentado leer 78 bytes de cabecera del fichero, luego los 768 que en teoría corresponderían a la paleta de colores y por último los 64000 que forman el dibujo en si.
Pues nada tío, me saca la paleta que le da la gana y cualquier parecido con la realidad es coincidencia (que todavía no se ha dado :-)). ¿Sabes tú como va eso?. Me empiezo a desesperar.
Gracias de antemano y felicitaciones por el curso ;-). A ver si te mando la respuesta a la encuesta que planteasteis.
Saludos
Sergio Cruz Moral
******************************************************************************
Hombre uno que me va a mandar la encuesta, te voy a poner un monumento en la plaza de mi pueblo. ;) Sobre la pregunta que planteas te voy a responder, pero no sólo quiero resolver esta duda, voy a proporcionaros un método para que podáis ver vosotros mismos el formato de diferentes archivos crudos. El método es simple, crearos una imagen toda del mismo color, por ejemplo el 01, después modificar la paleta y situar en el primer y último color unos valores para los componentes de RGB que podáis reconocer, por ejemplo, situad en los tres componentes el valor 02. Una vez hecho esto salvad la imagen en crudo, y con un editor binario, (PCT, NORTON...) mirad el resultado, fácilmente distinguiréis dónde está la cabecera, dónde la paleta y dónde la imagen.
Aplicando esta técnica para los ficheros .Pic de Animator Pro, que me mencionas descubrí su formato que es el siguiente: Esos ficheros están compuestos de una cabecera que ocupa 72 bytes, seguidamente a esta cabecera se sitúan los 768 bytes de la paleta, pero ojo, con una pequeña modificación, todos los valores de esta paleta se encuentran justificados a la izquierda por lo que hay que desplazarlos dos posiciones a la derecha o dividirlos por cuatro, antes de inicializarla. Seguidamente se guardan 6 bytes que son de relleno y después de estos, se sitúan los 64000 bytes de la imagen en crudo.
Os remito a los artículo La paleta y el formato gráfico PCX dónde tratamos asuntos relacionados con la paleta, su creación, utilización....
Veamos, siguiente pregunta.........
Puedo pasar el curso por el area de
programación
de Alcazar BBs, donde
estoy habitualmente, estamos de momento 2 en el area de
programación
y dentro
de poco 3, ahh es un area local.
Espero que no te importe que lo haga, aunque esperare tu respuesta.
******************************************************************************
David, veo que el apartado de condiciones no ha sido de los preferidos por ti, en ese apartado menciono que todas las lecciones distribuidas hasta el momento, pueden y nos gustarían que fuesen distribuidas por el mayor número de sitios posibles. Uno de los factores que determinarán si el CPV llegará a completarse algún día es el hecho de que se distribuyan las primeras lecciones a diestro y siniestro. Así que ya sabéis, 'dígaselo a su vecina'....
Hechos como este mensaje me emocionan, este país es el típico de dispara y después pregunta y David no ha actuado así, es un tío legal de verdad. Os voy a proporcionar el teléfono de ALCAZAR BBs por que si todos son como David seguro que es una BBS de primera, a ver si se apunta más gente al área de programación, espero que el CPV ayude a ello.
!NUEVA BBs¡ Alcazar BBs --> (926) 55 09 03
Que pase el siguiente.............
¿habéis pillado ya el CPV-01.ARJ?
Efectivamente está cojonudo, tal como esperábamos todos pero....
Unas peguillas:
El visualizador que viene con el cpv-01.arj no funciona, sale RUNTIME ERROR 0003 AT 0000:0A000 (tanto en msdos como en os/2).
El juego demostración "dardos" tampoco funciona: te muestra las instrucciones, pero luego se queda la pantalla en negro, y no sale de ahí. El pcx de la diana se ve correctamente (con un visualizador de pcx, claro).
¿Qué ha pasado
Jesus?
¿Os pasa a todos?
Bueno, y lo importante es que el texto escrito está muy bien, y sobre todo la rutinilla para mover texto haciendo un scroll por la pantalla está majísima 8).
******************************************************************************
La mayoría de las cuestiones que planteas ya las he respondido en el apartado de bugs, un hecho interesante que me comunicas es que ejecutas el CPV desde otro sistema operativo que no es MS-DOS, respecto a esa cuestión no se que decirte, en la primera lección no hurgamos demasiado en el interior de nuestra máquina pero a partir de este numero, empezamos a tocar componentes que puede que sean manipulados por otro sistemas operativos de diferente forma que lo hace el MS-DOS, recomiendo a todo el mundo, ejecutar el CPV desde el DOS de toda la vida, para evitar colisiones entre distintos procesos...
Que pase el último.....
De :Javier Manrique Tarrasa
Para :Benjamin Moreno Palacios
Tema :CPV-01
-----------------------------------------------------------------------------
Hola Benjamin. Te envio este MAIL para decirte que estoy encantado con vuestro CPV, y que espero que sigais en la misma linea que hasta ahora, es alucinante. Hace poco que he empezado a meterme en este mundillo de los videojuegos, y gracias a esta serie de articulos me vais a hacer la vida mas facil. Ya conocia otros cursillos de este tipo pero ninguno en espanol, y tan facil de entender. Me recuerda mucho al GDM, que es SHAREWARE (no habeis pensado distribuirlo de esta manera?, nos seria mas comodo a todos). Aparte de notificaros unos problemillas de incompatibilidad que tuve con el raton, me gustaria comentaros otras dudas generales que tengo sobre el CPV:
- En vuestro primer numero, prometisteis ofrecer algunos programas en C ademas de los de PASCAL, sin embargo solo han aparecido programas en PASCAL. Cuando comenzareis a dar algo en C ?
- En el temario que tambien distruisteis con este numero, comentais que a partir de la leccion cuarta, vendra un capitulo titulado 'modo 4x13h'. Es este el tan famoso MODO X?. De que va eso ?.
Nada mas POR AHORA, ya os seguire comentando mis dudas. Pero no quiero despedirme sin felicitaros una vez mas por vuestro trabajo, que espero se vea recompensado como merece, porque si a mi me lleva tiempo leerlo y ejecutar todo, me imagino lo que os estara costando a vosotros hacer el CPV. Hasta pronto.
*****************************************************************************
La verdad es que sí, estamos sudando sangre, pero recibir mensajes cómo el tuyo, nos da fuerza para seguir. 8D Intentaré responder a todas tus dudas:
- Es verdad que en un principio dijimos que iba a haber programas en C, (buena memoria Javier). Pues bien, a partir de la leccion tercera y cuarta, empezaremos a meter cosillas en C. Pero ojo, no os asustéis, las funciones que incluiremos ya os las habremos presentado en PASCAL y funcionarán de la misma manera sólo cambiará el lenguaje con el que serán codificadas, con esto al finalizar el CPV contaréis con una espléndida librería de funciones en dos lenguajes C y PASCAL.
- En cuanto a lo del modo 4x13h, nos referimos a un modo especial de la VGA (un modo 'tweaked') que se consigue a base de programar directamente ciertos registros de la VGA para obtener cuatro páginas de vídeo en vez de una. Las ventajas de tener estas cuatro páginas, es que podemos realizar una animación de sprites, efectuar unos 'scrolling' alucinantes... y mucho más.... El modo X, descubierto por Michael Abrash, tiene esta misma filosofía, sólo que para una resolución de 320x240. Existen multitud de modos tweaked, con otras resoluciones y otro número de páginas (360x200,360x240,376x564 ...), si tenemos tiempo (con esto de los exámenes, el curro de JASM y eso...) investigaremos la programación de estas resoluciones. Pero esto no está programado (por ahora), si alguien está puesto en estos temas, ya sabe a colaboraaaarrr. 8;)
En cuanto a la forma de distribución que nos comentas, la verdad es que nos lo estamos planteando seriamente, ya que, echando cuentas de lo que cuesta traerse un fichero de 300 Kb vía MODEM, os saldría más barato (a parte de aportar un donativo a nuestra causa) encargar las lecciones para que os lleguen cómodamente a vuestra casa por correo, obteniendo además, ventajas extras. Pero esto es todavía hacer conjeturas, para el numero tres de verdad, de verdad, de la buena, os comunicaremos la forma definitiva de distribución.8)
Me gustaría despedir este apartado dando las gracias a todo el mundo que colabora de cierta manera con el CPV poniéndose en contacto con los autores, es un hecho que nos gratifica ya que muchas veces nos sentimos muy solos.... :) 8)Todos coincidiremos al pensar que cualquier programa que soporta el ratón es más fácil de utilizar y puede ofrecer más posibilidades de forma sencilla, que otro que no lo soporte. Pero a mi modo de ver en la programación de videojuegos el ratón no es muy importante, baso esta afirmación en dos hechos: primero en los videojuegos, los jugadores suelen buscar acción y prefieren que se les agobie un poco con los controles y que tengan que usar las dos manos para manejar al endiablado muñequito ;) y segundo existe otro periférico más indicado para el entretenimiento, el joystick, del que hablaremos en una próxima lección. :)
De todos modos vamos a estudiar el ratón, por varias razones: es un dispositivo que todo el mundo posee, a diferencia del joystick que sólo lo tienen los ludópatas profundos como yo, ;)) además, existe un tipo de videojuego en los que está muy indicado, las videoaventuras del tipo de Monkey Island, Indiana Jones...) y como última razón, siempre existe la posibilidad de incluir en nuestro programa un bonito menu controlado por la rata.
Para manejar el ratón existen una serie de funciones que son suministradas por el driver del fabricante, este driver se suele instalar durante el arranque del ordenador bien mediante un programa 'mouse.com', o con un archivo de dispositivo 'mouse.sys', en cualquier caso lo que hace este proceso es configurar la tabla de vectores de interrupción para que la int 33h apunte a un driver que se situará en memoria ofreciendo sus servicios.
Como os dije en la primera lección, mediante las
interrupciones
software se pueden acceder tanto a servicios de la BIOS, del DOS o como
en este caso de un controlador de un fabricante de dispositivos.
Antes de ver las herramientas que podemos utilizar, tenemos que conocer
las posibilidades que existen para controlar el ratón.
Aquí
como en la mayoría de periféricos existen dos variantes:
Control mediante 'polling' (sondeo) o control por
interrupción:
El primero es el más sencillo y consiste en preguntar periódicamente al dispositivo por su estado, la pega de este método es que tenemos que perder tiempo de CPU preguntando repetidas veces al ratón, cuando a lo peor no ha cambiado el estado del mismo.
El segundo método se apoya en el uso de interrupciones.
Haciendo
uso de unas funciones especiales del driver, podemos crearnos nuestro
propio
controlador y hacer que sea llamado al producirse un cambio de estado
en
el ratón, la ventaja de esta alternativa es que no tenemos que
preguntar
nada al periférico ya que éste se encarga de informarnos
automáticamente de su estado, la desventaja es que es más
complicado de implementar.
Veamos ahora los servicios ofrecidos por el driver, en total existen 53 funciones pero sólo voy a exponer las más utilizadas:
int 33h Función 00h
Entrada:
ax
= 0000h Función: Resetear el driver del ratón
Salida:
ax = FFFFh -> Driver del ratón instalado
bx = Número de botones del ratón
ax = 0000h -> Driver no instalado
Esta función la utilizaremos para comprobar si el
driver
está instalado y
para hacer un réset del mismo.
------------------------------------------------------------------------------
int 33h Función 01h
Entrada:
ax
= 0001h Función: Mostrar el cursor del ratón
Salida:
Ninguna
En modo texto el cursor por defecto es un rectángulo,
en modo gráfico una
flecha. Se pueden crear cursores propios pero no vamos a
ver cómo, ya que es
una función que no se suele utilizar.
------------------------------------------------------------------------------
int 33h Función 02h
Entrada: ax = 0002h Función: Ocultar el driver del ratón
Salida:
Ninguna
Aunque el cursor esté oculto se sigue actualizando
su posición.
------------------------------------------------------------------------------
int 33h Función 03h
Entrada:
ax
= 0003h Función: Obtener posición del ratón
y estado
de los botones
Salida:
cx = Posición horizontal
dx = Posición vertical
bx = Estado de los botones
Bit 0 1=Pulsado botón izquierdo
Bit 1 1=Pulsado botón derecho
Bit 2 1=Pulsado botón central
Las coordenadas son respecto a la pantalla virtual del
ratón.
En modo 13h
éstas van del rango:
Horizontal
0..639 (*Tendremos que dividirlas por 2*)
Vertical
0..199
Esta será la función que utilizaremos en el
método de polling.
------------------------------------------------------------------------------
int 33h Función 04h
Entrada:
ax
= 0004h Función: Posiciona el cursor del ratón
cx = Posición horizontal
dx = Posición vertical
Salida:
Ninguna
------------------------------------------------------------------------------
int 33h Función 07h
Entrada:
ax
= 0007h Función: Limita zona de movimiento horizontal
del ratón
cx = Mínima posición horizontal
dx = Máxima posición horizontal
Salida: Ninguna
Esta función y la siguiente nos servirán
para
determinar la zona en la que
permitiremos el uso del ratón. El ratón es
centrado automaticamente en dicha
zona.
------------------------------------------------------------------------------
int 33h Función 08h
Entrada:
ax
= 0008h Función: Limita zona de movimiento vertical
del ratón
cx = Mínima posición vertical
dx = Máxima posición vertical
Salida:
Ninguna
------------------------------------------------------------------------------
int 33h Función 0Ch
Entrada:
ax
= 000Ch Función: Instala controlador de eventos
cx = Máscara de eventos que provocarán que el
controlador
sea llamado.
Bit 0 Movimiento del ratón
Bit 1 Pulsado el botón izquierdo
Bit 2 Soltado el botón izquierdo
Bit 3 Pulsado el botón derecho
Bit 4 Soltado el botón derecho
Bit 5 Pulsado el botón central
Bit 6 Soltado el botón central
es:dx = Dirección del controlador a instalar
Salida: Ninguna
Está será la función que utilizaremos
en el método de interrupción. Aunque
hemos hablado continuamente de interrupciones, el controlador
en verdad será
invocado por el driver del ratón mediante una llamada
Far call, esto quiere
decir que el controlador deberá terminar con la
instrucción
ret.
Los registros deberán ser salvados y posteriormente
recuperados en el
controlador si van a ser modificados. (Las rutinas embebidas
en ensamblador
en Pascal 'creo' que guardan automaticamente todos los
registros)
El driver del ratón le pasará al controlador
de eventos la siguiente
información en los registros del procesador:
ax = Máscara de
eventos.
Indicará los eventos que se han producido,
puede haber ocurrido algún otro además del que nosotros
interceptábamos.
bx = Estado de los botones
Bit 0 Pulsado botón
izquierdo
*
Bit 1 Pulsado botón derecho
Bit 2 Pulsado botón central
cx = Coordenada horizontal
del ratón.
dx = Coordenada vertical del
ratón.
si = Longitud del
último
movimiento horizontal del ratón
di = Longitud del
último
movimiento vertical del ratón
Tanto si como di vendrán en la unidades de medida del
ratón
o
Mickeys :)) que se corresponden a 1/200 o 1/400 pulgadas. Os cuento
esto para que fardéis como lo hago yo, ;) pero no vamos a
utilizar
estos valores.
ds = Segmento de datos del
driver del Ratón. ¡Ojo! ésto a mi me consto
mucho darme cuenta, Oo·:( si queréis utilizar en vuestro
controlador variables Pascal tendréis que poner en ds el valor
apropiado. Ver demo para más detalles.
------------------------------------------------------------------------------
Bueno, ya os he contado la teoría, pasemos a la práctica. En el siguiente programa os muestro un ejemplo de utilización de las funciones BIOS para el control del ratón, entiendo que alguien considere el programa un tanto machista, pero hasta ahora no he recibido ningún mensaje de chicas :) 8 -< y a ver si con ésto empiezan a participar.... ;)
Pulsa F2 para ejecutar el programa Ratón - Posibilidad no disponible en la versión HTML-.
En la lección anterior, ya vimos que un punto en pantalla se representa con un byte que indica su color. Como con 8 bits se pueden codificar 256 valores, este número será el máximo de colores representables simultáneamente en pantalla.
Que sólo podamos ver a la vez 256 colores no significa que no dispongamos de más posibilidades, en verdad esos 256 forman parte de un total de 262144 colores que podemos seleccionar. Para saber de dónde viene este número tenemos que conocer cómo se construye un color.
Un color en las tarjetas VGA se define a partir de tres colores primarios: rojo, verde y azul (de ahí vienen los monitores RGB). Cada uno de estos componentes se representa con 6 bits, luego cada color se definirá con 18 bits (6+6+6) y echando cuentas (2 elevado a 18=262144) nos sale el número de colores que podemos ver, pero recuerdo, a la vez sólo podemos visualizar 256 de éstos.
Como complemento a la explicación y para afianzar las ideas, podéis ejecutar el programa COLOR para que 'veáis' cómo se forma un color:
Pulsa F2 para ejecutar el programa COLOR. - Posibilidad no disponible en la versión HTML-.
Una estructura que podemos utilizar para almacenar un color sería la siguiente:
Color:record
Rojo:byte;
(*Utilizaremos sólo 6 de los 8 bits*)
Verde:byte;
Azul:byte;
end;
Pero a nosotros nos va a interesar guardar los 256 colores que podemos visualizar en cada momento. Estos 256 colores son conocidos como paleta gráfica y la vamos a representar con la siguiente variable:
Paleta:Array[1..256] of Color;
En la tarjeta de vídeo la paleta gráfica se almacena
en 256 registros, de donde podrá ser referenciada más
rápidamente
que si se almacenase en memoria. Nosotros utilizaremos nuestra variable
paleta para cambiar los valores de esos registros que al fin y al cabo
son los que vamos a poder ver en pantalla.
Existen distintas herramientas para modificar la paleta gráfica, podemos trabajar con las funciones BIOS o utilizar los puertos de la tarjeta gráfica. Como el overhead (ver lección 1) en este caso es pequeño, el escoger una u otra posibilidad depende de vosotros. ;)
Las funciones BIOS más importantes para trabajar con la paleta gráfica son :
int 10h Función
10h
Subfunción 10h
Entrada:
ah
= 10h Función: trabajar con la paleta
al = 10h Modificar el valor de un registro de
color
bx = Número de registro
dh = Porcentaje de rojo (0..63)
ch = Porcentaje de verde (0..63)
cl = Porcentaje de azul (0..63)
Salida:
Ninguna
------------------------------------------------------------------------------
int 10h Función
10h
Subfunción 12h
Entrada:
ah
= 10h Función: trabajar con la paleta
al = 12h Modificar el valor de un conjunto de
registros
bx = Primer color (registro) a modificar
cx = Número de colores a modificar
es:ds = Puntero a la tabla con los nuevos colores
Salida:
Ninguna
------------------------------------------------------------------------------
int 10h Función
10h
Subfunción 15h
Entrada:
ah
= 10h Función: trabajar con la paleta
al = 15h Leer el valor de un registro de color
bx = Número de registro
Salida:
dh = Porcentaje de rojo (0..63)
ch = Porcentaje de verde (0..63)
cl = Porcentaje de azul (0..63)
int 10h Función
10h
Subfunción 17h
Entrada:
ah
= 10h Función: trabajar con la paleta
al = 17h Leer los valores de un conjunto de
registros
bx = Primer color (registro) a leer
cx = Número de registros a leer
es:dx = Puntero a un búffer donde almacenar los
colores
Salida:
Puntero al búffer con los valores pedidos
Si utilizásemos los puertos de la VGA, tenendríamos que
saber que el número de color que queremos cambiar debe situarse
en el puerto 3C8h y los tres componentes de dicho color deberan
mandarse
consecutivamente a través del puerto 3C9h (Primero Rojo,
depués
Verde y finalmente Azul.
Veamos como ejemplo esta rutina que cambiaría un color de la paleta:
port[$3C8]:=Color; (*Puerto donde ponemos el color a modificar*)
port[$3c9]:=Paleta[Color].Rojo;
(*Porcentaje de rojo*)
port[$3c9]:=Paleta[Color].Verde;
(*Porcentaje de verde*)
port[$3c9]:=Paleta[Color].Azul;
(*Porcentaje de azul*)
Si quisiéramos cambiar un conjunto de colores:
port[$3c8]:=Color
(*Primer color a modificar se incrementa
automáticamente*)
for i:=color to
UltimoColor
do (*Grupo de colores*)
begin
port[$3c9]:=Paleta[i].Rojo;
(*Porcentaje de rojo*)
port[$3c9]:=Paleta[i].Verde;
(*Porcentaje de verde*)
port[$3c9]:=Paleta[i].Azul;
(*Porcentaje de azul*)
end;
Para que veáis cómo utilizar estos servicios ejecuta y consulta cuando quieras el programa PALETA. :)
Pulsa F2 para ejecutar el programa PALETA. - Posibilidad no disponible en la versión HTML-.
Bueno ya sabemos cómo instalar una paleta, ahora tenemos que ver qué podemos hacer con ella aparte de conseguir que las imágenes se visualicen con sus correspondientes colores. Como os habréis dado cuenta al ejecutar el programa anterior podemos producir un cambio instantáneo en una imagen con sólo cambiar su paleta. Esto se debe a que no hay que volver a dibujar la imagen, ésta no se modifica, lo que cambia es el color que representa cada byte en la memoria de vídeo.
Pongamos un ejemplo, si tenemos en una imagen un cielo de color azul, (supongamos número de color 50) si queremos oscurecer el cielo para hacer un efecto de atardecer, no tendríamos que dibujar todo el cielo con el color azul oscuro, (supongamos color 51), únicamente tendríamos que intercambiar los valores de RVA de ambos colores, hecho que es casi instantáneo con cualquier método que utilicemos.
En esta idea se basa uno de los efectos más utilizados tanto en la programación de videojuegos, como en resto de áreas de la programación. Los fundidos (del inglés fade). Este efecto puede hacerse de dos maneras, o partimos de la imagen original y la vamos oscureciendo hasta que quede la pantalla negra (fundido descendiente o fade out), o al reves (fundido ascendente o fade in). El fundido descendiente se realiza de la siguiente manera:
Para hacer el efecto, nos valdremos de una paleta auxiliar que nos servirá para hacer las modificaciones, ya que si utilizásemos la paleta original perderíamos los valores de ésta y tendríamos que volver a recuperarla o generarla. El truco consiste en ir multiplicando los tres componentes de cada color de la paleta original por un factor y almacenar el resultado en la paleta auxiliar, cuando hayamos multiplicado los 256 colores 'instalamos' la paleta auxiliar y volvemos a multiplicar todos los componentes de los colores por un nuevo factor, si éste va disminuyendo de 1 hasta 0 conseguiremos que los colores de nuestra imagen, se conviertan desde su color original (factor=1) hasta el color negro (factor=0). La rapidez del fundido dependerá de la rapidez con que disminuyamos nuestro factor. Veamos una rutina en Pascal que realizaría un fundido:
procedure FundidoD(Paleta:TipoPaleta);
const Pasos=200;
var i,j:integer;
Paletaux:TipoPaleta; (*Variable
para almacenar la paleta en cada paso*)
begin
for i:=Pasos downto 0 do (*Número de pasos del
fundido*)
begin
for j:=0 to 255 do
(*Todos
los colores*)
begin
Paletaux[j].Rojo:=(Paleta[j].Rojo*i)
div Pasos;
Paletaux[j].Verde:=(Paleta[j].Verde*i)
div Pasos;
Paletaux[j].Azul:=(Paleta[j].Azul*i)
div Pasos;
end;
CambiarColoresA(Paletaux);
(*Instalamos la nueva paleta en cada paso*)
end;
end;
Os he mostrado cómo realizar un fundido descendente, para hacer un fundido ascendente tendréis que utilizar la misma rutina con la modificación de que el factor tiene que variar desde 0 hasta 1, ésto lo conseguimos con sólo cambiar el primer bucle for por el siguiente:
for i:=0 to Pasos do
Podéis ejecutar ahora el programa FUNDIDO donde apreciaréis el efecto conseguido con este truco. :)
Pulsa F2 para ejecutar el programa FUNDIDO - Posibilidad no disponible en la versión HTML-.
A lo peor durante la realización del efecto os aparece un
tedioso
parpadeo que estropea el fundido. Cómo evitar este contratiempo
será uno de los temas para la siguiente lección.
Además
empezaremos una serie de artículos dónde jugaremos con la
paleta para conseguir distintos efectos gráficos. Tened
paciencia.
;)
Existen diferentes versiones dentro del mismo formato, la mayor clasificación se hace teniendo en cuenta la profundidad de color (o número de bits con los que se codifica un color), según esta clasificación podemos distinguir versiones de 4, 8 o 24 bits.
Nosotros nos vamos a centrar en el formato de 8 bits o de 256 colores y para el tamaño de 320x200, pero extrapolar mis explicaciones a otros tamaños es sencillo. :)
El formato PCX consta de una cabecera de 128 bytes, ésta
contiene
toda la información necesaria para identificar la versión
y el tamaño de la imagen que contiene el archivo. Os muestro
ahora
detalladamente toda la información que contiene la cabecera:
:
Posición Longitud
(bytes)
Significado
Valor en modo 13h
0
1
Identificador
PCX
0A
1
1
Versión
05
2
1
Codificado RLE
(1=SI)
01
3
1
Bits por
píxel
08
4
2
Esquina superior izqd. X 0000
6
2
Esquina superior izqd. Y 0000
8
2
Anchura -
1
013F
10
2
Altura -
1
00C7
12
2
Resolución
horizontal
0060
14
2
Resolución
vertical
0060
16
48
Paleta de colores EGA No lo
utilizamos
64
1
Sin
uso
00
65
1
Planos de
color
01
66
2
Bytes por
línea
0140
68
2
Tipo de
paleta
0001
70
58
Sin
uso
00
Me gustaría destacar dos cosas, primero los valores que constan de dos bytes son números enteros que se almacenan en memoria de la forma llamada de punta delgada, esto en cristiano quiere decir que primero viene el byte de menor peso y seguido el byte de mayor peso. Por ejemplo el número 140 se almacenaría como 40 01.
El segundo asunto que quería comentaros es la forma de almacenar la paleta que tiene el formato PCX. Como os habréis dado cuenta al ver la cabecera, ésta tiene un espacio reservado para contener la paleta, pero sólo para la tarjeta EGA, como en ese espacio no se podía guardar de ninguna manera la paleta VGA, se optó por almacenar ésta al final del archivo situando antes el valor 0C para identificarla y después los 768 bytes de la paleta. Los valores de la paleta se encuentran justificados a la izquierda en cada byte por lo que hay que desplazarlos a la derecha 2 posiciones o dividir por 4, antes de almacenar lo leído en nuestra variable paleta. El por qué de este rodeo preguntárselo al ingeniador.
La imagen en sí, se almacena justo detrás de la cabecera, es decir, a partir del byte 129. Esta imagen no viene en un formato crudo, como vimos en la primera lección, sino que viene comprimida mediante el algoritmo RLE (Run Length Encoding), cuya traducción Shakespiriana sería algo así como codificación por longitud de serie. Este método se basa en el hecho de que en la mayoría de los gráficos, se repiten consecutivamente muchos colores, por ejemplo imaginemos un fondo de cielo todo azul.
El funcionamiento del algoritmo lo expondré a través de un ejemplo. Imaginemos que en un gráfico se presenta la siguiente serie de colores:
21 21 21 21 21 21 21
en el fichero PCX esta cadena se almacenaría como 07 21, es decir, la longitud de la serie seguido del elemento que se repite, pero para que no se produzca una confusión al reconocer un byte y distinguir entre la longitud y el valor de un color se optó por el siguiente criterio:
Si el byte indica la longitud de una cadena tendrá los dos bits de mayor peso 6 y 7, puestos a 1, el resto de ese byte (0..5) indicarán la longitud de la serie. Detrás de este byte se situará el color codificado con 8 bits. Para el caso de que no exista una serie y haya que codificar sólo un color éste se representará normalmente, con un sólo byte, siempre que el color sea menor de 192, sino es así, se representa como una serie de longitud 1. :)
Un ejemplo más completo podría ser el siguiente:
Cadena original 5x3 Cadena comprimida RLE
21 21 21 21
FA
C4 21 C1 FA
28 1A 1A 1A
1A
28 C4 1A
3E 3E 3E 3E
2A
C4 3E 2A
Relación de compresión 15:10 <> 3:2 <> 66 por ciento del tamaño original.
Sabiendo cómo se almacena la imagen ya somos capaces de
recuperar
y visualizar una imagen almacenada con formato PCX, veamos los pasos
detallados:
1º Leer la cabecera del dibujo y comprobar que se trata de un fichero PCX de dimensiones 320x200 y con 256 colores.2º Posicionarse sobre los últimos 768 del fichero para leer la paleta del dibujo.
3º Inicializar dicha paleta si queremos visualizar la imagen según se descomprime. Otra opción es empezar con la paleta a negro y una vez la imagen descomprimida, 'cargar' la paleta original. :)
4ª Situarse detrás de la cabecera, y empezar a descomprimir la imagen.
4.1 Leer un byte del archivo.4.2 Si es mayor de 192, o lo que es lo mismo los dos bits de mayor peso puestos a 1, es el indicador de una cadena luego cogemos los seis bits de menor peso que será la longitud de la serie y leemos el siguiente byte que será el color. Si no es mayor de 192 la longitud de la serie será de uno y el color ya lo tenemos.
4.3 Llevamos a la pantalla tantas veces el color leído como indique longitud. Lo situamos en las coordenadas que correspondan.
4.4 Si estamos dentro de las coordenadas 320x200 vamos al paso 1, si no es así se acabó. ;)
Como es habitual, con el presente artículo os suministro
un programa de demostración con sus fuentes, para que
veáis
implementado el algoritmo anterior.
Pulsa F2 para ejecutar el programa VISU_PCX. - Posibilidad no disponible en la versión HTML-.
Como os daréis cuenta, la imagen que muestra no es nuestra pero con imágenes como esa luce más el programa, ;)) desde luego los de Microprose se lucieron de verdad al realizar esa magnífica presentación y suministrarla en formato FLI. X-))
Bueno con el programita acaba esta lección, próximamente trataremos el formato gráfico GIF, mucho mejor y por tanto, como suele ser normal más complicado. :)Un sprite no es más que un bloque rectangular de puntos que representa una imagen determinada. Estas imágenes serán los objetos animados de los videojuegos, a diferencia del resto de gráficos estáticos que formarán el llamado fondo de la pantalla. También pueden existir sprites que no necesariamente se tengan que mover (un cargador para nuestra ametralladora, sangre extra... ya sabéis, brutalidades de ésas ;) pero que pueden ser situados libremente en la pantalla por lo que también los consideraremos animados.
Una definición más general y quizás más acertada sería considerar los sprites como todo objeto que tiene un significado en el juego y que no es simplemente un elemento decorativo. :)
Como he dicho, los sprites son rectangulares, aunque siempre los distingamos como objetos irregulares. Se almacenan bajo esa forma geométrica para que los gráficos puedan ser llevados más rápidamente a la pantalla conociendo únicamente las dos dimensiones del rectángulo, anchura y altura. Si se almacenasen con su forma original habría que tener muchísima más información para reconocer el contorno del dibujo, luego no es viable.
Para almacenar los sprites en memoria secundaria (disco duro) se
pueden
utilizar varias técnicas:
Nosotros utilizaremos la primera técnica ya que en el programa
de dibujo que solemos emplear (Autodesk 2d Animator. ¡Toma
publicidad
gratuita! ;) , existen un tipo de elemento que se corresponde
exactamente
con la definición de sprite, los archivos CEL.
Estos archivos se utilizan para salvar partes de una pantalla, la forma de almacenarse es idéntica a la del archivo crudo aatemp2 que explicamos en la primera lección, esto es, fila tras fila. La diferencia está en el tamaño de los archivos y la forma de acceder a ellos.
El tamaño ahora es variable (no 64800 como antes) depende de la anchura y altura del sprite. Imaginemos que salvamos en un archivo Cel un pequeño cuadrado de pantalla que tiene un tamaño de 10x10. El archivo Cel tendrá un tamaño de 32 bytes de cabecera + 768 de la paleta + (10x10) de la imagen= 810 bytes.
La otra diferencia es la forma de obtener los gráficos ya que ahora se puede acceder a ellos directamente y no tenemos que irnos a directorios temporales y rollos de esos. :)
Los archivos Cel también pueden ser utilizados para almacenar pantallas enteras de 320x200, en este caso podemos utilizarlos en programas como Imagen, suministrado en la lección 1.
Otra característica importante de los archivos Cel es la posibilidad que tenemos de reconocer la anchura y altura de la imagen contenida en el archivo. Estos datos son almacenados en la cabecera, la anchura en la posición 3 y la altura en la posición 5, en verdad se utilizan dos bytes, pero como no utilizaremos sprites más grandes de 255 pixels no habrá problema. :)
Lo último que os quiero comentar sobre los archivos Cel es el hecho de que en cada fichero se almacene la paleta. Sabiendo ésto, si recuperamos distintos sprites que fueron realizados con la misma paleta, sólo deberemos inicializarla una vez, aunque la leamos en todos los casos.
Ya sabemos cómo se guardan nuestros muñequitos en el
disco,
ahora queda saber cómo los almacenaremos en nuestro programa.
Tenemos
también varias posibilidades:
Los que tenéis buenos conocimientos en estructuras abstractas
de datos ya sabéis cual es la solución óptima.
Para
los que no, me explicaré lo mejor que pueda. Si optamos por
cualquiera
de las tres primeras opciones, tendremos que definirnos los arrays
antes
de saber el tamaño de los sprites, con lo cual fijaremos un
tamaño
máximo para los mismos y estaremos desaprovechando memoria.Un
ejemplito:
Tenemos dos sprites uno de tamaño 20x20 y otro de 50x50, si nos definimos nuestro TipoSprite como:
TipoSprite=Array[1..30,1..30] of byte;
En el primer caso estaremos desperdiciando 500 bytes de memoria y en el segundo no podremos almacenar el sprite en una variable de ese tipo.
La solución es utilizar la asignación dinámica de memoria. El método consiste en definirnos la variable donde vamos a almacenar el sprite como un puntero general, en pascal Pointer, y una vez sepamos el tamaño del dibujo asignarle la memoria estrictamente necesaria, mediante instrucciones como Getmem(Puntero,Tamano) de Pascal. En el ejemplo anterior nos definiríamos dos variables tipo Pointer:
var Sprite1,Sprite2:Pointer;
Y a cada una le asignaríamos, una vez calculado el tamaño, su correspondiente memoria
GetMem(Sprite1,10*10);
GetMem(Sprite2,30*30);
Para liberar la memoria asignada dinámicamente y dejar así que otros programas utilicen la misma existen instrucciones como la FreeMem de Pascal
FreeMem(Sprite1,10*10);
El problema de este método es saber cuál es la anchura y altura de la imagen referenciada por el puntero. Para ello nosotros optamos por una fácil solución, almacenar la anchura y altura del sprite en las primeras posiciones de la memoria apuntada por el puntero. Ojo tened en cuenta que ahora tendremos que reservar al sprite un área de memoria de tamaño dos bytes mayor que antes.
Una vez esté la imagen en memoria principal el sacarla por pantalla es tarea fácil, leer fila a fila la imagen y visualizarlas. Para hacer este trabajo tenemos varias posibilidades, utilizar BIOS o ADMV (Acceso Directo a Memoria de Vídeo) para llevar puntos a la pantalla y utilizar lenguaje LAN o ASM. En las rutinas que entregaremos con esta lección utilizaremos ADMV y LAN, en la próxima lección os daremos las buenas ADMV y ASM.
Ejecutad ahora y consultad cuando podáis el programa demostración que carga y visualiza un sprite en pantalla. :)
Pulse F2 para ejecutar el programa SPRITE1. - Posibilidad no disponible en la versión HTML-.
Una vez que sabemos sacar sprites por pantalla, hacer una animación es sencillo. Una secuencia animada es una sucesión de imágenes estáticas que visualizadas rápida y consecutivamente producen un efecto de movimiento.
La animación puede constar de una única imagen que se desplaza por la pantalla,(ejemplo: una nave espacial), por varias imagenes que se suceden en la misma posición (una hoguera) o por varias imagenes que se suceden y se desplazan por la pantalla (una hormiguita con un peazo ametralladora que anda por la pantalla). X-))
La forma de realizar una animación también es simple. Almacenar en un array todas las imágenes que componen la secuencia e ir cambiando el índice del array para mostrar un sprite diferente en cada paso.
Type
TipoSprite=Pointer
Var
Animacion:Array [1..3] of TipoSprite;
Indice:integer;
Indice:=1;
repeat
???
PonSprite(x,y,Animacion[Indice];
Indice:=(Indice mod
3)+1;
(*Hace variar el indice de 1..3*)
???
until ???
Bueno se acabó este capítulo.... ¿Qué..? ¿Qué decís...?, ¡Ah! que queréis más información, bueeeeeno, ;)) tomad una demo. :)
Pulsa F2 para ejecutar el programa ANIMACIO. - Posibilidad no disponible en la versión HTML-
Podéis ver qué sencillo es animar una imagen, lo difícil de verdad es dibujarlas, como veréis una de las animaciones se compone de 10 imagenes...Gracias de verdad a Juán Antonio Ubeda Torres (grafista de Hormigator). :)
En la próxima y última entrega sobre el modo 13h, os mostraremos cómo hacer que las imágenes respeten el fondo al visualizarse, evitaremos los parpadeos tediosos de la pantalla y aceleraremos nuestros videojuegos trabajando en ensamblador puro y duro, así que ya sabéis, ;) nos vemos... :)
Sí, sí, aquí acaba este capítulo. ;)
En el artículo sobre el speaker de la lección anterior,
ya hablamos de este componente del PC, entonces sólo vimos lo
que
se necesitaba para generar una onda cuadrada a través del
tímer
2, pero éste dispositivo puede dar mucho más juego como
veremos
en éste y otros artículos. :)
EL PIT es una de tantas pastillitas que forman nuestro PC,
el
circuito integrado que lo implementa se conoce como 8253 o 8254.
La palabra PIT viene de Programable Interval Timer y la
traducción
literal sería 'temporizador programable de intervalos'. El 8253
cuenta con tres tímers independientes y para ver qué es
un
tímer me basaré en las tres palabras que forma el
acrónimo
PIT ya que definen perfectamente al aparatillo en cuestión:
Cada uno de los tímers del PIT tiene una misión
específica:
Cada uno de estos tímers pueden ser programado de diferentes
maneras, veamos los 6 posibles modos de funcionamiento:
Modo 0: (Interrupción al final de cuenta) Una vez
cargado
un valor en el contador, la salida permanece a nivel bajo hasta que
llegue
a cero, momento en que la salida permanecerá a nivel alto hasta
nueva carga del contador.
Los modos 1 y 5 necesitan de una transición (cambio de nivel
0 a 1 ) en una de las patillas del chip (Pin Gate), para comenzar la
cuenta.
Bueno una vez visto qué podemos hacer, os tengo que enseñar cómo hacerlo:
El PIT cuenta con 4 puertos, éstos son:
El puerto de control sirve para indicar el modo de funcionamiento
de cada tímer, los valores posibles para este byte:
---------------------------------
A: Selección de contador:
| 7 | 6 | 5 | 4 | 3
| 2 | 1 | 0 | 00
= Timer 0
---------------------------------
01 = Timer 1
======= =======
===========
===
10 = Timer 2
11 = Comando de lectura
|
|
| |
|
|
|
|
B: Forma de acceso al contador:
|
|
|
|
00 = Comando de latch
A
B
C
D
Es como el lap de los
cronómetros, el contador
C: Modo de
funcionamiento:
sigue funcionando, pero
la salida está fija.
000 = Modo
0
01 = Lectura/escritura del
001 = Modo
1
byte menos significativo
010 = Modo
2
del contador( 16 bits)
011 = Modo
3
10 = L/E del byte más sign.
100 = Modo
4
11 = L/E primero del B-S
101 = Modo
5
después del B+S.
D: Formato de la cuenta:
0 = Binario
1 = BCD
Como siempre la forma de entender el manejo del puerto del estado será con un ejemplo, en el artículo de la primera lección sobre el speaker, os dije que para programar el tímer 2 para que genere una onda cuadrada era $B6, os prometí una justificación pues aquí está:
<---- B
---->
<---- 6 ---->
---------------------------------
Programación del tímer 2,
| 1 | 0 | 1 | 1 | 0 | 1 |
1 | 0 | para generar una onda
cuadrada.
---------------------------------
======= =======
===========
===
Timer
2
| Modo 3 Cuenta
en
binario lo más normal
|
Como visteis, primero
cargábamos el byte menos
significativo y después
el más significativo.
Bien, una vez programado el PIT es necesario indicar el valor para el contador, la forma de mandar los valores ya estará decidida y normalmente será mandando dos bytes (B-S, B+S). Para calcular el valor del contador, ya os conté el método, pero me voy a repetir cómo el pepino. :)
1193180 <-- $1234DD (hexadecimal)
Contador
= ----------
Frecuencia
deseada
Ese tochazo de valor es la frecuencia del reloj interno que regula
el funcionamiento del PC, suele ser un oscilador del tipo 8284, y como
curiosidad os diré que el valor se obtiene a partir de la
división
(4.77272 / 4 MHz).
En ése artículo, os mostré cómo generar un sonido por el speaker sin intervención de la CPU, con ello ya podíamos hacer un sonido residente. El problema es que ésto sólo nos vale para sacar una nota, un pitido, en el caso de querer emitir una pequeña melodía (sucesión de notas) con éste método tendríamos que controlar la duración, apagar la nota actual y hacer sonar la siguiente. En el programa demostración de aquella lección utilizábamos esta técnica y como visteis las posibilidades estaban bastante limitadas. En el caso de un videojuego no podemos estar pendientes de que una melodía se ejecute nota a nota, ya que estaremos bastante ocupados 'con otras cosas'. :)
Tenemos que hacer que 'algo', ajeno a nuestro proceso, se encargue de ir cambiando las notas de nuestros efectos sonoros, ahí es donde entra en juego el PIT (al que hemos dedicado un artículo completo). Cuando os expliqué el funcionamiento del Tímer 0, os dije, que era ideal para controlar procesos demonios... y tal y tal, veamos ahora de qué va eso.
El nombre de procesos demonios lo escuché por primera vez al estudiar los sistemas operativos multitarea, en concreto UNIX. En estos sistemas existen dos tipos de procesos: interactivos o sometidos (background). La mayor diferencia entre ambos, es que los interactivos necesitan de la acción del usuario y los sometidos no, además estos últimos suelen ejecutarse en los 'ratos libres' del ordenador. En el caso de los PC-DOS hablar de demonios es bastante erróneo, ya que como sabréis, a pesar de que los procesadores Intel a partir del 386 soportan la existencia de varias tareas, el D.O.S. no aprovecha esta capacidad al trabajar en modo real y sólo soporta la ejecución de un proceso a la vez (monotarea). Gracias al PIT y en concreto al tímer 0 vamos a poder tener un pseudo-demonio, que se ejecute periódicamente, realizando taréas que no necesiten de nuestra intervención, en nuestro caso, que se encargue de sustituir las notas de los efectos sonoros del speaker.
Bueno, llega el momento de ponerse manos a la obra, lo primero que necesitaremos en nuestro programa es una estructura de datos donde se almacenarán las melodías, los tipos de datos siempre podréis variarlos para adaptarlos a vuestras necesidades, nosotros utilizamos una estructura estática como la siguiente:
Const MaxNotas=30; (*Máximo número de notas de la melodía*)
Type
TipoNota=
record
(*Registro que representa cada nota*)
Frecuencia:word; (* de la melodía, almacena
su
*)
Duracion:integer; (* frecuencia y su
duración
*)
end;
TipoMusica=Array[1..MaxNotas] of
TipoNota; (*Tipo de nuestras melodías*)
Como véis, con ésta estructura limitamos nuestros sonidos a un número máximo de notas, lo que reducirá nuestras posibilidades a emitir pequeños efectos como los que vimos en la lección anterior. En verdad se pueden sacar auténticas sinfonías por el speaker, pero un abuso de este dispositivo puede resultar tedioso y el usuario en cuanto pueda, pasará del speaker y vuestro trabajo codificando canciones habrá sido en balde, y éso duele... :)
Un ejemplo de demonio que basándose en esta estructura emita sonidos podía ser el siguiente:
var
Musica:TipoMusica;
(*Variable que almacena la melodía a tocar*)
Ejecutando:boolean;
(*Se está emitiendo una melodía*)
Actual:byte;
(*Nota actual de la melodía*)
{$F+}
(*Fuerza llamadas Far -necesario para controladores*)
Procedure
Demonio;interrupt;
(*Procedimiento de interrupción*)
begin
if Ejecutando
then
(*¿Se está ejecutando algún sonido?*)
begin
(* SI*)
dec(Musica[Actual].Duracion);
(*Decrementamos la duración de la nota*)
if (Musica[Actual].Duracion=0) then (*¿Tenemos
que cambiar de nota?*)
begin
(* SI *)
inc(Actual);
(*Pasamos a la nota siguiente*)
if (Actual=MaxNotas+1) or
(Musica[Actual].Duracion=0)
then (*Fin melodía*)
begin
(* SI *)
Ejecutando:=false;
(*Ya no estamos emitiendo sonidos*)
Actual:=1;
(*La próxima será la primera nota*)
nosound;
(*Deja de emitir sonidos*)
end
else
(* NO fin de melodía*)
sound(Musica[Actual].Frecuencia);
(*Cambiamos la nota de la melodía*)
end
end
(* Fin if de cambiar nota*)
else
(* NO se está ejecutando sonido*)
if (Musica[Actual].Duracion<>0) then (*Cuando
actual
pase a valer 1*)
begin
(* pasaremos a ejecutar la melodía *)
Ejecutando:=True;
(*Estamos emitiendo música*)
Sound(Musica[Actual].Frecuencia);
(*Sacamos
la primera nota*)
end;
inline($9c);
(*Salva registro de bandera - necesario antes de int*)
Reloj_Proc;
(*Llamamos a la rutina original del IRQ 0*)
end;
{$F-}
(*Fin de directiva*)
Cuando queramos cambiar de sonido o empezar uno nuevo tendremos que ejecutar un rutina como la siguiente:
Procedure ActualizarMusica(NuevaMus:TipoMusica);
begin
inline($FA);
(*Instrucción ASM CLI no permite interrupciones*)
Musica:=NuevaMus;
(*Cambia
la melodía*)
Actual:=1;
(*Primera nota*)
Ejecutando:=false; (*El
demonio
se encargará de empezar la melodía*)
inline($FB);
(*Instrucción ASM STI permite interrupciones*)
end;
Quiero mencionaros un detalle, os habréis fijado que al final del proceso demonio, llamo al procedimiento Reloj_Proc; en este procedimiento guardaremos la rutina original que atiende a la IRQ 0. Como ya os he dicho en la lección, esta rutina se encarga de mantener en hora el reloj del sistema, al ejecutar más instrucciones antes de la rutina original estaremos retrasando la llamada al procedimiento y paralelamente el reloj del sistema, pero os diré que el mío está dos meses retrasado y no pasa na'. :)
Siendo radicales, las dos últimas instrucciones pueden ser sustituidas por la orden 'Port[$20]:=$20' con ella, mandamos un Ack a la CPU que indica que la llamada a la interrupción ha concluido normalmente, al no llamar a la rutina original, el reloj del sistema no se actualizaría, pero como os he dicho antes, el retraso producido no os tiene que preocupar.
Para hacer que nuestro demonio cantor 'se active' tenemos que sustituir la rutina que atiende a la IRQ 0, por la nuestra. La dirección de esta rutina se almacena en la posición 8 de la tabla de vectores de interrupción (Para más detalles sobre este tema consulta el artículo La Cacharrería de la lección 1), este proceso es idéntico al que utilizamos para sustituir el controlador del teclado, así que no voy a entrar en más detalles.
Como siempre os proporciono un programa demostración, donde implemento todo lo explicado en este artículo, me gustaría que en la siguiente demo probéis a apagar y encender el turbo, para que veáis que la IRQ 0 se genera con la frecuencia que fue programada y que es por tanto, independiente de la velocidad a la que funcione el microprocesador:
Pulse F2 para ejecutar el programa SPKBCK. - Posibilidad no disponible en la versión HTML-.
Con ésto ya podéis incluir el speaker perfectamente en vuestros juegos, 'Hormigator' llegó hasta aquí, pero el CPV va a ir un poco más lejos y en la próxima lección os voy a mostrar cómo sacar sonidos digitalizados por el speaker, os quiero ver a todos en clase para entonces, ahora, al recreo todos, vaaaaamos. ;)
Quizás éste sea el artículo más esperado
por muchos de vosotros,
- Ondiá, cómo hacer un juego, ya está me leo
ésto
y me hago un DOOM en cinco minutos
- No hijo no, si piensas así estas muuuuuy equivocado. :)
Como veréis esta sección es sólo un ejemplo de cómo aplicar lo explicado en el resto de los artículos para una aplicación en concreto y por consiguiente el objetivo es que una vez que os hayáis empollado el resto de artículos, paséis a estudiaros el juego del mes y así os resulte más fácil entenderlo. Además el programa que servirá de demostración no va a ser un nuevo lanzamiento mundial, todo lo contrario serán juegos sencillos y la mayoría clásicos, pero que os valdrán para entender los pasos básicos para la creación de un videojuego en su totalidad.
Estos pasos, son independientes del tipo de juego que vayáis a realizar, y por esta razón en un principio pensamos en incluir un único artículo al final del curso explicando el método, realizar un juego final y ya está. Pero las cosas cambiaron, nos dimos cuenta de que muchos estáis impacientes por empezar a darle a la tecla y si dejásemos lo bueno para el final quizas os estuviésemos defraudando, y a la vez, faltaríamos a nuestra palabra de realizar un CPV verdaderamente práctico.
Con todo ésto cambiamos nuestro parecer y decidimos realizar un juego por lección, explicarlo un poco por encima y sobre todo comentaros nuestra forma de proceder para realizar estas aplicaciones.
Para empezar con el tema os mostraré los pasos que solemos
seguir
para desarrollar un videojuego en general, para después
centrarnos
en cómo se hizo el programa Dardos. Al desarrollar un
videojuego
conviene seguir las siguientes etapas:
La parte de programación, aunque os pueda parecer la más dura, no es así, en verdad la codificación tiene mucha tarea la primera vez, pero una vez escritas las rutinas, éstas son perfectamente reutilizables. Por ejemplo, sacar una imagen por pantalla requiere el mismo proceso dibujemos un elefante que una patata.
Bueno ya os he comentado los pasos en general, me centraré
ahora en un programa en concreto DARDOS:
La primera fase, no nos llevó mucho tiempo, ya que nuestra política para la elección de ideas, como ya os he dicho, es realizar versiones propias de juegos ya conocidos, ahorrándonos así trabajo, tiempo y muchas neuronas.
En la segunda parte sí nos entretuvimos más, ya que uno de los hechos más importante para esta etapa fue decidir cómo podíamos detectar dónde el usuario 'clavaba' sus dardos. El nombre que reciben estas rutinas que se encargan de detectar los eventos del programa se conocen como algoritmos de colisión, existen multitud de ellos, tantos creo como programadores existen y ya dedicaremos algún artículo a ver algunas posibilidades. Por ahora como no queríamos utilizar alguna técnica complicada, empleamos un método bastante sencillo, éste es, cuando el usuario pulsa el botón de disparo, se presenta el sprite cruz en pantalla, leemos en las coordenadas actuales del ratón el color que hay en la pantalla y según este valor sabemos dónde impactó el dardo , para conseguir ésto al dibujar hay que seguir unas determinadas reglas (nota para el grafista) ya que las zonas de la diana con la misma puntuación deben llevar los mismos colores, (SI, todo amarillo pero que todos esos colores sean el color 57 por ejemplo, ya que podíamos tener un amarillo número de color 34, otro el 128, etc..). Una vez detectada la posición sólo nos quedaba aplicar las reglas del juego, pero en esta etapa no programamos nada, sólamente escogimos las estructuras de datos, lo demás sabíamos que es poner unas instrucciones u otras.
La tercera fase cómo ya os he comentado, no tiene por qué ser una tarea ardua y si no mirad, os voy a presentar todos los procedimientos que se emplean en este juego y os marcaré aquellos que son específicos para este programa el resto, formarán parte de nuestra ya nutrida librería:
Speaker
Modo13h
Paleta
----------------
------------------ --------------
Demonio
PonPunto
CambiarPaletaA
ActualizarSonido
CogePunto
FundidoA
InstalarSonido
Modo13h
FundidoD
DesinstalarSonido
ModoTexto
PonPaletaNegra
Juego-Caracteres
Formatos
Gráficos
Ratón
-----------------
------------------- ---------------
DamePuntero
LeePCX
InicializaRaton
VCadena
FinRaton
LimitaPantalla
Propios de
Dardos
(* Nuevos *)
MuestraRaton
-------------------------------------
OcultaRaton
Temblor
Disparo
EstadoActual
Cruz
PulsoSalida
PosicionaCursor
Reglas
Final
VisualizaPuntos
Creditos
BorraCruz
FinalJuego
Inicializa
Programa Principal
Como veréis un 80 por cien del código ya estaba hecho. De todos los procedimientos nuevos, nada hay que decir ya que es pura programación y no se utilizan en ellos técnicas especiales. Os presento el procedimiento Disparo que podemos considerar como núcleo del programa, para que veáis que no hay nada raro y para que notéis lo exhaustivamente comentado que viene el programa, como todos. :)
(*Procedimiento que comprueba si se pulsó el botón
1 Lanzar el dardo*)
procedure Disparo;
var St1:string;
begin
if Boton1
then
(*¿ Se pulsó botón izquierdo ?*)
begin
EscondeRaton;
(*Tenemos que ocultar el ratón antes de visualizar*)
(* nada, ya que el ratón ya salva automáticamente el *)
(* fondo antes de visualizarse y produciría un error*)
Cruz;
(*Visualiza la cruz recoge el color*)
Reglas;
(*Aplica las reglas del juego*)
VisualizaPuntos; (*Visualiza la
puntuación*)
delay(500);
(*Retardo para el sonido*)
nosound;
(*Para la música*)
Borracruz;
(*Recupera el fondo debajo de la cruz*)
MuestraRaton;
(*Muestra el ratón de nuevo*)
dardos:=dardos-1;(*Un dardo menos
en esta tirada*)
if dardos=0
then
(*¿Cambio de turno?*)
begin
jugador:=(jugador mod
2)+1; (*SI*)
dardos:=NumDardos;
end;
str(jugador,st1);
(*Visualiza el turno y el número de*)
Vcadena(98,187,st1,97,22);
(*de dardos*)
str(dardos,st1);
Vcadena(203,187,st1,97,22);
end;
end;
En los otros apartados de esta fase como veréis no me compliqué la vida, la diana la dibuje a la virulé y el sonido Beep Beep. :)
La cuarta fase en la que podemos considerar que Dardos se encuentra actualmente y ahí se quedará, Dardos es simplemente un programa de prueba y demostración.
Ya os dije al comienzo del artículo que leyendo ésto no ibais a programar un juego de la noche a la mañana, pero me gustaría que cogierais una idea importantísima, el programar un videojuego es un 80 por cien pensar una buena idea y realizar unos buenos gráficos y sonidos, el codificar no tiene ningún misterio, o bien os lo curráis una vez para vivir de las rentas u os hacéis con unas buenas rutinas, las nuestras por ejemplo, sin dar ni palo. En próximas lecciones, seguiré machacando esta idea y de momento ir perdiendo el miedo. :)
Bueno a qué esperáis, por qué no os vais... ¿qué?, ¿qué decís?.. ah! que dónde están los fuentes, ¡leshe!, se me había olvidado, venga tomad y que aproveche. :)
Pulse F2 para ejecutar el programa DARDOS. - Posibilidad no disponible en la versión HTML------------------------------------------------------------------------------
Para conocer los códigos scan y Ascii de cualquier tecla, ejecuta alguna de las demos TESTMFII y PLANTECL que incluimos con esta lección. Nosotros os mostramos los códigos make, para conocer los códigos release sólo tenéis que sumar 128 como es lógico ;)
Pulse F2 para ejecutar el programa PLANTECL. - Posibilidad no disponible en la versión HTML-
Me imagino que os habrá interesado este programa, en este capítulo no os proporcionamos los fuentes porque todavía no hemos visto la presentación de sprites en pantalla, pero en el próximo número os entregaremos los fuentes de PLANTECL. :)
------------------------------------------------------------------------------
Pues na' como lo prometido es deuda aquí tenéis los fuentes de este programa:
Pulse F2 para ejecutar el programa PLANTECL. - Posibilidad no disponible en la versión HTML-
Me gustaría destacar que Plantecl no lo consideramos parte del curso y por ello no lo he comentado exhaustivamente, sólo le he limpiado la cara un poco. Este programa se creó como una aplicación para obtener los códigos scan y Ascii de una manera más curiosa que con el programa TestmfII y no pretendemos con él, explicar ningún tipo de técnica especial.
Después de este detalle, os voy a pedir un pequeño favor, si no es mucha molestia, si no os importa, podríais, si queréis, por favor, sin problemas, sin compromiso y si os sobra tiempo rellenar el siguiente cuestionario y hacérnoslo llegar de alguna manera, aceptamos correo electrónico, correo terrestre, fichero de texto, telegrama, faxes, mensajero, paloma mensajera, tam tam, señales de humo, folios en forma de avioncito de papel, servilletas hechas pelotitas y lanzadas con fuerza, comunicación a voces como las vecinas del patio... etc, etc, etc....
1. ¿Qué te
parece la idea de crear un CPV?
2. ¿Qué opinas
sobre el entorno del CPV?
3. ¿Conoces
algún
curso de estas características, en español o
inglés?
4. EL contenido del temario
¿Te parece acertado?
5. ¿Qué tema
te gusta más de él ?
6. ¿Qué echas
en falta?
7. Según están
redactados los artículos ¿Te resulta fácil
entender
las explicaciones?
8. ¿Te
gustaría
que además de artículos de la lección se
incluyesen
otro tipo de secciones?
9. En caso afirmativo.
¿Cuáles
te gustarían?
10. Observaciones generales sobre
el CPV
11. ¿Qué
preguntarías
tú en este cuestionario para que la gente te haga más
caso?
Espero que se estrenen estas preguntas.
Ya hemos dicho varías veces lo 'pillaos' que andamos de tiempo, me imagino que la próxima lección saldrá para Marzo-Abril del 95, pero en gran medida el lanzamiento depende de las colaboraciones que recibamos. En la próxima lección tenemos previsto entre otras cosas ofrecer los siguientes artículos
-Efectos especiales.
-Ultima entrega sobre el
modo 13h.
-Formato gráfico
GIF.
-Sonido digital por el
speaker.
Un ejemplo de lo que seréis capaces de hacer en la próxima lección es el siguiente programa, tarda unos segundos en empezar, tened paciencia:
Pulsa F2 para ejecutar el programa EFECTO1. - Posibilidad
no
disponible en la versión HTML-
Quiero dar las GRACIAS a todas las personas que están colaborando con nosotros en el lanzamiento del CPV:
Gracias a Juán Antonio Ubeda Torres por permitirnos utilizar sus gráficos para el CPV.
Gracias a Cristobal Saraiba Bello por hacer de cartero para mi en Sakery BBS.
Gracias a Sara Martín Miedes por hacer las correcciones ortográficas a dos niños malos que dominan varios lenguajes pero todos de programación. :)
Gracias a David Blanco, Juan Carlos, Javier Aranda, Javier Ruiz, Miguel Angel Cortes y al resto de personas que me están ayudando a distribuir el CPV mano a mano.
Gracias a la gente de Sakery BBS por los mensajes que me están mandando.
Sakery Fox BBS 91- 413 98 55
Gracias en general a todos aquellos que han expresado su opinión sobre el CPV y nos la han hecho llegar.
Durante este período espero que estudiéis todo lo explicado hasta ahora, para comenzar con buen pie la nueva etapa del CPV, nos vemos en la próxima lección y mientras tanto no dejéis de comunicad y colaborad con nosotros.
Un saludo para todos de parte de:
JASM-BMP