sprite optimizations + static array fix (#454)
Some checks failed
Build and Deploy Doxygen Docs / docs (push) Has been cancelled

* optimizations

* fix prototype

* clang-format

* changes

* fix bug

* fix bug that came back after rebase

* make is_sprite_object_static more readable

* make it not broken

* actually make it compile...

* clang-format

* remove first extra check

* remove second extra check

* remove third extra check

* helper function 1

* second helper function

* how did i do this that wrong

* seperate epsilon

* combine if statements

* clarify comment

* remove redundant checks

* Remove braces around return

Co-authored-by: Rickey <ric@rf3.xyz>

* Move comment to above

Co-authored-by: Rickey <ric@rf3.xyz>

* clang-format

* simplify using abs()

Co-authored-by: Rickey <ric@rf3.xyz>

* fix syntax error from suggestion

* drop second epsilon + use abs()

* update comment

* extract sprite_oject_needs_position_sync from is_sprite_object_static

* figured out the root cause :)

* make it compile

---------

Co-authored-by: Rickey <ric@rf3.xyz>
This commit is contained in:
Elliot Tester
2026-05-17 06:08:47 +02:00
committed by GitHub
parent d5d5a6fd6b
commit dae65d035f
4 changed files with 40 additions and 15 deletions

View File

@@ -236,7 +236,7 @@ void sprite_object_reset_transform(SpriteObject* sprite_object);
*
* @param sprite_object pointer to SpriteObject to update. Cannot be **NULL**.
*/
void sprite_object_update(SpriteObject* sprite_object);
IWRAM_CODE void sprite_object_update(SpriteObject* sprite_object);
/**
* @brief Shake SpriteObject on screen and play a sound

View File

@@ -561,7 +561,7 @@ static inline void discarded_jokers_update_loop(void)
static inline void held_jokers_update_loop(void)
{
const int spacing_lut[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] = {
static const int spacing_lut[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] = {
{0, 0, 0, 0, 0 },
{13, -13, 0, 0, 0 },
{26, 0, -26, 0, 0 },
@@ -1838,6 +1838,7 @@ static inline void card_draw(void)
card_object->sprite_object->x = deck_x;
card_object->sprite_object->y = deck_y;
sprite_position(card_object->sprite_object->sprite, fx2int(deck_x), fx2int(deck_y));
hand[++hand_top] = card_object;
@@ -2828,10 +2829,17 @@ static inline void cards_in_hand_update_loop(void)
{
hand_y -= int2fx(CARD_FOCUSED_SEL_Y);
}
if (i != selected_card_idx && hand[i]->sprite_object->y > hand_y)
{
hand[i]->sprite_object->y = hand_y;
sprite_position(
hand[i]->sprite_object->sprite,
fx2int(hand[i]->sprite_object->x),
fx2int(hand_y)
);
// Set target y to match y. Ensures target is updated even when vy becomes
// 0, preventing immediate snap back.
hand[i]->sprite_object->ty = hand_y;
hand[i]->sprite_object->vy = 0;
}

View File

@@ -124,9 +124,8 @@ void game_main_menu_on_init(void)
void game_main_menu_on_update(void)
{
card_object_update(main_menu_ace);
main_menu_ace->sprite_object->trotation = lu_sin((g_game_vars.timer << 8) / 2) / 3;
main_menu_ace->sprite_object->rotation = main_menu_ace->sprite_object->trotation;
card_object_update(main_menu_ace);
// Seed randomization
g_game_vars.rng_seed++;

View File

@@ -209,8 +209,27 @@ void sprite_object_reset_transform(SpriteObject* sprite_object)
sprite_object->vrotation = 0;
}
void sprite_object_update(SpriteObject* sprite_object)
static inline bool sprite_object_has_velocity(const SpriteObject* sprite_object)
{
return sprite_object->vx != 0 || sprite_object->vy != 0 || sprite_object->vscale != 0 ||
sprite_object->vrotation != 0;
}
static inline bool sprite_object_at_target(const SpriteObject* s)
{
return s->x == s->tx && s->y == s->ty && s->scale == s->tscale && s->rotation == s->trotation;
}
static inline bool is_sprite_object_static(const SpriteObject* sprite_object)
{
return !sprite_object_has_velocity(sprite_object) && sprite_object_at_target(sprite_object);
}
IWRAM_CODE void sprite_object_update(SpriteObject* sprite_object)
{
if (is_sprite_object_static(sprite_object))
return;
sprite_object->vx += ((sprite_object->tx - sprite_object->x) * g_game_vars.game_speed) / 8;
sprite_object->vy += ((sprite_object->ty - sprite_object->y) * g_game_vars.game_speed) / 8;
@@ -220,10 +239,10 @@ void sprite_object_update(SpriteObject* sprite_object)
// Rotate the card when it's played
sprite_object->vrotation += (sprite_object->trotation - sprite_object->rotation) / 8;
// set velocity to 0 if it's close enough to the target
const FIXED epsilon = (FIX_ONE >> 6); // = 1/2^6 = 0.015625
if (sprite_object->vx < epsilon && sprite_object->vx > -epsilon &&
sprite_object->vy < epsilon && sprite_object->vy > -epsilon)
// Snap to target position when velocity is negligible to avoid infinite approach
if (abs(sprite_object->vx) < epsilon && abs(sprite_object->vy) < epsilon)
{
sprite_object->vx = 0;
sprite_object->vy = 0;
@@ -243,10 +262,10 @@ void sprite_object_update(SpriteObject* sprite_object)
}
// Set scale to 0 if it's close enough to the target
if (sprite_object->vscale < epsilon && sprite_object->vscale > -epsilon)
if (abs(sprite_object->vscale) < epsilon)
{
sprite_object->vscale = 0;
sprite_object->scale = sprite_object->tscale; // Set the scale to the target scale
sprite_object->scale = sprite_object->tscale;
}
else
{
@@ -256,14 +275,13 @@ void sprite_object_update(SpriteObject* sprite_object)
sprite_object->scale += sprite_object->vscale;
}
// Set rotation to 0 if it's close enough to the target
if (sprite_object->vrotation < epsilon && sprite_object->vrotation > -epsilon)
// For rotation, prioritize snapping to target if close enough, then zero velocity.
if (abs(sprite_object->vrotation) < epsilon)
{
sprite_object->vrotation = 0;
// Set the rotation to the target rotation
sprite_object->rotation = sprite_object->trotation;
}
else
else // Apply damping and update rotation if not yet settled
{
sprite_object->vrotation =
(sprite_object->vrotation * SPRING_DAMP_NUMERATOR + SPRING_DAMP_ROUNDING) >>