­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ P R O G R A M A C I O N B A S I C A E N E N S A M B L A D O R "S P R I T E S" (I) ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ (c) Warlord 28 diciembre 1992 Para más información sobre este tema, os recomiendo los libros: AMIGA HARDWARE REFERENCE MANUAL AMIGA SYSTEM PROGRAMERS GUIDE Como ya habréis supuesto, hoy hablaremos un poco de los Sprites. ÓCómo ob- tener uno?. Hay básicamente, dos formas, a saber: a) Echando 100-150 pts en una máquina de refrescos y pulsando el botón que dice "Sprite". b) Mediante el ordenador. En esta ocasión, solo trataremos la forma b). ÓQué es un sprite?. Pues es un objeto generado por el Denise y que se mueve independientemente del playfield (esto es, de la pantalla). Es decir, el playfield junto con los sprites, forman básicamente la "pantalla" del amiga.En un matamarcianos, los bichos son sprites y el fondo es el playfield Hay otros objetos, como por ejemplo los bobs (Blitter OBjectS) pero que no entraremos a discutirlos en esta ocasión. Los Sprites se generan por 8 canales DMA (Direct Memory Access), luego "teóricamente" sólo podemos tener hasta 8 sprites a la vez. Para generar un sprite necesitamos varias cosas: Posición en pantalla, su tamaño, su color y la propia imagen el sprite (ie, el dibujo en sí). POSICION: -------- Sabemos que la resolución de nuestra pantalla (PAL) es: Baja: 320x256 Entrelazado: 320x512 media:640x256 Alta: 640x512 Como siempre, la posición de un sprite en pantalla viene dada por dos coor- denadas: X, Y ... esto es, la posición horizontal y vertical, contando desde la esquina superior izqda (que por tanto sería el (0,0)). De todas formas, no toda la pantalla es utilizable. Hay un cierto rango de valores en los cuales no se visualiza el sprite. Esto corresponde al "borde" de la panalla. Así pues, si nuestra resolución es de 320x256, tenemos disponibles 320 pi- xels horizontalmente y 256 verticalmente, pero el primer pixel no sería el (0,0),sino una posición posterior ... (0,0) | V----------------------------------------------------------------------- | BORDE NO UTILIZABLE | | | | ---------------------------------------------------------------- | | | PANTALLA 320x256 | | Es decir, nuestros sprites se moverán horizontalmente entre los valores 64 a 383 (320 pixels:383-64+1). Verticalmente lo hace en el rango 44-299. Es decir, supongamos que tenemos un sprite que queremos mover en diagonal, des- de la posición (0,0) hasta la (320,256) de nuestra pantalla (no del borde). Tendríamos pues que sumarle en cada caso (64,44). Así el (1,1) sería el (65,45); el (2,2) sería (66,46), Et-cétera, Et-cétera (Íque dominio del latín!). Si se utilizan valores correspondientes al rango del borde, el sprite no aparecerá. Se convierte en un sprite invisible (ÍOooooh!). Si cambiamos la resolución, las coordenadas no se alteran. Es decir, si la pantalla es de 640x512, para el sprite serían la mitad pues maneja el mismo rango de coordenadas. Esto es porque los sprites son independientes de los modos de resolución de los playfields. El siempre actúa como si estuviera en baja resolución. ÓEstá claro, Ein? TAMAÑO: ------ 16 pixels de ancho, sin restricción de altura. Si se quiere más hay que "empalmar" uno al lado del otro... eso sí, teniendo cuidado de moverlos al unísono. (no sería muy fino que en un matamarcianos nos dejáramos los trozos de la nave por el camino) COLOR DEL SPRITE: ---------------- Podemos utilizar 3 colores para nuestros sprites+el color 0(o transparente) Si queremos más colores, también podemos combinar los sprites. FORMA DEL SPRITE: ---------------- Como antes dije, el sprite es 16 pixels de ancho. Así pues, cojemos una ho- ja de 16 cuadrículas de ancho y las que queramos de alto. Ponemos 0 donde no queramos que aparezca nada y 1, 2 ó 3, cuando queramos que aparezca un punto, del color 1, 2 o 3 (0 era el transparente). Un ejemplo es: 0000000000000001 Este Sprite es evidentemente, de 16 0000000000000001 pixels de ancho por 32 de alto. Como 2000000000000011 veis, tenemos los 3 colores básicos, 2000000000000011 enumerados de 1 a 3, además del 0 que 2200000000000111 es el color transparente. Así pues, 2200000000000111 donde vaya el 0, significa que se 2220000000001111 verá el "fondo" (el playfield) 2220000000001111 2222000000011111 El siguiente problema con el que nos 2222000000011111 encontramos, es el de pasar esta in- 2222200000111111 formación a binario, pues evidentemen 2222200000111111 te,nuestro 68000 sólo distingue entre 2222220001111111 0 y 1. Para ello, tomaremos cada lí- 2222220001111111 nea de este sprite y lo pasamos a 2222222011111111 binario, utilizando dos palabras, la 2222222011111111 palabra alta y la baja. Es pues lógi- 2222222311111111 co, que por cada sprite necesitaremos 2222222311111111 el 2x(altura sprite) de palabras. En 2222223331111111 nuestro caso, 64. 2222223331111111 2222233333111111 2222232333111111 2222333333311111 2222333333311111 2223333333331111 2223333333331111 2233333333333111 2233333333333111 2333333333333311 2333333333333311 3333333333333331 3333333333333331 Pasemos por ejemplo la primera linea a binario: 0000000000000001 Este caso es muy fácil: 0000000000000001 <-palabra baja 0000000000000000 <-palabra alta ---------------- 0000000000000001 Veamos una linea algo más complicada. Tomemos la antepenúltima 2333333333333311 0111111111111111 <-palabra baja 1111111111111100 <-palabra alta ---------------- 2333333333333311 Ólogico, no?. 0=00 ; 1=10; 2=01 ; 3=11 Es decir, a la hora de poner nuestro sprite, podíamos pasar todos estos números a hexadecimal, o dejarlo en binario. Tendríamos esto en nuestro pro- gramita: dc.w %0000000000000001,%0000000000000000 dc.w %0000000000000001,%0000000000000000 dc.w %0000000000000011,%1000000000000000 dc.w %0000000000000011,%1000000000000000 dc.w %0000000000000111,%1100000000000000 dc.w %0000000000000111,%1100000000000000 dc.w %0000000000001111,%1110000000000000 dc.w %0000000000001111,%1110000000000000 dc.w %0000000000011111,%1111000000000000 dc.w %0000000000011111,%1111000000000000 dc.w %0000000000111111,%1111100000000000 dc.w %0000000000111111,%1111100000000000 dc.w %0000000001111111,%1111110000000000 dc.w %0000000001111111,%1111110000000000 dc.w %0000000011111111,%1111111000000000 dc.w %0000000011111111,%1111111000000000 dc.w %0000000111111111,%1111111100000000 dc.w %0000000111111111,%1111111100000000 dc.w %0000001111111111,%1111111110000000 dc.w %0000001111111111,%1111111110000000 dc.w %0000011111111111,%1111111111000000 dc.w %0000011111111111,%1111111111000000 dc.w %0000111111111111,%1111111111100000 dc.w %0000111111111111,%1111111111100000 dc.w %0001111111111111,%1111111111110000 dc.w %0001111111111111,%1111111111110000 dc.w %0011111111111111,%1111111111111000 dc.w %0011111111111111,%1111111111111000 dc.w %0111111111111111,%1111111111111100 dc.w %0111111111111111,%1111111111111100 dc.w %1111111111111111,%1111111111111110 dc.w %1111111111111111,%1111111111111110 Los ceros y unos en las dos palabras de datos que definen cada línea del sprite forman un número binario. Este número binario apunta a uno de los cuatro registros de color asignados a ese canal DMA. Los 8 sprites usan los registros 16-31. Bien, ahora sólo necesitamos añadirle al sprite anterior, algunos datos,que le digan al Denise dónde debe colocar el sprite. Para ello utilizaremos dos palabras. En la primera diremos la posición horizontal y vertical inicial y en la segunda, la posición vertical final. Toda esta estructura esta alineada por palabras, es decir, que cada una de ellas han de estar en posiciones de memoria pares y se ha de situar en la zona de memoria Chip para poder ser accedido por los Custom Chips. Empecemos por la primera palabra. Como ya he dicho, guarda la posición ver- tical y horizontal de la posición inicial del sprite. De sus 16 bits, los que van del 7-0 guardan los 8 bits superiores de la posición horizontal ini- cial (HSTART), los bits 15-8 guardan los 8 bits inferiores de la posición vertical inicial (VSTART). La segunda palabra contiene la posición vertical de parada (VSTOP), así co- mo otros bits utilizados para conectar sprites. Esto es: Bits 15-8: Los 8 bits inferiores de VSTOP Bit 7: Usado para conectar sprites Bits 6-3: Sin usar (todos 0) Bit 2: Bit superior de VSTART Bit 1: Bit superior de VSTOP Bit 0: Bit inferior de HSTART En nuestro caso, como nuestro sprite es de 32 pixels de alto, VSTOP debe ser: VSTOP=VSTART+32-1 Si observais, guardamos las posiciones de comienzo y final en 8 bits, luego el máximo para comenzar o acabar sería sólo de 255. Esta es la razón por la que vemos que en la segunda palabra, se añaden 3 bits finales: 1 para VSTART otro para VSTOP y finalmente otro para HSTART. Gracias a estos bits, podemos llegar hasta un rango de 511 (9 bits todos en 1) Estas 2 palabras se colocan en el principio del bloque que define el sprite y al final se colocan otras 2 para decirnos que está acabado. Generalmente colocaremos 0,0. A la hora de colocar en pantalla hay que tener en cuenta que en el caso de que se solapen, se verá aquel que tenga más prioridad. El de mayor prioridad es el sprite0 y el de menor el 7 Ahora tendríamos por último que visualizar el Sprite. Hay que hacer lo siguiente: Como antes dijimos, podemos utilizar hasta 8 canales DMA. Lo primero será pues, decidir cual de ellos utilizamos. Supongamos que el sprite que hemos creado, queremos que lo maneje el canal 0. Cada uno de estos canales DMA usa dos punteros para conocer la dirección del sprite. Antes de visualizar el sprite necesitamos decirle donde está, cargando su dirección en estos punteros. Lo podemos hacer con el 68000, pero esto se hace con el copper, colocando los datos en la copperlist. Así, si el sprite se encuentra en $22000, se haría así: dc.w SPR0PTH,$0002 dc.w SPR0PTL,$2000 Como véis, los punteros se llaman SPRxPTH y SPRxPTL. (x es el número del canal DMA, de 0-7). El primero guarda los 3 bits superiores de la dirección y el segundo los 16 restantes. Con el 68000, sería algo así: MOVE.L #$22000,SPR0PTH+CUSTOM De todos modos, estos punteros varían mientras son leídos por el canal DMA. Es decir, van aumentando apuntando siempre a la siguiente palabra de su estructura de datos. Una vez que el DMA lo lee entero, si no los actuali- záramos otra vez, sólo se mostraría en pantalla una sóla vez, eso sí, en el comienzo de la línea de barrido (el llamado vertical blank)en la parte superior de la pantalla, pues si se reescribieran mientras el DMA visualiza el sprite, obtendríamos efectos indeseables. De esto también se encarga la copperlist (si no sabéis utilizar el copper, quizás lo explique en otra oca- sión). Otra cosa que hay que tener en cuenta es que los canales DMA de los sprites no se conectan individualmente, sino todos a la vez. Así pues, aquellos que no vayamos a usar, hay que también que cargar sus punteros hacia una dirección en la que haya un falso sprite. Esto es, si sólo utilizamos el canal 0, el resto podemos apuntarlo a la dirección, por ejemplo $25000. Y en esta dirección ponemos un sprite de una sóla línea y transparente. Así: move.l #$00000000,$25000 Para mover pues el sprite, bastaría cambiar su posición vertical y horizon- tal inicial, así como la vertical final en su estructura de datos. El propio custom chip se encarga de realizar el cambio de posición. Bueno, pues esto es todo por esta vez. Tengo que escribir más artículos (porque si no Raúl me mata). Para cualquier cuestión podéis escribirme al apdo 232, San Fernando 11100, Cádiz. ÍEsto es todo folks!