cpcrslib v.2 English
Texto
OBSOLETO, ver versión en inglés
Librería de
funciones para Amstrad CPC para el compilador z88dk.
Download last version (16/02/2009): cpcrslib
La librería cpcrslib contiene rutinas y funciones que permiten el
manejo de sprites y mapeado de tiles en el Amstrad CPC, programando en C y usando el compilador z88dk.
A parte de estas funciones, incorpora rutinas de teclado para redefinir y
detectar teclas, así como rutinas gráficas generales para cambiar el modo o los
colores.
Novedades.
16/02/2009
cpc_PutTrSpriteTileMap2b:
Rutina nueva similar a cpc_PutTrSpTileMap2b pero sin hacer el cálculo interno
de la posición en el superbuffer. Por eso requiere utilizar
cpc_SpUpdX y
cpc_SpUpdY para
actualizar la posición del sprite. O hacerlo del modo
habitual pero ejecutando luego cpc_SuperbufferAddress() después de actualizar la posición.
cpc_UpdateTileMap: Se ha
actualizado para incluir las rutinas cpc_PutTrSpTileMap2 y
cpc_PutTrSpriteTileMap2.
11/02/2009
cpc_ScrollLeft0,
cpc_ScrollLeft, cpc_ScrollRight0, cpc_ScrollRight:
Rutinas nuevas (beta) para hacer scroll horizontal
por software en el mapa de tiles.
09/02/2009
cpc_PutTrSpTileMap2b:
Dibuja un sprite en el mapa de tiles teniendo en cuenta que uno de los colores
es transparente. El color transparente se define en tiempo de compilación como
mascara1 y mascara2
16/01/2009
cpc_TestKey
:
Optimización de código, más pequeño y rápido.
cpc_RedefineKey: Optimización
de código, más pequeño y rápido.
cpc_AnyKeyPressed: Reescrita
de nuevo, más corta y más rápida…. Creo que la anterior no funcionaba bien.
cpc_SetBorder: Cambiada
la forma de llamar a esta función, ahora más corta y rápida.
cpc_InitTileMap: Cambiada
la forma de llamar a esta función, ahora más corta y rápida.
21/05/2008
Se
incorpora una nueva rutina descompresora: Exomizer.
El código Z80 es de Metalbrain, el algoritmo de
Magnus Lind. Los ficheros comprimidos con exomizer son más pequeños que los comprimidos con pucruch.
12/03/2008
Modificaciones
menores en rutinas de dibujado de sprites en mapa de
tiles: Se actualiza la posición del superbuffer
automáticamente.
28/02/2008
Añadida
una función que realiza todas las fases del dibujado de los sprites
en el mapa de tiles.: cpc_UpdateTileMap(ListaSprites) Se modifica el
ejemplo Small Sprite demo con esta nueva función.
21/02/2008
Modificado
el código de resetear los tiles tocados. Ahora basta
con definir el tamaño de la tabla en el fichero TileMapConf.asm
16/02/2008
Nuevas
funciones:
cpc_SetInkGphStr(char color, char
valor) Establece el color de las
letras en modo 0, sustituye a cpc_SetColorGphStr.
cpc_SetInkGphStrM1(char color, char valor) Establece
el color de las letras en modo 1.
cpc_PutMaskSpriteTileMap2b( sprite) Antes era cpc_PutSpTileMap2b,
cambio de nombre
cpc_PutSpTileMap2b( sprite) Dibuja un sprite sin máscara en el mapa de tiles
13/02/2008
Nuevas
funciones
cpc_PutTile4x16(int *tile, char
*x, char *y) Para
dibujar tiles directamente en pantalla de dimesiones
4x16 bytes
cpc_AnyKeyPressed() Devuelve 1
ó 0 según si se ha pulsado alguna tecla
cpc_SetColorGphStr(char color, char
valor) Establece el color de las
letras en modo 0.
Y se corrigen
las funciones de escritura en modo 0. Tenían un fallo que hacía que uno de los
4 pixels del ancho de cada letra no se escribiera.
Características.
Rutinas
y funciones incorporadas
Funciones para el dibujo de sprites.
En los
ejemplos se usarán estos datos para definir los sprites:
extern char sprite[];
extern char sprite_sd[];
extern char sprite_mask0[];
extern char sprite_mask[];
#asm
._sprite
defb
2,2
._sprite_sd
defb
$ff,$ff
defb
$ff, $ff
._sprite_mask0
defb
2,2
._sprite_mask
defb
&ff,0,&ff,0
defb
&ff,0,&ff,0
#endasm
cpc_PutSp(int *sprite, char *alto, char *ancho,
int *posicion);
Parámetros:
•datos
del sprite
•alto
del sprite
•ancho
del sprite
•destino
del sprite
Imprime el sprite en la posición especificada. Las dimensiones del sprite se indican en los parámetros, no en los datos del sprite.
Ejemplo:
cpc_PutSp(sprite_sd,2,2,0xc000);
cpc_PutSpXOR(int *sprite,
char *alto, char *ancho, int *posicion);
Parámetros:
•datos
del sprite
•alto
del sprite
•ancho
del sprite
•destino
del sprite
Imprime el sprite en la posición especificada usando la función XOR
con el byte de la pantalla.
Ejemplo:
cpc_PutSp(sprite_sd,2,2,0xc000);
cpc_PutMaskSp(int *sprite, char *alto, char *ancho, int *posicion);
Parámetros:
•datos
del sprite
•alto
del sprite
•ancho
del sprite
•destino
del sprite
Imprime un sprite con máscara. El primer byte es el de máscara, el
segundo lleva los datos del sprite.
Ejemplo:
cpc_PutMaskSp (sprite_mask,2,2,0xc000);
cpc_PutSpTr(int *sprite, char *alto, char *ancho,
int *posicion);
Parámetros:
•datos
del sprite
•alto
del sprite
•ancho
del sprite
•destino
del sprite
En modo 0,
imprime el sprite teniendo en cuenta que el color 0
es transparente y por lo tanto se ve el fondo.
Ejemplo:
cpc_PutSpTr(sprite_mask,2,2,0xc000);
cpc_PutMaskSprite(int *sprite, int *posicion);
Parámetros:
•datos
del sprite
•destino
del sprite
Imprime un sprite con máscara. El primer byte es el de máscara, el
segundo lleva los datos del sprite.
Ejemplo:
cpc_PutMaskSprite
(sprite_mask0, 0xc000);
cpc_PutSprite(int *sprite, int *posicion);
Parámetros:
•datos
del sprite
•destino
del sprite
Imprime un sprite
Ejemplo:
cpc_PutSprite (sprite,0xc000);
cpc_PutSpriteXOR(int *sprite, int *posicion);
Parámetros:
•datos
del sprite
•destino
del sprite
Imprime el sprite en la posición especificada usando la función XOR
con el byte de la pantalla.
La diferencia
entre este último y el anterior es que el sprite
tiene los dos primeros bytes indicando las dimensiones del sprite
(ancho alto). No se requiere, por eso, pasar esos parámetros.
Ejemplo:
cpc_PutSp(sprite,0xc000);
Otras rutinas
para sprites:
(Se pueden
ver en ejemplo_rot_sprites_modo1.c)
cpc_SpRRM1(sprite);
//rota a la derecha un sprite en modo 1
cpc_SpRLM1(sprite); //rota
a la derecha un sprite en modo 1
cpc_CollSp(struct sprite00, struct sprite01); //mira si hay colisión entre los dos sprites. En caso de colisión devuelve 1.
cpc_PutMaskSp2x8(int *sprite2x8_sd, int *posicion);
cpc_PutMaskSp4x16(int *sprite4x16_sd, int *posicion);
Imprimen el sprite en la posición indicada. La posición es una dirección
de memoria. Son rutinas para unas dimensiones específicas, que dibujan más
rápido.
Funciones sobre tiles
Los tiles son
elementos fijos en la pantalla, generalmente, para definir el mapeado. Las
rutinas que se usan son específicas para unas determinadas dimensiones (no van
incluidas en los datos del tile). En cualquier otro caso, se pueden usar las
rutinas de los sprites para dibujar los tiles ya que,
en realidad, se definen como sprites.
cpc_PutTile2x8(int *tile, char *x, char *y);
cpc_PutTile4x16(int *tile, char *x, char *y);
Imprimen el sprite de las dimensiones definidas en la posición
indicada. La posición se indica como coordenadas.
Ejemplo
general de sprites (ejemplo_sp_mask.c
en el paquete de la librería)
#include
"C:\z88dk\include\cpcrslib.h"
extern unsigned char sp_8x8[];
extern unsigned char sp_16x16[];
extern unsigned char tile_8x8[];
extern unsigned char buffer[];
#asm
._sp_8x8
defb $88,$70,$11,$E0 //MASCARA,SPRITE,MASCARA,SPRITE...
La máscara se dibuja con tinta 3 en modo 1.
defb
$11,$E0,$88,$70
defb
$00,$96,$00,$96
defb
$00,$F0,$00,$F0
defb
$00,$F7,$00,$FE
defb
$00,$C7,$00,$3E
defb
$00,$F3,$00,$FC
defb
$88,$70,$11,$E0
._sp_16x16
defb $88,$70,$11,$E0,$88,$70,$11,$E0 //MASCARA,SPRITE,MASCARA,SPRITE...
defb $11,$E0,$88,$70,$11,$E0,$88,$70
defb
$00,$96,$00,$96,$00,$96,$00,$96
defb
$00,$F0,$00,$F0,$00,$F0,$00,$F0
defb
$00,$F7,$00,$FE,$00,$F7,$00,$FE
defb
$00,$C7,$00,$3E,$00,$C7,$00,$3E
defb
$00,$F3,$00,$FC,$00,$F3,$00,$FC
defb
$88,$70,$11,$E0,$88,$70,$11,$E0
defb
$88,$70,$11,$E0,$88,$70,$11,$E0
defb
$11,$E0,$88,$70,$11,$E0,$88,$70
defb
$00,$96,$00,$96,$00,$96,$00,$96
defb
$00,$F0,$00,$F0,$00,$F0,$00,$F0
defb
$00,$F7,$00,$FE,$00,$F7,$00,$FE
defb
$00,$C7,$00,$3E,$00,$C7,$00,$3E
defb
$00,$F3,$00,$FC,$00,$F3,$00,$FC
defb
$88,$70,$11,$E0,$88,$70,$11,$E0
._tile_8x8
defb $07,$0E //Sin máscara
defb
$2D,$C3
defb
$0F,$2D
defb
$0F,$2D
defb
$0F,$0F
defb
$0F,$2D
defb
$0F,$0F
defb $07,$0E
._buffer
defs 64
#endasm
main(){
cpc_SetMode(1); //rutina hardware. Requiere cambiar el salto de las interrupciones
cpc_SetModo(1); //rutina firmware para cambiar el modo.
cpc_SetColour(17,11); //Ídem de lo mismo. Requiere cambiar el salto de las interrupciones
cpc_SetInk(17,11); //rutina firmware para cambiar los colores.
// Dibujar un sprite de 2x8 bytes en las coordenadas 10,90 de la pantalla
cpc_PutTile2x8(tile_8x8,10,90);
// Dibujar un sprite con máscara de dimensiones 2x8 bytes en la posición de pantalla indicada (&C00B)
cpc_PutMaskSp2x8(sp_8x8,0xc00b);
// Lo mismo pero con un sprite de 4x16 bytes
// cpc_PutMaskSp4x16(sprite
data,screen adress);
cpc_PutMaskSp4x16(sp_16x16,0xc190);
// Dibuja un sprite
en modo 0 teniendo en cuenta que el color 0 es transparente. Se especifican las
// dimensiones altoxancho.
//cpc_PutSpTr(sprite data,height,widh,screen adress);
cpc_PutSpTr(tile_8x8,8,2,0xc19b);
// imprime un sprite de las dimensiones indicadas en la pantalla
cpc_PutSp(tile_8x8,8,2,0xc19b);
// Captura de la pantalla el area indicada y la guarda en memoria.
cpc_GetSp(buffer,8,8,0xc054);
// En este ejemplo, imprime en &C190 el area capturada .
cpc_PutSp(buffer,8,8,0xc190);
while (1){} //Repeat until the end of the world
}
Hay dos
rutinas, una para detectar la pulsación de una tecla y otra para redefinir una
tecla. Se pueden tener un total de 12 teclas en uso.
There are two routines about keyboard. There can be 12
different keys in use.
cpc_RedefineKey(key number); //
Espera la pulsación de una tecla y la asigna a la tecla indicada por key number.
cpc_TestKey(Key number); // Comprueba si la tecla
indicada en key number se ha
pulsado (devuelve 1 si se detecta)
cpc_AnyKeyPressed(); //Devuelve 1 si se ha pulsado alguna
tecla y 0 si no se ha pulsado ninguna.
cpc_AssignKey(Key number, value) //asigna
una tecla al número de tecla indicado.
Ejemplo. cpc_AssignKey(0,0x4002)
asigna a la tecla 0 el cursor derecho. El valor se deduce de la tabla siguiente:
Tabla
de teclas (fuente: cpcwiki)
|
Byte: |
&80 |
&40 |
&20 |
&10 |
&08 |
&04 |
&02 |
&01 |
|
&40 |
F
Dot |
ENTER
|
F3
|
F6
|
F9
|
CURDOWN
|
CURRIGHT
|
CURUP
|
|
&41 |
F0
|
F2
|
F1
|
F5
|
F8
|
F7
|
COPY
|
CURLEFT
|
|
&42 |
CONTROL
|
\
|
SHIFT
|
F4
|
]
|
RETURN
|
[
|
CLR
|
|
&43 |
.
|
/
|
:
|
;
|
P
|
@
|
-
|
^
|
|
&44 |
,
|
M
|
K
|
L
|
I
|
O
|
9
|
0
|
|
&45 |
SPACE
|
N
|
J
|
H
|
Y
|
U
|
7
|
8
|
|
&46 |
V
|
B
|
F
|
G
|
T
|
R
|
5
|
6
|
|
&47 |
X
|
C
|
D
|
S
|
W
|
E
|
3
|
4
|
|
&48 |
Z
|
CAPSLOCK
|
A
|
TAB
|
Q
|
ESC
|
2
|
1
|
|
&49 |
DEL
|
-
|
-
|
-
|
-
|
-
|
-
|
-
|
Ejemplo
general de uso del teclado (prueba_teclado.c en el
paquete de la librería)
#include <stdio.h>
#include "cpcrslib.h"
extern unsigned char text[]
extern unsigned char text2[]
extern unsigned char ok[]
extern unsigned char no[]
#asm
._text
DEFM
"Pulsa la tecla a redefinir."
defb 0 //fin de la cadena
._text2
DEFM
"Pulsa la tecla para comprobar que fun- ciona."
defb 0 //fin de la cadena
._ok
DEFM
"OK"
defb 0
._no
DEFM
"no"
defb 0
#endasm
main(){
cpc_SetModo(1); //Set mode
using firmware
cpc_PrintStr(text); //Show text
using firmware
cpc_Redefine_Key(0); //redefine
key. There are 12 available keys (0..1)
cpc_PrintStr(text2);
while (1) {
if (cpc_TestKey(0)==1) { //test if the key has been pressed.
cpc_PrintStr(ok);
}
}
}
cpc_Uncrunch(origen_datos,destino_datos);
Se utiliza el
pucrunch para descomprimir un archivo comprimido:
cpc_UnExo(origen_datos,destino_datos);
Se utiliza el
UnExo para descomprimir un archivo comprimido:
Nota. En el
fichero se incluyen los ejecutables para comprimir desde una ventada DOS de
Windows. La sintaxis habitual es:
pucruch -d -c0 filein fileout
exo filein fileout
El fichero
generado (fileout) es el que se debe incorporar en el
programa para que la librería lo descomprima.
Ejemplo:
#include "cpcrslib.h"
extern unsigned char binary_data[];
#asm
._binary_data
BINARY
"sample.exp"
#endasm
main(){
cpc_SetModo(1);
// UnExo disables interrupts while processing file.
cpc_UnExo(binary_data,0xc000);
while (1) {}
}
Permiten
escribir en modo 0 o modo 1 un texto en mayúsculas en formato gráfico:
En modo 0:
cpc_PrintGphStr("HOLA;CARACOLA<",0xc190); //indicando
directamente la posición gráfica donde escribir
cpc_PrintGphStrXY("ADIOS;CARACOLA<",20,100); //indicando
la posición
//gráfica
donde escribir mediante coordenadas gráficas
cpc_SetInkGphStr(char color, char valor); //
Establece el color de las letras escritas en modo 0. Cada letra está definida
por 4 colores (0..3) y los valores que
puede tomar para un resultado agradable
son:
|
0 |
2 |
8 |
10 |
32 |
34 |
40 |
42 |
128 |
130 |
136 |
138 |
160 |
162 |
168 |
170 |
En modo 1:
cpc_PrintGphStrM1("HOLA;CARACOLA<",0xc190);
cpc_PrintGphStrXYM1("ADIOS;CARACOLA<",20,100);
cpc_SetInkGphStrM1(char color, char valor); // Establece el color de las letras
escritas en modo 0. Cada letra está definida por 4 colores (0..3).
Los valores válidos para resultados agradables son: 0, 8, 128,
136
Los
caracteres son de 4x8 pixeles. Se pueden cambiar en el archivo cpc_Chars.asm de
la librería. Cada byte define una línea,
dentro de cada byte, cada grupo de 2 bits define un píxel de un color (hay 4
colores como máximo en una letra).
Cambio de
modo:
cpc_SetMode(modo) //Accediendo
directamente al hardware. Requiere haber quitado el salto
//de
las interrupciones que trae el CPC por defecto.
cpc_SetModo(modo) //Usando
el firmware.
Cambio de
colores:
cpc_SetColour(numero
tinta, color) //Accediendo directamente al hardware.
Requiere haber quitado el salto
//de
las interrupciones que trae el CPC por defecto.
cpc_SetBorder(color) //Usando el firmware:
cpc_SetInk(numero_tinta, color)
cpc_GetScrAddress(x,y) //devuelve
la posición de memoria correspondiente a las coordenadas x,y
introducidas. Por ejemplo, para (x,y)=(0,0)
devuelve &C000
En cualquier
caso, todas las rutinas de la librería están utilizadas en los ejemplos
adjuntos y es el mejor método para entenderlas y aprender a usarlas.
Estas
rutinas se encuentran el la librería cpcwyzlib. Aún
no existe un programa compositor de música ni de efectos para el placer
pero sí que hay un ejemplo de música y
efectos de sonido en el paquete cpcrslib. No olvidar
compilar con –lcpcwyzlib.
Establecer
los datos que se utilizarán:
cpc_WyzInitPlayer(TABLA_SONIDOS,TABLA_PAUTAS,TABLA_EFECTOS,
TABLA_SONG);
cpc_WyzLoadSong(0); //selecciona
la canción
cpc_WyzSetPlayerOff(); //para
la música y el sonido
cpc_WyzSetPlayerOn(); //comienza
la música y los efectos
cpc_WyzStartEffect(0); //reproduce un efecto
Resumen de
rutinas y funciones:
cpc_UpdScr()
cpc_UpdScrAddresses()
cpc_ShowTileMap(z)
cpc_SetTile(x,y,tile)
cpc_SetTouchTile(x,y,tile)
cpc_ReadTile(x,y)
cpc_TouchTileXY(x,y)
cpc_ShowTouchedTiles()
cpc_PutSpTileMap(sprite)
cpc_PutTrSpTileMap2b(sprite)
cpc_PutTrSpriteTileMap2b(sprite)
cpc_PutMaskSpTileMap2b(sprite)
cpc_PutMaskSpriteTileMap2b(sprite)
cpc_PutORSpTileMap2b(sprite)
cpc_SuperbufferAddress(x,y)
cpc_ResetTouchedTiles()
cpc_ScrollRight0();
cpc_ScrollLeft0();
cpc_ScrollRight();
cpc_ScrollLeft();
Uso de las rutinas de mapeado de
tiles.
Un poco de teoría para intentar
aclarar conceptos.
Estas rutinas
permiten dibujar y move sprites
sobre la pantalla manteniendo el fondo y sin parpadeos. Los sprites pueden
ser del tamaño que se quiera y el número de ellos que se desee, pero hay que
tener en cuenta que las capacidades del CPC son limitadas y contra más sprites, más tiempo llevará al procesador dibujarlos y más
lento se moveá.
Los tiles son
de 2x8 bytes (ancho x alto). Se puede definir un área máxima de 40x20 tiles,
dependiendo del modo serán de 320x160 pixels en modo
1 y 160x160 pixels en modo 0.
Se crea una
copia del área de tiles que llamaremos superbuffer. El superbuffer está tileado. A la
pantalla visible se traspasan los tiles del superbuffer.
El superbuffer, en memoria utilizada sería 40x2x160 bytes=12800
bytes (&3200) como máximo. Por defecto, el inicio del superbuffer
se sitúa en &100 y llegaría como máximo hasta &3300
(&3200+&100). Es importante tener esto en cuenta para poner el inicio
del código del programa por encima del superbuffer,
si no, al usarlo, se machacará dando resultados inesperados en la ejecución.
Pasos para
dibujar el mapa en pantalla:
{
1, 1, 1, 1,
1, 1, 1, 1, 1, 1
0, 0,
0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0,
0, 0, 0, 0, 0, 0, 0
2, 2, 2, 2, 2, 2, 2, 2, 2, 2 }
Para
representar un sprite se realizan los siguientes
pasos:
Vamos a
utilizar dos tipos de coordenadas, las gráficas y las del mapa de tiles. Las
coordenadas gráficas indican incrementos de byte en byte y son las que se
utilizan para dibujar los sprites y serán las que se
denominen x,y. Las
coordenadas del mapa de tiles son referidas a tiles y se denominarán tx, ty. En principio, todas las
coordenadas serán tx, ty
excepto las que van dentro de los datos del sprite.
Por ejemplo,
dentro del mapa definido antes, la coordenada x=10, y =10 correspondería a un
punto dentro del tile marcado en rojo y la coordenada tx=2,
ty=3 sería el tile marcado en azul.
Un poco de práctica para afianzar los
conceptos no aclarados en la teoría:
El
funcionamiento, para definir la pantalla con tiles es:
1º
Se define la pantalla: se indican que tiles la componen usando
cpc_SetTile(tx,ty,tile);
El mapa del
ejemplo se podría rellenar de la siguiente manera:
void draw_tilemap(void) {
unsigned char x,y;
y=0;
for(x=0; x<10;x++) {
cpc_SetTile(x,y,1);
}
for(y=1;y<4;y++) {
for (x=0; x<10;x++) {
cpc_SetTile(x,y,0);
}
}
y=4;
for (x=0; x<10;x++) {
cpc_SetTile(x,y,2);
}
}
2º. Se
muestra la pantalla:
cpc_ShowTileMap(0);
El parámetro
indica los bytes de ancho que se quieren traspasar. Poniendo 0 se hace el
traspaso del ancho completo de la pantalla de tiles.
Con la
pantalla definida lo que hemos conseguido es tener un buffer con toda la
información que es donde se dibujan los sprites antes
de pasarlos a la pantalla. Los sprites tienen que
usar la estructura:
struct sprites{
int sp0; //2
bytes Sprite actual (con dimensiones)
int sp1; //2 bytes
Sprite anterior (con dimensiones)
int
coord0; //2 bytes posición en superbuffer
int
coord1; //2 bytes posición
anterior en superbuffer
unsigned
char cx, cy; //2 bytes coordenadas nuevas x,y
unsigned
char ox, oy; //2 bytes coordenadas actuales x,y
unsigned
char move; // si
NO es 0, el sprite se mueve. Todavía no implementado.
}
Si
se quieren añadir campos, se añadirían al final.
Para
iniciar un sprite hay que indicar, inicialmente los
campos
• sp0 (que es el sprite
a dibujar)
• sp1 (que es el sprite
anterior, pero se inicia con el anterior la primera vez)
• ox
(coordenada anterior x)
• oy
(coordenada anterior y)
• cx
(coordenada x)
• cy
(coordenada y)
Con estos
datos en los sprites, ya se pueden dibujar y move por el fondo sin que se estropee el mismo.
En un ciclo
de movimiento, lo primero que hay que hacer es resetear
la tabla de tiles tocados (los últimos que se han trasladado a la pantalla
visible):
cpc_ResetTouchedTiles();
Poner y
dibujar sprites consta de 4 pasos:
cpc_PutSpTileMap(sprite00);
cpc_PutSpTileMap(sprite01);
...
Esto
hace que se lean los tiles de la posición anterior del sprite
y los actuales y los meta en la tabla de tiles
tocados.
Si
en algún momento, nos interesa cambiar algún tile del fondo (por ejemplo, para
modificar una puerta abierta por una cerrada), se tiene que actualizar el
buffer en el buffer y pasarlo a la pantalla:
cpc_SetTile(tx,ty,tile);
cpc_TouchTileXY(tx,ty);
//mete el tile en la tabla de tiles tocados para restaurarlos
Para
los casos en los que se tengan que hacer estas dos funciones seguidas existe la
función
cpc_SetTouchTileXY(tx,ty,tile) que las realiza.
2. Se restaura el superbuffer
(limpia los sprites movidos para dibujar las nuevas
posiciones)
cpc_UpdScr();
3. Se dibujan los sprites
en el buffer en las coordenadas correspondientes (fase 2)
cpc_PutMaskSpTileMap2b(sprite00);
cpc_PutORSpTileMap2b(sprite01);
...
4. Ahora, después de este paso, el
buffer tiene los sprites limpios, sólo resta enviar a
la pantalla los tiles pertinentes que limpien la posición anterior y dibujen
los sprites en su sitio:
cpc_ShowTouchedTiles();
Y esto
es casi todo, hay algunas opciones
distintas para dibujar un sprite en el buffer
(fase2):
cpc_PutMaskSpTileMap2b(sprite00): Mete un sprite
con máscara
cpc_PutORSpTileMap2b(sprite00): Mete un sprite
sin máscara pero haciendo la operación OR.
cpc_PutSpTileMap2b(sprite00):
Mete un sprite sin máscara
cpc_PutTrSpTileMap2b(): dibuja un sprite
en el buffer teniendo en cuenta uno de los colores como transparente. El color
transparente se define en tiempo de compilación através
de los mascara1 y mascara2. Ver TileMapConf.asm
cpc_ReadTile(tx,ty) devuelve el número de tile
correspondiente a las coordenadas x,y del mapa de
tiles.
cpc_SuperbufferAddress(x,y) Establece el valor sprite.coord0
correspondiente a la posición dentro del superbuffer
determinada por las coordenadas del sprite sprite.cx,
sprite.cy
Hay otra
posibilidad a la hora de hacer la fase 2 con los sprites :
cpc_SpUpdX(struct sprite,
value) // mueve el sprite
a la izquierda (<0) o a la derecha (>0). El salto es el indicado en value.
cpc_SpUpdY(struct sprite,
value) // mueve el sprite
arriba (<0) o abajo (>0). El salto es el indicado en value.
cpc_PutMaskSpriteTileMap2b(struct sprite) //
Mete el sprite en el mapa de tiles (Superbuffer), es más rápida que la rutina cpc_PutMaskSpTileMap2b
pero requiere mover el sprite con las
funciones cpc_SpUpdX or cpc_SpUpdX. Hay un ejemplo en el archivo small_sprite_demo.c.
cpc_PutTrSpriteTileMap2b(struct sprite) // Mete el sprite en el mapa de
tiles (Superbuffer), es más rápida que la rutina cpc_PutTrSpTileMap2b
pero requiere mover el sprite con las
funciones cpc_SpUpdX or cpc_SpUpdX.
cpc_UpdateTileMap(listaSprites) //
engloba todas las funciones para dibujar los sprites
en la pantalla en una sola función. Serían los pasos 1,2,3 y 4 antes descritos,
sin incluir las funciones cpc_SetTile(tx,ty,tile), cpc_TouchTileXY(tx,ty) y cpc_SetTouchTileXY(tx,ty,tile) que se realizarían justo antes de cpc_UpdateTileMap() y después de cpc_ResetTouchedTiles()
La entrada
tiene que ser una lista de los sprites que se van a
representar. El último elemento de la lista será el valor 0xffff para marcar el
final.
int
spriteList[10];
spriteList[0]=sprite00;
...
sprite[n]=0xffff; //siempre cierro la lista con
0xffff para poder detectar que no hay más valores dentro.
Por otra parte, el control de si un sprite se dibuja
o restaura su fondo se hace con el valor move de la
estructura de sprites.
Para que se realice la primera fase el programa se fija en el bit 0 de move. Si es 0 no se realiza, si es 1, se realiza.
Para ver si el sprite se dibuja en el mapa de tiles,
se fija en los bits 1,2 y 3 de move. Si son 000 no se
dibuja el sprite. Los restantes valores hasta ahora
son:
001 -> cpc_PutMaskSpriteTileMap2b
010 -> cpc_PutMaskSpTileMap2b
011 -> cpc_PutORSpTileMap2b
100 -> cpc_PutSpTileMap2b
101 ->
cpc_PutTrSpTileMap2
110
-> cpc_PutTrSpriteTileMap2
Por ejemplo, quiero dibujar el sprite00 con la última función todo el rato, y
que siempre se restaure su fondo:
el valor move sería 00001001 en binario.... como no se cómo se pasa un número binario en z88dk, lo pongo en
decimal:
sprite00.move=9;
Si resulta que el sprite no se mueve de su sitio, me
basta con que se dibuje sin restaurar el fondo:
sprite00.move=8; //00001000
Si quiero restaurar el fondo pero que el sprite no se
dibuje (por ejemplo, para hacer desaparecer un sprite
que antes se dibujaba):
sprite00.move=1; //00000001
Y así sucesivamente.
Nota: El
ejemplo small sprite demo
se ha modificado para utilizar esta nueva función.
Rutinas de scroll
Se han incluído cuatro funciones nuevas para realizar scroll horizontal por software. No se consigue un scroll muy bueno pero algún uso se le podrá dar. Cada paso
de scroll corresponde a un tile (2bytes) y se realiza
en dos pasos:
1.
Se mueve el
mapa de tiles con cpc_ScrollLeft0()
or
cpcScrollRight0(). Después de este paso hay que actualizar la columna
derecha o izquierda del mapa de tiles para que refleje la nueva situación tras
el scroll.
2.
Se hace el
scroll del area visible con cpc_ScrollLeft() or cpcScrollRight(). Este paso mueve el area visible
hacia la derecha o izquierda y añada la nueva columna de tiles en su lugar
correspondiente.
Para
aclararlo se ha incluido un ejemplo en la scroll_transparent.
Para hacer el
scroll hay que definir la columna izquierda del área
visible en el archivo TileMapConf.asm
TileMapConf.asm
Este fichero
es básico para utilizar el mapeado de tiles ya que tiene los parámetros del
mapa y la definición del buffer y de las posiciones de memoria gráfica que se
utilizarán. A continuación se presenta la estructura básica del fichero, que tiene
que ser indicado en la compilación.
XLIB TileMapConf.asm
XDEF tiles
XDEF
pantalla_juego
XDEF
tiles_tocados
XDEF
posiciones_pantalla
XDEF
posiciones_super_buffer
XDEF posicion_inicial_area_visible
XDEF
posicion_inicial_superbuffer
XDEF
ancho_pantalla_bytes
XDEF
alto_pantalla_bytes
XDEF
ancho_pantalla_bytes_visible
; ***************************************************
;
Transparent colour for cpc_PutTrSpTileMap2b/
cpc_PutTrSpriteTileMap2b routine
XDEF mascara1
XDEF mascara2
; ***************************************************
;XDEF tile
; ***************************************************
; Scroll
Left Addresses column
; not requiered if scroll not used
XDEF ColumnScr
;
***************************************************
; ***************************************************
;
Transparent colour for cpc_PutTrSpTileMap2b routine
; For
printing sprites using transparent color (mode 0) transparent color selection
is requiered.
; Selección color transparente. Escribir las 2 máscaras que correspondan al color elegido.
;Example colour number 7:
defc mascara1 = $54
defc mascara2 = $a8
;0: $00, $00
;1: $80, $40
;2: $04, $08
;3: $44, $88
;4: $10, $20
;5: $50, $A0
;6: $14, $28
;7: $54, $A8
;8: $01, $02
;9: $41, $82
;10: $05, $0A
;11: $45, $8A
;12: $11, $22
;13: $51, $A2
;14: $15, $2A
;15: $55, $AA
; ***************************************************
;------------------------------------------------------------------------------------
; VALORES
QUE DEFINEN EL BUFFER Y
;------------------------------------------------------------------------------------
defc posicion_inicial_area_visible
= $c050 ;Indica la posición en pantalla del tile superior izquierdo.
defc posicion_inicial_superbuffer
= $100 ;Posición de inicio donde se guardan
los datos del buffer. El tamaño del
;buffer es 2x8xT_WIDTHxT_HEIGHT
;(El tamaño
del buffer es ancho_pantalla_bytes*alto_pantalla_bytes)
;------------------------------------------------------------------------------------
;------------------------------------------------------------------------------------
;DIMENSIONES DEL MAPA DE TILES
;------------------------------------------------------------------------------------
defc T_WIDTH = 32 ;max=40
tiles
defc T_HEIGHT = 16 ;max=20
tiles
;------------------------------------------------------------------------------------
;------------------------------------------------------------------------------------
;Parámetros que normalmente no se tocan
;------------------------------------------------------------------------------------
;------------------------------------------------------------------------------------
; El ancho
de pantalla influye determinantemente en numerosas
rutinas que hay que actualizar si se cambia.
defc ancho_pantalla_bytes =
2*T_WIDTH ;Cada tile es de 2 bytes de ancho.
defc alto_pantalla_bytes =
8*T_HEIGHT ;Cada tile es de 8 bytes de alto.
defc ancho_pantalla_bytes_visible
= 2*T_WIDTH ;dentro del area
definida, cuánto se debe mostrar.
.datos_mapeador
;------------------------------------------------------------------------------------
;Con la definición del mapeado hay que
tener en cuenta que las coordenadas son:
;ANCHO=64 bytes (128 pixels
en modo 0)
;ALTO=128 pixels
.posiciones_pantalla ;Posiciones en las que se dibujan los tiles
defw posicion_inicial_area_visible+$50*0
defw posicion_inicial_area_visible+$50*1
defw posicion_inicial_area_visible+$50*2
defw posicion_inicial_area_visible+$50*3
defw posicion_inicial_area_visible+$50*4
defw posicion_inicial_area_visible+$50*5
defw posicion_inicial_area_visible+$50*6
defw posicion_inicial_area_visible+$50*7
defw posicion_inicial_area_visible+$50*8
defw posicion_inicial_area_visible+$50*9
defw posicion_inicial_area_visible+$50*10
defw posicion_inicial_area_visible+$50*11
defw posicion_inicial_area_visible+$50*12
defw posicion_inicial_area_visible+$50*13
defw posicion_inicial_area_visible+$50*14
defw posicion_inicial_area_visible+$50*15
defw posicion_inicial_area_visible+$50*16
defw posicion_inicial_area_visible+$50*17
defw posicion_inicial_area_visible+$50*18
defw posicion_inicial_area_visible+$50*19
.posiciones_super_buffer ;muestra el inicio de cada línea
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*0
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*1
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*2
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*3
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*4
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*5
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*6
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*7
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*8
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*9
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*10
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*11
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*12
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*13
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*14
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*15
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*16
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*17
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*18
defw posicion_inicial_superbuffer+8*ancho_pantalla_bytes*19
.pantalla_actual defw 0
.pantalla_juego defs T_WIDTH*T_HEIGHT ;En tiles, es el mapa donde cada byte
dice el tile que tiene.
defb $FF ;Este byte es importante, marca el
fin de la pantalla.
.tiles_tocados defs 150 ;cuando un tile es tocado, se marca en esta
tabla para luego restaurarlo.
;Es
una tabla sin duplicados. Cada tile tocado se representa por 2 bytes. Se
pueden
;tocar
hasta 75 tiles.
;------------------------------------------------------------------------------------
;
***************************************************
; Scroll
Left Addresses column
; not requiered if scroll not used
comment it ;)
; one word for each scrollable line
.ColumnScr
defw $C0AA
defw $C8AA
defw $D0AA
defw $D8AA
defw $E0AA
defw $E8AA
defw $F0AA
defw $F8AA
…
; ***************************************************
;------------------------------------------------------------------------------------
;DEFINICIÓN DE LOS TILES. Se guardan a partir
de .tiles
;------------------------------------------------------------------------------------
.tiles ;Son de 2x8 bytes. Cada bloque de 16 bytes es un tile y en las
rutinas se hace la
;llamada
al mismo mediante su posición, desde 0 hasta el último.
;defb 2,8
;defb $70,$c0
;defb $f0,$68
;defb $f0,$84
;defb $f0,$e0
;defb $f0,$a4
;defb $e0,$c0
;defb $50,$60
;defb $00,$00
(c) Raúl
Simarro 2007-08 Contacto, dudas,
sugerencias, ...