Document Spinda spot algorithm

This commit is contained in:
GriffinR 2022-01-17 13:19:52 -05:00
parent 4024b3f1b3
commit 225147a94f
2 changed files with 63 additions and 26 deletions

View File

@ -239,10 +239,13 @@ struct BattleMove
u8 flags;
};
#define SPINDA_SPOT_WIDTH 16
#define SPINDA_SPOT_HEIGHT 16
struct SpindaSpot
{
u8 x, y;
u16 image[16];
u16 image[SPINDA_SPOT_HEIGHT];
};
struct __attribute__((packed)) LevelUpMove

View File

@ -1345,10 +1345,10 @@ static const u16 sHoennToNationalOrder[NUM_SPECIES - 1] =
const struct SpindaSpot gSpindaSpotGraphics[] =
{
{16, 7, INCBIN_U16("graphics/spinda_spots/spot_0.bin")},
{40, 8, INCBIN_U16("graphics/spinda_spots/spot_1.bin")},
{22, 25, INCBIN_U16("graphics/spinda_spots/spot_2.bin")},
{34, 26, INCBIN_U16("graphics/spinda_spots/spot_3.bin")}
{.x = 16, .y = 7, .image = INCBIN_U16("graphics/spinda_spots/spot_0.bin")},
{.x = 40, .y = 8, .image = INCBIN_U16("graphics/spinda_spots/spot_1.bin")},
{.x = 22, .y = 25, .image = INCBIN_U16("graphics/spinda_spots/spot_2.bin")},
{.x = 34, .y = 26, .image = INCBIN_U16("graphics/spinda_spots/spot_3.bin")}
};
#include "data/pokemon/item_effects.h"
@ -5653,42 +5653,76 @@ u16 SpeciesToCryId(u16 species)
return gSpeciesIdToCryId[species - (SPECIES_TREECKO - 1)];
}
#define DRAW_SPINDA_SPOTS \
// To draw the spot, add 4 to the color indexes
#define SPOT_COLOR_ADJUSTMENT 4
/*
The macro below handles drawing the randomly-placed spots on Spinda's front sprite.
Spinda has 4 spots, each with an entry in gSpindaSpotGraphics. Each entry contains
a base x and y coordinate for the spot and a 16x16 binary image. Each bit in the image
determines whether that pixel should be considered part of the spot.
The position of each spot is randomized using the Spinda's personality. The entire 32 bit
personality value is used, 4 bits for each coordinate of the 4 spots. If the personality
value is 0x87654321, then 0x1 will be used for the 1st spot's x coord, 0x2 will be used for
the 1st spot's y coord, 0x3 will be used for the 2nd spot's x coord, and so on. Each
coordinate is calculated as (baseCoord + (given 4 bits of personality) - 8). In effect this
means each spot can start at any position -8 to +7 off of its base coordinates (256 possibilities).
The macro then loops over the 16x16 spot image. For each bit in the spot's binary image, if
if the bit is set then it's part of the spot; try to draw it. A pixel is drawn on Spinda
if the pixel on Spinda satisfies the following formula: (colorIndex - 1 <= 2). The -1 excludes
transparent pixels, as these are index 0. Therefore only colors 1, 2, or 3 on Spinda will
allow a spot to be drawn. These color indexes are Spinda's light brown body colors. To create
the spot it adds 4 to the color index, so Spinda's spots will be colors 5, 6, and 7.
The above is done two different ways in the macro: one with << 4, and one without. This
is because Spinda's sprite is a 4 bits per pixel image, but the pointer to Spinda's pixels
(destPixels) is an 8 bit pointer, so it addresses two pixels. Shifting by 4 accesses the 2nd
of these pixels, so this is done every other time.
*/
#define DRAW_SPINDA_SPOTS(personality, dest) \
{ \
int i; \
for (i = 0; i < 4; i++) \
s32 i; \
for (i = 0; i < (s32)ARRAY_COUNT(gSpindaSpotGraphics); i++) \
{ \
int j; \
s32 row; \
u8 x = gSpindaSpotGraphics[i].x + ((personality & 0x0F) - 8); \
u8 y = gSpindaSpotGraphics[i].y + (((personality & 0xF0) >> 4) - 8); \
\
for (j = 0; j < 16; j++) \
for (row = 0; row < SPINDA_SPOT_HEIGHT; row++) \
{ \
int k; \
s32 row = gSpindaSpotGraphics[i].image[j]; \
s32 column; \
s32 spotPixelRow = gSpindaSpotGraphics[i].image[row]; \
\
for (k = x; k < x + 16; k++) \
for (column = x; column < x + SPINDA_SPOT_WIDTH; column++) \
{ \
u8 *val = dest + ((k / 8) * 32) + \
((k % 8) / 2) + \
((y >> 3) << 8) + \
((y & 7) << 2); \
/* Get target pixels on Spinda's sprite */ \
u8 *destPixels = dest + ((column / 8) * TILE_SIZE_4BPP) + \
((column % 8) / 2) + \
((y / 8) * TILE_SIZE_4BPP * 8) + \
((y % 8) * 4); \
\
if (row & 1) \
/* Is this pixel in the 16x16 spot image part of the spot? */ \
if (spotPixelRow & 1) \
{ \
if (k & 1) \
/* destPixels addressess two pixels, alternate which */ \
/* of the two pixels is being considered for drawing */ \
if (column & 1) \
{ \
if ((u8)((*val & 0xF0) - 0x10) <= 0x20) \
*val += 0x40; \
/* Draw spot pixel if this is Spinda's body color */ \
if ((u8)((*destPixels & 0xF0) - (1 << 4)) <= (2 << 4)) \
*destPixels += (SPOT_COLOR_ADJUSTMENT << 4); \
} \
else \
{ \
if ((u8)((*val & 0xF) - 0x01) <= 0x02) \
*val += 0x04; \
/* Draw spot pixel if this is Spinda's body color */ \
if ((u8)((*destPixels & 0xF) - 1) <= 2) \
*destPixels += SPOT_COLOR_ADJUSTMENT; \
} \
} \
\
row >>= 1; \
spotPixelRow >>= 1; \
} \
\
y++; \
@ -5705,13 +5739,13 @@ static void DrawSpindaSpotsUnused(u16 species, u32 personality, u8 *dest)
if (species == SPECIES_SPINDA
&& dest != gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT]
&& dest != gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_RIGHT])
DRAW_SPINDA_SPOTS;
DRAW_SPINDA_SPOTS(personality, dest);
}
void DrawSpindaSpots(u16 species, u32 personality, u8 *dest, bool8 isFrontPic)
{
if (species == SPECIES_SPINDA && isFrontPic)
DRAW_SPINDA_SPOTS;
DRAW_SPINDA_SPOTS(personality, dest);
}
void EvolutionRenameMon(struct Pokemon *mon, u16 oldSpecies, u16 newSpecies)