- 6
- Posts
- 1
- Years
- Seen Dec 26, 2024
I might be in way over my head here but I've sloppily pulled together some code to prototype a scrollable list of moves for each species in the Pokédex. I've also added the relevant move type sprite icon alongside each move in the list - I've added these as sprites rather than background tiles so I can attribute the right palette colours to each one, and because all backgrounds are in use.
I have the list working and scrolling almost exactly as I want, but there's a small issue which is driving me mad. The function which updates the scrolling animation is a modified version of
I thought this may have been due to how unoptimised the code was, and that there was just too much going on between each frame, but I get the same behaviour when reducing down to a single sprite with hardcoded increments. My guess is that the GPU register and the sprites are updated visually on-screen at different points, and that's what's causing the discrepancy. But since I mostly just tinker with game logic rather than graphics programming, I don't really know where to start on finding a solution. I did wonder if there was a way to force the frame to be drawn later, so that both the sprites and the background would be in sync, but I've not figured that out yet.
Any help would be appreciated, as I'm struggling to find much I can read up on to understand the cause of the issue.
I will also share the function which scrolls the list below (apologies, I know it's gross - the idea was to get something working and then tidy up from there):
I have the list working and scrolling almost exactly as I want, but there's a small issue which is driving me mad. The function which updates the scrolling animation is a modified version of
UpdateDexListScroll
and works by incrementing the GPU register REG_OFFSET_BG3VOFS
at the same time and increment as the move type sprites, so that they would move in unison. However, despite debug statements confirming that the increments are identical each frame, the visual rendering is not. The list in BG3 begins updating its position on screen before the sprites do, and sometimes either jumps ahead or skips a frame when moving. Here's how that looks in practice (notice the 'jostling'):I thought this may have been due to how unoptimised the code was, and that there was just too much going on between each frame, but I get the same behaviour when reducing down to a single sprite with hardcoded increments. My guess is that the GPU register and the sprites are updated visually on-screen at different points, and that's what's causing the discrepancy. But since I mostly just tinker with game logic rather than graphics programming, I don't really know where to start on finding a solution. I did wonder if there was a way to force the frame to be drawn later, so that both the sprites and the background would be in sync, but I've not figured that out yet.
Any help would be appreciated, as I'm struggling to find much I can read up on to understand the cause of the issue.
I will also share the function which scrolls the list below (apologies, I know it's gross - the idea was to get something working and then tidy up from there):
Spoiler: UpdateMovesListScroll
C:
static bool8 UpdateMovesListScroll(u8 direction, u8 monMoveIncrement, u8 scrollTimerMax)
{
s32 offset, newOffset, moveIndex;
u32 step, moveType;
u32 i;
if (sMovesView->scrollTimer)
{
sMovesView->scrollTimer--;
offset = sMovesView->listMovingVOffset * LIST_SCROLL_STEP;
step = LIST_SCROLL_STEP * (scrollTimerMax - sMovesView->scrollTimer) / scrollTimerMax;
newOffset = (direction == 1) ? (offset - step) : (offset + step);
for (i = 0; i < 10; i++)
{
gSprites[sMovesView->spriteIds[i]].y = sMovesView->spriteYPos[i] + (direction == 1 ? step : -step);
}
SetGpuReg(REG_OFFSET_BG3VOFS, sMovesView->initialVOffset + newOffset);
return FALSE;
}
else
{
for (i = 0; i < 10; i++)
{
struct Sprite* currentSprite = &gSprites[sMovesView->spriteIds[i]];
currentSprite->y = sMovesView->spriteYPos[i];
moveIndex = sMovesView->selectedMove + i - 4;
if(moveIndex < 0 || moveIndex >= sMovesView->movesListCount)
{
currentSprite->invisible = TRUE;
}
else
{
currentSprite->invisible = FALSE;
moveType = gBattleMoves[sMovesView->movesList[moveIndex].move].type;
StartSpriteAnim(currentSprite, moveType);
currentSprite->oam.paletteNum = sMoveTypeToOamPaletteNum[moveType];
}
}
SetGpuReg(REG_OFFSET_BG3VOFS, sMovesView->initialVOffset + sMovesView->listVOffset * LIST_SCROLL_STEP);
return TRUE;
}
}
Last edited: