Revistas en disco
 Fanzine Nº3 - Enero 1993
Anterior
Menú
Logotipo

Fanzine 3
ÉPOCA II. ENERO 1993

PROGRAMACIÓN BÁSICA EN ENSAMBLADOR
"S P R I T E S" (I)

© 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 obtener uno?. Hay básicamente, dos formas, a saber:

  1. Echando 100-150 pts en una máquina de refrescos y pulsando el botón que dice "Sprite".

  2. 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 coordenadas: 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 pixels horizontalmente y 256 verticalmente, pero el primer píxel 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, desde 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), Etcétera, Etcé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, cogemos una hoja 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
0000000000000001
2000000000000011
2000000000000011
2200000000000111
2200000000000111
2220000000001111
2220000000001111
2222000000011111
2222000000011111
2222200000111111
2222200000111111
2222220001111111
2222220001111111
2222222011111111
2222222011111111
2222222311111111
2222222311111111
2222223331111111
2222223331111111
2222233333111111
2222233333111111
2222333333311111
2222333333311111
2223333333331111
2223333333331111
2233333333333111
2233333333333111
2333333333333311
2333333333333311
3333333333333331
3333333333333331

Este Sprite es evidentemente, de 16 pixels de ancho por 32 de alto. Como veis, tenemos los 3 colores básicos, enumerados de 1 a 3, además del 0 que es el color transparente. Así pues, donde vaya el 0, significa que se verá el "fondo" (el playfield)

El siguiente problema con el que nos encontramos, es el de pasar esta información a binario, pues evidentemente, nuestro 68000 sólo distingue entre 0 y 1. Para ello, tomaremos cada línea de este sprite y lo pasamos a binario, utilizando dos palabras, la palabra alta y la baja. Es pues lógico, que por cada sprite necesitaremos el 2x(altura sprite) de palabras. En nuestro caso, 64.

Pasemos por ejemplo la primera línea a binario:

0000000000000001   Este caso es muy fácil:
0000000000000001 <-palabra baja
0000000000000000 <-palabra alta
----------------
0000000000000001

Veamos una línea algo más complicada. Tomemos la antepenúltima.

2333333333333311
0111111111111111 <-palabra baja
1111111111111100 <-palabra alta
----------------
2333333333333311

¿lógico, 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 programita:

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 vertical 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 inicial (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í como 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 observáis, 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 veis, 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 actualizáramos otra vez, sólo se mostraría en pantalla una sola 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 ocasió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 sola línea y transparente. Así:

move.l #$00000000,$25000

Para mover pues el sprite, bastaría cambiar su posición vertical y horizontal 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).

¡Esto es todo folks!

NOTA ENCANTA: La dirección postal ha sido omitida.


Envía esta página web a un amigo:
Esta opción está desactivada temporalmente, rogamos disculpen las molestias

Volver a la página anterior

Al menú principal