Chris Dick
/
Gameduino_Invaders_game
Invaders game for the Gameduino
Diff: graphics.cpp
- Revision:
- 2:20a89dc286d5
- Parent:
- 1:f44175dd69fd
- Child:
- 4:e82f4a87df9e
diff -r f44175dd69fd -r 20a89dc286d5 graphics.cpp --- a/graphics.cpp Sat Sep 29 13:01:42 2012 +0000 +++ b/graphics.cpp Thu Dec 20 21:33:52 2012 +0000 @@ -1,394 +1,395 @@ -#include "game.h" - -SPI spigraphics(ARD_MOSI, ARD_MISO, ARD_SCK); // mosi, miso, sclk - -typedef prog_uint8_t char_data; -typedef prog_uint16_t sprite_data; - -/*--------------------------------------------- - Graphics - made by typing in the hex... :-) ----------------------------------------------*/ -static PROGMEM sprite_data invaderT[] = { - 0x0c00, 0x0c00, - 0x1e00, 0x1e00, - 0x3f00, 0x3f00, - 0x6d80, 0x6d80, - 0x7f80, 0x7f80, - 0x1200, 0x2d00, - 0x2d00, 0x4080, - 0x5280, 0x2100 -}; -static PROGMEM sprite_data invaderM[] = { - 0x2080, 0x2080, - 0x9120, 0x1100, - 0xbfa0, 0x3f80, - 0xeee0, 0x6ec0, - 0xffe0, 0xffe0, - 0x7fc0, 0xbfa0, - 0x2080, 0xa0a0, - 0x4040, 0x1b00 -}; -static PROGMEM sprite_data invaderB[] = { - 0x0f00, 0x0f00, - 0x7fe0, 0x7fe0, - 0xfff0, 0xfff0, - 0xe670, 0xe670, - 0xfff0, 0xfff0, - 0x1980, 0x1980, - 0x36c0, 0x6660, - 0xc030, 0x30c0 -}; -static PROGMEM sprite_data invader_explosion[] = { - 0x0880, - 0x4510, - 0x2020, - 0x1040, - 0xc018, - 0x1040, - 0x2520, - 0x4890 -}; -static PROGMEM sprite_data player[] = { - 0x0200, 0x1004, 0x0200, - 0x0700, 0x8219, 0x0010, - 0x0700, 0x10c0, 0x02a0, - 0x7ff0, 0x0202, 0x1200, - 0xfff8, 0x4b31, 0x01b0, - 0xfff8, 0x21c4, 0x45a8, - 0xfff8, 0x1ff0, 0x1fe4, - 0xfff8, 0x37f2, 0x3ff5 -}; -static PROGMEM sprite_data bullet[] = { - 0x0200, - 0x0200, - 0x0200, - 0x0200, - 0x0000, - 0x0000, - 0x0000, - 0x0000 -}; -static PROGMEM sprite_data bullet_blast[] = { - 0x1120, - 0x0440, - 0x0fc0, - 0x1fe0, - 0x1fe0, - 0x0fc0, - 0x0480, - 0x1220 -}; -static PROGMEM sprite_data saucer[] = { - 0x0000, 0x1281, 0x4800, - 0x07e0, 0x0806, 0x1000, - 0x1ff8, 0x51e3, 0x0000, - 0x3ffc, 0x03f9, 0xc800, - 0x6db6, 0x0754, 0xe400, - 0xffff, 0x11f1, 0x8000, - 0x399c, 0x40a3, 0x1000, - 0x1008, 0x1110, 0x8000 -}; -static PROGMEM sprite_data saucerScore[] = { - 0x007c, 0x1038, 0x107c, 0x7c38, - 0x0040, 0x3044, 0x3040, 0x0444, - 0x0078, 0x104c, 0x1078, 0x084c, - 0x0004, 0x1054, 0x1004, 0x1854, - 0x0004, 0x1064, 0x1004, 0x0464, - 0x0044, 0x1044, 0x1044, 0x4444, - 0x0038, 0x3838, 0x3838, 0x3838, - 0x0000, 0x0000, 0x0000, 0x0000 -}; -static PROGMEM sprite_data saucerZero[] = { - 0x3800, - 0x4400, - 0x4c00, - 0x5400, - 0x6400, - 0x4400, - 0x3800, - 0x0000 -}; -static PROGMEM sprite_data zigzagBomb[] = { - 0x0200, 0x0400, 0x0200, 0x0100, - 0x0400, 0x0300, 0x0100, 0x0200, - 0x0200, 0x0100, 0x0200, 0x0400, - 0x0100, 0x0200, 0x0400, 0x0200, - 0x0200, 0x0400, 0x0200, 0x0100, - 0x0400, 0x0200, 0x0100, 0x0200, - 0x0100, 0x0100, 0x0200, 0x0400, - 0x0000, 0x0000, 0x0000, 0x0000 -}; -static PROGMEM sprite_data barBomb[] = { - 0x0200, 0x0200, 0x0200, 0x0700, - 0x0200, 0x0200, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0700, 0x0200, - 0x0200, 0x0700, 0x0200, 0x0200, - 0x0200, 0x0200, 0x0200, 0x0200, - 0x0700, 0x0200, 0x0200, 0x0200, - 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000 -}; -static PROGMEM sprite_data diagBomb[] = { - 0x0200, 0x0200, 0x0200, 0x0300, - 0x0200, 0x0200, 0x0200, 0x0600, - 0x0200, 0x0600, 0x0200, 0x0200, - 0x0200, 0x0300, 0x0200, 0x0300, - 0x0200, 0x0200, 0x0200, 0x0600, - 0x0200, 0x0600, 0x0200, 0x0200, - 0x0200, 0x0300, 0x0200, 0x0200, - 0x0000, 0x0000, 0x0000, 0x0000 -}; -static PROGMEM sprite_data bomb_blast[] = { - 0x0100, - 0x0440, - 0x01a0, - 0x03c0, - 0x05c0, - 0x03e0, - 0x05c0, - 0x02a0 -}; - -static PROGMEM sprite_data shield[] = { - 0x0fff, 0xc000, - 0x1fff, 0xe000, - 0x3fff, 0xf000, - 0x7fff, 0xf800, - 0xffff, 0xfc00, - 0xffff, 0xfc00, - 0xffff, 0xfc00, - 0xffff, 0xfc00, - 0xffff, 0xfc00, - 0xffff, 0xfc00, - 0xffff, 0xfc00, - 0xffff, 0xfc00, - 0xfe03, 0xfc00, - 0xfc01, 0xfc00, - 0xf800, 0xfc00, - 0xf800, 0xfc00 -}; - -/*--------------------------------------------- - Turn raw data into Gameduino sprites - - We're using four color sprites so each - sprite can contain four images. This - function interleaves the data... ----------------------------------------------*/ -void makeSprite(byte index, byte height, const sprite_data* g1, byte s1=1, const sprite_data* g2=0, byte s2=0, const sprite_data* g3=0, byte s3=0, const sprite_data* g4=0, byte s4=0) -{ - const unsigned int topBit = 0x8000; - unsigned int d1=0,d2=0,d3=0,d4=0; - unsigned int dest = RAM_SPRIMG+(index*256); - for (byte i=0; i<height; ++i) { // Space invaders are only 8 pixels tall - d1 = *g1; g1 += s1; - if (g2) { d2 = *g2; g2 += s2; } - if (g3) { d3 = *g3; g3 += s3; } - if (g4) { d4 = *g4; g4 += s4; } - for (byte j=0; j<16; ++j) { - unsigned int m1 = (d1&topBit)>>15; - unsigned int m2 = (d2&topBit)>>13; - unsigned int m3 = (d3&topBit)>>11; - unsigned int m4 = (d4&topBit)>>9; - GD.wr(dest++,m1+m2+m3+m4); - d1 <<= 1; - d2 <<= 1; - d3 <<= 1; - d4 <<= 1; - } - } -} -void makeInvader(byte gr, const sprite_data *data) -{ - makeSprite(gr,8,data,2,data+1,2,invader_explosion,1); -} -void makeSp3(byte gr, const sprite_data *d) -{ - makeSprite(gr,8, d,3, d+1,3, d+2,3); -} -void makeSp4(byte gr, const sprite_data *d) -{ - makeSprite(gr,8, d,4, d+1,4, d+2,4, d+3,4); -} - -/*--------------------------------------------- - Char data ----------------------------------------------*/ -static PROGMEM char_data floorChar[] = { - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xff, - 0x00 -}; -static PROGMEM char_data playerLeft[] = { - 0x02, - 0x07, - 0x07, - 0x7f, - 0xff, - 0xff, - 0xff, - 0xff -}; -static PROGMEM char_data playerRight[] = { - 0x00, - 0x00, - 0x00, - 0xf0, - 0xf8, - 0xf8, - 0xf8, - 0xf8 -}; - -/*--------------------------------------------- - Make a character ----------------------------------------------*/ -static PROGMEM prog_uint8_t stretch[16] = { - 0x00, 0x03, 0x0c, 0x0f, - 0x30, 0x33, 0x3c, 0x3f, - 0xc0, 0xc3, 0xcc, 0xcf, - 0xf0, 0xf3, 0xfc, 0xff -}; -static void makeChar(byte index, const char_data *ch, unsigned int color) -{ - // Bitmap - GD.__wstart(RAM_CHR+(16*index)); - for (int i=0; i<8; i++) { - byte b = *ch++; - spigraphics.write((*stretch+(b >> 4))); - spigraphics.write((*stretch+(b & 15))); - } - GD.__end(); - // Colors - GD.setpal((4*index)+3, color); -} - -/*--------------------------------------------- - Make all the game sprites ----------------------------------------------*/ -void makeGraphics() -{ - // Sprites - makeInvader(GR_INVADER_T,invaderT); - makeInvader(GR_INVADER_M,invaderM); - makeInvader(GR_INVADER_B,invaderB); - makeSp3(GR_PLAYER,player); - makeSprite(GR_BULLET,8,bullet,1,bullet_blast,1); - makeSprite(GR_BULLET,8,bullet,1,bullet_blast,1, saucerZero,1); - makeSp3(GR_SAUCER,saucer); - makeSp4(GR_BOMB_ZIGZAG,zigzagBomb); - makeSp4(GR_BOMB_BARS, barBomb); - makeSp4(GR_BOMB_DIAG, diagBomb); - makeSp4(GR_SAUCER_SCORE,saucerScore); - makeSprite(GR_BOMB_OTHER,8,bomb_blast,1); - GD.wr16(PALETTE4A+0,0x8000); // Transparent - GD.wr16(PALETTE4A+2,0x7fff); // White - // Charset - GD.ascii(); - //const unsigned int red = 0x7c00; - const unsigned int green = 0x03e0; - makeChar(CH_FLOOR,floorChar,green); - makeChar(CH_PLAYERL,playerLeft,green); - makeChar(CH_PLAYERR,playerRight,green); -} - - -/*--------------------------------------------------- - The shields are sprites but we use them as bitmaps - so we need to be able to shoot/bomb/rebuild them - on demand. ----------------------------------------------------*/ -void remakeShields() -{ - for (int i=0; i<4; ++i) { - makeSprite(GR_SHIELD1+i,16,shield,2,shield+1,2); - } -} - -int8 zapShield(int n, int8 x, bool withBullet) -{ - int y = 0; - if ((n >= 0) and (n <= 3)) { - n += GR_SHIELD1; - const unsigned int spriteMem = RAM_SPRIMG+(n*256); - int col = x+6; // The pixels in the bullet are in column 6 of the graphic - if (col < 0 ) col = 0; - if (col > 31) col = 31; - // Scan the shield and find the top/bottom pixel in column 'x' - byte pixelMask = 0x03; - if (col > 15) { - pixelMask = 0x0c; - col &= 15; - } - unsigned int s = spriteMem+col; - const sprite_data *blastMap = bullet_blast; - if (withBullet) { - // Go from the top, find lowest pixel - for (int8 r=0; r<16; ++r) { - if ((GD.rd(s)&pixelMask)!=0) { - y = r; - } - s += 16; - } - x += 3; - y -= 5; - } - else { - // Go from the bottom, find highest pixel - y = 16; - s += 256; - int8 offset = 3; - for (int8 r=0; r<16; ++r) { - s -= 16; - // Bombs are wider...we check three columns - if ((GD.rd(s)&pixelMask)!=0) { - y = 15-r; - offset = 2; - } - else if ((col!=0) and ((GD.rd(s-1)&pixelMask)!=0)) { - y = 15-r; - offset = 1; - } - else if ((col!=31) and ((GD.rd(s+1)&pixelMask)!=0)) { - y = 15-r; - offset = 3; - } - } - x += offset; - y -= 4; - blastMap = bomb_blast; - } - // Blast a hole in it - for (int8 j=0; j<8; ++j) { // 8 lines tall - const int py = y+j; - if ((py>=0) and (py<=15)) { - unsigned int blastMask = 0x1000; - unsigned int blastGraphic = pgm_read_word_near(blastMap); - for (int8 i=0; i<8; ++i) { // 8 pixels wide... - if ((blastGraphic&blastMask)!=0) { - // Set shield pixel to 0 where there's a 1 in the source graphic - int px = x+i; - if ((px>=0) and (px<=31)) { - byte pixelMask = 0xfc; - if (px > 15) { - px &= 15; - pixelMask = 0xf3; - } - unsigned int s = spriteMem+(py*16)+px; - GD.wr(s,GD.rd(s)&pixelMask); - } - } - blastMask >>= 1; - } - } - ++blastMap; - } - - } - return y; -} +#include "game.h" + +SPI spigraphics(ARD_MOSI, ARD_MISO, ARD_SCK); // mosi, miso, sclk + +typedef prog_uint8_t char_data; +typedef prog_uint16_t sprite_data; + +extern GDClass GD; +/*--------------------------------------------- + Graphics - made by typing in the hex... :-) +---------------------------------------------*/ +static PROGMEM sprite_data invaderT[] = { + 0x0c00, 0x0c00, + 0x1e00, 0x1e00, + 0x3f00, 0x3f00, + 0x6d80, 0x6d80, + 0x7f80, 0x7f80, + 0x1200, 0x2d00, + 0x2d00, 0x4080, + 0x5280, 0x2100 +}; +static PROGMEM sprite_data invaderM[] = { + 0x2080, 0x2080, + 0x9120, 0x1100, + 0xbfa0, 0x3f80, + 0xeee0, 0x6ec0, + 0xffe0, 0xffe0, + 0x7fc0, 0xbfa0, + 0x2080, 0xa0a0, + 0x4040, 0x1b00 +}; +static PROGMEM sprite_data invaderB[] = { + 0x0f00, 0x0f00, + 0x7fe0, 0x7fe0, + 0xfff0, 0xfff0, + 0xe670, 0xe670, + 0xfff0, 0xfff0, + 0x1980, 0x1980, + 0x36c0, 0x6660, + 0xc030, 0x30c0 +}; +static PROGMEM sprite_data invader_explosion[] = { + 0x0880, + 0x4510, + 0x2020, + 0x1040, + 0xc018, + 0x1040, + 0x2520, + 0x4890 +}; +static PROGMEM sprite_data player[] = { + 0x0200, 0x1004, 0x0200, + 0x0700, 0x8219, 0x0010, + 0x0700, 0x10c0, 0x02a0, + 0x7ff0, 0x0202, 0x1200, + 0xfff8, 0x4b31, 0x01b0, + 0xfff8, 0x21c4, 0x45a8, + 0xfff8, 0x1ff0, 0x1fe4, + 0xfff8, 0x37f2, 0x3ff5 +}; +static PROGMEM sprite_data bullet[] = { + 0x0200, + 0x0200, + 0x0200, + 0x0200, + 0x0000, + 0x0000, + 0x0000, + 0x0000 +}; +static PROGMEM sprite_data bullet_blast[] = { + 0x1120, + 0x0440, + 0x0fc0, + 0x1fe0, + 0x1fe0, + 0x0fc0, + 0x0480, + 0x1220 +}; +static PROGMEM sprite_data saucer[] = { + 0x0000, 0x1281, 0x4800, + 0x07e0, 0x0806, 0x1000, + 0x1ff8, 0x51e3, 0x0000, + 0x3ffc, 0x03f9, 0xc800, + 0x6db6, 0x0754, 0xe400, + 0xffff, 0x11f1, 0x8000, + 0x399c, 0x40a3, 0x1000, + 0x1008, 0x1110, 0x8000 +}; +static PROGMEM sprite_data saucerScore[] = { + 0x007c, 0x1038, 0x107c, 0x7c38, + 0x0040, 0x3044, 0x3040, 0x0444, + 0x0078, 0x104c, 0x1078, 0x084c, + 0x0004, 0x1054, 0x1004, 0x1854, + 0x0004, 0x1064, 0x1004, 0x0464, + 0x0044, 0x1044, 0x1044, 0x4444, + 0x0038, 0x3838, 0x3838, 0x3838, + 0x0000, 0x0000, 0x0000, 0x0000 +}; +static PROGMEM sprite_data saucerZero[] = { + 0x3800, + 0x4400, + 0x4c00, + 0x5400, + 0x6400, + 0x4400, + 0x3800, + 0x0000 +}; +static PROGMEM sprite_data zigzagBomb[] = { + 0x0200, 0x0400, 0x0200, 0x0100, + 0x0400, 0x0300, 0x0100, 0x0200, + 0x0200, 0x0100, 0x0200, 0x0400, + 0x0100, 0x0200, 0x0400, 0x0200, + 0x0200, 0x0400, 0x0200, 0x0100, + 0x0400, 0x0200, 0x0100, 0x0200, + 0x0100, 0x0100, 0x0200, 0x0400, + 0x0000, 0x0000, 0x0000, 0x0000 +}; +static PROGMEM sprite_data barBomb[] = { + 0x0200, 0x0200, 0x0200, 0x0700, + 0x0200, 0x0200, 0x0200, 0x0200, + 0x0200, 0x0200, 0x0700, 0x0200, + 0x0200, 0x0700, 0x0200, 0x0200, + 0x0200, 0x0200, 0x0200, 0x0200, + 0x0700, 0x0200, 0x0200, 0x0200, + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000 +}; +static PROGMEM sprite_data diagBomb[] = { + 0x0200, 0x0200, 0x0200, 0x0300, + 0x0200, 0x0200, 0x0200, 0x0600, + 0x0200, 0x0600, 0x0200, 0x0200, + 0x0200, 0x0300, 0x0200, 0x0300, + 0x0200, 0x0200, 0x0200, 0x0600, + 0x0200, 0x0600, 0x0200, 0x0200, + 0x0200, 0x0300, 0x0200, 0x0200, + 0x0000, 0x0000, 0x0000, 0x0000 +}; +static PROGMEM sprite_data bomb_blast[] = { + 0x0100, + 0x0440, + 0x01a0, + 0x03c0, + 0x05c0, + 0x03e0, + 0x05c0, + 0x02a0 +}; + +static PROGMEM sprite_data shield[] = { + 0x0fff, 0xc000, + 0x1fff, 0xe000, + 0x3fff, 0xf000, + 0x7fff, 0xf800, + 0xffff, 0xfc00, + 0xffff, 0xfc00, + 0xffff, 0xfc00, + 0xffff, 0xfc00, + 0xffff, 0xfc00, + 0xffff, 0xfc00, + 0xffff, 0xfc00, + 0xffff, 0xfc00, + 0xfe03, 0xfc00, + 0xfc01, 0xfc00, + 0xf800, 0xfc00, + 0xf800, 0xfc00 +}; + +/*--------------------------------------------- + Turn raw data into Gameduino sprites + + We're using four color sprites so each + sprite can contain four images. This + function interleaves the data... +---------------------------------------------*/ +void makeSprite(byte index, byte height, const sprite_data* g1, byte s1=1, const sprite_data* g2=0, byte s2=0, const sprite_data* g3=0, byte s3=0, const sprite_data* g4=0, byte s4=0) +{ + const unsigned int topBit = 0x8000; + unsigned int d1=0,d2=0,d3=0,d4=0; + unsigned int dest = RAM_SPRIMG+(index*256); + for (byte i=0; i<height; ++i) { // Space invaders are only 8 pixels tall + d1 = *g1; g1 += s1; + if (g2) { d2 = *g2; g2 += s2; } + if (g3) { d3 = *g3; g3 += s3; } + if (g4) { d4 = *g4; g4 += s4; } + for (byte j=0; j<16; ++j) { + unsigned int m1 = (d1&topBit)>>15; + unsigned int m2 = (d2&topBit)>>13; + unsigned int m3 = (d3&topBit)>>11; + unsigned int m4 = (d4&topBit)>>9; + GD.wr(dest++,m1+m2+m3+m4); + d1 <<= 1; + d2 <<= 1; + d3 <<= 1; + d4 <<= 1; + } + } +} +void makeInvader(byte gr, const sprite_data *data) +{ + makeSprite(gr,8,data,2,data+1,2,invader_explosion,1); +} +void makeSp3(byte gr, const sprite_data *d) +{ + makeSprite(gr,8, d,3, d+1,3, d+2,3); +} +void makeSp4(byte gr, const sprite_data *d) +{ + makeSprite(gr,8, d,4, d+1,4, d+2,4, d+3,4); +} + +/*--------------------------------------------- + Char data +---------------------------------------------*/ +static PROGMEM char_data floorChar[] = { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xff, + 0x00 +}; +static PROGMEM char_data playerLeft[] = { + 0x02, + 0x07, + 0x07, + 0x7f, + 0xff, + 0xff, + 0xff, + 0xff +}; +static PROGMEM char_data playerRight[] = { + 0x00, + 0x00, + 0x00, + 0xf0, + 0xf8, + 0xf8, + 0xf8, + 0xf8 +}; + +/*--------------------------------------------- + Make a character +---------------------------------------------*/ +static PROGMEM prog_uint8_t stretch[16] = { + 0x00, 0x03, 0x0c, 0x0f, + 0x30, 0x33, 0x3c, 0x3f, + 0xc0, 0xc3, 0xcc, 0xcf, + 0xf0, 0xf3, 0xfc, 0xff +}; +static void makeChar(byte index, const char_data *ch, unsigned int color) +{ + // Bitmap + GD.__wstart(RAM_CHR+(16*index)); + for (int i=0; i<8; i++) { + byte b = *ch++; + spigraphics.write((*stretch+(b >> 4))); + spigraphics.write((*stretch+(b & 15))); + } + GD.__end(); + // Colors + GD.setpal((4*index)+3, color); +} + +/*--------------------------------------------- + Make all the game sprites +---------------------------------------------*/ +void makeGraphics() +{ + // Sprites + makeInvader(GR_INVADER_T,invaderT); + makeInvader(GR_INVADER_M,invaderM); + makeInvader(GR_INVADER_B,invaderB); + makeSp3(GR_PLAYER,player); + makeSprite(GR_BULLET,8,bullet,1,bullet_blast,1); + makeSprite(GR_BULLET,8,bullet,1,bullet_blast,1, saucerZero,1); + makeSp3(GR_SAUCER,saucer); + makeSp4(GR_BOMB_ZIGZAG,zigzagBomb); + makeSp4(GR_BOMB_BARS, barBomb); + makeSp4(GR_BOMB_DIAG, diagBomb); + makeSp4(GR_SAUCER_SCORE,saucerScore); + makeSprite(GR_BOMB_OTHER,8,bomb_blast,1); + GD.wr16(PALETTE4A+0,0x8000); // Transparent + GD.wr16(PALETTE4A+2,0x7fff); // White + // Charset + GD.ascii(); + //const unsigned int red = 0x7c00; + const unsigned int green = 0x03e0; + makeChar(CH_FLOOR,floorChar,green); + makeChar(CH_PLAYERL,playerLeft,green); + makeChar(CH_PLAYERR,playerRight,green); +} + + +/*--------------------------------------------------- + The shields are sprites but we use them as bitmaps + so we need to be able to shoot/bomb/rebuild them + on demand. +---------------------------------------------------*/ +void remakeShields() +{ + for (int i=0; i<4; ++i) { + makeSprite(GR_SHIELD1+i,16,shield,2,shield+1,2); + } +} + +int8 zapShield(int n, int8 x, bool withBullet) +{ + int y = 0; + if ((n >= 0) and (n <= 3)) { + n += GR_SHIELD1; + const unsigned int spriteMem = RAM_SPRIMG+(n*256); + int col = x+6; // The pixels in the bullet are in column 6 of the graphic + if (col < 0 ) col = 0; + if (col > 31) col = 31; + // Scan the shield and find the top/bottom pixel in column 'x' + byte pixelMask = 0x03; + if (col > 15) { + pixelMask = 0x0c; + col &= 15; + } + unsigned int s = spriteMem+col; + const sprite_data *blastMap = bullet_blast; + if (withBullet) { + // Go from the top, find lowest pixel + for (int8 r=0; r<16; ++r) { + if ((GD.rd(s)&pixelMask)!=0) { + y = r; + } + s += 16; + } + x += 3; + y -= 5; + } + else { + // Go from the bottom, find highest pixel + y = 16; + s += 256; + int8 offset = 3; + for (int8 r=0; r<16; ++r) { + s -= 16; + // Bombs are wider...we check three columns + if ((GD.rd(s)&pixelMask)!=0) { + y = 15-r; + offset = 2; + } + else if ((col!=0) and ((GD.rd(s-1)&pixelMask)!=0)) { + y = 15-r; + offset = 1; + } + else if ((col!=31) and ((GD.rd(s+1)&pixelMask)!=0)) { + y = 15-r; + offset = 3; + } + } + x += offset; + y -= 4; + blastMap = bomb_blast; + } + // Blast a hole in it + for (int8 j=0; j<8; ++j) { // 8 lines tall + const int py = y+j; + if ((py>=0) and (py<=15)) { + unsigned int blastMask = 0x1000; + unsigned int blastGraphic = pgm_read_word_near(blastMap); + for (int8 i=0; i<8; ++i) { // 8 pixels wide... + if ((blastGraphic&blastMask)!=0) { + // Set shield pixel to 0 where there's a 1 in the source graphic + int px = x+i; + if ((px>=0) and (px<=31)) { + byte pixelMask = 0xfc; + if (px > 15) { + px &= 15; + pixelMask = 0xf3; + } + unsigned int s = spriteMem+(py*16)+px; + GD.wr(s,GD.rd(s)&pixelMask); + } + } + blastMask >>= 1; + } + } + ++blastMap; + } + + } + return y; +}