Merge branch 'main' into jokers_with_graphics

This commit is contained in:
MeirGavish
2025-08-08 00:32:10 +03:00
8 changed files with 129 additions and 63 deletions
+37 -32
View File
@@ -1836,7 +1836,7 @@ static void game_shop_create_items(JokerObject *shop_jokers[], bool first_time)
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);
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)
@@ -2150,6 +2150,39 @@ void game_round_end()
}
}
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);
}
if (timer >= 7) // Shift the shop icon
{
int timer_offset = timer - 6;
// TODO: Extract to generic function?
for (int y = 0; y < timer_offset; y++)
{
int y_from = 26 + y - timer_offset;
int y_to = 0 + y;
Rect from = { 0, y_from, 8, y_from };
BG_POINT to = { 0, y_to };
main_bg_se_copy_rect(from, to);
}
}
if (timer == 12)
{
state = 1;
timer = 0; // Reset the timer
}
}
void game_shop()
{
change_background(BG_ID_SHOP);
@@ -2198,36 +2231,7 @@ void game_shop()
{
case 0: // Intro sequence (menu and shop icon coming into frame)
{
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SE_UP);
if (timer == 1)
{
game_shop_create_items(shop_jokers, true);
}
if (timer >= 7) // Shift the shop icon
{
int timer_offset = timer - 6;
// TODO: Extract to generic function?
for (int y = 0; y < timer_offset; y++)
{
int y_from = 26 + y - timer_offset;
int y_to = 0 + y;
Rect from = {0, y_from, 8, y_from};
BG_POINT to = {0, y_to};
main_bg_se_copy_rect(from, to);
}
}
if (timer == 12)
{
state = 1;
timer = 0; // Reset the timer
}
game_shop_intro(shop_jokers);
break;
}
case 1: // Shop menu input and selection
@@ -2329,7 +2333,8 @@ void game_shop()
Rect joker_price_rect;
joker_price_rect.left = fx2int(shop_jokers[i]->sprite_object->tx);
joker_price_rect.top = fx2int(shop_jokers[i]->sprite_object->ty) + TILE_SIZE;
// 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;
+49 -20
View File
@@ -39,16 +39,52 @@ static bool used_layers[MAX_JOKER_OBJECTS] = {false}; // Track used layers for j
// Maps the spritesheet index to the palette bank index allocated to it.
// Spritesheets that were not allocated are
static int* joker_spritesheet_pb_map;
static int joker_pb_num_sprite_users[JOKER_LAST_PB - JOKER_BASE_PB + 1] = { 0 };
static int get_num_spritesheets()
{
return (get_joker_registry_size() + NUM_JOKERS_PER_SPRITESHEET - 1) / NUM_JOKERS_PER_SPRITESHEET;
}
static int joker_get_spritesheet_idx(u8 joker_id)
{
return joker_id / NUM_JOKERS_PER_SPRITESHEET;
}
// TODO: This should be generalized so any sprite can have dynamic swapping
static void joker_pb_add_sprite_user(int pb)
{
joker_pb_num_sprite_users[pb - JOKER_BASE_PB]++;
}
static void joker_pb_remove_sprite_user(int pb)
{
int num_sprite_users = joker_pb_num_sprite_users[pb - JOKER_BASE_PB];
joker_pb_num_sprite_users[pb - JOKER_BASE_PB] = max(0, num_sprite_users - 1);
}
static int joker_pb_get_num_sprite_users(int joker_pb)
{
return joker_pb_num_sprite_users[joker_pb - JOKER_BASE_PB];
}
static int get_unused_joker_pb()
{
for (int i = 0; i < NUM_ELEM_IN_ARR(joker_pb_num_sprite_users); i++)
{
if (joker_pb_num_sprite_users[i] == 0)
{
return (i + JOKER_BASE_PB);
}
}
return UNDEFINED;
}
static int allocate_pb_if_needed(u8 joker_id)
{
int joker_spritesheet_idx = joker_id / NUM_JOKERS_PER_SPRITESHEET;
int joker_spritesheet_idx = joker_get_spritesheet_idx(joker_id);
int joker_pb = joker_spritesheet_pb_map[joker_spritesheet_idx];
if (joker_pb != UNDEFINED)
{
@@ -57,23 +93,9 @@ static int allocate_pb_if_needed(u8 joker_id)
}
// Allocate a new palette
joker_pb = int_arr_max(joker_spritesheet_pb_map, get_num_spritesheets());
joker_pb = get_unused_joker_pb();
if (joker_pb == UNDEFINED)
{
// This is the first palette loaded
joker_pb = JOKER_BASE_PB;
}
else
{
// The new palette bank is a 1 increment of the last allocated one
/* TODO: This doesn't account for removal, we need to address that,
* track sprite usage and remove palettes for unused sprites
*/
joker_pb = joker_pb + 1;
}
if (joker_pb == NUM_PALETTES)
{
// Ran out of palettes, default to base and pray
joker_pb = JOKER_BASE_PB;
@@ -137,7 +159,7 @@ Joker *joker_new(u8 id)
joker->id = id;
joker->modifier = BASE_EDITION; // TODO: Make this a parameter
joker->value = jinfo->base_value + edition_price_lut[joker->modifier]; // Base value + edition price
joker->value = jinfo->base_value + edition_price_lut[joker->modifier];
joker->rarity = jinfo->rarity;
joker->processed = false;
@@ -180,12 +202,13 @@ JokerObject *joker_object_new(Joker *joker)
int tile_index = JOKER_TID + (layer * JOKER_SPRITE_OFFSET);
int joker_spritesheet_idx = joker->id / NUM_JOKERS_PER_SPRITESHEET;
int joker_spritesheet_idx = joker_get_spritesheet_idx(joker->id);
int joker_idx = joker->id % NUM_JOKERS_PER_SPRITESHEET;
int joker_pb = allocate_pb_if_needed(joker->id);
joker_pb_add_sprite_user(joker_pb);
memcpy32(&tile_mem[4][tile_index], &joker_gfxTiles[joker_spritesheet_idx][joker_idx * TILE_SIZE * JOKER_SPRITE_OFFSET], TILE_SIZE * JOKER_SPRITE_OFFSET);
sprite_object_set_sprite
(
joker_object->sprite_object,
@@ -206,10 +229,16 @@ JokerObject *joker_object_new(Joker *joker)
void joker_object_destroy(JokerObject **joker_object)
{
if (*joker_object == NULL) return;
if (joker_object == NULL || *joker_object == NULL) return;
int layer = sprite_get_layer(joker_object_get_sprite(*joker_object)) - JOKER_STARTING_LAYER;
used_layers[layer] = false;
joker_pb_remove_sprite_user(sprite_get_pb(joker_object_get_sprite(*joker_object)));
if (joker_pb_get_num_sprite_users((sprite_get_pb(joker_object_get_sprite(*joker_object)))) == 0)
{
joker_spritesheet_pb_map[joker_get_spritesheet_idx((*joker_object)->joker->id)] = UNDEFINED;
}
sprite_object_destroy(&(*joker_object)->sprite_object); // Destroy the sprite
joker_destroy(&(*joker_object)->joker); // Destroy the joker
free(*joker_object);
+11 -2
View File
@@ -1,5 +1,6 @@
#include "sprite.h"
#include "util.h"
#include "audio_utils.h"
#include <tonc.h>
#include <stdlib.h>
@@ -100,6 +101,15 @@ void sprite_draw()
oam_copy(oam_mem, obj_buffer, MAX_SPRITES);
}
int sprite_get_pb(const Sprite *sprite)
{
if (sprite == NULL)
{
return UNDEFINED;
}
return (sprite->obj->attr2 & ATTR2_PALBANK_MASK) >> ATTR2_PALBANK_SHIFT;
}
// SpriteObject methods
SpriteObject* sprite_object_new()
{
@@ -206,8 +216,7 @@ void sprite_object_shake(SpriteObject* sprite_object, mm_word sound_id)
if (sound_id == UNDEFINED) return; // If no sound ID is provided, do nothing
mm_sound_effect sfx_select = { {sound_id}, 1024, 0, 255, 128, };
mmEffectEx(&sfx_select);
play_sfx(sound_id, MM_BASE_PITCH_RATE);
}
void sprite_object_set_selected(SpriteObject* sprite_object, bool selected)