From f84268c14d8d8170018da52d4f8829c31c09a2db Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Thu, 7 Aug 2025 19:47:55 +0300 Subject: [PATCH 1/7] Added int list for joker pooling --- include/list.h | 19 +++++++++++++++ source/int_list.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 include/list.h create mode 100644 source/int_list.c diff --git a/include/list.h b/include/list.h new file mode 100644 index 0000000..b3ee749 --- /dev/null +++ b/include/list.h @@ -0,0 +1,19 @@ +#ifndef LIST_H +#define LIST_H + +#include + +typedef struct IntList +{ + int* _array; + int size; + int allocated_size; +} IntList; + +IntList *int_list_new(int init_size); +void int_list_destroy(IntList **list); +bool int_list_add(IntList *list, int value); +bool int_list_remove(IntList *list, int index); +int int_list_get(IntList *list, int index); + +#endif diff --git a/source/int_list.c b/source/int_list.c new file mode 100644 index 0000000..458b564 --- /dev/null +++ b/source/int_list.c @@ -0,0 +1,61 @@ +#include +#include +#include "list.h" + +IntList *int_list_new(int init_size) { + IntList *list = (IntList *)malloc(sizeof(IntList)); + if (list == NULL) return NULL; + list->_array = (int *)malloc(sizeof(int) * init_size); + if (!list->_array) + { + free(list); + return NULL; + } + list->size = 0; + list->allocated_size = init_size; + return list; +} + +void int_list_destroy(IntList **list) { + if (list == NULL || *list == NULL) + return; + { + free((*list)->_array); + free(*list); + } + + *list = NULL; +} + +bool int_list_add(IntList *list, int value) +{ + if (list->size >= list->allocated_size) + { + int new_size = list->allocated_size * 2; + int *new_arr = (int *)realloc(list->_array, sizeof(int) * new_size); + if (new_arr == NULL) + return false; + list->_array = new_arr; + list->allocated_size = new_size; + } + list->_array[list->size++] = value; + return true; +} + +bool int_list_remove(IntList *list, int index) { + if (index < 0 || index >= list->size) + return false; + for (int i = index; i < list->size - 1; ++i) + { + list->_array[i] = list->_array[i + 1]; + } + list->size--; + return true; +} + +int int_list_get(IntList *list, int index) +{ + if (index < 0 || index >= list->size) + return 0; + return list->_array[index]; +} \ No newline at end of file From 3441a1dae83b86959c8df2729e7e5d847723064e Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Sat, 9 Aug 2025 20:48:18 +0300 Subject: [PATCH 2/7] Joker pooling - Existing or owned jokers can't appear in shop + shop code refactor --- include/list.h | 10 +- source/game.c | 421 ++++++++++++++++++++++++++-------------------- source/int_list.c | 29 +++- 3 files changed, 274 insertions(+), 186 deletions(-) diff --git a/include/list.h b/include/list.h index b3ee749..64341f7 100644 --- a/include/list.h +++ b/include/list.h @@ -3,6 +3,10 @@ #include +/* Defining an int list for simplicity + * If another list is needed, a generic void* + * list should be defined.... + */ typedef struct IntList { int* _array; @@ -12,8 +16,10 @@ typedef struct IntList IntList *int_list_new(int init_size); void int_list_destroy(IntList **list); -bool int_list_add(IntList *list, int value); -bool int_list_remove(IntList *list, int index); +bool int_list_append(IntList *list, int value); +bool int_list_remove_by_idx(IntList *list, int index); int int_list_get(IntList *list, int index); +int int_list_get_size(IntList *list); +bool int_list_remove_by_value(IntList *list, int value); #endif diff --git a/source/game.c b/source/game.c index 05f7a94..9ec5d81 100644 --- a/source/game.c +++ b/source/game.c @@ -23,6 +23,8 @@ #include "soundbank.h" +#include "list.h" + // This seed system is temporary. static uint rng_seed = 2048; static bool seeded = false; @@ -171,6 +173,8 @@ int get_jokers_top(void) { return jokers_top; } +IntList* jokers_available_to_shop; + // Consts // Rects left top right bottom @@ -998,8 +1002,21 @@ void game_set_state(enum GameState new_game_state) game_state = new_game_state; } +void jokers_avialable_to_shop_init() +{ + int num_defined_jokers = get_joker_registry_size(); + jokers_available_to_shop = int_list_new(get_joker_registry_size()); + for (int i = 0; i < num_defined_jokers; i++) + { + // Add all joker IDs sequentially + int_list_append(jokers_available_to_shop, i); + } +} + void game_init() { + jokers_avialable_to_shop_init(); + hands = max_hands; discards = max_discards; @@ -1818,41 +1835,6 @@ static void game_round_end_cashout() display_score(score); // Set the score display } -static void game_shop_create_items(JokerObject *shop_jokers[], bool first_time) -{ - tte_erase_rect_wrapper(SHOP_PRICES_TEXT_RECT); - - for (int i = 0; i < MAX_SHOP_JOKERS; i++) - { - if (shop_jokers[i] != NULL) - { - joker_object_destroy(&shop_jokers[i]); // Destroy the joker object if it exists - } - - u8 joker_id = random() % get_joker_registry_size(); - // TODO: don't pick a joker that we already own - // TODO: weight the random choice by joker rarity - - shop_jokers[i] = joker_object_new(joker_new(joker_id)); - shop_jokers[i]->sprite_object->x = int2fx(120 + i * 32); - shop_jokers[i]->sprite_object->y = int2fx(160); - shop_jokers[i]->sprite_object->tx = shop_jokers[i]->sprite_object->x; - shop_jokers[i]->sprite_object->ty = int2fx(71); - - int x = fx2int(shop_jokers[i]->sprite_object->tx) + TILE_SIZE - (get_digits_even(shop_jokers[i]->joker->value) - 1) * TILE_SIZE; - int y = fx2int(shop_jokers[i]->sprite_object->ty) + CARD_SPRITE_SIZE + TILE_SIZE; - tte_printf("#{P:%d,%d; cx:0xC000}$%d", x, y, shop_jokers[i]->joker->value); - - if (first_time == false) - { - shop_jokers[i]->sprite_object->y = shop_jokers[i]->sprite_object->ty; // If it's not the first time, set the y position to the target position - joker_object_shake(shop_jokers[i], UNDEFINED); // Give the joker a little wiggle animation - } - - sprite_position(joker_object_get_sprite(shop_jokers[i]), fx2int(shop_jokers[i]->sprite_object->x), fx2int(shop_jokers[i]->sprite_object->y)); - } -} - void game_playing() { // TODO: Blind rect sliding into view animation... @@ -2155,13 +2137,47 @@ void game_round_end() } } -void game_shop_intro(JokerObject* shop_jokers[]) +static void game_shop_create_items(JokerObject *shop_jokers[]) +{ + tte_erase_rect_wrapper(SHOP_PRICES_TEXT_RECT); + + for (int i = 0; i < MAX_SHOP_JOKERS; i++) + { + + // Note: this needs to happen after the existing joker destruction above + if (int_list_get_size(jokers_available_to_shop) == 0) + { + // No jokers to create + continue; + } + + // TODO: weight the random choice by joker rarity + int joker_idx = random() % int_list_get_size(jokers_available_to_shop); + int joker_id = int_list_get(jokers_available_to_shop, joker_idx); + int_list_remove_by_idx(jokers_available_to_shop, joker_idx); + + shop_jokers[i] = joker_object_new(joker_new(joker_id)); + shop_jokers[i]->sprite_object->x = int2fx(120 + i * 32); + shop_jokers[i]->sprite_object->y = int2fx(160); + shop_jokers[i]->sprite_object->tx = shop_jokers[i]->sprite_object->x; + shop_jokers[i]->sprite_object->ty = int2fx(71); + + int x = fx2int(shop_jokers[i]->sprite_object->tx) + TILE_SIZE - (get_digits_even(shop_jokers[i]->joker->value) - 1) * TILE_SIZE; + int y = fx2int(shop_jokers[i]->sprite_object->ty) + CARD_SPRITE_SIZE + TILE_SIZE; + tte_printf("#{P:%d,%d; cx:0xC000}$%d", x, y, shop_jokers[i]->joker->value); + + sprite_position(joker_object_get_sprite(shop_jokers[i]), fx2int(shop_jokers[i]->sprite_object->x), fx2int(shop_jokers[i]->sprite_object->y)); + } +} + +// Intro sequence (menu and shop icon coming into frame) +static void game_shop_intro(JokerObject* shop_jokers[]) { main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP); if (timer == 1) { - game_shop_create_items(shop_jokers, true); + game_shop_create_items(shop_jokers); } if (timer >= 7) // Shift the shop icon @@ -2188,6 +2204,181 @@ void game_shop_intro(JokerObject* shop_jokers[]) } } +static void game_shop_reroll(JokerObject** shop_jokers, int *reroll_cost) +{ + money -= *reroll_cost; + display_money(money); // Update the money display + for (int i = 0; i < MAX_SHOP_JOKERS; i++) + { + if (shop_jokers[i] != NULL) + { + int_list_append(jokers_available_to_shop, shop_jokers[i]->joker->id); + joker_object_destroy(&shop_jokers[i]); // Destroy the joker object if it exists + } + } + + game_shop_create_items(shop_jokers); + + for (int i = 0; i < MAX_SHOP_JOKERS; i++) + { + if (shop_jokers[i] != NULL) + { + shop_jokers[i]->sprite_object->y = shop_jokers[i]->sprite_object->ty; // Set the y position to the target position + joker_object_shake(shop_jokers[i], UNDEFINED); // Give the joker a little wiggle animation + } + } + + (*reroll_cost)++; + tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, *reroll_cost); +} + +// Shop menu input and selection +static void game_shop_process_user_input(JokerObject** shop_jokers) +{ + const int REROLL_BASE_COST = 5; // Base cost for rerolling the shop items + static int reroll_cost = REROLL_BASE_COST; + + // temp variables for future implementation + const ushort max_items_top = MAX_SHOP_JOKERS; + const ushort max_items_bottom = 0; + + if (timer == 1) + { + tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, reroll_cost); + } + + // Shop input logic + if (key_hit(KEY_UP)) + { + selection_y = 0; + + if (selection_x > max_items_top) + { + selection_x = max_items_top; + } + } + else if (key_hit(KEY_DOWN)) + { + selection_y = 1; + + if (selection_x > max_items_bottom) + { + selection_x = max_items_bottom; + } + } + else if (key_hit(KEY_LEFT)) + { + if (selection_x > 0) + { + selection_x--; + } + } + else if (key_hit(KEY_RIGHT)) + { + // TODO: Don't allow cursor on sold items + if (selection_y == 0 && selection_x < max_items_top) + { + selection_x++; + } + else if (selection_y == 1 && selection_x < max_items_bottom) + { + selection_x++; + } + } + + memcpy16(&pal_bg_mem[7], &pal_bg_mem[3], 1); + memcpy16(&pal_bg_mem[5], &pal_bg_mem[16], 1); + + // Shop selection logic + if (selection_x == 0 && selection_y == 0) // Next round button + { + memset16(&pal_bg_mem[5], 0xFFFF, 1); + + if (key_hit(SELECT_CARD)) + { + // Go to next blind selection game state + state = 2; // Go to the outro sequence state + timer = 0; // Reset the timer + reroll_cost = REROLL_BASE_COST; + + memcpy16(&pal_bg_mem[5], &pal_bg_mem[6], 1); + + // memcpy16(&pal_bg_mem[16], &pal_bg_mem[6], 1); + // This changes the color of the button to a dark red. + // However, it shares a palette with the shop icon, so it will change the color of the shop icon as well. + // And I don't care enough to fix it right now. + } + } + else if (selection_x == 0 && selection_y == 1) // Reroll button + { + memset16(&pal_bg_mem[7], 0xFFFF, 1); + + if (key_hit(SELECT_CARD) && money >= reroll_cost) + { + game_shop_reroll(shop_jokers, &reroll_cost); + } + } + + for (int i = 0; i < MAX_SHOP_JOKERS; i++) // Item selection logic + { + if (shop_jokers[i] != NULL) + { + if (i == selection_x - 1 && selection_y == 0) + { + shop_jokers[i]->sprite_object->ty = int2fx(61); + + if (key_hit(SELECT_CARD) && jokers_top < MAX_JOKERS_HELD_SIZE - 1 && money >= shop_jokers[i]->joker->value) + { + joker_push(shop_jokers[i]); + money -= shop_jokers[i]->joker->value; // Deduct the money spent on the joker + display_money(money); // Update the money display + + Rect joker_price_rect; + joker_price_rect.left = fx2int(shop_jokers[i]->sprite_object->tx); + // 2*TILE_SIZE because the item is highlighted and raised by 1 additional tile + joker_price_rect.top = fx2int(shop_jokers[i]->sprite_object->ty) + CARD_SPRITE_SIZE + 2*TILE_SIZE; + joker_price_rect.right = joker_price_rect.left + TILE_SIZE * 3; + joker_price_rect.bottom = joker_price_rect.top + TILE_SIZE; + + tte_erase_rect_wrapper(joker_price_rect); + + shop_jokers[i] = NULL; // Remove the joker from the shop + } + } + else + { + shop_jokers[i]->sprite_object->ty = int2fx(71); + } + } + } +} + +static void game_shop_lights_anim_frame() +{ + // Shift palette around the border of the shop icon + COLOR shifted_palette[4]; + memcpy16(&shifted_palette[0], &pal_bg_mem[14], 1); + memcpy16(&shifted_palette[1], &pal_bg_mem[17], 1); + memcpy16(&shifted_palette[2], &pal_bg_mem[22], 1); + memcpy16(&shifted_palette[3], &pal_bg_mem[8], 1); + + // Circularly shift the palette + int last = shifted_palette[3]; + + for (int i = 3; i > 0; --i) + { + shifted_palette[i] = shifted_palette[i - 1]; + } + + shifted_palette[0] = last; + + memcpy16(&pal_bg_mem[14], &shifted_palette[0], 1); // Copy the shifted palette to the next 4 slots + memcpy16(&pal_bg_mem[17], &shifted_palette[1], 1); + memcpy16(&pal_bg_mem[22], &shifted_palette[2], 1); + memcpy16(&pal_bg_mem[8], &shifted_palette[3], 1); +} + + void game_shop() { change_background(BG_ID_SHOP); @@ -2202,159 +2393,21 @@ void game_shop() } } - const int reroll_base_cost = 5; // Base cost for rerolling the shop items - static int reroll_cost = reroll_base_cost; - - // temp variables for future implementation - const ushort max_items_top = MAX_SHOP_JOKERS; - const ushort max_items_bottom = 0; - - if (timer % 20 == 0) // Shift palette around the border of the shop icon + if (timer % 20 == 0) { - COLOR shifted_palette[4]; - memcpy16(&shifted_palette[0], &pal_bg_mem[14], 1); - memcpy16(&shifted_palette[1], &pal_bg_mem[17], 1); - memcpy16(&shifted_palette[2], &pal_bg_mem[22], 1); - memcpy16(&shifted_palette[3], &pal_bg_mem[8], 1); - - // Circularly shift the palette - int last = shifted_palette[3]; - - for (int i = 3; i > 0; --i) { - shifted_palette[i] = shifted_palette[i - 1]; - } - - shifted_palette[0] = last; - - memcpy16(&pal_bg_mem[14], &shifted_palette[0], 1); // Copy the shifted palette to the next 4 slots - memcpy16(&pal_bg_mem[17], &shifted_palette[1], 1); - memcpy16(&pal_bg_mem[22], &shifted_palette[2], 1); - memcpy16(&pal_bg_mem[8], &shifted_palette[3], 1); + game_shop_lights_anim_frame(); } switch (state) // I'm only using magic numbers here for the sake of simplicity since it's just sequential, but you can replace them with named constants or enums if it makes it clearer { - case 0: // Intro sequence (menu and shop icon coming into frame) + case 0: { game_shop_intro(shop_jokers); break; } - case 1: // Shop menu input and selection + case 1: { - if (timer == 1) - { - tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, reroll_cost); - } - - // Shop input logic - if (key_hit(KEY_UP)) - { - selection_y = 0; - - if (selection_x > max_items_top) - { - selection_x = max_items_top; - } - } - else if (key_hit(KEY_DOWN)) - { - selection_y = 1; - - if (selection_x > max_items_bottom) - { - selection_x = max_items_bottom; - } - } - else if (key_hit(KEY_LEFT)) - { - if (selection_x > 0) - { - selection_x--; - } - } - else if (key_hit(KEY_RIGHT)) - { - if (selection_y == 0 && selection_x < max_items_top) - { - selection_x++; - } - else if (selection_y == 1 && selection_x < max_items_bottom) - { - selection_x++; - } - } - - memcpy16(&pal_bg_mem[7], &pal_bg_mem[3], 1); - memcpy16(&pal_bg_mem[5], &pal_bg_mem[16], 1); - - // Shop selection logic - if (selection_x == 0 && selection_y == 0) - { - memset16(&pal_bg_mem[5], 0xFFFF, 1); - - if (key_hit(SELECT_CARD)) - { - // Go to next blind selection game state - state = 2; // Go to the outro sequence state - timer = 0; // Reset the timer - - memcpy16(&pal_bg_mem[5], &pal_bg_mem[6], 1); - - // memcpy16(&pal_bg_mem[16], &pal_bg_mem[6], 1); - // This changes the color of the button to a dark red. - // However, it shares a palette with the shop icon, so it will change the color of the shop icon as well. - // And I don't care enough to fix it right now. - } - } - else if (selection_x == 0 && selection_y == 1) - { - memset16(&pal_bg_mem[7], 0xFFFF, 1); - - if (key_hit(SELECT_CARD) && money >= reroll_cost) - { - money -= reroll_cost; - display_money(money); // Update the money display - - game_shop_create_items(shop_jokers, false); - - reroll_cost++; - tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, reroll_cost); - } - } - - for (int i = 0; i < MAX_SHOP_JOKERS; i++) - { - if (shop_jokers[i] != NULL) - { - if (i == selection_x - 1 && selection_y == 0) - { - shop_jokers[i]->sprite_object->ty = int2fx(61); - - if (key_hit(SELECT_CARD) && jokers_top < MAX_JOKERS_HELD_SIZE - 1 && money >= shop_jokers[i]->joker->value) - { - joker_push(shop_jokers[i]); - money -= shop_jokers[i]->joker->value; // Deduct the money spent on the joker - display_money(money); // Update the money display - - Rect joker_price_rect; - joker_price_rect.left = fx2int(shop_jokers[i]->sprite_object->tx); - // 2*TILE_SIZE because the item is highlighted and raised by 1 additional tile - joker_price_rect.top = fx2int(shop_jokers[i]->sprite_object->ty) + CARD_SPRITE_SIZE + 2*TILE_SIZE; - joker_price_rect.right = joker_price_rect.left + TILE_SIZE * 3; - joker_price_rect.bottom = joker_price_rect.top + TILE_SIZE; - - tte_erase_rect_wrapper(joker_price_rect); - - shop_jokers[i] = NULL; // Remove the joker from the shop - } - } - else - { - shop_jokers[i]->sprite_object->ty = int2fx(71); - } - } - } - + game_shop_process_user_input(shop_jokers); break; } case 2: // Outro sequence (menu and shop icon going out of frame) @@ -2402,13 +2455,17 @@ void game_shop() } default: state = 0; // Reset the state - reroll_cost = reroll_base_cost; selection_x = 0; // Reset the selection selection_y = 0; // Reset the selection for (int i = 0; i < MAX_SHOP_JOKERS; i++) { + if (shop_jokers[i] != NULL) + { + // Make the joker available back to shop + int_list_append(jokers_available_to_shop, shop_jokers[i]->joker->id); + } joker_object_destroy(&shop_jokers[i]); // Destroy the joker objects } @@ -2419,6 +2476,8 @@ void game_shop() } } + + void game_blind_select() { switch (state) // I'm only using magic numbers here for the sake of simplicity since it's just sequential, but you can replace them with named constants or enums if it makes it clearer diff --git a/source/int_list.c b/source/int_list.c index 458b564..0b65f3d 100644 --- a/source/int_list.c +++ b/source/int_list.c @@ -1,6 +1,7 @@ #include #include #include "list.h" +#include "util.h" IntList *int_list_new(int init_size) { IntList *list = (IntList *)malloc(sizeof(IntList)); @@ -27,7 +28,7 @@ void int_list_destroy(IntList **list) { *list = NULL; } -bool int_list_add(IntList *list, int value) +bool int_list_append(IntList *list, int value) { if (list->size >= list->allocated_size) { @@ -42,7 +43,7 @@ bool int_list_add(IntList *list, int value) return true; } -bool int_list_remove(IntList *list, int index) { +bool int_list_remove_by_idx(IntList *list, int index) { if (index < 0 || index >= list->size) return false; for (int i = index; i < list->size - 1; ++i) @@ -53,9 +54,31 @@ bool int_list_remove(IntList *list, int index) { return true; } +bool int_list_remove_by_value(IntList *list, int value) +{ + for (int i = 0; i < list->size; i++) + { + if (list->_array[i] == value) + { + return int_list_remove_by_idx(list, i); + } + } + + return false; +} + int int_list_get(IntList *list, int index) { if (index < 0 || index >= list->size) return 0; return list->_array[index]; -} \ No newline at end of file +} + +int int_list_get_size(IntList *list) +{ + if (list == NULL) + { + return UNDEFINED; + } + return list->size; +} From 38282d0f2af4d0f0a5234cf78da188bcd23cc113 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Sat, 9 Aug 2025 21:31:41 +0300 Subject: [PATCH 3/7] Small refactors --- source/game.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/source/game.c b/source/game.c index 9ec5d81..f58d644 100644 --- a/source/game.c +++ b/source/game.c @@ -173,7 +173,7 @@ int get_jokers_top(void) { return jokers_top; } -IntList* jokers_available_to_shop; +IntList* jokers_available_to_shop; // List of joker IDs // Consts @@ -1005,7 +1005,7 @@ void game_set_state(enum GameState new_game_state) void jokers_avialable_to_shop_init() { int num_defined_jokers = get_joker_registry_size(); - jokers_available_to_shop = int_list_new(get_joker_registry_size()); + jokers_available_to_shop = int_list_new(num_defined_jokers); for (int i = 0; i < num_defined_jokers; i++) { // Add all joker IDs sequentially @@ -2140,17 +2140,14 @@ void game_round_end() static void game_shop_create_items(JokerObject *shop_jokers[]) { tte_erase_rect_wrapper(SHOP_PRICES_TEXT_RECT); + if (int_list_get_size(jokers_available_to_shop) == 0) + { + // No jokers to create + return; + } for (int i = 0; i < MAX_SHOP_JOKERS; i++) { - - // Note: this needs to happen after the existing joker destruction above - if (int_list_get_size(jokers_available_to_shop) == 0) - { - // No jokers to create - continue; - } - // TODO: weight the random choice by joker rarity int joker_idx = random() % int_list_get_size(jokers_available_to_shop); int joker_id = int_list_get(jokers_available_to_shop, joker_idx); @@ -2235,7 +2232,7 @@ static void game_shop_reroll(JokerObject** shop_jokers, int *reroll_cost) // Shop menu input and selection static void game_shop_process_user_input(JokerObject** shop_jokers) { - const int REROLL_BASE_COST = 5; // Base cost for rerolling the shop items + static const int REROLL_BASE_COST = 5; // Base cost for rerolling the shop items static int reroll_cost = REROLL_BASE_COST; // temp variables for future implementation @@ -2469,7 +2466,7 @@ void game_shop() joker_object_destroy(&shop_jokers[i]); // Destroy the joker objects } - increment_blind(BLIND_DEFEATED); + increment_blind(BLIND_DEFEATED); // TODO: Move to game_round_end()? game_set_state(GAME_BLIND_SELECT); // If we reach here, we should go to the blind select state break; From 05af8217ff8dd6596f11011b7c81c0cd17f5e01d Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 12 Aug 2025 01:59:04 +0300 Subject: [PATCH 4/7] Small affine background CBB/SBB fix --- source/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/main.c b/source/main.c index 76abc07..269fc09 100644 --- a/source/main.c +++ b/source/main.c @@ -44,7 +44,7 @@ void init() // BG1 is the main background layer REG_BG1CNT = BG_PRIO(1) | BG_CBB(MAIN_BG_CBB) | BG_SBB(MAIN_BG_SBB) | BG_8BPP; // BG2 is the affine background layer - REG_BG2CNT = BG_PRIO(2) | BG_CBB(AFFINE_BG_CBB) | BG_SBB(AFFINE_BG_CBB) | BG_8BPP | BG_WRAP | BG_AFF_32x32; + REG_BG2CNT = BG_PRIO(2) | BG_CBB(AFFINE_BG_CBB) | BG_SBB(AFFINE_BG_SBB) | BG_8BPP | BG_WRAP | BG_AFF_32x32; int win1_left = 72; int win1_top = 44; From 658b0572d9a391e15bf3822d803ee48031d9a673 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 12 Aug 2025 03:01:02 +0300 Subject: [PATCH 5/7] Removed all uses of float for optimization --- source/game.c | 2 +- source/sprite.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/game.c b/source/game.c index f58d644..83ef525 100644 --- a/source/game.c +++ b/source/game.c @@ -1576,7 +1576,7 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection FIXED played_x = int2fx(120); FIXED played_y = int2fx(70); - FIXED played_scale = float2fx(1.0f); + FIXED played_scale = FIX_ONE; played_x = played_x + (int2fx(played_top - i) - int2fx(played_top) / 2) * -27; diff --git a/source/sprite.c b/source/sprite.c index a93b953..fb973c3 100644 --- a/source/sprite.c +++ b/source/sprite.c @@ -145,9 +145,9 @@ void sprite_object_reset_transform(SpriteObject* sprite_object) sprite_object->y = 0; sprite_object->vx = 0; sprite_object->vy = 0; - sprite_object->tscale = float2fx(1.0f); // Target scale - sprite_object->scale = float2fx(1.0f); - sprite_object->vscale = float2fx(0.0f); + sprite_object->tscale = FIX_ONE; // Target scale + sprite_object->scale = FIX_ONE; + sprite_object->vscale = 0; sprite_object->trotation = 0; // Target rotation sprite_object->rotation = 0; sprite_object->vrotation = 0; @@ -163,7 +163,7 @@ void sprite_object_update(SpriteObject* sprite_object) sprite_object->vrotation += (sprite_object->trotation - sprite_object->rotation) / 8; // Rotate the card when it's played // set velocity to 0 if it's close enough to the target - const float epsilon = float2fx(0.01f); + const FIXED epsilon = FIX_ONE>>7; // 1/(2^7) = 1/128 = 0.0078125 if (sprite_object->vx < epsilon && sprite_object->vx > -epsilon && sprite_object->vy < epsilon && sprite_object->vy > -epsilon) { sprite_object->vx = 0; @@ -211,8 +211,8 @@ void sprite_object_update(SpriteObject* sprite_object) void sprite_object_shake(SpriteObject* sprite_object, mm_word sound_id) { - sprite_object->vscale = float2fx(0.3f); // Scale down the card when it's scored - sprite_object->vrotation = float2fx(8.0f); // Rotate the card when it's scored + sprite_object->vscale = FIX_ONE >> 2; // (1/4 = 0.25) Scale down the card when it's scored + sprite_object->vrotation = FIX_ONE << 3; // (2^3 = 8) Rotate the card when it's scored if (sound_id == UNDEFINED) return; // If no sound ID is provided, do nothing From 0e080b916e5caf704ffb9f86784adc59ff7b23c1 Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 12 Aug 2025 11:40:22 +0300 Subject: [PATCH 6/7] Reverted removals of float2fx() as they're compiler-optimized but kept float optimization --- source/sprite.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/sprite.c b/source/sprite.c index fb973c3..df1e917 100644 --- a/source/sprite.c +++ b/source/sprite.c @@ -163,7 +163,7 @@ void sprite_object_update(SpriteObject* sprite_object) sprite_object->vrotation += (sprite_object->trotation - sprite_object->rotation) / 8; // Rotate the card when it's played // set velocity to 0 if it's close enough to the target - const FIXED epsilon = FIX_ONE>>7; // 1/(2^7) = 1/128 = 0.0078125 + const FIXED epsilon = float2fx(0.01f); if (sprite_object->vx < epsilon && sprite_object->vx > -epsilon && sprite_object->vy < epsilon && sprite_object->vy > -epsilon) { sprite_object->vx = 0; @@ -211,8 +211,8 @@ void sprite_object_update(SpriteObject* sprite_object) void sprite_object_shake(SpriteObject* sprite_object, mm_word sound_id) { - sprite_object->vscale = FIX_ONE >> 2; // (1/4 = 0.25) Scale down the card when it's scored - sprite_object->vrotation = FIX_ONE << 3; // (2^3 = 8) Rotate the card when it's scored + sprite_object->vscale = float2fx(0.3f); + sprite_object->vrotation = float2fx(8.0f); //Rotate the card when it's scored if (sound_id == UNDEFINED) return; // If no sound ID is provided, do nothing From 5ef7fa49aa8505c76d8500ba3d96e2511a3bcd1b Mon Sep 17 00:00:00 2001 From: MeirGavish Date: Tue, 12 Aug 2025 17:22:42 +0300 Subject: [PATCH 7/7] Added more undesired IDE artifacts to .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 542edaa..be9866f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /build /.vs *.sln -*.vcxproj* \ No newline at end of file +*.vcxproj* +/balatro-gba/x64/**