Document minigame countdown

This commit is contained in:
GriffinR 2021-03-11 14:16:40 -05:00
parent 69f7882b5e
commit b1a69d95ea
6 changed files with 457 additions and 325 deletions

View File

Before

Width:  |  Height:  |  Size: 778 B

After

Width:  |  Height:  |  Size: 778 B

View File

@ -62,7 +62,7 @@
#define LINKCMD_0x6666 0x6666
#define LINKCMD_0x7777 0x7777
#define LINKCMD_BLENDER_PLAY_AGAIN 0x7779
#define LINKCMD_0x7FFF 0x7FFF
#define LINKCMD_COUNTDOWN 0x7FFF
#define LINKCMD_CONT_BLOCK 0x8888
#define LINKCMD_BLENDER_NO_BERRIES 0x9999
#define LINKCMD_BLENDER_NO_PBLOCK_SPACE 0xAAAA

View File

@ -38,6 +38,8 @@
#include "constants/rgb.h"
#include "constants/songs.h"
#define TAG_COUNTDOWN 0x1000
struct BerryCrushGame_Player
{
u8 unk0[PLAYER_NAME_LENGTH + 1 + 4];
@ -2295,7 +2297,7 @@ static u32 sub_80232EC(struct BerryCrushGame *r4, __attribute__((unused)) u8 *r
case 1:
if (!IsLinkTaskFinished())
return 0;
StartMinigameCountdown(0x1000, 0x1000, 120, 80, 0);
StartMinigameCountdown(TAG_COUNTDOWN, TAG_COUNTDOWN, 120, 80, 0);
break;
case 2:
if (IsMinigameCountdownRunning())

View File

@ -149,12 +149,14 @@ enum {
#define GFXTAG_STATUS 1
#define GFXTAG_BERRIES 2
#define GFXTAG_CLOUD 5
#define GFXTAG_COUNTDOWN 7
#define PALTAG_DODRIO_NORMAL 0
#define PALTAG_DODRIO_SHINY 1
#define PALTAG_STATUS 2
#define PALTAG_BERRIES 3
#define PALTAG_CLOUD 6
#define PALTAG_COUNTDOWN 8
#define NUM_CLOUDS 2
@ -871,7 +873,7 @@ static void DoCountdown(void)
switch (sGame->state)
{
case 0:
StartMinigameCountdown(7, 8, 120, 80, 0);
StartMinigameCountdown(GFXTAG_COUNTDOWN, PALTAG_COUNTDOWN, 120, 80, 0);
sGame->state++;
break;
case 1:

View File

@ -5,15 +5,366 @@
#include "sound.h"
#include "task.h"
#include "trig.h"
#include "minigame_countdown.h"
#include "constants/songs.h"
/*
This file contains two types of '3-2-1 Start' countdowns intended for use by the wireless minigames.
One is static, where the numbers simply appear and disappear without moving. This version is unused.
The other (used) version has the numbers squish and bounce up as they appear.
*/
#define TAG_STATIC_COUNTDOWN 0x2000
enum {
STATE_IDLE = 1,
STATE_START,
STATE_RUN,
STATE_END,
};
enum {
FUNC_INIT,
FUNC_FREE,
FUNC_START,
FUNC_RUN,
};
enum {
ANIM_THREE,
ANIM_TWO,
ANIM_ONE,
ANIM_START_LEFT,
ANIM_START_MID,
ANIM_START_RIGHT,
};
extern const struct OamData gOamData_AffineOff_ObjNormal_32x32;
static void sub_802E6D0(u8 taskId);
static void sub_802E83C(u8 taskId);
static void sub_802E8C8(u8 taskId);
static void sub_802EA50(u8 taskId);
static void sub_802EAB0(u8 taskId);
static void Task_StaticCountdown(u8 taskId);
static void Task_StaticCountdown_Init(u8 taskId);
static void Task_StaticCountdown_Free(u8 taskId);
static void Task_StaticCountdown_Start(u8 taskId);
static void Task_StaticCountdown_Run(u8 taskId);
static const u16 s321Start_Static_Pal[] = INCBIN_U16("graphics/link_games/321start_static.gbapal");
static const u32 s321Start_Static_Gfx[] = INCBIN_U32("graphics/link_games/321start_static.4bpp.lz");
static const struct CompressedSpriteSheet sSpriteSheet_321Start_Static[] =
{
{s321Start_Static_Gfx, 0xC00, TAG_STATIC_COUNTDOWN},
{},
};
static const struct SpritePalette sSpritePalette_321Start_Static[] =
{
{s321Start_Static_Pal, TAG_STATIC_COUNTDOWN},
{},
};
static const union AnimCmd sAnim_StaticCountdown_Three[] =
{
ANIMCMD_FRAME(0, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_StaticCountdown_Two[] =
{
ANIMCMD_FRAME(16, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_StaticCountdown_One[] =
{
ANIMCMD_FRAME(32, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_StaticCountdown_StartLeft[] =
{
ANIMCMD_FRAME(64, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_StaticCountdown_StartMid[] =
{
ANIMCMD_FRAME(48, 0),
ANIMCMD_END
};
static const union AnimCmd sAnim_StaticCountdown_StartRight[] =
{
ANIMCMD_FRAME(80, 0),
ANIMCMD_END
};
static const union AnimCmd *const sAnims_StaticCountdown[] =
{
[ANIM_THREE] = sAnim_StaticCountdown_Three,
[ANIM_TWO] = sAnim_StaticCountdown_Two,
[ANIM_ONE] = sAnim_StaticCountdown_One,
[ANIM_START_LEFT] = sAnim_StaticCountdown_StartLeft,
[ANIM_START_MID] = sAnim_StaticCountdown_StartMid,
[ANIM_START_RIGHT] = sAnim_StaticCountdown_StartRight
};
static const struct SpriteTemplate sSpriteTemplate_StaticCountdown[] =
{
{
.tileTag = TAG_STATIC_COUNTDOWN,
.paletteTag = TAG_STATIC_COUNTDOWN,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = sAnims_StaticCountdown,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
};
static const TaskFunc sStaticCountdownFuncs[][4] =
{
{
[FUNC_INIT] = Task_StaticCountdown_Init,
[FUNC_FREE] = Task_StaticCountdown_Free,
[FUNC_START] = Task_StaticCountdown_Start,
[FUNC_RUN] = Task_StaticCountdown_Run
},
};
#define tState data[0]
#define tFuncSetId data[1] // These 4 data elements are indexes into
#define tSpriteTemplateId data[2] // arrays that only have 1 element with
#define tSpriteSheetId data[3] // data. As such their only legal value
#define tSpritePalId data[4] // is 0. Unclear why they were used.
#define tInterval data[5]
#define tPriority data[6]
#define tSubpriority data[7]
#define tNumSprites data[8]
#define tX data[9]
#define tY data[10]
#define tPrevTime data[10] // Re-used
#define tTimer data[11]
#define tLinkTimer data[12]
// 13-15 hold sprite ids
// tSpriteIds(0) is used for the number sprites, and the leftmost part of 'Start'
// tSpriteIds(1) is used for the middle part of 'Start'
// tSpriteIds(2) is used for for the rightmost part of 'Start'
#define tSpriteIds(i) data[13 + i]
#define sInterval data[1] // Never read
#define sAnimNum data[2]
#define sTaskId data[3]
#define sId data[4] // Never read
#define sNumberSpriteId data[5] // Never read
// Unused
static u32 CreateStaticCountdownTask(u8 funcSetId, u8 taskPriority)
{
u8 taskId = CreateTask(Task_StaticCountdown, taskPriority);
struct Task *task = &gTasks[taskId];
task->tState = STATE_IDLE;
task->tFuncSetId = funcSetId;
sStaticCountdownFuncs[funcSetId][FUNC_INIT](taskId);
return taskId;
}
static bool32 StartStaticCountdown(void)
{
u8 taskId = FindTaskIdByFunc(Task_StaticCountdown);
if (taskId == TASK_NONE)
return FALSE;
gTasks[taskId].tState = STATE_START;
return TRUE;
}
static bool32 IsStaticCountdownRunning(void)
{
return FuncIsActiveTask(Task_StaticCountdown);
}
static void Task_StaticCountdown(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (tState)
{
// STATE_IDLE does nothing; wait until started
case STATE_START:
sStaticCountdownFuncs[tFuncSetId][FUNC_START](taskId);
tState = STATE_RUN;
break;
case STATE_RUN:
sStaticCountdownFuncs[tFuncSetId][FUNC_RUN](taskId);
break;
case STATE_END:
sStaticCountdownFuncs[tFuncSetId][FUNC_FREE](taskId);
DestroyTask(taskId);
break;
}
}
static void StaticCountdown_CreateSprites(u8 taskId, s16 *data)
{
u8 i;
struct Sprite *sprite;
LoadCompressedSpriteSheet(&sSpriteSheet_321Start_Static[tSpriteSheetId]);
LoadSpritePalette(&sSpritePalette_321Start_Static[tSpritePalId]);
for (i = 0; i < tNumSprites; i++)
tSpriteIds(i) = CreateSprite(&sSpriteTemplate_StaticCountdown[tSpriteTemplateId], tX, tY, tSubpriority);
for (i = 0; i < tNumSprites; i++)
{
sprite = &gSprites[tSpriteIds(i)];
sprite->oam.priority = tPriority;
sprite->invisible = TRUE;
sprite->sInterval = tInterval;
sprite->sTaskId = taskId;
sprite->sId = i;
sprite->sNumberSpriteId = tSpriteIds(0);
}
}
static void Task_StaticCountdown_Init(u8 taskId)
{
s16 *data = gTasks[taskId].data;
tSpriteTemplateId = 0;
tSpriteSheetId = 0;
tSpritePalId = 0;
tInterval = 60;
tPriority = 0;
tSubpriority = 0;
tNumSprites = 3;
tX = 120;
tY = 88;
StaticCountdown_CreateSprites(taskId, data);
StartSpriteAnim(&gSprites[tSpriteIds(1)], ANIM_START_MID);
gSprites[tSpriteIds(1)].pos2.x = -32;
StartSpriteAnim(&gSprites[tSpriteIds(2)], ANIM_START_RIGHT);
gSprites[tSpriteIds(2)].pos2.x = 32;
}
static void Task_StaticCountdown_Free(u8 taskId)
{
u8 i = 0;
s16 *data = gTasks[taskId].data;
for (i = 0; i < tNumSprites; i++)
DestroySprite(&gSprites[tSpriteIds(i)]);
FreeSpriteTilesByTag(sSpriteSheet_321Start_Static[tSpriteSheetId].tag);
FreeSpritePaletteByTag(sSpritePalette_321Start_Static[tSpritePalId].tag);
}
static void SpriteCB_StaticCountdown(struct Sprite *sprite)
{
s16 *data = gTasks[sprite->sTaskId].data;
if (tTimer % tInterval != 0)
return;
if (tTimer == tPrevTime)
return;
tPrevTime = tTimer;
switch (sprite->sAnimNum)
{
case ANIM_THREE:
sprite->invisible = FALSE;
case ANIM_TWO:
case ANIM_ONE:
// Set sprite to a number
PlaySE(SE_BALL_BOUNCE_1);
StartSpriteAnim(sprite, sprite->sAnimNum);
break;
case ANIM_START_LEFT:
// Set sprite to 'Start'
PlaySE(SE_PIN);
StartSpriteAnim(sprite, sprite->sAnimNum);
gSprites[tSpriteIds(1)].invisible = FALSE;
gSprites[tSpriteIds(2)].invisible = FALSE;
break;
case ANIM_START_LEFT + 1: // End
// Hide countdown
sprite->invisible = TRUE;
gSprites[tSpriteIds(1)].invisible = TRUE;
gSprites[tSpriteIds(2)].invisible = TRUE;
tState = STATE_END;
return;
}
sprite->sAnimNum++;
}
static void Task_StaticCountdown_Start(u8 taskId)
{
s16 *data = gTasks[taskId].data;
PlaySE(SE_BALL_BOUNCE_1);
gSprites[tSpriteIds(0)].callback = SpriteCB_StaticCountdown;
gSprites[tSpriteIds(0)].invisible = FALSE;
gTasks[taskId].tState = STATE_RUN;
}
// Increment timer for progressing the countdown.
// If the player is the link leader, increment a
// separate timer and send it to group members for
// them to read and use.
static void Task_StaticCountdown_Run(u8 taskId)
{
u16 packet[RFU_PACKET_SIZE];
s16 *data = gTasks[taskId].data;
if (gReceivedRemoteLinkPlayers != 0)
{
// Read link timer
if (gRecvCmds[0][1] == LINKCMD_COUNTDOWN)
tTimer = gRecvCmds[0][2];
if (GetMultiplayerId() == 0)
{
// Player is link leader.
// Send timer to group members
tLinkTimer++;
memset(packet, 0, sizeof(packet));
packet[0] = LINKCMD_COUNTDOWN;
packet[1] = tLinkTimer;
Rfu_SendPacket(packet);
}
}
else
{
// Local, just increment own timer
tTimer++;
}
}
#undef tState
#undef tFuncSetId
#undef tSpriteTemplateId
#undef tSpriteSheetId
#undef tSpritePalId
#undef tInterval
#undef tPriority
#undef tSubpriority
#undef tNumSprites
#undef tX
#undef tY
#undef tPrevTime
#undef tTimer
#undef tLinkTimer
#undef tSpriteIds
#undef sInterval
#undef sAnimNum
#undef sTaskId
#undef sId
#undef sNumberSpriteId
/*
The countdown that actually gets used by
the wireless minigames starts here
*/
static void Task_MinigameCountdown(u8 taskId);
static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId);
static bool32 IsStartGraphicAnimRunning(u8 spriteId);
@ -23,260 +374,8 @@ static void CreateStartSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subprior
static void InitStartGraphic(u8 spriteId1, u8 spriteId2, u8 spriteId3);
static void SpriteCB_Start(struct Sprite *sprite);
static const u16 sSpritePal_321Start_2[] = INCBIN_U16("graphics/link_games/321start_2.gbapal");
static const u32 sSpriteSheet_321Start_2[] = INCBIN_U32("graphics/link_games/321start_2.4bpp.lz");
static const struct CompressedSpriteSheet gUnknown_082FE6C8[] =
{
{sSpriteSheet_321Start_2, 0xC00, 0x2000},
{},
};
static const struct SpritePalette gUnknown_082FE6D8[] =
{
{sSpritePal_321Start_2, 0x2000},
{},
};
static const union AnimCmd sSpriteAnim_82FE6E8[] =
{
ANIMCMD_FRAME(0, 0),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_82FE6F0[] =
{
ANIMCMD_FRAME(16, 0),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_82FE6F8[] =
{
ANIMCMD_FRAME(32, 0),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_82FE700[] =
{
ANIMCMD_FRAME(64, 0),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_82FE708[] =
{
ANIMCMD_FRAME(48, 0),
ANIMCMD_END
};
static const union AnimCmd sSpriteAnim_82FE710[] =
{
ANIMCMD_FRAME(80, 0),
ANIMCMD_END
};
static const union AnimCmd *const sSpriteAnimTable_82FE718[] =
{
sSpriteAnim_82FE6E8,
sSpriteAnim_82FE6F0,
sSpriteAnim_82FE6F8,
sSpriteAnim_82FE700,
sSpriteAnim_82FE708,
sSpriteAnim_82FE710
};
static const struct SpriteTemplate gUnknown_082FE730[] =
{
{
.tileTag = 0x2000,
.paletteTag = 0x2000,
.oam = &gOamData_AffineOff_ObjNormal_32x32,
.anims = sSpriteAnimTable_82FE718,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
},
};
static const TaskFunc gUnknown_082FE748[][4] =
{
{
sub_802E83C,
sub_802E8C8,
sub_802EA50,
sub_802EAB0
},
};
static const u16 sSpritePal_321Start[] = INCBIN_U16("graphics/link_games/321start.gbapal");
static const u32 sSpriteSheet_321Start[] = INCBIN_U32("graphics/link_games/321start.4bpp.lz");
// Unused
static u32 sub_802E63C(u8 funcSetId, u8 taskPriority)
{
u8 taskId = CreateTask(sub_802E6D0, taskPriority);
struct Task *task = &gTasks[taskId];
task->data[0] = 1;
task->data[1] = funcSetId;
gUnknown_082FE748[funcSetId][0](taskId);
return taskId;
}
static bool32 sub_802E688(void)
{
u8 taskId = FindTaskIdByFunc(sub_802E6D0);
if (taskId == TASK_NONE)
return FALSE;
gTasks[taskId].data[0] = 2;
return TRUE;
}
static bool32 sub_802E6BC(void)
{
return FuncIsActiveTask(sub_802E6D0);
}
static void sub_802E6D0(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (data[0])
{
case 2:
gUnknown_082FE748[data[1]][2](taskId);
data[0] = 3;
break;
case 3:
gUnknown_082FE748[data[1]][3](taskId);
break;
case 4:
gUnknown_082FE748[data[1]][1](taskId);
DestroyTask(taskId);
break;
}
}
static void sub_802E75C(u8 taskId, s16 *data)
{
u8 i;
struct Sprite *sprite;
LoadCompressedSpriteSheet(&gUnknown_082FE6C8[data[3]]);
LoadSpritePalette(&gUnknown_082FE6D8[data[4]]);
for (i = 0; i < data[8]; i++)
data[13 + i] = CreateSprite(&gUnknown_082FE730[data[2]], data[9], data[10], data[7]);
for (i = 0; i < data[8]; i++)
{
sprite = &gSprites[data[13 + i]];
sprite->oam.priority = data[6];
sprite->invisible = TRUE;
sprite->data[1] = data[5];
sprite->data[3] = taskId;
sprite->data[4] = i;
sprite->data[5] = data[13];
}
}
static void sub_802E83C(u8 taskId)
{
s16 *data = gTasks[taskId].data;
data[2] = 0;
data[3] = 0;
data[4] = 0;
data[5] = 60;
data[6] = 0;
data[7] = 0;
data[8] = 3;
data[9] = 120;
data[10] = 88;
sub_802E75C(taskId, data);
StartSpriteAnim(&gSprites[data[14]], 4);
gSprites[data[14]].pos2.x = -32;
StartSpriteAnim(&gSprites[data[15]], 5);
gSprites[data[15]].pos2.x = 32;
}
static void sub_802E8C8(u8 taskId)
{
u8 i = 0;
s16 *data = gTasks[taskId].data;
for (i = 0; i < data[8]; i++)
DestroySprite(&gSprites[data[13 + i]]);
FreeSpriteTilesByTag(gUnknown_082FE6C8[data[3]].tag);
FreeSpritePaletteByTag(gUnknown_082FE6D8[data[4]].tag);
}
static void sub_802E938(struct Sprite *sprite)
{
s16 *data = gTasks[sprite->data[3]].data;
if (data[11] % data[5] != 0)
return;
if (data[11] == data[10])
return;
data[10] = data[11];
switch (sprite->data[2])
{
case 0:
sprite->invisible = FALSE;
case 1:
case 2:
PlaySE(SE_BALL_BOUNCE_1);
StartSpriteAnim(sprite, sprite->data[2]);
break;
case 3:
PlaySE(SE_PIN);
StartSpriteAnim(sprite, sprite->data[2]);
gSprites[data[14]].invisible = FALSE;
gSprites[data[15]].invisible = FALSE;
break;
case 4:
sprite->invisible = TRUE;
gSprites[data[14]].invisible = TRUE;
gSprites[data[15]].invisible = TRUE;
data[0] = 4;
return;
}
sprite->data[2]++;
}
static void sub_802EA50(u8 taskId)
{
s16 *data = gTasks[taskId].data;
PlaySE(SE_BALL_BOUNCE_1);
gSprites[data[13]].callback = sub_802E938;
gSprites[data[13]].invisible = FALSE;
gTasks[taskId].data[0] = 3;
}
static void sub_802EAB0(u8 taskId)
{
u16 packet[6];
s16 *data = gTasks[taskId].data;
if (gReceivedRemoteLinkPlayers != 0)
{
if (gRecvCmds[0][1] == LINKCMD_0x7FFF)
data[11] = gRecvCmds[0][2];
if (GetMultiplayerId() == 0)
{
data[12]++;
memset(packet, 0, sizeof(packet));
packet[0] = LINKCMD_0x7FFF;
packet[1] = data[12];
Rfu_SendPacket(packet);
}
}
else
{
data[11]++;
}
}
static const u16 s321Start_Pal[] = INCBIN_U16("graphics/link_games/321start.gbapal");
static const u32 s321Start_Gfx[] = INCBIN_U32("graphics/link_games/321start.4bpp.lz");
#define tState data[0]
#define tTilesTag data[2]
@ -288,7 +387,7 @@ static void sub_802EAB0(u8 taskId)
#define tSpriteId2 data[8]
#define tSpriteId3 data[9]
void StartMinigameCountdown(s16 tilesTag, s16 palTag, s16 x, s16 y, u8 subpriority)
void StartMinigameCountdown(u16 tilesTag, u16 palTag, s16 x, s16 y, u8 subpriority)
{
u8 taskId = CreateTask(Task_MinigameCountdown, 80);
gTasks[taskId].tTilesTag = tilesTag;
@ -337,69 +436,82 @@ static void Task_MinigameCountdown(u8 taskId)
}
}
#define sState data[0]
#define sTimer data[2]
#define sAnimNum data[4]
static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId)
{
struct Sprite *sprite = &gSprites[spriteId];
switch (sprite->data[0])
switch (sprite->sState)
{
case 0:
sub_8007E18(sprite, 0x800, 0x1A);
sprite->data[0]++;
sprite->sState++;
// fallthrough
case 1:
if (sprite->data[2] == 0)
if (sprite->sTimer == 0)
PlaySE(SE_BALL_BOUNCE_2);
if (++sprite->data[2] >= 20)
if (++sprite->sTimer >= 20)
{
sprite->data[2] = 0;
// Ready for jump
sprite->sTimer = 0;
StartSpriteAffineAnim(sprite, 1);
sprite->data[0]++;
sprite->sState++;
}
break;
case 2:
if (sprite->affineAnimEnded)
sprite->data[0]++;
sprite->sState++;
break;
case 3:
if (++sprite->data[2] >= 4)
if (++sprite->sTimer >= 4)
{
sprite->data[2] = 0;
sprite->data[0]++;
// Start jump
sprite->sTimer = 0;
sprite->sState++;
StartSpriteAffineAnim(sprite, 2);
}
break;
case 4:
// Moving up from jump
sprite->pos1.y -= 4;
if (++sprite->data[2] >= 8)
if (++sprite->sTimer >= 8)
{
if (sprite->data[4] <= 1)
if (sprite->sAnimNum < 2)
{
StartSpriteAnim(sprite, sprite->data[4] + 1);
sprite->data[2] = 0;
sprite->data[0]++;
// Swap to the next number
StartSpriteAnim(sprite, sprite->sAnimNum + 1);
sprite->sTimer = 0;
sprite->sState++;
}
else
{
sprite->data[0] = 7;
// End
sprite->sState = 7;
return FALSE;
}
}
break;
case 5:
// Falling after jump
sprite->pos1.y += 4;
if (++sprite->data[2] >= 8)
if (++sprite->sTimer >= 8)
{
sprite->data[2] = 0;
// Land from jump
sprite->sTimer = 0;
StartSpriteAffineAnim(sprite, 3);
sprite->data[0]++;
sprite->sState++;
}
break;
case 6:
if (sprite->affineAnimEnded)
{
sprite->data[4]++;
sprite->data[0] = 1;
// Restart for next number
sprite->sAnimNum++;
sprite->sState = 1;
}
break;
case 7:
@ -409,6 +521,10 @@ static bool32 RunMinigameCountdownDigitsAnim(u8 spriteId)
return TRUE;
}
#undef sState
#undef sTimer
#undef sAnimNum
// First argument is unused.
static void InitStartGraphic(u8 spriteId1, u8 spriteId2, u8 spriteId3)
{
@ -425,60 +541,70 @@ static bool32 IsStartGraphicAnimRunning(u8 spriteId)
return gSprites[spriteId].callback == SpriteCB_Start;
}
#define sState data[0]
#define sTimer data[1]
#define sYSpeed data[4]
#define sY data[5]
static void SpriteCB_Start(struct Sprite *sprite)
{
int y;
s16 *data = sprite->data;
switch (data[0])
switch (sState)
{
case 0:
data[4] = 64;
data[5] = sprite->pos2.y << 4;
data[0]++;
sYSpeed = 64;
sY = sprite->pos2.y << 4;
sState++;
case 1:
data[5] += data[4];
data[4]++;
sprite->pos2.y = data[5] >> 4;
sY += sYSpeed;
sYSpeed++;
sprite->pos2.y = sY >> 4;
if (sprite->pos2.y >= 0)
{
PlaySE(SE_BALL_BOUNCE_2);
sprite->pos2.y = 0;
data[0]++;
sState++;
}
break;
case 2:
data[1] += 12;
if (data[1] >= 128)
sTimer += 12;
if (sTimer >= 128)
{
PlaySE(SE_BALL_BOUNCE_2);
data[1] = 0;
data[0]++;
sTimer = 0;
sState++;
}
y = gSineTable[data[1]];
y = gSineTable[sTimer];
sprite->pos2.y = -(y >> 4);
break;
case 3:
data[1] += 16;
if (data[1] >= 128)
sTimer += 16;
if (sTimer >= 128)
{
PlaySE(SE_BALL_BOUNCE_2);
data[1] = 0;
data[0]++;
sTimer = 0;
sState++;
}
sprite->pos2.y = -(gSineTable[data[1]] >> 5);
sprite->pos2.y = -(gSineTable[sTimer] >> 5);
break;
case 4:
if (++data[1] > 40)
if (++sTimer > 40)
sprite->callback = SpriteCallbackDummy;
break;
}
}
#undef sState
#undef sTimer
#undef sYSpeed
#undef sY
static void Load321StartGfx(u16 tileTag, u16 palTag)
{
struct CompressedSpriteSheet spriteSheet = {sSpriteSheet_321Start, 0xE00, 0};
struct SpritePalette spritePalette = {sSpritePal_321Start, 0};
struct CompressedSpriteSheet spriteSheet = {s321Start_Gfx, 0xE00, 0};
struct SpritePalette spritePalette = {s321Start_Pal, 0};
spriteSheet.tag = tileTag;
spritePalette.tag = palTag;
@ -564,26 +690,26 @@ static const union AnimCmd *const sAnimTable_Start[] =
sAnim_StartRight
};
static const union AffineAnimCmd sAffineAnim_Numbers_0[] =
static const union AffineAnimCmd sAffineAnim_Numbers_Normal[] =
{
AFFINEANIMCMD_FRAME(256, 256, 0, 0),
AFFINEANIMCMD_END
};
static const union AffineAnimCmd sAffineAnim_Numbers_1[] =
static const union AffineAnimCmd sAffineAnim_Numbers_Squash[] =
{
AFFINEANIMCMD_FRAME(256, 256, 0, 0),
AFFINEANIMCMD_FRAME(16, -16, 0, 8),
AFFINEANIMCMD_END
};
static const union AffineAnimCmd sAffineAnim_Numbers_2[] =
static const union AffineAnimCmd sAffineAnim_Numbers_Stretch[] =
{
AFFINEANIMCMD_FRAME(-18, 18, 0, 8),
AFFINEANIMCMD_END
};
static const union AffineAnimCmd sAffineAnim_Numbers_3[] =
static const union AffineAnimCmd sAffineAnim_Numbers_Land[] =
{
AFFINEANIMCMD_FRAME( 6, -6, 0, 8),
AFFINEANIMCMD_FRAME( -4, 4, 0, 8),
@ -593,10 +719,10 @@ static const union AffineAnimCmd sAffineAnim_Numbers_3[] =
static const union AffineAnimCmd *const sAffineAnimTable_Numbers[] =
{
sAffineAnim_Numbers_0,
sAffineAnim_Numbers_1,
sAffineAnim_Numbers_2,
sAffineAnim_Numbers_3
sAffineAnim_Numbers_Normal,
sAffineAnim_Numbers_Squash, // Push down before the jump
sAffineAnim_Numbers_Stretch, // Stretch up for the jump
sAffineAnim_Numbers_Land // Land after the jump
};
static u8 CreateNumberSprite(u16 tileTag, u16 palTag, s16 x, s16 y, u8 subpriority)

View File

@ -135,10 +135,12 @@ enum {
#define GFXTAG_VINE2 6
#define GFXTAG_VINE3 7
#define GFXTAG_VINE4 8
#define GFXTAG_COUNTDOWN 9
#define GFXTAG_STAR 10
#define PALTAG_1 5
#define PALTAG_2 6
#define PALTAG_COUNTDOWN 7
#define TAG_DIGITS 800
@ -3007,7 +3009,7 @@ static void UpdateVineAnim(struct PokemonJumpGfx *jumpGfx, int vineState)
static void StartPokeJumpCountdown(struct PokemonJumpGfx *jumpGfx)
{
StartMinigameCountdown(9, 7, 120, 80, 0);
StartMinigameCountdown(GFXTAG_COUNTDOWN, PALTAG_COUNTDOWN, 120, 80, 0);
Gfx_ResetMonSpriteSubpriorities(jumpGfx);
}