Campo de estrellas 2D En el tutorial anterior Pintando pixeles: Introducción a la memoria de video aprendimos como pintar pixeles independientes en la pantalla, vamos a usarlo para generar un sencillo y bonito efecto de campo de estrellas. Para hacerlo vamos primero a fijar el modo 0 y cambiar la paleta, para usar los colores negro, amarillo, amarillo pastel y amarillo brillante. Usaremos el negro para el fondo, y los tres tonos de amarillo para distinguir estrellas más o menos lejanas y que se mueven con mayor o menor velocidad. Como ya vimos en anteriores tutoriales, para cambiar al modo 0, lo hacemos desde ensamblador, usando el comando del firmware SCR SET MODE (BC0E), para la paleta lo haremos con el comando del firmware SCR SET INK (BC32) y para dejar el borde en negro también usaremos el comando SCR SET BORDER (BC38), de la siguiente forma: //SCR_SET_MODE 0 __asm ld a, #0 call #0xBC0E __endasm; //PALETE __asm ld a, #0 ld b, #0 ;black ld c, b call #0xBC32 ;SCR SET INK ld a, #1 ld b, #12 ;Yellow ld c, b call #0xBC32 ;SCR SET INK ld a, #2 ld b, #25 ;Pastel Yellow ld c, b call #0xBC32 ;SCR SET INK ld a, #3 ld b, #24 ;Bright Yellow ld c, b call #0xBC32 ;SCR SET INK __endasm; //SCR SET BORDER 0 __asm ld b, #0 ;black ld c, b call #0xBC38 __endasm; Para las estrellas usaremos una estructura con la posición y el tipo de estrella y el bucle principal básicamente lo que hará es recorrerse todas las estrellas, borrar el pixel de la posición anterior, actualizar la posición y volver a pintar la estrella. Mejor vemos directamente el código fuente completo, para sdcc (al final de tutorial se puede descargar un zip): //////////////////////////////////////////////////////////////////////// // starfield.c // 2D Star Field // Mochilote - www.cpcmania.com //////////////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> #include <string.h> void SetMode0PixelColor(unsigned char *pByteAddress, unsigned char nColor, unsigned char nPixel) { unsigned char nByte = *pByteAddress; if(nPixel == 0) { nByte &= 85; if(nColor & 1) nByte |= 128; if(nColor & 2) nByte |= 8; if(nColor & 4) nByte |= 32; if(nColor & 8) nByte |= 2; } else { nByte &= 170; if(nColor & 1) nByte |= 64; if(nColor & 2) nByte |= 4; if(nColor & 4) nByte |= 16; if(nColor & 8) nByte |= 1; } *pByteAddress = nByte; } void PutPixelMode0(unsigned char nX, unsigned char nY, unsigned char nColor) { unsigned char nPixel = 0; unsigned int nAddress = 0xC000 + ((nY / 8) * 80) + ((nY % 8) * 2048) + (nX / 2); nPixel = nX % 2; SetMode0PixelColor((unsigned char *)nAddress, nColor, nPixel); } struct _tStar { unsigned char nX; unsigned char nY; unsigned char nStarType; }; #define STARS_NUM 40 struct _tStar aStars[STARS_NUM]; void main() { unsigned char nStar = 0; memset(aStars, 0, sizeof(aStars)); //SCR_SET_MODE 0 __asm ld a, #0 call #0xBC0E __endasm; //PALETE __asm ld a, #0 ld b, #0 ;black ld c, b call #0xBC32 ;SCR SET INK ld a, #1 ld b, #12 ;Yellow ld c, b call #0xBC32 ;SCR SET INK ld a, #2 ld b, #25 ;Pastel Yellow ld c, b call #0xBC32 ;SCR SET INK ld a, #3 ld b, #24 ;Bright Yellow ld c, b call #0xBC32 ;SCR SET INK __endasm; //SCR SET BORDER 0 __asm ld b, #0 ;black ld c, b call #0xBC38 __endasm; //Init for(nStar = 0; nStar < STARS_NUM; nStar++) { aStars[nStar].nX = rand() % 160; aStars[nStar].nY = rand() % 200; aStars[nStar].nStarType = rand() % 3; } while(1) { for(nStar = 0; nStar < STARS_NUM; nStar++) { //delete star PutPixelMode0(aStars[nStar].nX, aStars[nStar].nY, 0); //move star switch(aStars[nStar].nStarType) { case 0: //slow star aStars[nStar].nX += 1; break; case 1: //medium star aStars[nStar].nX += 2; break; case 2: //fast star aStars[nStar].nX += 3; break; } if(aStars[nStar].nX >= 160) { aStars[nStar].nX = 0; aStars[nStar].nY = rand() % 200; aStars[nStar].nStarType = rand() % 3; continue; } //paint star PutPixelMode0(aStars[nStar].nX, aStars[nStar].nY, aStars[nStar].nStarType + 1); } } } //////////////////////////////////////////////////////////////////////// Compilamos y generamos dsk con los siguientes comandos (starfield.bat): sdcc -mz80 --code-loc 0x6038 --data-loc 0 --no-std-crt0 crt0_cpc.rel starfield.c hex2bin starfield.ihx CPCDiskXP -File starfield.bin -AddAmsdosHeader 6000 -AddToNewDsk starfield.dsk Ejecutamos en el emulador y obtenemos algo similar a esto (en el emulador no da tirones): Está limitado a 40 estrellas simultaneas, ya que si ponemos más empiezan los tirones y habría que optimizar el código e implementar partes en ensamblador... quizás en un futuro tutorial. Podéis bajar un zip con todos ficheros (código fuente, bat's para compilar, binarios y dsk's) aquí: Campo_de_estrellas_2D.zip |
www.CPCMania.com 2012 |