Implement a global SpriteObject update loop (#553)

* Implement `sprite_object_update_all`

* clang format

* Change update order

* tmp

* make it crash

* Fix bad address crash

* Address @MeirGavish's comments

* Tweaked card draw position further

* Tweaked card draw position further, again

---------

Co-authored-by: MathisMartin31 <mathis.martin31@gmail.com>
This commit is contained in:
Geralt
2026-06-17 19:26:53 -07:00
committed by GitHub
co-authored by MathisMartin31
parent d2cdc7af1b
commit c706a387a9
10 changed files with 27 additions and 44 deletions
-1
View File
@@ -75,7 +75,6 @@ u8 card_get_value(Card* card);
// CardObject methods // CardObject methods
CardObject* card_object_new(Card* card); CardObject* card_object_new(Card* card);
void card_object_destroy(CardObject** card_object); void card_object_destroy(CardObject** card_object);
void card_object_update(CardObject* card_object); // Update the card object position and scale
void card_object_set_sprite(CardObject* card_object, int layer); void card_object_set_sprite(CardObject* card_object, int layer);
void card_object_set_sprite_face_down(CardObject* card_object, enum DeckType deck, int layer); void card_object_set_sprite_face_down(CardObject* card_object, enum DeckType deck, int layer);
void card_object_shake(CardObject* card_object, mm_word sound_id); void card_object_shake(CardObject* card_object, mm_word sound_id);
-1
View File
@@ -195,7 +195,6 @@ int joker_get_sell_value(const Joker* joker);
JokerObject* joker_object_new(Joker* joker); JokerObject* joker_object_new(Joker* joker);
void joker_object_destroy(JokerObject** joker_object); void joker_object_destroy(JokerObject** joker_object);
void joker_object_update(JokerObject* joker_object);
// This doesn't actually score anything, it just performs an animation and plays a sound effect // This doesn't actually score anything, it just performs an animation and plays a sound effect
void joker_object_shake(JokerObject* joker_object, mm_word sound_id); void joker_object_shake(JokerObject* joker_object, mm_word sound_id);
// This scores the joker and returns true if it was scored successfully // This scores the joker and returns true if it was scored successfully
+7
View File
@@ -238,6 +238,13 @@ void sprite_object_reset_transform(SpriteObject* sprite_object);
*/ */
IWRAM_CODE void sprite_object_update(SpriteObject* sprite_object); IWRAM_CODE void sprite_object_update(SpriteObject* sprite_object);
/**
* @brief Update all SpriteObjects, to be called once per frame in the main update loop.
*
* TODO: try and put this function in IWRAM for performance purposes. Crashed the last time I tried.
*/
void sprite_object_update_all(void);
/** /**
* @brief Shake SpriteObject on screen and play a sound * @brief Shake SpriteObject on screen and play a sound
* *
-7
View File
@@ -118,13 +118,6 @@ void card_object_destroy(CardObject** card_object)
*card_object = NULL; *card_object = NULL;
} }
void card_object_update(CardObject* card_object)
{
if (card_object == NULL)
return;
sprite_object_update(card_object->sprite_object);
}
void card_object_set_sprite(CardObject* card_object, int layer) void card_object_set_sprite(CardObject* card_object, int layer)
{ {
int tile_index = CARD_TID + (layer * CARD_SPRITE_OFFSET); int tile_index = CARD_TID + (layer * CARD_SPRITE_OFFSET);
+3 -11
View File
@@ -195,7 +195,7 @@ static const Rect DECK_SIZE_RECT = {200, 152, 240, 160
static const Rect ROUND_TEXT_RECT = {48, 144, UNDEFINED, UNDEFINED }; static const Rect ROUND_TEXT_RECT = {48, 144, UNDEFINED, UNDEFINED };
static const Rect ANTE_TEXT_RECT = {8, 144, UNDEFINED, UNDEFINED }; static const Rect ANTE_TEXT_RECT = {8, 144, UNDEFINED, UNDEFINED };
static const BG_POINT CARD_DRAW_POS = {208, 110}; static const BG_POINT CARD_DRAW_POS = {208, 118};
static const BG_POINT CARD_DISCARD_PNT = {240, 70}; static const BG_POINT CARD_DISCARD_PNT = {240, 70};
static const BG_POINT HAND_START_POS = {120, 90}; static const BG_POINT HAND_START_POS = {120, 90};
static const BG_POINT HAND_PLAY_POS = {120, 70}; static const BG_POINT HAND_PLAY_POS = {120, 70};
@@ -467,7 +467,6 @@ static inline void discarded_jokers_update_loop(void)
while ((joker_object = list_itr_next(&itr))) while ((joker_object = list_itr_next(&itr)))
{ {
joker_object_update(joker_object);
if (joker_object->sprite_object->x == joker_object->sprite_object->tx && if (joker_object->sprite_object->x == joker_object->sprite_object->tx &&
joker_object->sprite_object->y == joker_object->sprite_object->ty) joker_object->sprite_object->y == joker_object->sprite_object->ty)
{ {
@@ -499,7 +498,6 @@ static inline void held_jokers_update_loop(void)
if (joker != game_shop_get_description_card()) if (joker != game_shop_get_description_card())
joker->sprite_object->tx = hand_x - int2fx(spacing_lut[jokers_top][i]); joker->sprite_object->tx = hand_x - int2fx(spacing_lut[jokers_top][i]);
i++; i++;
joker_object_update(joker);
} }
} }
@@ -515,8 +513,6 @@ static inline void expired_jokers_update_loop(void)
while ((joker_object = list_itr_next(&itr))) while ((joker_object = list_itr_next(&itr)))
{ {
joker_object_update(joker_object);
// let just enough frames pass that we see it rotating and shrinking // let just enough frames pass that we see it rotating and shrinking
if (g_game_vars.timer % FRAMES(EXPIRE_ANIMATION_FRAME_COUNT) == 0) if (g_game_vars.timer % FRAMES(EXPIRE_ANIMATION_FRAME_COUNT) == 0)
{ {
@@ -556,6 +552,8 @@ void game_update()
jokers_update_loop(); jokers_update_loop();
state_machine_update(); state_machine_update();
sprite_object_update_all();
} }
void game_change_state(enum GameState new_game_state) void game_change_state(enum GameState new_game_state)
@@ -2148,7 +2146,6 @@ static inline void played_cards_update_loop(void)
} }
played[played_idx]->sprite_object->tscale = FIX_ONE; played[played_idx]->sprite_object->tscale = FIX_ONE;
card_object_update(played[played_idx]);
} }
} }
@@ -2262,13 +2259,9 @@ static inline void game_playing_discarded_cards_loop(void)
discarded_card_object->sprite_object->ty = int2fx(112); discarded_card_object->sprite_object->ty = int2fx(112);
discarded_card_object->sprite_object->x = int2fx(240); discarded_card_object->sprite_object->x = int2fx(240);
discarded_card_object->sprite_object->y = int2fx(80); discarded_card_object->sprite_object->y = int2fx(80);
card_object_update(discarded_card_object);
} }
else else
{ {
card_object_update(discarded_card_object);
if (discarded_card_object->sprite_object->y >= discarded_card_object->sprite_object->ty) if (discarded_card_object->sprite_object->y >= discarded_card_object->sprite_object->ty)
{ {
deck_push(discarded_card_object->card); // Put the card back into the deck deck_push(discarded_card_object->card); // Put the card back into the deck
@@ -2448,7 +2441,6 @@ static inline void cards_in_hand_update_loop(void)
hand[i]->sprite_object->tx = hand_x; hand[i]->sprite_object->tx = hand_x;
hand[i]->sprite_object->ty = hand_y; hand[i]->sprite_object->ty = hand_y;
card_object_update(hand[i]);
} }
} }
} }
-2
View File
@@ -108,7 +108,6 @@ void game_main_menu_on_init(void)
main_menu_ace->sprite_object->sprite->obj->attr0 |= ATTR0_AFF_DBL; main_menu_ace->sprite_object->sprite->obj->attr0 |= ATTR0_AFF_DBL;
main_menu_ace->sprite_object->tscale = float2fx(0.8f); main_menu_ace->sprite_object->tscale = float2fx(0.8f);
sprite_object_position(main_menu_ace->sprite_object, MAIN_MENU_ACE_T_X, MAIN_MENU_ACE_T_Y); sprite_object_position(main_menu_ace->sprite_object, MAIN_MENU_ACE_T_X, MAIN_MENU_ACE_T_Y);
card_object_update(main_menu_ace);
// Select last highlighted button, Play button by default. // Select last highlighted button, Play button by default.
// e.g. if we return from the options menu, we want the Options button to be highlighted. // e.g. if we return from the options menu, we want the Options button to be highlighted.
@@ -122,7 +121,6 @@ void game_main_menu_on_init(void)
void game_main_menu_on_update(void) void game_main_menu_on_update(void)
{ {
main_menu_ace->sprite_object->trotation = lu_sin((g_game_vars.timer << 8) / 2) / 3; main_menu_ace->sprite_object->trotation = lu_sin((g_game_vars.timer << 8) / 2) / 3;
card_object_update(main_menu_ace);
selection_grid_process_input(&main_menu_selection_grid); selection_grid_process_input(&main_menu_selection_grid);
} }
-2
View File
@@ -589,8 +589,6 @@ void game_run_setup_on_init(void)
RUN_SETUP_DECK_SPRITE_T_Y RUN_SETUP_DECK_SPRITE_T_Y
); );
card_object_update(run_setup_deck);
/* Uncomment these lines when we figure out how to properly restore a game save /* Uncomment these lines when we figure out how to properly restore a game save
is_saved_game_valid = is_game_data_valid(); is_saved_game_valid = is_game_data_valid();
if (is_saved_game_valid) if (is_saved_game_valid)
-15
View File
@@ -990,21 +990,6 @@ void game_shop_on_update(void)
{ {
timer++; timer++;
List* shop_jokers_list = &s_shop_jokers_list;
if (!list_is_empty(shop_jokers_list))
{
ListItr itr = list_itr_create(shop_jokers_list);
JokerObject* joker_object;
while ((joker_object = list_itr_next(&itr)))
{
if (joker_object != NULL)
{
joker_object_update(joker_object);
}
}
}
if (timer % 20 == 0) if (timer % 20 == 0)
{ {
game_shop_lights_anim_frame(); game_shop_lights_anim_frame();
-5
View File
@@ -255,11 +255,6 @@ void joker_object_destroy(JokerObject** joker_object)
*joker_object = NULL; *joker_object = NULL;
} }
void joker_object_update(JokerObject* joker_object)
{
sprite_object_update(joker_object->sprite_object);
}
void joker_object_shake(JokerObject* joker_object, mm_word sound_id) void joker_object_shake(JokerObject* joker_object, mm_word sound_id)
{ {
sprite_object_shake(joker_object->sprite_object, sound_id); sprite_object_shake(joker_object->sprite_object, sound_id);
+17
View File
@@ -28,6 +28,8 @@ OBJ_AFFINE* obj_aff_buffer = (OBJ_AFFINE*)obj_buffer;
static Sprite* free_sprites[MAX_SPRITES] = {NULL}; static Sprite* free_sprites[MAX_SPRITES] = {NULL};
static bool free_affines[MAX_AFFINES] = {false}; static bool free_affines[MAX_AFFINES] = {false};
static List sprite_objects_list = LIST_DEFAULT;
// Sprite methods // Sprite methods
Sprite* sprite_new(u16 a0, u16 a1, u32 tid, u32 pb, int sprite_index) Sprite* sprite_new(u16 a0, u16 a1, u32 tid, u32 pb, int sprite_index)
{ {
@@ -174,6 +176,8 @@ SpriteObject* sprite_object_new()
sprite_object_reset_transform(sprite_object); sprite_object_reset_transform(sprite_object);
sprite_object->focused = false; sprite_object->focused = false;
list_push_back(&sprite_objects_list, sprite_object);
return sprite_object; return sprite_object;
} }
@@ -181,6 +185,9 @@ void sprite_object_destroy(SpriteObject** sprite_object)
{ {
if (*sprite_object == NULL) if (*sprite_object == NULL)
return; return;
list_remove_data(&sprite_objects_list, *sprite_object);
sprite_destroy(&(*sprite_object)->sprite); sprite_destroy(&(*sprite_object)->sprite);
POOL_FREE(SpriteObject, *sprite_object); POOL_FREE(SpriteObject, *sprite_object);
*sprite_object = NULL; *sprite_object = NULL;
@@ -301,6 +308,16 @@ IWRAM_CODE void sprite_object_update(SpriteObject* sprite_object)
sprite_position(sprite_object->sprite, fx2int(sprite_object->x), fx2int(sprite_object->y)); sprite_position(sprite_object->sprite, fx2int(sprite_object->x), fx2int(sprite_object->y));
} }
void sprite_object_update_all(void)
{
SpriteObject* sprite_object = NULL;
ListItr itr = list_itr_create(&sprite_objects_list);
while ((sprite_object = list_itr_next(&itr)))
{
sprite_object_update(sprite_object);
}
}
void sprite_object_shake(SpriteObject* sprite_object, mm_word sound_id) void sprite_object_shake(SpriteObject* sprite_object, mm_word sound_id)
{ {
if (sprite_object == NULL) if (sprite_object == NULL)