Refactor/blind select screen (#461)

Refactor Blind Select Screen.

Based on #363
---------

Co-authored-by: emiyl <me@emiyl.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Rickey
2026-05-06 00:56:59 -07:00
committed by GitHub
parent 877bd09576
commit d01b1ba12d
15 changed files with 844 additions and 738 deletions
+10
View File
@@ -24,6 +24,16 @@
#define BLIND_TOKENS_PER_SPRITESHEET 2
#define BLIND_TOKEN_PALETTE_SIZE 8
// The sprites that display the blinds when in "GAME_BLIND_SELECT" state
// There are only 3 blinds per Ante, so we don't need more sprites than that
enum BlindTokens
{
SMALL_BLIND,
BIG_BLIND,
BOSS_BLIND,
NUM_BLINDS_PER_ANTE
};
// Order of the Blind sprites' colors as encoded in the files' palettes with Aseprite
enum BlindColorIndex
{
+7 -4
View File
@@ -1,9 +1,8 @@
#ifndef GAME_H
#define GAME_H
#include "blind.h"
#include "game/common_ui.h"
#include "game_variables.h"
#include "graphic_utils.h"
#include <tonc.h>
@@ -123,6 +122,7 @@ typedef struct ContainedHandTypes
// clang-format on
typedef void (*GameStateCallback)(void);
typedef void (*SubStateActionFn)(void);
typedef struct
{
@@ -163,8 +163,6 @@ void set_mult(u32 new_mult);
void display_mult(void);
void display_money(void);
void set_retrigger(bool new_retrigger);
enum BlindType get_current_blind(void);
enum BlindType get_next_boss_blind(void);
u32 get_rand(void);
@@ -179,4 +177,9 @@ void game_start(void);
// old system incrementally and without losing functionality.
void change_background_legacy(enum BackgroundId id);
void display_round(void);
void reset_top_left_panel_bottom_row(void);
void reset_background(void);
#endif // GAME_H
+33
View File
@@ -0,0 +1,33 @@
/**
* @file blind_select.h
*
* @brief Blind select state functions
*/
#ifndef GAME_BLIND_SELECT_H
#define GAME_BLIND_SELECT_H
#include "blind.h"
/**
* @brief Change to the blind select background
*/
void game_blind_select_change_background(void);
/**
* @brief Blind select state initialization
*/
void game_blind_select_on_init(void);
/**
* @brief Blind select state update
*/
void game_blind_select_on_update(void);
/**
* @brief Blind select cleanup
*/
void game_blind_select_on_exit(void);
void increment_blind(enum BlindState increment_reason);
#endif // GAME_BLIND_SELECT_H
+3 -1
View File
@@ -6,6 +6,8 @@
#ifndef COMMON_UI_H
#define COMMON_UI_H
#include <stdbool.h>
/**
* @brief Enum of possible backgrounds to render with @ref change_background
*/
@@ -26,6 +28,6 @@ enum BackgroundId
*
* @param id @ref BackgroundId to render to screen
*/
void change_background(enum BackgroundId id);
void change_background(enum BackgroundId id, bool force_redraw);
#endif // COMMON_UI_H
+8
View File
@@ -6,6 +6,8 @@
#ifndef GAME_VARIABLES_H
#define GAME_VARIABLES_H
#include "blind.h"
#include <tonc.h>
#define GAME_SPEED_MIN 1
@@ -41,6 +43,12 @@ typedef struct
int ante;
int money;
// Blind variables
enum BlindType current_blind;
enum BlindType next_boss_blind;
enum BlindState blinds_states[NUM_BLINDS_PER_ANTE];
// Options variables
// BY DEFAULT IS SET TO 1, but if changed to 2 or more, should speed up all (or most) of the
+5
View File
@@ -357,4 +357,9 @@ void memcpy32_tile8_with_palette_offset(u32* dst, const u32* src, uint wcount, u
*/
void toggle_windows(bool win0, bool win1);
/**
* @brief Restores the bottom row of the top-left panel from the background map.
*/
void reset_top_left_panel_bottom_row(void);
#endif // GRAPHIC_UTILS_H
+21
View File
@@ -0,0 +1,21 @@
/**
* @file layout.h
*
* @brief Header of shared rects and points needed for ui
*/
#ifndef LAYOUT_H
#define LAYOUT_H
#include "graphic_utils.h"
// clang-format off
// Points x y
static const BG_POINT CUR_BLIND_TOKEN_POS = {8, 18};
static const BG_POINT TOP_LEFT_PANEL_POINT = {0, 0, };
// Rects left top right bottom
static const Rect TOP_LEFT_PANEL_ANIM_RECT = {0, 0, 8, 4};
static const Rect POP_MENU_ANIM_RECT = {9, 7, 24, 31};
static const Rect TOP_LEFT_ITEM_SRC_RECT = {0, 20, 8, 25};
// clang-format on
#endif // LAYOUT_H
+3 -1
View File
@@ -9,4 +9,6 @@
#define TM_ZERO 0
#endif // TIMER_H
#define MENU_POP_OUT_ANIM_FRAMES 20
#endif // TIMER_H
+95 -726
View File
File diff suppressed because it is too large Load Diff
+637
View File
@@ -0,0 +1,637 @@
#include "blind_select.h"
#include "audio_utils.h"
#include "background_blind_select_gfx.h"
#include "blind.h"
#include "button.h"
#include "game.h"
#include "game_variables.h"
#include "graphic_utils.h"
#include "layout.h"
#include "soundbank.h"
#include "sprite.h"
#include "timer.h"
#include "util.h"
#include <maxmod.h>
#define BLIND_SELECT_BTN_PID 15
#define TM_DISP_BLIND_PANEL_FINISH 7
#define TM_DISP_BLIND_PANEL_START 1
#define BLIND_SKIP_BTN_PID 5
#define BLIND_SKIP_BTN_SELECTED_BORDER_PID 10
#define BLIND_SELECT_BTN_SELECTED_BORDER_PID 18
static int timer;
static void game_blind_select_start_anim_seq(void);
static void game_blind_select_handle_input(void);
static void game_blind_select_selected_anim_seq(void);
static void game_blind_select_display_blind_panel(void);
static Rect game_blind_select_get_req_score_rect(enum BlindTokens blind);
static void game_blind_select_print_blinds_reqs_and_rewards(void);
static enum BlindType get_blind_type_from_token(enum BlindTokens blind);
static void blind_tokens_init(void);
enum BlindSelectState
{
START_ANIM_SEQ,
BLIND_SELECT,
BLIND_SELECTED_ANIM_SEQ,
DISPLAY_BLIND_PANEL,
BLIND_SELECT_MAX
};
// TODO: this will be refactored into common state machine
static const SubStateActionFn blind_select_state_actions[] = {
game_blind_select_start_anim_seq,
game_blind_select_handle_input,
game_blind_select_selected_anim_seq,
game_blind_select_display_blind_panel
};
// clang-format off
// Points x y
static const BG_POINT TOP_LEFT_PANEL_EMPTY_3W_ROW_POS = {29, 31};
// Rects left top right bottom
static const Rect BLIND_SKIP_BTN_GRAY_RECT = {0, 24, 4, 27};
static const Rect BLIND_SKIP_BTN_PREANIM_DEST_RECT = {9, 29, 19, 31};
static const Rect SINGLE_BLIND_SEL_REQ_SCORE_RECT = {80, 120, 104, 128};
static const Rect SINGLE_BLIND_SELECT_RECT = {9, 7, 13, 31};
// clang-format on
static const u32 TM_END_ANIM_SEQ = 12;
static const u32 TM_BLIND_SELECT_START = 1;
static const u32 BLIND_LEFT_X = 80;
static const u32 BLIND_CENTER_X = 120;
static const u32 BLIND_RIGHT_X = 160;
static const u32 BLIND_ROW = 0;
static const u32 SKIP_ROW = 1;
static int selection_x = 0;
static int selection_y = 0;
static enum BlindSelectState substate;
static Sprite* blind_select_tokens[NUM_BLINDS_PER_ANTE] = {NULL};
static void game_blind_select_start_anim_seq()
{
// main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SCREEN_UP);
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SCREEN_UP);
for (int i = 0; i < NUM_BLINDS_PER_ANTE; i++)
{
sprite_position(
blind_select_tokens[i],
blind_select_tokens[i]->pos.x,
blind_select_tokens[i]->pos.y - TILE_SIZE
);
}
if (timer == TM_END_ANIM_SEQ)
{
game_blind_select_print_blinds_reqs_and_rewards();
substate = BLIND_SELECT;
timer = TM_ZERO; // Reset the timer
}
}
static inline void game_blind_select_erase_blind_reqs_and_rewards()
{
for (enum BlindTokens curr_blind = SMALL_BLIND; curr_blind < NUM_BLINDS_PER_ANTE; curr_blind++)
{
Rect blind_req_and_reward_rect = SINGLE_BLIND_SEL_REQ_SCORE_RECT;
// To account for both raised blind and reward
blind_req_and_reward_rect.top -= TILE_SIZE;
blind_req_and_reward_rect.bottom += TILE_SIZE;
// To account for overflow
blind_req_and_reward_rect.right += TILE_SIZE;
blind_req_and_reward_rect.left +=
curr_blind * rect_width(&SINGLE_BLIND_SELECT_RECT) * TILE_SIZE;
blind_req_and_reward_rect.right +=
curr_blind * rect_width(&SINGLE_BLIND_SELECT_RECT) * TILE_SIZE;
tte_erase_rect_wrapper(blind_req_and_reward_rect);
}
}
void increment_blind(enum BlindState increment_reason)
{
switch (g_game_vars.current_blind)
{
// defeated small blind: go to big
case BLIND_TYPE_SMALL:
g_game_vars.current_blind = BLIND_TYPE_BIG;
g_game_vars.blinds_states[SMALL_BLIND] = increment_reason;
g_game_vars.blinds_states[BIG_BLIND] = BLIND_STATE_CURRENT;
break;
// defeated big blind: go to next boss
case BLIND_TYPE_BIG:
g_game_vars.current_blind = g_game_vars.next_boss_blind;
g_game_vars.blinds_states[BIG_BLIND] = increment_reason;
g_game_vars.blinds_states[BOSS_BLIND] = BLIND_STATE_CURRENT;
break;
// defeated a boss: reset everything
default:
g_game_vars.current_blind = BLIND_TYPE_SMALL;
g_game_vars.blinds_states[SMALL_BLIND] = BLIND_STATE_CURRENT;
g_game_vars.blinds_states[BIG_BLIND] = BLIND_STATE_UPCOMING;
g_game_vars.blinds_states[BOSS_BLIND] = BLIND_STATE_UPCOMING;
break;
}
}
// TODO: convert these to proper buttons.
static inline void highlight_select_button(void)
{
memset16(&pal_bg_mem[BLIND_SELECT_BTN_SELECTED_BORDER_PID], 0xFFFF, 1);
memcpy16(&pal_bg_mem[BLIND_SKIP_BTN_SELECTED_BORDER_PID], &pal_bg_mem[BLIND_SKIP_BTN_PID], 1);
}
static inline void highlight_skip_button(void)
{
memcpy16(
&pal_bg_mem[BLIND_SELECT_BTN_SELECTED_BORDER_PID],
&pal_bg_mem[BLIND_SELECT_BTN_PID],
1
);
memset16(&pal_bg_mem[BLIND_SKIP_BTN_SELECTED_BORDER_PID], 0xFFFF, 1);
}
static void game_blind_select_handle_input()
{
if (timer == TM_BLIND_SELECT_START && g_game_vars.current_blind == BLIND_TYPE_BOSS)
{
selection_y = BLIND_ROW;
}
// Blind select input logic
if (key_hit(KEY_UP))
{
selection_y = BLIND_ROW;
highlight_select_button();
}
else if (key_hit(KEY_DOWN) && g_game_vars.current_blind <= BLIND_TYPE_BIG)
{
selection_y = SKIP_ROW;
highlight_skip_button();
}
else if (key_hit(SELECT_CARD))
{
game_blind_select_erase_blind_reqs_and_rewards();
switch (selection_y)
{
case BLIND_ROW:
play_sfx(SFX_BUTTON, MM_BASE_PITCH_RATE, BUTTON_SFX_VOLUME);
substate = BLIND_SELECTED_ANIM_SEQ;
timer = TM_ZERO;
++g_game_vars.round;
display_round();
break;
case SKIP_ROW:
if (g_game_vars.current_blind <= BLIND_TYPE_BIG)
{
play_sfx(SFX_BUTTON, MM_BASE_PITCH_RATE, BUTTON_SFX_VOLUME);
increment_blind(BLIND_STATE_SKIPPED);
selection_y = BLIND_ROW; // Reset selection to first option
change_background(BG_BLIND_SELECT, true);
// TODO: Create a generic vertical move by any number of tiles to avoid for
// loops?
for (int i = 0; i < 12; i++)
{
main_bg_se_copy_rect_1_tile_vert(POP_MENU_ANIM_RECT, SCREEN_UP);
}
for (int i = 0; i < NUM_BLINDS_PER_ANTE; i++)
{
sprite_position(
blind_select_tokens[i],
blind_select_tokens[i]->pos.x,
blind_select_tokens[i]->pos.y - (TILE_SIZE * 12)
);
}
game_blind_select_print_blinds_reqs_and_rewards();
timer = TM_ZERO;
}
break;
default:
break;
}
}
}
static void game_blind_select_selected_anim_seq()
{
if (timer < 15)
{
Rect blinds_rect = POP_MENU_ANIM_RECT;
blinds_rect.top -= 1; // Because of the raised blind
main_bg_se_move_rect_1_tile_vert(blinds_rect, SCREEN_DOWN);
for (int i = 0; i < NUM_BLINDS_PER_ANTE; i++)
{
sprite_position(
blind_select_tokens[i],
blind_select_tokens[i]->pos.x,
blind_select_tokens[i]->pos.y + TILE_SIZE
);
}
}
else if (timer >= MENU_POP_OUT_ANIM_FRAMES)
{
for (int i = 0; i < NUM_BLINDS_PER_ANTE; i++)
{
obj_hide(blind_select_tokens[i]->obj);
}
substate = DISPLAY_BLIND_PANEL; // Reset the state
timer = TM_ZERO; // Reset the timer
}
}
static void game_blind_select_display_blind_panel()
{
if (timer >= TM_DISP_BLIND_PANEL_FINISH)
{
substate = BLIND_SELECT_MAX;
return;
}
// Switches to the selecting background and clears the blind panel area
if (timer == TM_DISP_BLIND_PANEL_START)
{
change_background(BG_CARD_SELECTING, false);
// Need to clear the top left panel as a side effect of change_background()
main_bg_se_copy_expand_3w_row(TOP_LEFT_PANEL_ANIM_RECT, TOP_LEFT_PANEL_EMPTY_3W_ROW_POS);
reset_top_left_panel_bottom_row();
}
// Shift the blind panel down onto screen
for (int y = 0; y < timer; y++)
{
int y_from = 26 + y - timer;
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);
}
}
static Rect game_blind_select_get_req_score_rect(enum BlindTokens blind)
{
Rect blind_req_score_rect = SINGLE_BLIND_SEL_REQ_SCORE_RECT;
blind_req_score_rect.left += blind * rect_width(&SINGLE_BLIND_SELECT_RECT) * TILE_SIZE;
blind_req_score_rect.right += blind * rect_width(&SINGLE_BLIND_SELECT_RECT) * TILE_SIZE;
if (g_game_vars.blinds_states[blind] == BLIND_STATE_CURRENT)
{
// Current blind is raised
blind_req_score_rect.top -= TILE_SIZE;
blind_req_score_rect.bottom -= TILE_SIZE;
}
return blind_req_score_rect;
}
static enum BlindType get_blind_type_from_token(enum BlindTokens blind)
{
enum BlindType blind_type;
switch (blind)
{
case SMALL_BLIND:
blind_type = BLIND_TYPE_SMALL;
break;
case BIG_BLIND:
blind_type = BLIND_TYPE_BIG;
break;
default:
blind_type = g_game_vars.next_boss_blind;
break;
}
return blind_type;
}
static inline void game_blind_select_print_blind_req(enum BlindTokens blind)
{
Rect blind_req_score_rect = game_blind_select_get_req_score_rect(blind);
u32 blind_req = blind_get_requirement(get_blind_type_from_token(blind), g_game_vars.ante);
char blind_req_str_buff[UINT_MAX_DIGITS + 1];
truncate_uint_to_suffixed_str(
blind_req,
rect_width(&blind_req_score_rect) / TTE_CHAR_SIZE,
blind_req_str_buff
);
update_text_rect_to_right_align_str(&blind_req_score_rect, blind_req_str_buff, OVERFLOW_RIGHT);
tte_printf(
"#{P:%d,%d; cx:0x%X000}%s",
blind_req_score_rect.left,
blind_req_score_rect.top,
TTE_RED_PB,
blind_req_str_buff
);
}
static inline void game_blind_select_print_blind_reward(enum BlindTokens blind)
{
int blind_reward = blind_get_reward(get_blind_type_from_token(blind));
Rect blind_reward_rect = game_blind_select_get_req_score_rect(blind);
// The reward is right below the score.
blind_reward_rect.top += TILE_SIZE;
blind_reward_rect.bottom += TILE_SIZE;
char blind_reward_str_buff[UINT_MAX_DIGITS + 2]; // +2 for null terminator and "$"
snprintf(blind_reward_str_buff, sizeof(blind_reward_str_buff), "$%d", blind_reward);
update_text_rect_to_right_align_str(&blind_reward_rect, blind_reward_str_buff, OVERFLOW_RIGHT);
tte_printf(
"#{P:%d,%d; cx:0x%X000}%s",
blind_reward_rect.left,
blind_reward_rect.top,
TTE_YELLOW_PB,
blind_reward_str_buff
);
}
static void game_blind_select_print_blinds_reqs_and_rewards(void)
{
for (enum BlindTokens curr_blind = 0; curr_blind < NUM_BLINDS_PER_ANTE; curr_blind++)
{
game_blind_select_print_blind_req(curr_blind);
game_blind_select_print_blind_reward(curr_blind);
}
}
static inline void reroll_boss_blind(bool no_tiles)
{
// Showdown blinds only show up on ante 8, 16, etc...
g_game_vars.next_boss_blind =
roll_blind_type((g_game_vars.ante % 8 == 0) && (g_game_vars.ante > 0));
if (!no_tiles)
{
apply_blind_tiles(g_game_vars.next_boss_blind, BOSS_BLIND_TOKEN_LAYER);
}
}
static void blind_tokens_init()
{
if (g_game_vars.current_blind == BLIND_TYPE_SMALL)
reroll_boss_blind(true);
sprite_destroy(&blind_select_tokens[SMALL_BLIND]);
sprite_destroy(&blind_select_tokens[BIG_BLIND]);
sprite_destroy(&blind_select_tokens[BOSS_BLIND]);
blind_select_tokens[SMALL_BLIND] = blind_token_new(
BLIND_TYPE_SMALL,
CUR_BLIND_TOKEN_POS.x,
CUR_BLIND_TOKEN_POS.y,
SMALL_BLIND_TOKEN_LAYER
);
blind_select_tokens[BIG_BLIND] = blind_token_new(
BLIND_TYPE_BIG,
CUR_BLIND_TOKEN_POS.x,
CUR_BLIND_TOKEN_POS.y,
BIG_BLIND_TOKEN_LAYER
);
blind_select_tokens[BOSS_BLIND] = blind_token_new(
g_game_vars.next_boss_blind,
CUR_BLIND_TOKEN_POS.x,
CUR_BLIND_TOKEN_POS.y,
BOSS_BLIND_TOKEN_LAYER
);
for (int i = 0; i < NUM_BLINDS_PER_ANTE; i++)
{
obj_hide(blind_select_tokens[i]->obj);
}
}
void game_blind_select_on_init(void)
{
timer = TM_ZERO;
substate = START_ANIM_SEQ;
selection_x = 0;
selection_y = 0;
blind_tokens_init();
// TODO: silly bug rn, the sprite tokens are unhidden on a background change.
// this probably shouldn't be here. also need to force redraw or the callback
// doesn't run that moves the tokens. that should probably happen here.
change_background(BG_BLIND_SELECT, true);
highlight_select_button();
play_sfx(SFX_POP, MM_BASE_PITCH_RATE, SFX_DEFAULT_VOLUME);
}
void game_blind_select_on_update(void)
{
timer++;
if (substate == BLIND_SELECT_MAX)
{
reset_background();
game_change_state(GAME_STATE_PLAYING);
return;
}
blind_select_state_actions[substate]();
}
void game_blind_select_on_exit(void)
{
// For some reason that I haven't figured out yet,
// if I don't destroy the blind tokens they won't
// show up on the next run.
sprite_destroy(&blind_select_tokens[SMALL_BLIND]);
sprite_destroy(&blind_select_tokens[BIG_BLIND]);
sprite_destroy(&blind_select_tokens[BOSS_BLIND]);
reset_background();
selection_y = 0;
g_game_vars.timer = TM_ZERO;
}
void game_blind_select_change_background(void)
{
for (int i = 0; i < NUM_BLINDS_PER_ANTE; i++)
{
obj_unhide(blind_select_tokens[i]->obj, 0);
}
// Default y position for the blind select tokens. 12 is the amount of tiles the background
// is shifted down by
const int default_y = 89 + (TILE_SIZE * 12);
// TODO refactor magic numbers '80/120/160' into a map to loop with
sprite_position(blind_select_tokens[SMALL_BLIND], BLIND_LEFT_X, default_y);
sprite_position(blind_select_tokens[BIG_BLIND], BLIND_CENTER_X, default_y);
sprite_position(blind_select_tokens[BOSS_BLIND], BLIND_RIGHT_X, default_y);
toggle_windows(false, true);
GRIT_CPY(pal_bg_mem, background_blind_select_gfxPal);
GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_blind_select_gfxTiles);
GRIT_CPY(&se_mem[MAIN_BG_SBB], background_blind_select_gfxMap);
// Copy boss blind colors to blind select palette
memset16(
&pal_bg_mem[1],
blind_get_color(g_game_vars.next_boss_blind, BLIND_BACKGROUND_MAIN_COLOR_INDEX),
1
);
memset16(
&pal_bg_mem[7],
blind_get_color(g_game_vars.next_boss_blind, BLIND_BACKGROUND_SHADOW_COLOR_INDEX),
1
);
// Disable the button highlight colors
// Select button PID is 15 and the outline is 18
memcpy16(
&pal_bg_mem[BLIND_SELECT_BTN_SELECTED_BORDER_PID],
&pal_bg_mem[BLIND_SELECT_BTN_PID],
1
);
// It seems the skip button (and score multiplier and deck) PB idx is
// actually 5, not 10. 10 is the selected border color
// Setting this palette value though doesn't seem to have an
// effect.
memcpy16(&pal_bg_mem[BLIND_SKIP_BTN_SELECTED_BORDER_PID], &pal_bg_mem[BLIND_SKIP_BTN_PID], 1);
for (int i = 0; i < NUM_BLINDS_PER_ANTE; i++)
{
Rect curr_blind_rect = SINGLE_BLIND_SELECT_RECT;
// There's no gap between them
curr_blind_rect.left += i * rect_width(&SINGLE_BLIND_SELECT_RECT);
curr_blind_rect.right += i * rect_width(&SINGLE_BLIND_SELECT_RECT);
if (g_game_vars.blinds_states[i] != BLIND_STATE_CURRENT &&
(i == BLIND_TYPE_SMALL || i == BLIND_TYPE_BIG)) // Make the skip button gray
{
BG_POINT skip_blind_btn_pos_dest = {
BLIND_SKIP_BTN_PREANIM_DEST_RECT.left,
BLIND_SKIP_BTN_PREANIM_DEST_RECT.top
};
skip_blind_btn_pos_dest.x = curr_blind_rect.left;
Rect skip_blind_btn_rect_src = BLIND_SKIP_BTN_GRAY_RECT;
skip_blind_btn_rect_src.top += i * rect_height(&BLIND_SKIP_BTN_GRAY_RECT);
skip_blind_btn_rect_src.bottom += i * rect_height(&BLIND_SKIP_BTN_GRAY_RECT);
main_bg_se_copy_rect(skip_blind_btn_rect_src, skip_blind_btn_pos_dest);
}
switch (g_game_vars.blinds_states[i])
{
case BLIND_STATE_CURRENT: // Raise the blind panel up a bit
{
// TODO: Replace copies with main_bg_se_copy_rect() of named rects
int x_from = 0;
int y_from = 27;
main_bg_se_copy_rect_1_tile_vert(curr_blind_rect, SCREEN_UP);
int x_to = curr_blind_rect.left;
int y_to = 31;
if (i == BLIND_TYPE_BIG)
{
y_from = 31;
}
else if (i > BLIND_TYPE_BIG)
{
x_from = x_to;
y_from = 30;
}
// Copy plain tiles onto the bottom of the raised blind panel to fill the gap
// created by the raise
Rect gap_fill_rect =
{x_from, y_from, x_from + rect_width(&SINGLE_BLIND_SELECT_RECT) - 1, y_from};
BG_POINT gap_fill_point = {x_to, y_to};
main_bg_se_copy_rect(gap_fill_rect, gap_fill_point);
// Move token up by a tile
sprite_position(
blind_select_tokens[i],
blind_select_tokens[i]->pos.x,
blind_select_tokens[i]->pos.y - TILE_SIZE
);
break;
}
case BLIND_STATE_UPCOMING: // Change the select icon to "NEXT"
{
int x_from = 0;
int y_from = 20;
int x_to = 10 + (i * rect_width(&SINGLE_BLIND_SELECT_RECT));
int y_to = 20;
memcpy16(
&se_mem[MAIN_BG_SBB][x_to + 32 * y_to],
&se_mem[MAIN_BG_SBB][x_from + 32 * y_from],
3
);
break;
}
case BLIND_STATE_SKIPPED: // Change the select icon to "SKIP"
{
int x_from = 3;
int y_from = 20;
int x_to = 10 + (i * 5);
int y_to = 20;
memcpy16(
&se_mem[MAIN_BG_SBB][x_to + 32 * y_to],
&se_mem[MAIN_BG_SBB][x_from + 32 * y_from],
3
);
break;
}
case BLIND_STATE_DEFEATED: // Change the select icon to "DEFEATED"
{
int x_from = 6;
int y_from = 20;
int x_to = 10 + (i * 5);
int y_to = 20;
memcpy16(
&se_mem[MAIN_BG_SBB][x_to + 32 * y_to],
&se_mem[MAIN_BG_SBB][x_from + 32 * y_from],
3
);
break;
}
default:
break;
}
}
}
+8 -2
View File
@@ -1,5 +1,6 @@
#include "game/common_ui.h"
#include "blind_select.h"
#include "game.h"
#include "game/main_menu.h"
#include "game/options_menu.h"
@@ -15,13 +16,18 @@ static const BackgroundRenderCallback bgCallbacks[] = {
[BG_CARD_PLAYING] = NULL,
[BG_ROUND_END] = NULL,
[BG_SHOP] = NULL,
[BG_BLIND_SELECT] = NULL,
[BG_BLIND_SELECT] = game_blind_select_change_background,
[BG_OPTIONS_MENU] = game_options_menu_change_background,
[BG_MAIN_MENU] = game_main_menu_change_background,
};
void change_background(enum BackgroundId id)
void change_background(enum BackgroundId id, bool force_redraw)
{
if (force_redraw)
{
background = BG_NONE;
reset_background();
}
if (id != background && bgCallbacks[id] != NULL)
{
bgCallbacks[id]();
+1 -1
View File
@@ -102,7 +102,7 @@ void game_main_menu_change_background(void)
void game_main_menu_on_init(void)
{
affine_background_change_background(AFFINE_BG_MAIN_MENU);
change_background(BG_MAIN_MENU);
change_background(BG_MAIN_MENU, false);
main_menu_ace = card_object_new(card_new(SPADES, ACE));
card_object_set_sprite(main_menu_ace, 0);
main_menu_ace->sprite_object->sprite->obj->attr0 |= ATTR0_AFF_DBL;
+1 -1
View File
@@ -392,7 +392,7 @@ void game_options_menu_change_background(void)
void game_options_menu_on_init(void)
{
change_background(BG_OPTIONS_MENU);
change_background(BG_OPTIONS_MENU, false);
// Select game speed button by default
options_menu_selection_grid.selection = OPTIONS_MENU_INIT_SEL;
+11 -2
View File
@@ -1,13 +1,14 @@
#include "graphic_utils.h"
#include "util.h"
#include "layout.h"
#include <string.h>
#include <tonc_core.h>
#include <tonc_math.h>
#include <tonc_tte.h>
const Rect FULL_SCREENBLOCK_RECT = {0, 0, SE_ROW_LEN - 1, SE_COL_LEN - 1};
static const Rect FULL_SCREENBLOCK_RECT = {0, 0, SE_ROW_LEN - 1, SE_COL_LEN - 1};
static const Rect TOP_LEFT_PANEL_BOTTOM_ROW_RESET_RECT = {0, 28, 8, 28};
static void clip_se_rect_to_screenblock(Rect* rect);
static void bg_se_copy_or_move_rect_1_tile_vert(
@@ -410,3 +411,11 @@ void main_bg_se_clear_rect(Rect se_rect)
memset16(&(se_mat[MAIN_BG_SBB][y][se_rect.left]), 0x0000, rect_width(&se_rect));
}
}
void reset_top_left_panel_bottom_row()
{
BG_POINT top_left_panel_bottom_row_pos = TOP_LEFT_PANEL_POINT;
// Use the source rect height to offset to the bottom row point
top_left_panel_bottom_row_pos.y += rect_height(&TOP_LEFT_ITEM_SRC_RECT) - 1;
main_bg_se_copy_rect(TOP_LEFT_PANEL_BOTTOM_ROW_RESET_RECT, top_left_panel_bottom_row_pos);
}
+1
View File
@@ -1,4 +1,5 @@
#include "game.h"
#include "game_variables.h"
#include "hand_analysis.h"
#include "joker.h"
#include "list.h"