2D Starfield Pincha aquí para verlo en español In the previous tutorial Painting pixels: Introduction to video memory we learned how to paint pixels on the screen, we will use it to generate a nice and simple star field effect. To do this, we will set the mode 0 and change the palette to use the colors black, yellow, pastel yellow and bright yellow. We will use the black for the background, and three shades of yellow to distinguish more or less distant stars and moving with varying speed. As we saw in previous tutorials, to switch to mode 0, we have to do from assembler, using the firmware command SCR SET MODE (BC0E), to change the palette we have to use the command SCR SET INK (BC32) and to put the border to black color, we have to use the command SET BORDER SCR (BC38), as follows : //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; For the stars we will use a c structure with the position and type of star. In the main loop will go one to one star, erasing the previous pixel position, updating the position and repainting the star. Here is the complete source code for sdcc (at the end of tutorial you can download in a 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); } } } //////////////////////////////////////////////////////////////////////// Compile and generate dsk with the following commands (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 Run in the emulator and get something like this (in the emulator works best): Is limited to 40 stars simultaneously, because if we put more stars, the program starts to run slow and we would have to optimize the code and implement parts in assembly ... perhaps in a future tutorial. You could download a zip with all files (source code, bat to compile, binary and dsk's) here: 2D_Starfield.zip |
www.CPCMania.com 2012 |