Merge pull request #78 from cellos51/jokers_palette_swapping
Updated joker palette swapping system to reuse palettes when jokers are removed Also includes some refactoring in game.c for the shop intro And also in sprite.c/.h I removed the unused pb and tid fields and provided a sprite_get_pb() function to access the actual parameter from the object
This commit is contained in:
+7
-1
@@ -6,10 +6,16 @@
|
|||||||
#include "sprite.h"
|
#include "sprite.h"
|
||||||
#include "card.h"
|
#include "card.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "graphic_utils.h"
|
||||||
|
|
||||||
#define JOKER_TID (MAX_HAND_SIZE + MAX_SELECTION_SIZE) * JOKER_SPRITE_OFFSET // Tile ID for the starting index in the tile memory
|
#define JOKER_TID (MAX_HAND_SIZE + MAX_SELECTION_SIZE) * JOKER_SPRITE_OFFSET // Tile ID for the starting index in the tile memory
|
||||||
#define JOKER_SPRITE_OFFSET 16 // Offset for the joker sprites
|
#define JOKER_SPRITE_OFFSET 16 // Offset for the joker sprites
|
||||||
#define JOKER_BASE_PB 4 // Palette bank for the default jokers
|
#define JOKER_BASE_PB 4 // The starting palette index for the jokers
|
||||||
|
#define JOKER_LAST_PB (NUM_PALETTES - 1)
|
||||||
|
// Currently allocating the rest of the palettes for the jokers.
|
||||||
|
// This number needs to be decreased once we need to allocated palettes for other sprites
|
||||||
|
// such as planet cards etc.
|
||||||
|
|
||||||
#define JOKER_STARTING_LAYER 27
|
#define JOKER_STARTING_LAYER 27
|
||||||
|
|
||||||
#define BASE_EDITION 0
|
#define BASE_EDITION 0
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,6 @@ typedef struct
|
|||||||
{
|
{
|
||||||
OBJ_ATTR *obj;
|
OBJ_ATTR *obj;
|
||||||
OBJ_AFFINE *aff;
|
OBJ_AFFINE *aff;
|
||||||
u32 tid, pb;
|
|
||||||
POINT pos;
|
POINT pos;
|
||||||
} Sprite;
|
} Sprite;
|
||||||
|
|
||||||
@@ -46,6 +45,7 @@ INLINE void sprite_position(Sprite *sprite, int x, int y)
|
|||||||
// Sprite functions
|
// Sprite functions
|
||||||
void sprite_init();
|
void sprite_init();
|
||||||
void sprite_draw();
|
void sprite_draw();
|
||||||
|
int sprite_get_pb(const Sprite* sprite);
|
||||||
|
|
||||||
// SpriteObject methods
|
// SpriteObject methods
|
||||||
SpriteObject *sprite_object_new();
|
SpriteObject *sprite_object_new();
|
||||||
|
|||||||
+35
-31
@@ -29,7 +29,7 @@ static uint timer = 0; // This might already exist in libtonc but idk so i'm jus
|
|||||||
static int game_speed = 1;
|
static int game_speed = 1;
|
||||||
static int background = 0;
|
static int background = 0;
|
||||||
|
|
||||||
static enum GameState game_state = GAME_BLIND_SELECT; // The current game state, this is used to determine what the game is doing at any given time
|
static enum GameState game_state = GAME_SHOP; // The current game state, this is used to determine what the game is doing at any given time
|
||||||
static enum HandState hand_state = HAND_DRAW;
|
static enum HandState hand_state = HAND_DRAW;
|
||||||
static enum PlayState play_state = PLAY_PLAYING;
|
static enum PlayState play_state = PLAY_PLAYING;
|
||||||
static int state = 0; // General state variable, used for switch statements in each game state related function
|
static int state = 0; // General state variable, used for switch statements in each game state related function
|
||||||
@@ -2146,6 +2146,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()
|
void game_shop()
|
||||||
{
|
{
|
||||||
change_background(BG_ID_SHOP);
|
change_background(BG_ID_SHOP);
|
||||||
@@ -2194,36 +2227,7 @@ void game_shop()
|
|||||||
{
|
{
|
||||||
case 0: // Intro sequence (menu and shop icon coming into frame)
|
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);
|
game_shop_intro(shop_jokers);
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 1: // Shop menu input and selection
|
case 1: // Shop menu input and selection
|
||||||
|
|||||||
+49
-20
@@ -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.
|
// Maps the spritesheet index to the palette bank index allocated to it.
|
||||||
// Spritesheets that were not allocated are
|
// Spritesheets that were not allocated are
|
||||||
static int* joker_spritesheet_pb_map;
|
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()
|
static int get_num_spritesheets()
|
||||||
{
|
{
|
||||||
return (get_joker_registry_size() + NUM_JOKERS_PER_SPRITESHEET - 1) / NUM_JOKERS_PER_SPRITESHEET;
|
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
|
// 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)
|
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];
|
int joker_pb = joker_spritesheet_pb_map[joker_spritesheet_idx];
|
||||||
if (joker_pb != UNDEFINED)
|
if (joker_pb != UNDEFINED)
|
||||||
{
|
{
|
||||||
@@ -57,23 +93,9 @@ static int allocate_pb_if_needed(u8 joker_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allocate a new palette
|
// 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)
|
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
|
// Ran out of palettes, default to base and pray
|
||||||
joker_pb = JOKER_BASE_PB;
|
joker_pb = JOKER_BASE_PB;
|
||||||
@@ -131,7 +153,7 @@ Joker *joker_new(u8 id)
|
|||||||
|
|
||||||
joker->id = id;
|
joker->id = id;
|
||||||
joker->modifier = BASE_EDITION; // TODO: Make this a parameter
|
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->rarity = jinfo->rarity;
|
||||||
joker->processed = false;
|
joker->processed = false;
|
||||||
|
|
||||||
@@ -174,12 +196,13 @@ JokerObject *joker_object_new(Joker *joker)
|
|||||||
|
|
||||||
int tile_index = JOKER_TID + (layer * JOKER_SPRITE_OFFSET);
|
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_idx = joker->id % NUM_JOKERS_PER_SPRITESHEET;
|
||||||
int joker_pb = allocate_pb_if_needed(joker->id);
|
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);
|
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
|
sprite_object_set_sprite
|
||||||
(
|
(
|
||||||
joker_object->sprite_object,
|
joker_object->sprite_object,
|
||||||
@@ -200,10 +223,16 @@ JokerObject *joker_object_new(Joker *joker)
|
|||||||
|
|
||||||
void joker_object_destroy(JokerObject **joker_object)
|
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;
|
int layer = sprite_get_layer(joker_object_get_sprite(*joker_object)) - JOKER_STARTING_LAYER;
|
||||||
used_layers[layer] = false;
|
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
|
sprite_object_destroy(&(*joker_object)->sprite_object); // Destroy the sprite
|
||||||
joker_destroy(&(*joker_object)->joker); // Destroy the joker
|
joker_destroy(&(*joker_object)->joker); // Destroy the joker
|
||||||
free(*joker_object);
|
free(*joker_object);
|
||||||
|
|||||||
@@ -101,6 +101,15 @@ void sprite_draw()
|
|||||||
oam_copy(oam_mem, obj_buffer, MAX_SPRITES);
|
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 methods
|
||||||
SpriteObject* sprite_object_new()
|
SpriteObject* sprite_object_new()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user