7c62cfc950
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.
230 lines
6.3 KiB
C
230 lines
6.3 KiB
C
#include "game/main_menu.h"
|
|
|
|
#include "affine_background.h"
|
|
#include "audio_utils.h"
|
|
#include "background_main_menu_gfx.h"
|
|
#include "button.h"
|
|
#include "card.h"
|
|
#include "game.h"
|
|
#include "game/common_ui.h"
|
|
#include "game_variables.h"
|
|
#include "graphic_utils.h"
|
|
#include "selection_grid.h"
|
|
#include "soundbank.h"
|
|
#include "sprite.h"
|
|
#include "version.h"
|
|
|
|
#include <stdint.h>
|
|
#include <tonc.h>
|
|
#include <tonc_math.h>
|
|
#include <tonc_memdef.h>
|
|
|
|
#define PLAY_BUTTON_MAIN_COLOR_PID 1
|
|
#define PLAY_BUTTON_OUTLINE_PID 2
|
|
#define OPTIONS_BUTTON_MAIN_COLOR_PID 3
|
|
#define OPTIONS_BUTTON_OUTLINE_PID 4
|
|
|
|
enum MainButtons
|
|
{
|
|
PLAY_BTN_IDX,
|
|
OPTIONS_BTN_IDX,
|
|
MAIN_MENU_NB_BTN
|
|
};
|
|
|
|
// Pixel sizes
|
|
#define MAIN_MENU_ACE_T_X 88
|
|
#define MAIN_MENU_ACE_T_Y 26
|
|
|
|
// clang-format off
|
|
static const BG_POINT GBALATRO_VERSION_TEXT_POS = {0, 152};
|
|
static const Rect GBALATRO_VERSION_TEXT_RECT = {0, 152, 240, 160};
|
|
// clang-format on
|
|
|
|
// Define SelectionGrid for the main menu buttons
|
|
|
|
static int main_menu_return_row_size(void);
|
|
static bool main_menu_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
);
|
|
static void main_menu_on_key_transit(SelectionGrid* selection_grid, Selection* selection);
|
|
|
|
static void play_on_pressed(void);
|
|
static void options_on_pressed(void);
|
|
|
|
// clang-format off
|
|
static SelectionGridRow main_menu_selection_rows[] = {
|
|
{
|
|
0,
|
|
main_menu_return_row_size,
|
|
main_menu_on_selection_changed,
|
|
main_menu_on_key_transit,
|
|
{.wrap = false}
|
|
},
|
|
};
|
|
|
|
static Button main_menu_buttons[] = {
|
|
{PLAY_BUTTON_OUTLINE_PID, PLAY_BUTTON_MAIN_COLOR_PID, play_on_pressed, NULL},
|
|
{OPTIONS_BUTTON_OUTLINE_PID, OPTIONS_BUTTON_MAIN_COLOR_PID, options_on_pressed, NULL},
|
|
};
|
|
|
|
static SelectionGrid main_menu_selection_grid = {
|
|
main_menu_selection_rows,
|
|
1,
|
|
{0, 0}
|
|
};
|
|
// clang-format on
|
|
|
|
// Main menu sprite - the ace of spades
|
|
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)
|
|
{
|
|
toggle_windows(false, false);
|
|
|
|
tte_erase_screen();
|
|
GRIT_CPY(pal_bg_mem, background_main_menu_gfxPal);
|
|
GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_main_menu_gfxTiles);
|
|
GRIT_CPY(&se_mem[MAIN_BG_SBB], background_main_menu_gfxMap);
|
|
|
|
// Disable all button highlight colors
|
|
for (int i = 0; i < MAIN_MENU_NB_BTN; i++)
|
|
{
|
|
button_set_highlight(&main_menu_buttons[i], false);
|
|
}
|
|
}
|
|
|
|
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
|
|
s_main_menu_ace->sprite->obj->attr0 |= ATTR0_AFF_DBL;
|
|
s_main_menu_ace->tscale = float2fx(0.8f);
|
|
sprite_object_position((SpriteObject*)s_main_menu_ace, MAIN_MENU_ACE_T_X, MAIN_MENU_ACE_T_Y);
|
|
|
|
// Select last highlighted button, Play button by default.
|
|
// e.g. if we return from the options menu, we want the Options button to be highlighted.
|
|
Selection sel_init = {s_last_highlighted_button, 0};
|
|
main_menu_selection_grid.selection = sel_init;
|
|
|
|
// Highlight current button
|
|
button_set_highlight(&main_menu_buttons[main_menu_selection_grid.selection.x], true);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void game_main_menu_on_exit(void)
|
|
{
|
|
// Save selected button
|
|
s_last_highlighted_button = main_menu_selection_grid.selection.x;
|
|
|
|
// Normally I would just cache these and hide/unhide but I didn't feel like dealing with
|
|
// defining a layer for it
|
|
card_destroy(&s_main_menu_ace->card);
|
|
card_object_destroy(&s_main_menu_ace);
|
|
}
|
|
|
|
// Implement SelectionGrid handler functions
|
|
|
|
static int main_menu_return_row_size(void)
|
|
{
|
|
return MAIN_MENU_NB_BTN;
|
|
}
|
|
|
|
static bool main_menu_on_selection_changed(
|
|
SelectionGrid* selection_grid,
|
|
int row_idx,
|
|
const Selection* prev_selection,
|
|
const Selection* new_selection
|
|
)
|
|
{
|
|
if (prev_selection->x >= 0 && prev_selection->x < MAIN_MENU_NB_BTN)
|
|
{
|
|
button_set_highlight(&main_menu_buttons[prev_selection->x], false);
|
|
}
|
|
|
|
play_sfx(SFX_BUTTON, MM_BASE_PITCH_RATE, BUTTON_SFX_VOLUME);
|
|
button_set_highlight(&main_menu_buttons[new_selection->x], true);
|
|
|
|
return true;
|
|
}
|
|
|
|
static void main_menu_on_key_transit(SelectionGrid* selection_grid, Selection* selection)
|
|
{
|
|
// DEBUG: toggle git hash display by pressing L+R+START+SELECT
|
|
static bool combo_pressed = false;
|
|
static bool show_version = false;
|
|
if (key_is_down(KEY_START) && key_is_down(KEY_SELECT) && key_is_down(KEY_L) &&
|
|
key_is_down(KEY_R))
|
|
{
|
|
if (!combo_pressed)
|
|
{
|
|
show_version = !show_version;
|
|
if (show_version)
|
|
{
|
|
tte_printf(
|
|
"#{P:%d,%d; cx:0x%X000}%s",
|
|
GBALATRO_VERSION_TEXT_POS.x,
|
|
GBALATRO_VERSION_TEXT_POS.y,
|
|
TTE_WHITE_PB,
|
|
gbalatro_version
|
|
);
|
|
}
|
|
else
|
|
{
|
|
tte_erase_rect_wrapper(GBALATRO_VERSION_TEXT_RECT);
|
|
s_gallery_prompt_drawn = false;
|
|
}
|
|
}
|
|
|
|
combo_pressed = true;
|
|
}
|
|
else
|
|
{
|
|
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]);
|
|
}
|
|
}
|
|
|
|
static void play_on_pressed(void)
|
|
{
|
|
game_change_state(GAME_STATE_RUN_SETUP);
|
|
}
|
|
|
|
static void options_on_pressed(void)
|
|
{
|
|
game_change_state(GAME_STATE_OPTIONS_MENU);
|
|
}
|