5#include "background_game_over_gfx.h"
23#define RED_BTN_MAIN_COLOR_PAL_IDX 6
24#define BLUE_BTN_MAIN_COLOR_PAL_IDX 7
25#define REUSE_SEED_BTN_OUTLINE_PAL_IDX 8
26#define NEW_RUN_BTN_OUTLINE_PAL_IDX 9
27#define MAIN_MENU_BTN_OUTLINE_PAL_IDX 10
28#define ENDLESS_BTN_OUTLINE_PAL_IDX 11
38static const Rect GAME_OVER_ANIM_RECT = { 3, 5, 26, 31};
40static const Rect GAME_OVER_TEXT_TILES_SRC_RECT_1 = { 27, 24, 31, 25};
41static const Rect GAME_OVER_TEXT_TILES_SRC_RECT_2 = { 27, 26, 31, 27};
42static const BG_POINT GAME_OVER_TEXT_TILES_DEST_POS_1 = { 10, 21};
43static const BG_POINT GAME_OVER_TEXT_TILES_DEST_POS_2 = { 15, 21};
45static const Rect DEFEATED_BY_TEXT_SRC_RECT = { 28, 30, 31, 31};
46static const BG_POINT DEFEATED_BY_TEXT_DEST_POS = { 22, 24};
47static const BG_POINT DEFEATED_BY_TOKEN_INIT_POS = {180, 207};
49static const Rect REUSE_SEED_BTN_OFF_SRC_RECT = { 28, 28, 29, 29};
50static const Rect REUSE_SEED_BTN_ON_SRC_RECT = { 30, 28, 31, 29};
51static const BG_POINT REUSE_SEED_BTN_DEST_POS = { 4, 11};
53static const Rect BEST_HAND_SCORE_RECT = {126, 64, 166, 72};
54static const Rect MOST_PLAYED_HAND_RECT = {112, 80, 168, 88};
55static const BG_POINT SEED_VALUE_POS = {112, 96};
57static const BG_POINT NEW_RUN_BTN_TEXT_POS = { 48, 112};
58static const BG_POINT MAIN_MENU_BTN_TEXT_POS = {120, 112};
61static const u32 GAME_OVER_ANIM_FRAMES = 17;
62static const mm_byte GAME_OVER_SFX_VOL = 178;
63static const mm_word GAME_OVER_WHOOSH_RATE = 922;
70 GAME_OVER_RUN_MENU_ROW,
74#define GAME_OVER_SEED_BTN_COL 0
75#define GAME_OVER_NEW_RUN_BTN_COL 0
76#define GAME_OVER_MAIN_MENU_BTN_COL 1
78static int game_over_get_row_size1(
void)
82static int game_over_get_row_size2(
void)
87static void game_over_on_key_transit(
SelectionGrid* selection_grid, Selection* selection);
88static bool game_over_on_selection_changed(
91 const Selection* prev_selection,
92 const Selection* new_selection
96 {GAME_OVER_SEED_ROW, game_over_get_row_size1, game_over_on_selection_changed, game_over_on_key_transit, {.wrap =
false}},
97 {GAME_OVER_RUN_MENU_ROW, game_over_get_row_size2, game_over_on_selection_changed, game_over_on_key_transit, {.wrap =
false}}
100static const Selection GAME_OVER_INIT_SEL = {0, GAME_OVER_RUN_MENU_ROW};
102 game_over_selection_rows,
109static void reuse_seed_on_pressed(
void);
110static void new_run_on_pressed(
void);
111static void main_menu_on_pressed(
void);
112static Button* game_over_get_button_from_sel(
const Selection* selection);
115static Button game_over_buttons[GAME_OVER_ROW_MAX][2] = {
118 { REUSE_SEED_BTN_OUTLINE_PAL_IDX, RED_BTN_MAIN_COLOR_PAL_IDX, reuse_seed_on_pressed, NULL }
122 { NEW_RUN_BTN_OUTLINE_PAL_IDX, RED_BTN_MAIN_COLOR_PAL_IDX, new_run_on_pressed, NULL },
123 { MAIN_MENU_BTN_OUTLINE_PAL_IDX, RED_BTN_MAIN_COLOR_PAL_IDX, main_menu_on_pressed, NULL }
130static enum EndCondition s_end_condition = END_CONDITION_NONE;
131static u32 s_timer = TM_ZERO;
132static bool s_reuse_seed =
false;
133static bool s_continue_run =
false;
135static void game_over_common_init(
enum EndCondition init_condition)
137 s_end_condition = init_condition;
139 s_reuse_seed =
false;
140 s_continue_run =
false;
152 while (get_deck_top() >= 0)
162 GRIT_CPY(pal_bg_mem, background_game_over_gfxPal);
163 GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_game_over_gfxTiles);
164 GRIT_CPY(&se_mem[MAIN_BG_SBB], background_game_over_gfxMap);
168 g_game_vars.playing_blind_token,
169 DEFEATED_BY_TOKEN_INIT_POS.x,
170 DEFEATED_BY_TOKEN_INIT_POS.y
174 game_over_selection_grid.selection = GAME_OVER_INIT_SEL;
177 &game_over_buttons[GAME_OVER_RUN_MENU_ROW][GAME_OVER_NEW_RUN_BTN_COL],
181 &game_over_buttons[GAME_OVER_RUN_MENU_ROW][GAME_OVER_MAIN_MENU_BTN_COL],
190 game_over_common_init(END_CONDITION_WIN);
197 play_sfx(SFX_WHOOSH2_LOSE, GAME_OVER_WHOOSH_RATE, GAME_OVER_SFX_VOL);
201 game_over_common_init(END_CONDITION_LOSS);
221 if (s_timer < GAME_OVER_ANIM_FRAMES)
226 g_game_vars.playing_blind_token,
227 g_game_vars.playing_blind_token->
pos.x,
233 else if (s_timer == GAME_OVER_ANIM_FRAMES)
235 char best_hand_str[UINT_MAX_DIGITS + 1];
237 g_game_vars.best_hand_score,
241 Rect best_hand_rect = BEST_HAND_SCORE_RECT;
244 "#{P:%d,%d; cx:0x%X000}%s",
252 enum HandType most_played_hand = HIGH_CARD;
253 for (
enum HandType hand_type = PAIR; hand_type <= HAND_TYPE_MAX; hand_type++)
255 if (g_game_vars.nb_played_hands[hand_type - 1] >
256 g_game_vars.nb_played_hands[most_played_hand - 1])
257 most_played_hand = hand_type;
260 const char* hand_name_str = get_hand_type_name(most_played_hand);
261 Rect hand_type_rect = MOST_PLAYED_HAND_RECT;
264 "#{P:%d,%d; cx:0x%X000}%s",
272 char seed_str[BASE36_MAX_DIGITS + 1] = {
'\0'};
275 "#{P:%d,%d; cx:0x%X000}%s",
284 "#{P:%d,%d; cx:0x%X000}New Run",
285 NEW_RUN_BTN_TEXT_POS.x,
286 NEW_RUN_BTN_TEXT_POS.y,
290 "#{P:%d,%d; cx:0x%X000}Main Menu",
291 MAIN_MENU_BTN_TEXT_POS.x,
292 MAIN_MENU_BTN_TEXT_POS.y,
297 if (s_timer >= GAME_OVER_ANIM_FRAMES)
306 s_end_condition = END_CONDITION_NONE;
308 u32 previous_seed = g_game_vars.rng_info.
seed;
316 g_game_vars.rng_info.
seed = UNDEFINED;
321static Button* game_over_get_button_from_sel(
const Selection* selection)
323 return &game_over_buttons[selection->y][selection->x];
326static void game_over_on_key_transit(
SelectionGrid* selection_grid, Selection* selection)
328 if (key_hit(SELECT_CARD))
329 button_press(&game_over_buttons[selection->y][selection->x]);
332static bool game_over_on_selection_changed(
335 const Selection* prev_selection,
336 const Selection* new_selection
339 if (row_idx == prev_selection->y)
342 if (row_idx == new_selection->y)
350static void reuse_seed_on_pressed(
void)
352 s_reuse_seed = !s_reuse_seed;
354 s_reuse_seed ? REUSE_SEED_BTN_ON_SRC_RECT : REUSE_SEED_BTN_OFF_SRC_RECT,
355 REUSE_SEED_BTN_DEST_POS
359static void new_run_on_pressed(
void)
361 game_change_state(GAME_STATE_RUN_SETUP);
364static void main_menu_on_pressed(
void)
366 game_change_state(GAME_STATE_MAIN_MENU);
Utilities for affine background on GBA.
void affine_background_set_color(COLOR color)
Update the affine background color.
Utilities for using maxmod to play sound effects.
void play_regular_music(void)
Play music at a normal pitch and tempo.
void play_lose_music(void)
Play music at a low pitch and slow tempo (lose screen)
#define MM_BASE_PITCH_RATE
The default pitch rate for the sound effect played.
void play_sfx(mm_word id, mm_word rate, mm_byte volume)
Play a sound effect, wrapper for mmEffectEx() See https://maxmod.org/ref/functions/mm_sound_effect....
#define SFX_DEFAULT_VOLUME
Default volume for sound effects.
Game Over screen state functions.
void game_lose_on_init(void)
Game Over screen state initialization when losing.
void game_over_on_update(void)
Game Over screen state update.
void game_over_on_exit(void)
Game Over screen cleanup, common to both losing and winning.
void game_win_on_init(void)
Game Over screen state initialization when winning.
Graphic utility functions.
void main_bg_se_move_rect_1_tile_vert(Rect se_rect, enum ScreenVertDir direction)
Moves a rect in the main background vertically in direction by a single tile.
void main_bg_se_copy_rect(Rect se_rect, BG_POINT dest_pos)
Copies a rect in the main background from se_rect to the position (x, y).
void toggle_windows(bool win0, bool win1)
Toggles the visibility of the window layers.
void update_text_rect_to_center_str(Rect *rect, const char *str, enum ScreenHorzDir bias_direction)
Updates a rect so a string is centered within it.
#define TILE_SIZE
Tile size in pixels, both height and width as tiles are square.
#define TTE_CHAR_SIZE
By default TTE characters occupy a single tile.
INLINE int rect_width(const Rect *rect)
Get the width of a rectangle.
Functions relative to manipulating and analyzing the contents of the Hand, a.k.a. the Cards we hold a...
Functions relative to the handling of Jokers.
Header of shared rects and points needed for ui.
void * list_itr_next(ListItr *itr)
ListItr list_itr_create(List *list)
Common functions to handle RNG manipulation. Using this interface has three goals:
void rng_set_seed(u32 seed)
Set the rng seed to the chosen value, and reset the step counter to 0. The seed will be capped at MAX...
An implementation for a selection grid that handles directional selection.
void selection_grid_process_input(SelectionGrid *selection_grid)
Processes user input for the selection grid.
Data structures and functions related to the handling of Skip Tags.
void remove_all_skip_tags(void)
Delete all owned Skip Tags.
INLINE void sprite_position(Sprite *sprite, int x, int y)
Set sprite position. Inlined for efficiency.
void sprite_object_hide(SpriteObject *sprite_object)
Hides the SpriteObject by manipulating ATTR0_HIDE in OAM.
The core selection grid struct, represents the grid itself and its state.
A sprite object is a sprite that is focusable and movable in animation.
POINT pos
Sprite position on screen in pixels.
Utilities relating around number string representation and protected arithmatic helper functions.
void truncate_uint_to_suffixed_str(uint32_t num, int num_req_chars, char out_str_buff[UINT_MAX_DIGITS+1])
Truncate an unsigned number into a suffixed string representation e.g. 12000 -> "12K" The least signi...
void u32_to_base36(uint32_t n, char b36_str[])
Convert a 32-bit unsigned integer to its base-36 string representation. This will perform 6 divisions...