Sprites II: Sprite animation (C & ASM with SDCC) Pincha aquí para verlo en español In this tutorial we will see how simple it is to simulate the movement of a character by sprites. We will continue using the character Nick of Snow Bros. Let's make the character walk from right to left across the screen, so we need to get the graphics / sprites of all the steps of the animation. To make it simple I captured from the original arcade only 3 sprites to walk to the left and the same 3 sprites horizontally reversed to walk right. (Where necessary for memory problems, could be programmed a routine to draw the sprites horizontally reversed, so only need 3 sprites for left and right, but for now we will not do). The graphics are the following:
I decided to do everything together in a single graph instead of in 6 individual graphics can also be seen that there is a white pixel on each side, to avoid leaving a trail or garbage or having to delete, to move the sprite. Let's convert to Mode 0, palette of 16 colors to use in the cpc. To do this we again use ConvImgCPC as we saw in the tutorial Converting and displaying an image on the screen, I have configured as follows: As you can see I used the options "Keep original size", "Overscan" putting 168 (28 * 6) high and 12 wide (12 bytes in mode 0 = 24 pixels). We see that Nick has put on some weight due to the aspect ratio of the mode 0, but hey it does not worry us right now. To export we select options "asm mode"and "Linear" and clik on"Save Picture". Save the file in asm and easily convert it to C as we saw in the tutorial Converting and displaying an image on the screen, finally we have a file like this: /* ;Généré par ConvImgCpc Version 0.16 ; Mode 0 ; 12x168 ; Linear */ #define NICK_WIDTH 12 #define NICK_HEIGHT 28 #define NUM_COLORS 16 const unsigned char NickPalette[NUM_COLORS] = {26, 0, 13, 2, 1, 10, 11, 20, 15, 3, 14, 0, 0, 0, 0, 0}; const char NickSprite[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x84 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x48, 0xE8, 0x08, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x04, 0xC0, 0xC0, 0xD4, 0xFC , 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xC0 , 0x08, 0x0C, 0x5C, 0xF8, 0xE0, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x48, 0x08, 0x00, 0x00, 0x48, 0xF0 , 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00 , 0x00, 0x00, 0x04, 0xD0, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x04, 0x48 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x48, 0x80 , 0x00, 0x00, 0x00, 0x0C, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x0C , 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80 , 0x41, 0x02, 0x04, 0x0C, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x40, 0x08, 0x41, 0x83, 0x00, 0x0C, 0x48 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x04, 0xC1, 0x83 , 0x02, 0x0C, 0xCC, 0x98, 0x84, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x81, 0x02, 0x00, 0xC4, 0x3C, 0x00 , 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 , 0x48, 0x8D, 0x28, 0x00, 0x00, 0x84, 0x00, 0x00 , 0x00, 0x00, 0x84, 0x0C, 0x84, 0x1C, 0x2C, 0x00 , 0x00, 0x48, 0x08, 0x00, 0x00, 0x00, 0x48, 0x0C , 0x08, 0x14, 0x6C, 0x08, 0x00, 0x04, 0x80, 0x00 , 0x00, 0x00, 0x04, 0xC0, 0x00, 0x14, 0x3C, 0x24 , 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x00, 0x1C, 0x1E, 0x98, 0x0C, 0x04, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x48, 0x00, 0x9C, 0x1E, 0xCC , 0x24, 0x48, 0x08, 0x00, 0x00, 0x00, 0x00, 0x84 , 0x4C, 0x2D, 0x3C, 0xCC, 0x30, 0x84, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x80, 0xCC, 0x07, 0x6C, 0x98 , 0x60, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x84 , 0x49, 0x8D, 0x6C, 0x30, 0xC0, 0x30, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x48, 0xC4, 0x3C, 0xCC, 0x60 , 0x90, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 , 0xC4, 0x9C, 0x98, 0xC4, 0x98, 0x70, 0xE0, 0x00 , 0x00, 0x00, 0x00, 0x04, 0xC0, 0x98, 0x60, 0x48 , 0xC4, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x04, 0xC0 , 0xFC, 0xF8, 0xE0, 0xD0, 0xF0, 0xF0, 0x84, 0x00 , 0x00, 0x00, 0x40, 0xFC, 0xFC, 0xF0, 0xE0, 0xF0 , 0xF0, 0xE0, 0x08, 0x00, 0x00, 0x00, 0x04, 0xC0 , 0xC0, 0xC0, 0x84, 0xC0, 0xC0, 0x84, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x04, 0x84, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xE8 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 , 0xC0, 0xC0, 0xD4, 0xFC, 0x84, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x04, 0xC0, 0x08, 0x0C, 0x5C, 0xF8 , 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x08 , 0x00, 0x00, 0x48, 0xF0, 0x84, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x84, 0x00, 0x00, 0x00, 0x04, 0xD0 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00 , 0x00, 0x00, 0x04, 0x48, 0x08, 0x00, 0x00, 0x00 , 0x00, 0x40, 0x48, 0x80, 0x00, 0x00, 0x00, 0x0C , 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80 , 0x00, 0x00, 0x00, 0x0C, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x40, 0x40, 0x80, 0x41, 0x02, 0x04, 0x0C , 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x41 , 0x83, 0x00, 0x0C, 0x48, 0x08, 0x00, 0x00, 0x00 , 0x00, 0x04, 0xC1, 0x83, 0x02, 0x0C, 0x3C, 0x98 , 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x02 , 0x00, 0x94, 0x00, 0x4C, 0x60, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x80, 0x00, 0x48, 0x28, 0x00, 0x04 , 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x84, 0x0C , 0x84, 0x28, 0x00, 0x04, 0x30, 0x80, 0x00, 0x00 , 0x00, 0x00, 0x48, 0x0C, 0x08, 0x2C, 0x00, 0x00 , 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0xC0 , 0x00, 0x6C, 0x08, 0x00, 0x18, 0x80, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x40, 0x00, 0x9C, 0x8C, 0x00 , 0x18, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x00, 0x9C, 0x8C, 0x00, 0x18, 0x80, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x40, 0x1C, 0x2D, 0x6C, 0x0C , 0x90, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 , 0xCC, 0x16, 0x6C, 0x60, 0x30, 0x80, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x04, 0xC1, 0xCC, 0xCC, 0x30 , 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x48, 0xC4, 0x9C, 0x98, 0x84, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x9C, 0x6C , 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x48, 0xD4, 0xFC, 0xF8, 0xE0, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0xD4, 0xFC, 0xF8, 0xF0 , 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x48, 0xC0, 0xC0, 0xC0, 0x08, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x84 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x48, 0xE8, 0x08, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x04, 0xC0, 0xC0, 0xD4, 0xFC , 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xC0 , 0x08, 0x0C, 0x5C, 0xF8, 0xE0, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x48, 0x08, 0x00, 0x00, 0x48, 0xF0 , 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x00 , 0x00, 0x00, 0x04, 0xD0, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x04, 0x80, 0x00, 0x00, 0x00, 0x04, 0x48 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x48, 0x80 , 0x00, 0x00, 0x00, 0x0C, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x0C , 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x80 , 0x41, 0x02, 0x04, 0x0C, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x40, 0x08, 0x41, 0x83, 0x00, 0x0C, 0x48 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x04, 0xC1, 0x83 , 0x02, 0x0C, 0x3C, 0x98, 0x84, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x81, 0x02, 0x00, 0x94, 0x6C, 0x6C , 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00 , 0x48, 0x28, 0x08, 0xCC, 0x60, 0x08, 0x00, 0x00 , 0x00, 0x00, 0x84, 0x0C, 0x84, 0x00, 0x00, 0x4C , 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0C , 0x08, 0x00, 0x00, 0x4C, 0x30, 0x80, 0x00, 0x00 , 0x00, 0x00, 0x04, 0xC0, 0x00, 0x00, 0x00, 0x90 , 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x00, 0x00, 0x04, 0x90, 0x30, 0x80, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x90 , 0x30, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x1C, 0x00, 0x48, 0x30, 0x98, 0x80, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x40, 0xCC, 0x0C, 0x90, 0x64 , 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 , 0xC1, 0xCC, 0x9C, 0x6C, 0x98, 0x84, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x40, 0xCC, 0x30, 0xCC, 0x1E , 0xCC, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40 , 0xCC, 0x30, 0xC4, 0xCC, 0x30, 0xF0, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x40, 0x98, 0x30, 0xC0, 0x90 , 0xFC, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x48, 0xC0 , 0xFC, 0xE0, 0x48, 0xD4, 0xF8, 0xE0, 0x08, 0x00 , 0x00, 0x00, 0xD4, 0xFC, 0xF8, 0xE0, 0xD4, 0xFC , 0xE0, 0x84, 0x00, 0x00, 0x00, 0x00, 0x48, 0xC0 , 0xC0, 0x84, 0x48, 0xC0, 0x84, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 , 0xD4, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x48, 0xFC, 0xE8, 0xC0, 0xC0 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0 , 0xF4, 0xAC, 0x0C, 0x04, 0xC0, 0x08, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x48, 0xF0, 0x84, 0x00, 0x00 , 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 , 0xE0, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x04, 0x84, 0x08, 0x00, 0x00 , 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x0C, 0x00, 0x00, 0x00, 0x40, 0x84, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0x00 , 0x40, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x0C, 0x08, 0x01, 0x82, 0x40, 0x80, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x04, 0x84, 0x0C, 0x00, 0x43 , 0x82, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x48 , 0x64, 0xCC, 0x0C, 0x01, 0x43, 0xC2, 0x08, 0x00 , 0x00, 0x00, 0x04, 0x80, 0x00, 0x3C, 0xC8, 0x00 , 0x01, 0x42, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00 , 0x00, 0x14, 0x4E, 0x84, 0x00, 0x40, 0x00, 0x00 , 0x00, 0x04, 0x84, 0x00, 0x00, 0x1C, 0x2C, 0x48 , 0x0C, 0x48, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00 , 0x04, 0x9C, 0x28, 0x04, 0x0C, 0x84, 0x00, 0x00 , 0x00, 0x40, 0x08, 0x00, 0x18, 0x3C, 0x28, 0x00 , 0xC0, 0x08, 0x00, 0x00, 0x00, 0x40, 0x08, 0x0C , 0x64, 0x2D, 0x2C, 0x00, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x04, 0x84, 0x18, 0xCC, 0x2D, 0x6C, 0x00 , 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x30 , 0xCC, 0x3C, 0x1E, 0x8C, 0x48, 0x00, 0x00, 0x00 , 0x00, 0x04, 0x90, 0x90, 0x64, 0x9C, 0x0B, 0xCC , 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0xC0 , 0x30, 0x9C, 0x4E, 0x86, 0x48, 0x00, 0x00, 0x00 , 0x00, 0x48, 0x30, 0x60, 0x90, 0xCC, 0x3C, 0xC8 , 0x84, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xB0, 0x64 , 0xC8, 0x64, 0x6C, 0xC8, 0x00, 0x00, 0x00, 0x00 , 0x00, 0xD0, 0xF0, 0xC8, 0x84, 0x90, 0x64, 0xC0 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x48, 0xF0, 0xF0 , 0xE0, 0xD0, 0xF4, 0xFC, 0xC0, 0x08, 0x00, 0x00 , 0x00, 0x04, 0xD0, 0xF0, 0xF0, 0xD0, 0xF0, 0xFC , 0xFC, 0x80, 0x00, 0x00, 0x00, 0x00, 0x48, 0xC0 , 0xC0, 0x48, 0xC0, 0xC0, 0xC0, 0x08, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x48, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x04, 0xD4, 0x84, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48 , 0xFC, 0xE8, 0xC0, 0xC0, 0x08, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0xD0, 0xF4, 0xAC, 0x0C, 0x04 , 0xC0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48 , 0xF0, 0x84, 0x00, 0x00, 0x04, 0x84, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x40, 0xE0, 0x08, 0x00, 0x00 , 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 , 0x84, 0x08, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00 , 0x00, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0x00 , 0x40, 0x84, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x0C, 0x00, 0x00, 0x00, 0x40, 0x80, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x40, 0x0C, 0x08, 0x01, 0x82 , 0x40, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04 , 0x84, 0x0C, 0x00, 0x43, 0x82, 0x04, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x48, 0x64, 0x3C, 0x0C, 0x01 , 0x43, 0xC2, 0x08, 0x00, 0x00, 0x00, 0x00, 0x90 , 0x8C, 0x00, 0x68, 0x00, 0x01, 0x42, 0x00, 0x00 , 0x00, 0x00, 0x04, 0x90, 0x08, 0x00, 0x14, 0x84 , 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x40, 0x30 , 0x08, 0x00, 0x14, 0x48, 0x0C, 0x48, 0x00, 0x00 , 0x00, 0x00, 0x40, 0x30, 0x00, 0x00, 0x1C, 0x04 , 0x0C, 0x84, 0x00, 0x00, 0x00, 0x00, 0x40, 0x24 , 0x00, 0x04, 0x9C, 0x00, 0xC0, 0x08, 0x00, 0x00 , 0x00, 0x00, 0x40, 0x24, 0x00, 0x4C, 0x6C, 0x00 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x24 , 0x00, 0x4C, 0x6C, 0x00, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x40, 0x60, 0x0C, 0x9C, 0x1E, 0x2C , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x30 , 0x90, 0x9C, 0x29, 0xCC, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x04, 0x90, 0x30, 0xCC, 0xCC, 0xC2 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48 , 0x64, 0x6C, 0xC8, 0x84, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x48, 0x9C, 0x6C, 0x84, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0 , 0xF4, 0xFC, 0xE8, 0x84, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x48, 0xF0, 0xF4, 0xFC, 0xE8 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 , 0xC0, 0xC0, 0xC0, 0x84, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x48, 0x08, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04 , 0xD4, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x48, 0xFC, 0xE8, 0xC0, 0xC0 , 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0 , 0xF4, 0xAC, 0x0C, 0x04, 0xC0, 0x08, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x48, 0xF0, 0x84, 0x00, 0x00 , 0x04, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40 , 0xE0, 0x08, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00 , 0x00, 0x00, 0x00, 0x04, 0x84, 0x08, 0x00, 0x00 , 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x0C, 0x00, 0x00, 0x00, 0x40, 0x84, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x40, 0x0C, 0x00, 0x00, 0x00 , 0x40, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x40 , 0x0C, 0x08, 0x01, 0x82, 0x40, 0x80, 0x80, 0x00 , 0x00, 0x00, 0x00, 0x04, 0x84, 0x0C, 0x00, 0x43 , 0x82, 0x04, 0x80, 0x00, 0x00, 0x00, 0x00, 0x48 , 0x64, 0x3C, 0x0C, 0x01, 0x43, 0xC2, 0x08, 0x00 , 0x00, 0x00, 0x00, 0x90, 0x9C, 0x9C, 0x68, 0x00 , 0x01, 0x42, 0x00, 0x00, 0x00, 0x00, 0x04, 0x90 , 0xCC, 0x04, 0x14, 0x84, 0x00, 0x40, 0x00, 0x00 , 0x00, 0x00, 0x40, 0x30, 0x8C, 0x00, 0x00, 0x48 , 0x0C, 0x48, 0x00, 0x00, 0x00, 0x00, 0x40, 0x30 , 0x8C, 0x00, 0x00, 0x04, 0x0C, 0x84, 0x00, 0x00 , 0x00, 0x00, 0x40, 0x30, 0x60, 0x00, 0x00, 0x00 , 0xC0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x30 , 0x60, 0x08, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x40, 0x30, 0x60, 0x80, 0x00, 0x00 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x64 , 0x30, 0x84, 0x00, 0x2C, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x00, 0x04, 0x90, 0x98, 0x60, 0x0C, 0xCC , 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x64 , 0x9C, 0x6C, 0xCC, 0xC2, 0x08, 0x00, 0x00, 0x00 , 0x00, 0x04, 0x90, 0xCC, 0x2D, 0xCC, 0x30, 0xCC , 0x80, 0x00, 0x00, 0x00, 0x00, 0x40, 0xF0, 0x30 , 0xCC, 0xC8, 0x30, 0xCC, 0x80, 0x00, 0x00, 0x00 , 0x00, 0x40, 0xF0, 0xFC, 0x60, 0xC0, 0x30, 0x64 , 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD0, 0xF4 , 0xE8, 0x84, 0xD0, 0xFC, 0xC0, 0x84, 0x00, 0x00 , 0x00, 0x00, 0x48, 0xD0, 0xFC, 0xE8, 0xD0, 0xF4 , 0xFC, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48 , 0xC0, 0x84, 0x48, 0xC0, 0xC0, 0x84, 0x00, 0x00 };
For our program we use the routines that we saw in the previous tutorial Sprites I: Introduction to using sprites to set the palette and paint the sprites. Let's make the character move from left to right, inserting the graphics that we have exported to simulate that the character walks. To do so easily, we will introduce several C advanced concepts such as enumerations, structures and pointers to pointer. For example, to simplify the direction of motion we use the following enum: enum _eDirection { Direction_Left, Direction_Right, Direction_Max };
To handle the character, position, motion and animation we will use the following structure: struct _tSprite { int nY; int nX; int nKey; unsigned int nSpeed; unsigned int nLastMoveTime; enum _eDirection eDirection; }_tSprite;
To manage and store different 'frames' of the animation we will use this array that points to each one of the 4 frames for both left and right animation: char *aKeyFrames[Direction_Max][4]; Which is filled as follows: aKeyFrames[Direction_Left][0] = (char *)NickSprite; aKeyFrames[Direction_Left][1] = (char *)NickSprite + NICK_WIDTH * NICK_HEIGHT; aKeyFrames[Direction_Left][2] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 2; aKeyFrames[Direction_Left][3] = (char *)NickSprite + NICK_WIDTH * NICK_HEIGHT; aKeyFrames[Direction_Right][0] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 3; aKeyFrames[Direction_Right][1] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 4; aKeyFrames[Direction_Right][2] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 5; aKeyFrames[Direction_Right][3] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 4; Although we have 3 different graphics for each direction, we have 4 frames, This is so because the sequence is in the following manner: Left foot forward, feet together, right foot forward, feet together and then start again. Finally the entire source code of the program is as follows: //////////////////////////////////////////////////////////////////////// // sprite01.c // Mochilote - www.cpcmania.com //////////////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> #include <string.h> #include "Nick.h" #define MAX_X 79 #define MAX_Y 199 void SetColor(unsigned char nColorIndex, unsigned char nPaletteIndex) { __asm ld a, 4 (ix) ld b, 5 (ix) ld c, b call #0xBC32 ;SCR SET INK __endasm; } void SetPalette(const unsigned char *pPalette) { unsigned char nColor = 0; for(nColor = 0; nColor < NUM_COLORS; nColor++) SetColor(nColor, pPalette[nColor]); } void PutSpriteMode0(unsigned char *pAddress, unsigned char nWidth, unsigned char nHeight, unsigned char *pSprite) { __asm LD L, 4(IX) LD H, 5(IX) LD C, 6(IX) LD B, 7(IX) LD E, 8(IX) LD D, 9(IX) _loop_alto: PUSH BC LD B,C PUSH HL _loop_ancho: LD A,(DE) LD (HL),A INC DE INC HL DJNZ _loop_ancho POP HL LD A,H ADD #0x08 LD H,A SUB #0xC0 JP NC, _sig_linea LD BC, #0xC050 ADD HL,BC _sig_linea: POP BC DJNZ _loop_alto __endasm; } //////////////////////////////////////////////////////////////////////// unsigned char char1,char2,char3,char4; unsigned int GetTime() { unsigned int nTime = 0; __asm CALL #0xBD0D ;KL TIME PLEASE PUSH HL POP DE LD HL, #_char3 LD (HL), D LD HL, #_char4 LD (HL), E __endasm; nTime = (char3 << 8) + char4; return nTime; } //////////////////////////////////////////////////////////////////////// enum _eDirection { Direction_Left, Direction_Right, Direction_Max }; char *aKeyFrames[Direction_Max][4]; struct _tSprite { int nY; int nX; int nKey; unsigned int nSpeed; unsigned int nLastMoveTime; enum _eDirection eDirection; }_tSprite; #define NUM_SPRITES 1 struct _tSprite aSprites[NUM_SPRITES]; void main() { //SCR_SET_MODE 0 __asm ld a, #0 call #0xBC0E __endasm; //SCR SET BORDER 0 __asm ld b, #0 ;black ld c, b call #0xBC38 __endasm; SetPalette(NickPalette); aKeyFrames[Direction_Left][0] = (char *)NickSprite; aKeyFrames[Direction_Left][1] = (char *)NickSprite + NICK_WIDTH * NICK_HEIGHT; aKeyFrames[Direction_Left][2] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 2; aKeyFrames[Direction_Left][3] = (char *)NickSprite + NICK_WIDTH * NICK_HEIGHT; aKeyFrames[Direction_Right][0] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 3; aKeyFrames[Direction_Right][1] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 4; aKeyFrames[Direction_Right][2] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 5; aKeyFrames[Direction_Right][3] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 4; aSprites[0].eDirection = Direction_Right; aSprites[0].nKey = 0; aSprites[0].nX = 0; aSprites[0].nY = 75; aSprites[0].nSpeed = 20; aSprites[0].nLastMoveTime = GetTime(); while(1) { unsigned char nSprite = 0; for(nSprite = 0; nSprite < NUM_SPRITES; nSprite++) { if(GetTime() - aSprites[nSprite].nLastMoveTime < aSprites[nSprite].nSpeed) continue; aSprites[nSprite].nLastMoveTime += aSprites[nSprite].nSpeed; //move aSprites[nSprite].nX += (aSprites[nSprite].eDirection == Direction_Right ? 1 : -1); if(aSprites[nSprite].nX <= 0) { aSprites[nSprite].nX = 0; aSprites[nSprite].eDirection = Direction_Right; aSprites[nSprite].nKey = 0; } if(aSprites[nSprite].nX >= (MAX_X - NICK_WIDTH)) { aSprites[nSprite].nX = MAX_X - NICK_WIDTH; aSprites[nSprite].eDirection = Direction_Left; aSprites[nSprite].nKey = 0; } aSprites[nSprite].nKey++; if(aSprites[nSprite].nKey > 3) aSprites[nSprite].nKey = 0; PutSpriteMode0((unsigned char *)(0xC000 + ((aSprites[nSprite].nY / 8u) * 80u) + ((aSprites[nSprite].nY % 8u) * 2048u) + aSprites[nSprite].nX), NICK_WIDTH, NICK_HEIGHT, (unsigned char *)aKeyFrames[aSprites[nSprite].eDirection][aSprites[nSprite].nKey]); } } } //////////////////////////////////////////////////////////////////////// If you compile and run on the emulator get the following:
Let us now modify minimally the program to handle 4 characters simultaneously, with 4 different speeds: //////////////////////////////////////////////////////////////////////// // sprite02.c // Mochilote - www.cpcmania.com //////////////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> #include <string.h> #include "Nick.h" #define MAX_X 79 #define MAX_Y 199 void SetColor(unsigned char nColorIndex, unsigned char nPaletteIndex) { __asm ld a, 4 (ix) ld b, 5 (ix) ld c, b call #0xBC32 ;SCR SET INK __endasm; } void SetPalette(const unsigned char *pPalette) { unsigned char nColor = 0; for(nColor = 0; nColor < NUM_COLORS; nColor++) SetColor(nColor, pPalette[nColor]); } void PutSpriteMode0(unsigned char *pAddress, unsigned char nWidth, unsigned char nHeight, unsigned char *pSprite) { __asm LD L, 4(IX) LD H, 5(IX) LD C, 6(IX) LD B, 7(IX) LD E, 8(IX) LD D, 9(IX) _loop_alto: PUSH BC LD B,C PUSH HL _loop_ancho: LD A,(DE) LD (HL),A INC DE INC HL DJNZ _loop_ancho POP HL LD A,H ADD #0x08 LD H,A SUB #0xC0 JP NC, _sig_linea LD BC, #0xC050 ADD HL,BC _sig_linea: POP BC DJNZ _loop_alto __endasm; } //////////////////////////////////////////////////////////////////////// unsigned char char1,char2,char3,char4; unsigned int GetTime() { unsigned int nTime = 0; __asm CALL #0xBD0D ;KL TIME PLEASE PUSH HL POP DE LD HL, #_char3 LD (HL), D LD HL, #_char4 LD (HL), E __endasm; nTime = (char3 << 8) + char4; return nTime; } //////////////////////////////////////////////////////////////////////// enum _eDirection { Direction_Left, Direction_Right, Direction_Max }; char *aKeyFrames[Direction_Max][4]; struct _tSprite { int nY; int nX; int nKey; unsigned int nSpeed; unsigned int nLastMoveTime; enum _eDirection eDirection; }_tSprite; #define NUM_SPRITES 4 struct _tSprite aSprites[NUM_SPRITES]; void main() { //SCR_SET_MODE 0 __asm ld a, #0 call #0xBC0E __endasm; //SCR SET BORDER 0 __asm ld b, #0 ;black ld c, b call #0xBC38 __endasm; SetPalette(NickPalette); aKeyFrames[Direction_Left][0] = (char *)NickSprite; aKeyFrames[Direction_Left][1] = (char *)NickSprite + NICK_WIDTH * NICK_HEIGHT; aKeyFrames[Direction_Left][2] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 2; aKeyFrames[Direction_Left][3] = (char *)NickSprite + NICK_WIDTH * NICK_HEIGHT; aKeyFrames[Direction_Right][0] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 3; aKeyFrames[Direction_Right][1] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 4; aKeyFrames[Direction_Right][2] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 5; aKeyFrames[Direction_Right][3] = (char *)NickSprite + (NICK_WIDTH * NICK_HEIGHT) * 4; aSprites[0].eDirection = Direction_Right; aSprites[0].nKey = 0; aSprites[0].nX = 0; aSprites[0].nY = 25; aSprites[0].nSpeed = 20; aSprites[0].nLastMoveTime = GetTime(); aSprites[1].eDirection = Direction_Left; aSprites[1].nKey = 0; aSprites[1].nX = 50; aSprites[1].nY = 25; aSprites[1].nSpeed = 15; aSprites[1].nLastMoveTime = GetTime(); aSprites[2].eDirection = Direction_Right; aSprites[2].nKey = 0; aSprites[2].nX = 0; aSprites[2].nY = 75; aSprites[2].nSpeed = 5; aSprites[2].nLastMoveTime = GetTime(); aSprites[3].eDirection = Direction_Right; aSprites[3].nKey = 0; aSprites[3].nX = 0; aSprites[3].nY = 150; aSprites[3].nSpeed = 10; aSprites[3].nLastMoveTime = GetTime(); while(1) { unsigned char nSprite = 0; for(nSprite = 0; nSprite < NUM_SPRITES; nSprite++) { if(GetTime() - aSprites[nSprite].nLastMoveTime < aSprites[nSprite].nSpeed) continue; aSprites[nSprite].nLastMoveTime += aSprites[nSprite].nSpeed; //move aSprites[nSprite].nX += (aSprites[nSprite].eDirection == Direction_Right ? 1 : -1); if(aSprites[nSprite].nX <= 0) { aSprites[nSprite].nX = 0; aSprites[nSprite].eDirection = Direction_Right; aSprites[nSprite].nKey = 0; } if(aSprites[nSprite].nX >= (MAX_X - NICK_WIDTH)) { aSprites[nSprite].nX = MAX_X - NICK_WIDTH; aSprites[nSprite].eDirection = Direction_Left; aSprites[nSprite].nKey = 0; } aSprites[nSprite].nKey++; if(aSprites[nSprite].nKey > 3) aSprites[nSprite].nKey = 0; PutSpriteMode0((unsigned char *)(0xC000 + ((aSprites[nSprite].nY / 8u) * 80u) + ((aSprites[nSprite].nY % 8u) * 2048u) + aSprites[nSprite].nX), NICK_WIDTH, NICK_HEIGHT, (unsigned char *)aKeyFrames[aSprites[nSprite].eDirection][aSprites[nSprite].nKey]); } } } //////////////////////////////////////////////////////////////////////// If you compile and run on the emulator get the following: As we see, with just 3 graphics have made your character walk and even at different speeds. If you look at the two characters from the top, we see that the collision between them is a very typical effect in many games in our cpc. You could download a zip with all files (source code, bat to compile, binary and dsk's) here: Sprites_II.zip |
www.CPCMania.com 2012 |