Implement arbitrary-sized joker spritesheets (#285)
* Convert static joker sprites indexes to maps for dynamic spritesheets size * tmp commit * reorder Joker spritesheets * more reordering * Joker maps, will test later * More reorders and palette optimizations. Sprites now work * Fix Joker gfx * Format joker.c * Fix rebase error * Integrate Shoot the Moon art * format * format * removing useless GBAL_UNUSED from photograph Joker effect func * Tidy up joker.c variables formatting * Fix magic number * Add context for map in joker.c Co-authored-by: Rickey <ric@rf3.xyz> * Update source/joker.c Co-authored-by: Rickey <ric@rf3.xyz> * Apply suggestion from @ricfehr3 Co-authored-by: Rickey <ric@rf3.xyz> * format * reduce clutter in joker_effects.c file by defining a macro for forward static declarations of joker effect funcs * refactored some maps in joker.c to make it more concise * clang format * adding back how to mark functions as unused when Jokers don't have a sprite yet * format * Remove comment about unused functions for Jokers without art --------- Co-authored-by: MathisMartin31 <mathis.martin31@gmail.com> Co-authored-by: Rickey <ric@rf3.xyz>
This commit is contained in:
+66
-25
@@ -12,17 +12,17 @@
|
||||
#include <string.h>
|
||||
#include <tonc.h>
|
||||
|
||||
#define JOKER_SCORE_TEXT_Y 48
|
||||
#define HELD_CARD_SCORE_TEXT_Y 108
|
||||
#define MAX_CARD_SCORE_STR_LEN 2
|
||||
#define NUM_JOKERS_PER_SPRITESHEET 2
|
||||
#define JOKER_SCORE_TEXT_Y 48
|
||||
#define HELD_CARD_SCORE_TEXT_Y 108
|
||||
#define MAX_CARD_SCORE_STR_LEN 2
|
||||
// what it was before (MAX_DEFINEABLE_JOKERS / JOKERS_PER_SPRITESHEET)
|
||||
#define MAX_NUM_JOKERS_SPRITESHEETS 75
|
||||
|
||||
static const unsigned int* joker_gfxTiles[] = {
|
||||
#define DEF_JOKER_GFX(idx) joker_gfx##idx##Tiles,
|
||||
#include "../include/def_joker_gfx_table.h"
|
||||
#undef DEF_JOKER_GFX
|
||||
};
|
||||
|
||||
static const unsigned short* joker_gfxPal[] = {
|
||||
#define DEF_JOKER_GFX(idx) joker_gfx##idx##Pal,
|
||||
#include "def_joker_gfx_table.h"
|
||||
@@ -44,16 +44,53 @@ const static u8 edition_price_lut[MAX_EDITIONS] = {
|
||||
logic. But I'm going to use a simpler approach for the joker objects since I'm lazy and sorting
|
||||
them wouldn't look good enough to warrant the effort.
|
||||
*/
|
||||
static bool _used_layers[MAX_JOKER_OBJECTS] = {false}; // Track used layers for joker sprites
|
||||
static bool used_layers[MAX_JOKER_OBJECTS] = {false}; // Track used layers for joker sprites
|
||||
// TODO: Refactor sorting into SpriteObject?
|
||||
|
||||
// Maps the spritesheet index to the palette bank index allocated to it.
|
||||
// Spritesheets that were not allocated are
|
||||
static int _joker_spritesheet_pb_map[(MAX_DEFINABLE_JOKERS + 1) / NUM_JOKERS_PER_SPRITESHEET];
|
||||
static int _joker_pb_num_sprite_users[JOKER_LAST_PB - JOKER_BASE_PB + 1] = {0};
|
||||
static int joker_spritesheet_pb_map[MAX_NUM_JOKERS_SPRITESHEETS];
|
||||
static int joker_pb_num_sprite_users[JOKER_LAST_PB - JOKER_BASE_PB + 1] = {0};
|
||||
|
||||
// See linked issue for context of maps
|
||||
// https://github.com/GBALATRO/balatro-gba/issues/274#issue-3685075538
|
||||
|
||||
// clang-format off
|
||||
// Map of Joker ID -> Spritesheet idx
|
||||
static int joker_id_to_sprite_map[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 1,
|
||||
2, 2,
|
||||
3, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5,
|
||||
6, 6, 6, 6,
|
||||
7, 7,
|
||||
8, 8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
};
|
||||
|
||||
// Map of Spritesheet idx -> first Joker ID in sheet
|
||||
// This is used to determine the sprite index of a Joker's sprite
|
||||
// within its spritesheet by substracting its ID to this starting ID.
|
||||
// Notice how spritesheets with only one Joker have sequential starting IDs.
|
||||
static int spritesheet_idx_to_starting_joker_id[] = {
|
||||
0, 18, 20, 22, 27, 32, 36, 40, 42, 44,
|
||||
45, 46, 47, 48, 49, 50, 51, 52
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
static int s_get_num_spritesheets(void);
|
||||
static int s_joker_get_spritesheet_idx(u8 joker_id);
|
||||
static int s_joker_get_sprite_idx_in_sheet(u8 joker_id, int spritesheet_idx);
|
||||
static void s_joker_pb_add_sprite_user(int pb);
|
||||
static void s_joker_pb_remove_sprite_user(int pb);
|
||||
static int s_joker_pb_get_num_sprite_users(int joker_pb);
|
||||
@@ -67,7 +104,7 @@ void joker_init()
|
||||
|
||||
for (int i = 0; i < num_spritesheets; i++)
|
||||
{
|
||||
_joker_spritesheet_pb_map[i] = UNDEFINED;
|
||||
joker_spritesheet_pb_map[i] = UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,10 +168,10 @@ JokerObject* joker_object_new(Joker* joker)
|
||||
int layer = 0;
|
||||
for (int i = 0; i < MAX_JOKER_OBJECTS; i++)
|
||||
{
|
||||
if (!_used_layers[i])
|
||||
if (!used_layers[i])
|
||||
{
|
||||
layer = i;
|
||||
_used_layers[i] = true; // Mark this layer as used
|
||||
used_layers[i] = true; // Mark this layer as used
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -145,7 +182,7 @@ JokerObject* joker_object_new(Joker* joker)
|
||||
int tile_index = JOKER_TID + (layer * JOKER_SPRITE_OFFSET);
|
||||
|
||||
int joker_spritesheet_idx = s_joker_get_spritesheet_idx(joker->id);
|
||||
int joker_idx = joker->id % NUM_JOKERS_PER_SPRITESHEET;
|
||||
int joker_idx = s_joker_get_sprite_idx_in_sheet(joker->id, joker_spritesheet_idx);
|
||||
int joker_pb = s_allocate_pb_if_needed(joker->id);
|
||||
s_joker_pb_add_sprite_user(joker_pb);
|
||||
|
||||
@@ -175,12 +212,12 @@ void joker_object_destroy(JokerObject** joker_object)
|
||||
return;
|
||||
|
||||
int layer = sprite_get_layer(joker_object_get_sprite(*joker_object)) - JOKER_STARTING_LAYER;
|
||||
_used_layers[layer] = false;
|
||||
used_layers[layer] = false;
|
||||
s_joker_pb_remove_sprite_user(sprite_get_pb(joker_object_get_sprite(*joker_object)));
|
||||
if (s_joker_pb_get_num_sprite_users((sprite_get_pb(joker_object_get_sprite(*joker_object)))) ==
|
||||
0)
|
||||
{
|
||||
_joker_spritesheet_pb_map[s_joker_get_spritesheet_idx((*joker_object)->joker->id)] =
|
||||
joker_spritesheet_pb_map[s_joker_get_spritesheet_idx((*joker_object)->joker->id)] =
|
||||
UNDEFINED;
|
||||
}
|
||||
|
||||
@@ -354,36 +391,40 @@ int joker_get_random_rarity()
|
||||
|
||||
static int s_get_num_spritesheets()
|
||||
{
|
||||
return (get_joker_registry_size() + NUM_JOKERS_PER_SPRITESHEET - 1) /
|
||||
NUM_JOKERS_PER_SPRITESHEET;
|
||||
return MAX_NUM_JOKERS_SPRITESHEETS;
|
||||
}
|
||||
|
||||
static int s_joker_get_spritesheet_idx(u8 joker_id)
|
||||
{
|
||||
return joker_id / NUM_JOKERS_PER_SPRITESHEET;
|
||||
return joker_id_to_sprite_map[joker_id];
|
||||
}
|
||||
|
||||
static int s_joker_get_sprite_idx_in_sheet(u8 joker_id, int spritesheet_idx)
|
||||
{
|
||||
return joker_id - spritesheet_idx_to_starting_joker_id[joker_id_to_sprite_map[joker_id]];
|
||||
}
|
||||
|
||||
static void s_joker_pb_add_sprite_user(int pb)
|
||||
{
|
||||
_joker_pb_num_sprite_users[pb - JOKER_BASE_PB]++;
|
||||
joker_pb_num_sprite_users[pb - JOKER_BASE_PB]++;
|
||||
}
|
||||
|
||||
static void s_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);
|
||||
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 s_joker_pb_get_num_sprite_users(int joker_pb)
|
||||
{
|
||||
return _joker_pb_num_sprite_users[joker_pb - JOKER_BASE_PB];
|
||||
return joker_pb_num_sprite_users[joker_pb - JOKER_BASE_PB];
|
||||
}
|
||||
|
||||
static int s_get_unused_joker_pb()
|
||||
{
|
||||
for (int i = 0; i < NUM_ELEM_IN_ARR(_joker_pb_num_sprite_users); i++)
|
||||
for (int i = 0; i < NUM_ELEM_IN_ARR(joker_pb_num_sprite_users); i++)
|
||||
{
|
||||
if (_joker_pb_num_sprite_users[i] == 0)
|
||||
if (joker_pb_num_sprite_users[i] == 0)
|
||||
{
|
||||
return (i + JOKER_BASE_PB);
|
||||
}
|
||||
@@ -395,7 +436,7 @@ static int s_get_unused_joker_pb()
|
||||
static int s_allocate_pb_if_needed(u8 joker_id)
|
||||
{
|
||||
int joker_spritesheet_idx = s_joker_get_spritesheet_idx(joker_id);
|
||||
int joker_pb = _joker_spritesheet_pb_map[joker_spritesheet_idx];
|
||||
int joker_pb = joker_spritesheet_pb_map[joker_spritesheet_idx];
|
||||
if (joker_pb != UNDEFINED)
|
||||
{
|
||||
// Already allocated
|
||||
@@ -412,7 +453,7 @@ static int s_allocate_pb_if_needed(u8 joker_id)
|
||||
}
|
||||
else
|
||||
{
|
||||
_joker_spritesheet_pb_map[joker_spritesheet_idx] = joker_pb;
|
||||
joker_spritesheet_pb_map[joker_spritesheet_idx] = joker_pb;
|
||||
memcpy16(
|
||||
&pal_obj_mem[PAL_ROW_LEN * joker_pb],
|
||||
joker_gfxPal[joker_spritesheet_idx],
|
||||
|
||||
Reference in New Issue
Block a user