diff --git a/src/Sprites.cpp b/src/Sprites.cpp index d4b833e..39baa5c 100644 --- a/src/Sprites.cpp +++ b/src/Sprites.cpp @@ -12,6 +12,13 @@ void Sprites::drawExternalMask(int16_t x, int16_t y, const uint8_t *bitmap, draw(x, y, bitmap, frame, mask, mask_frame, SPRITE_MASKED); } +void Sprites::drawMaskedSprite(int16_t x, int16_t y, + const uint8_t *bitmap, uint8_t frame, + const uint8_t *mask, uint8_t mask_frame) +{ + draw(x, y, bitmap, frame, mask, mask_frame, SPRITE_MASK_SPRITE); +} + void Sprites::drawOverwrite(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame) { draw(x, y, bitmap, frame, NULL, 0, SPRITE_OVERWRITE); @@ -241,6 +248,33 @@ void Sprites::drawBitmap(int16_t x, int16_t y, } break; + case SPRITE_MASK_SPRITE: + for (uint8_t a = 0; a < loop_h; a++) { + for (uint8_t iCol = 0; iCol < rendered_width; iCol++) { + // load data and bit shift + mask_data = pgm_read_byte(mask_ofs) * mul_amt; + bitmap_data = pgm_read_byte(bofs) * mul_amt; + + if (sRow >= 0) { + data = Arduboy2Base::sBuffer[ofs]; + data |= (uint8_t)(bitmap_data & mask_data); + Arduboy2Base::sBuffer[ofs] = data; + } + if (yOffset != 0 && sRow < 7) { + data = Arduboy2Base::sBuffer[ofs + WIDTH]; + data |= (*((unsigned char *) (&bitmap_data) + 1)) & (*((unsigned char *) (&mask_data) + 1)); + Arduboy2Base::sBuffer[ofs + WIDTH] = data; + } + ofs++; + mask_ofs++; + bofs++; + } + sRow++; + bofs += w - rendered_width; + mask_ofs += w - rendered_width; + ofs += WIDTH - rendered_width; + } + break; case SPRITE_PLUS_MASK: // *2 because we use double the bits (mask + bitmap) diff --git a/src/Sprites.h b/src/Sprites.h index 58a738b..a1a7e44 100644 --- a/src/Sprites.h +++ b/src/Sprites.h @@ -13,6 +13,7 @@ #define SPRITE_UNMASKED 2 #define SPRITE_OVERWRITE 2 #define SPRITE_PLUS_MASK 3 +#define SPRITE_MASK_SPRITE 4 #define SPRITE_IS_MASK 250 #define SPRITE_IS_MASK_ERASE 251 #define SPRITE_AUTO_MODE 255 @@ -85,6 +86,43 @@ class Sprites void drawExternalMask(int16_t x, int16_t y, const uint8_t *bitmap, const uint8_t *mask, uint8_t frame, uint8_t mask_frame); + /** \brief + * Draw a partial sprite using a separate image and mask array only showing masked part of the image. + * + * \param x,y The coordinates of the top left pixel location. + * \param bitmap A pointer to the array containing the image frames. + * \param mask A pointer to the array containing the mask frames. + * \param frame The frame number of the image to draw. + * \param mask_frame The frame number for the mask to use (can be different + * from the image frame number). + * + * \details + * An array containing the image frames, and another array containing + * corresponding mask frames, are used to draw a sprite. + * + * Only bits set to 1 in the mask and the image will be drawn. + * Partial sprite will be added (&) to the screen buffer. + * + * image mask before after + * + * ..... ..... ..... ..... + * ..O.. ..... ..... ..... + * OO.OO OOOOO ..... OO.OO + * ..O.. OOOOO ..... ..O.. + * ..... .OOO. ..... ..... + * + * image mask before after + * + * ..... ..... OOOOO OOOOO + * ..O.. ..... OOOOO OOOOO + * OO.OO OOOOO OOOOO OOOOO + * ..O.. OOOOO OOOOO OOOOO + * ..... .OOO. OOOOO OOOOO + */ + void Sprites::drawMaskedSprite(int16_t x, int16_t y, + const uint8_t *bitmap, uint8_t frame, + const uint8_t *mask, uint8_t mask_frame); + /** \brief * Draw a sprite using an array containing both image and mask values. *