Add a main-menu Joker gallery
Expose every registered Joker from a paged review screen entered with Start or Select. Reuse the gameplay card art and description renderers, support controller navigation, and clean up the preview object when returning to the menu.
This commit is contained in:
@@ -2,6 +2,12 @@
|
||||
// (stateEnum, on_init, on_update, on_exit)
|
||||
DEF_STATE_INFO(GAME_STATE_SPLASH_SCREEN, splash_screen_on_init, splash_screen_on_update, splash_screen_on_exit )
|
||||
DEF_STATE_INFO(GAME_STATE_MAIN_MENU, game_main_menu_on_init, game_main_menu_on_update, game_main_menu_on_exit )
|
||||
DEF_STATE_INFO(
|
||||
GAME_STATE_JOKER_GALLERY,
|
||||
game_joker_gallery_on_init,
|
||||
game_joker_gallery_on_update,
|
||||
game_joker_gallery_on_exit
|
||||
)
|
||||
DEF_STATE_INFO(GAME_STATE_OPTIONS_MENU, game_options_menu_on_init, game_options_menu_on_update, game_options_menu_on_exit)
|
||||
DEF_STATE_INFO(GAME_STATE_RUN_SETUP , game_run_setup_on_init, game_run_setup_on_update, game_run_setup_on_exit )
|
||||
DEF_STATE_INFO(GAME_STATE_GAME_START, noop, game_start, noop )
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @file joker_gallery.h
|
||||
*
|
||||
* @brief Main-menu Joker description gallery state functions.
|
||||
*/
|
||||
#ifndef GAME_JOKER_GALLERY_H
|
||||
#define GAME_JOKER_GALLERY_H
|
||||
|
||||
/**
|
||||
* @brief Initialize the Joker gallery and display the selected Joker.
|
||||
*/
|
||||
void game_joker_gallery_on_init(void);
|
||||
|
||||
/**
|
||||
* @brief Process Joker gallery navigation input.
|
||||
*/
|
||||
void game_joker_gallery_on_update(void);
|
||||
|
||||
/**
|
||||
* @brief Destroy gallery resources before leaving the state.
|
||||
*/
|
||||
void game_joker_gallery_on_exit(void);
|
||||
|
||||
#endif // GAME_JOKER_GALLERY_H
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "game/blind_select.h"
|
||||
#include "game/common_ui.h"
|
||||
#include "game/game_over.h"
|
||||
#include "game/joker_gallery.h"
|
||||
#include "game/joker_row.h"
|
||||
#include "game/main_menu.h"
|
||||
#include "game/options_menu.h"
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
#include "game/joker_gallery.h"
|
||||
|
||||
#include "affine_background.h"
|
||||
#include "game.h"
|
||||
#include "game/common_ui.h"
|
||||
#include "graphic_utils.h"
|
||||
#include "joker.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <tonc.h>
|
||||
|
||||
#define SHOP_DESC_RARITY_MAIN_COLOR_PAL_IDX 27
|
||||
#define SHOP_DESC_RARITY_SHADOW_COLOR_PAL_IDX 28
|
||||
|
||||
// clang-format off
|
||||
static const Rect VISIBLE_SCREEN_TILE_RECT = { 0, 0, 29, 19};
|
||||
static const BG_POINT CLEAR_TILE_SOURCE = {30, 1};
|
||||
static const Rect CARD_DESC_PANEL_RECT = { 9, 6, 28, 18};
|
||||
static const NinePatchRect CARD_DESC_PANEL_SOURCE = {
|
||||
.patch_rect = {27, 25, 31, 31},
|
||||
.margins = { 2, 3, 2, 3}
|
||||
};
|
||||
static const int CARD_DESC_MAX_TEXT_HEIGHT = CARD_DESC_PANEL_RECT.bottom -
|
||||
CARD_DESC_PANEL_RECT.top + 1 -
|
||||
CARD_DESC_PANEL_SOURCE.margins.top -
|
||||
CARD_DESC_PANEL_SOURCE.margins.bottom;
|
||||
static const Rect CARD_DESC_TEXT_RECT = {11, 9, 26, 18};
|
||||
static const Rect CARD_NAME_TEXT_RECT = {10, 7, 27, 7};
|
||||
static const BG_POINT JOKER_SPRITE_POS = {135, 9};
|
||||
// clang-format on
|
||||
|
||||
static JokerObject* s_gallery_joker = NULL;
|
||||
static size_t s_joker_index = 0;
|
||||
|
||||
static void game_joker_gallery_render(void)
|
||||
{
|
||||
size_t joker_count = get_joker_registry_size();
|
||||
const JokerInfo* info = get_joker_registry_entry(s_joker_index);
|
||||
|
||||
tte_erase_screen();
|
||||
main_bg_se_copy_expand_tile(VISIBLE_SCREEN_TILE_RECT, CLEAR_TILE_SOURCE);
|
||||
|
||||
if (joker_count == 0 || info == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s_gallery_joker = joker_object_new(joker_new(s_joker_index));
|
||||
if (s_gallery_joker == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sprite_object_position((SpriteObject*)s_gallery_joker, JOKER_SPRITE_POS.x, JOKER_SPRITE_POS.y);
|
||||
|
||||
int desc_bottom_offset = CARD_DESC_MAX_TEXT_HEIGHT -
|
||||
info->joker_print_desc(s_gallery_joker->joker, CARD_DESC_TEXT_RECT);
|
||||
desc_bottom_offset = max(0, desc_bottom_offset);
|
||||
|
||||
pal_bg_mem[SHOP_DESC_RARITY_MAIN_COLOR_PAL_IDX] = joker_get_rarity_color(info->rarity, true);
|
||||
pal_bg_mem[SHOP_DESC_RARITY_SHADOW_COLOR_PAL_IDX] = joker_get_rarity_color(info->rarity, false);
|
||||
|
||||
Rect panel_rect = CARD_DESC_PANEL_RECT;
|
||||
panel_rect.bottom -= desc_bottom_offset;
|
||||
main_bg_se_copy_expand_9_patch(panel_rect, &CARD_DESC_PANEL_SOURCE);
|
||||
|
||||
tte_printf(
|
||||
TTE_WHITE_TAG "#{P:%d,%d}%*s%s",
|
||||
CARD_NAME_TEXT_RECT.left * TILE_SIZE,
|
||||
CARD_NAME_TEXT_RECT.top * TILE_SIZE,
|
||||
(rect_width(&CARD_NAME_TEXT_RECT) - strlen(info->name)) / 2,
|
||||
"",
|
||||
info->name
|
||||
);
|
||||
|
||||
const char* rarity = joker_get_rarity_string(info->rarity);
|
||||
tte_printf(
|
||||
TTE_WHITE_TAG "#{P:%d,%d}%*s%s",
|
||||
CARD_DESC_TEXT_RECT.left * TILE_SIZE,
|
||||
(CARD_DESC_TEXT_RECT.bottom - desc_bottom_offset - 1) * TILE_SIZE,
|
||||
(rect_width(&CARD_DESC_TEXT_RECT) - strlen(rarity)) / 2,
|
||||
"",
|
||||
rarity
|
||||
);
|
||||
|
||||
tte_printf(TTE_WHITE_TAG "#{P:8,16}JOKER\n#{P:8,24}GALLERY");
|
||||
tte_printf(TTE_YELLOW_TAG "#{P:8,48}%02d/%02d", (int)s_joker_index + 1, (int)joker_count);
|
||||
tte_printf(TTE_WHITE_TAG "#{P:8,80}L PREV\n#{P:8,96}R NEXT\n#{P:8,120}B BACK");
|
||||
}
|
||||
|
||||
static void game_joker_gallery_change_page(int direction)
|
||||
{
|
||||
size_t joker_count = get_joker_registry_size();
|
||||
if (joker_count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
joker_object_destroy(&s_gallery_joker);
|
||||
if (direction < 0)
|
||||
{
|
||||
s_joker_index = (s_joker_index + joker_count - 1) % joker_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
s_joker_index = (s_joker_index + 1) % joker_count;
|
||||
}
|
||||
game_joker_gallery_render();
|
||||
}
|
||||
|
||||
void game_joker_gallery_on_init(void)
|
||||
{
|
||||
affine_background_change_background(AFFINE_BG_MAIN_MENU);
|
||||
change_background(BG_SHOP, true);
|
||||
toggle_windows(false, false);
|
||||
tte_colors_setup();
|
||||
|
||||
if (s_joker_index >= get_joker_registry_size())
|
||||
{
|
||||
s_joker_index = 0;
|
||||
}
|
||||
|
||||
game_joker_gallery_render();
|
||||
}
|
||||
|
||||
void game_joker_gallery_on_update(void)
|
||||
{
|
||||
if (key_hit(KEY_LEFT | KEY_L))
|
||||
{
|
||||
game_joker_gallery_change_page(-1);
|
||||
}
|
||||
else if (key_hit(KEY_RIGHT | KEY_R | KEY_A))
|
||||
{
|
||||
game_joker_gallery_change_page(1);
|
||||
}
|
||||
else if (key_hit(KEY_B))
|
||||
{
|
||||
game_change_state(GAME_STATE_MAIN_MENU);
|
||||
}
|
||||
}
|
||||
|
||||
void game_joker_gallery_on_exit(void)
|
||||
{
|
||||
joker_object_destroy(&s_gallery_joker);
|
||||
tte_erase_screen();
|
||||
}
|
||||
@@ -82,6 +82,7 @@ static CardObject* s_main_menu_ace = NULL;
|
||||
|
||||
// Keep track of last highlighted button
|
||||
static enum MainButtons s_last_highlighted_button = PLAY_BTN_IDX;
|
||||
static bool s_gallery_prompt_drawn = false;
|
||||
|
||||
void game_main_menu_change_background(void)
|
||||
{
|
||||
@@ -103,6 +104,7 @@ void game_main_menu_on_init(void)
|
||||
{
|
||||
affine_background_change_background(AFFINE_BG_MAIN_MENU);
|
||||
change_background(BG_MAIN_MENU, true);
|
||||
s_gallery_prompt_drawn = false;
|
||||
s_main_menu_ace = card_object_new(card_new(SPADES, ACE));
|
||||
card_object_set_sprite(s_main_menu_ace, 0);
|
||||
// TODO: NULL-check sprite
|
||||
@@ -123,6 +125,13 @@ void game_main_menu_on_update(void)
|
||||
{
|
||||
s_main_menu_ace->trotation = lu_sin((g_game_vars.timer << 8) / 2) / 3;
|
||||
|
||||
// The splash state clears TTE after transitioning, so draw this on the first menu update.
|
||||
if (!s_gallery_prompt_drawn)
|
||||
{
|
||||
tte_printf(TTE_WHITE_TAG "#{P:128,152}START: JOKERS");
|
||||
s_gallery_prompt_drawn = true;
|
||||
}
|
||||
|
||||
selection_grid_process_input(&main_menu_selection_grid);
|
||||
}
|
||||
|
||||
@@ -186,6 +195,7 @@ static void main_menu_on_key_transit(SelectionGrid* selection_grid, Selection* s
|
||||
else
|
||||
{
|
||||
tte_erase_rect_wrapper(GBALATRO_VERSION_TEXT_RECT);
|
||||
s_gallery_prompt_drawn = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,6 +206,12 @@ static void main_menu_on_key_transit(SelectionGrid* selection_grid, Selection* s
|
||||
combo_pressed = false;
|
||||
}
|
||||
|
||||
if ((key_hit(KEY_START) || key_hit(KEY_SELECT)) && !key_is_down(KEY_L) && !key_is_down(KEY_R))
|
||||
{
|
||||
game_change_state(GAME_STATE_JOKER_GALLERY);
|
||||
return;
|
||||
}
|
||||
|
||||
if (key_hit(SELECT_CARD))
|
||||
{
|
||||
button_press(&main_menu_buttons[selection->x]);
|
||||
|
||||
Reference in New Issue
Block a user