Merge pull request #105 from cellos51/game_over_screen
Game over (and win) screen
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -32,6 +32,7 @@ enum GameState
|
||||
GAME_SHOP,
|
||||
GAME_BLIND_SELECT,
|
||||
GAME_LOSE,
|
||||
GAME_WIN
|
||||
};
|
||||
|
||||
enum HandState
|
||||
|
||||
+41
-12
@@ -1,6 +1,8 @@
|
||||
#ifndef GRAPHIC_UTILS_H
|
||||
#define GRAPHIC_UTILS_H
|
||||
|
||||
#include <tonc_video.h>
|
||||
|
||||
/* This file contains general utils and wrappers that relate to
|
||||
* graphics/video/vram and generally displaying things on the screen.
|
||||
* Mostly wrappers and defines for using tonc.
|
||||
@@ -24,6 +26,19 @@
|
||||
#define PAL_ROW_LEN 16
|
||||
#define NUM_PALETTES 16
|
||||
|
||||
#define TTE_BIT_UNPACK_OFFSET 14
|
||||
#define TTE_BIT_ON_CLR_IDX TTE_BIT_UNPACK_OFFSET + 1
|
||||
|
||||
#define TTE_YELLOW_PB 12 // 0xC
|
||||
#define TTE_BLUE_PB 13 // 0xD
|
||||
#define TTE_RED_PB 14 // 0xE
|
||||
#define TTE_WHITE_PB 15 // 0xF
|
||||
|
||||
#define TEXT_CLR_YELLOW RGB15(31, 20, 0) // 0x029F
|
||||
#define TEXT_CLR_BLUE RGB15(0, 18, 31) // 0x7E40
|
||||
#define TEXT_CLR_RED RGB15(31, 9, 8) // 0x213F
|
||||
#define TEXT_CLR_WHITE CLR_WHITE
|
||||
|
||||
/* Dimensions for a screenblock.
|
||||
* A 1024 size screenblock is arranged in a grid of 32x32 screen entries
|
||||
* Interestingly since each block is 8x8 pixels, the 240x160 GBA screen
|
||||
@@ -52,19 +67,14 @@
|
||||
// By default TTE characters occupy a single tile
|
||||
#define TTE_CHAR_SIZE TILE_SIZE
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
} Rect;
|
||||
// When making this, missed that it already exists in tonc_math.h
|
||||
typedef RECT Rect;
|
||||
|
||||
/* Gets the screenblock tile for the given coordinates (x, y).
|
||||
/* Gets the screenblock entry for the given coordinates (x, y).
|
||||
* x and y are in number of tiles.
|
||||
* Returns the screenblock tile.
|
||||
* Returns the screenblock entry.
|
||||
*/
|
||||
u16 main_bg_se_get_tile(BG_POINT pos);
|
||||
SE main_bg_se_get_se(BG_POINT pos);
|
||||
|
||||
INLINE int rect_width(const Rect* rect)
|
||||
{
|
||||
@@ -79,6 +89,15 @@ INLINE int rect_height(const Rect* rect)
|
||||
return (((rect)->bottom) - ((rect)->top) + 1);
|
||||
}
|
||||
|
||||
/* Copies an SE rect vertically in direction by a single tile.
|
||||
* bg_sbb is the SBB of the background in which to move the rect
|
||||
* direction must be either SE_UP or SE_DOWN.
|
||||
* se_rect dimensions are in number of tiles.
|
||||
*
|
||||
* NOTE: This does not work with TTE_SBB, probably because it's 4BPP...
|
||||
*/
|
||||
void bg_se_copy_rect_1_tile_vert(u16 bg_sbb, Rect se_rect, int direction);
|
||||
|
||||
/* Clears a rect in the main background.
|
||||
* The se_rect dimensions need to be in number of tiles.
|
||||
*/
|
||||
@@ -96,11 +115,21 @@ void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction);
|
||||
*/
|
||||
void main_bg_se_copy_rect(Rect se_rect, BG_POINT pos);
|
||||
|
||||
/* Copies a tile to a rect in the main background.
|
||||
/* Copies a screen entry to a rect in the main background.
|
||||
* se_rect dimensions are in number of tiles.
|
||||
* The tile is copied to the top left corner of the rect.
|
||||
*/
|
||||
void main_bg_se_copy_tile_to_rect(u16 tile, Rect se_rect);
|
||||
void main_bg_se_fill_rect_with_se(SE tile, Rect se_rect);
|
||||
|
||||
/* Copies a 3x3 rect into se_rect_dest, the 3x3 rect is stretched to fill se_rect_dest.
|
||||
* The corners are copied, the sides are stretched, and the center is filled.
|
||||
* The parameter se_rect_src_3x3_top_left points to the top left corner of the source
|
||||
* 3x3 rect.
|
||||
* Dest rect sides can be of length 2, then the sides are not copied, only the corners.
|
||||
* But dest rect sides must be at least 2.
|
||||
*/
|
||||
void main_bg_se_copy_expand_3x3_rect(Rect se_rect_dest, BG_POINT se_rect_src_3x3_top_left);
|
||||
|
||||
/* Moves a rect in the main background vertically in direction by a single tile.
|
||||
* Note that tiles in the previous location will be transparent (0x000)
|
||||
* so maybe copy would be a better choice if you don't want to delete things
|
||||
|
||||
+261
-161
@@ -186,7 +186,7 @@ static const Rect POP_MENU_ANIM_RECT = {9, 7, 24, 31 };
|
||||
// This is because when popping, the target position is blank so we just animate
|
||||
// the whole rect so we don't have to track its position
|
||||
|
||||
static const Rect SINGLE_BLIND_SELECT_RECT = { 9, 7, 13, 32 };
|
||||
static const Rect SINGLE_BLIND_SELECT_RECT = {9, 7, 13, 32 };
|
||||
|
||||
static const Rect HAND_BG_RECT_SELECTING = {9, 11, 24, 17 };
|
||||
// TODO: Currently unused, remove?
|
||||
@@ -205,6 +205,9 @@ static const Rect TOP_LEFT_PANEL_ANIM_RECT = {0, 0, 8, 4 };
|
||||
static const BG_POINT TOP_LEFT_BLIND_TITLE_POINT = {0, 21, };
|
||||
static const Rect BIG_BLIND_TITLE_SRC_RECT = {0, 26, 8, 26 };
|
||||
static const Rect BOSS_BLIND_TITLE_SRC_RECT = {0, 27, 8, 27 };
|
||||
static const BG_POINT GAME_OVER_SRC_RECT_3X3_POS = {25, 29};
|
||||
static const Rect GAME_OVER_DIALOG_DEST_RECT= {11, 21, 23, 26};
|
||||
static const Rect GAME_OVER_ANIM_RECT = {11, 8, 23, 26};
|
||||
|
||||
// Rects for TTE (in pixels)
|
||||
static const Rect HAND_SIZE_RECT = {128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING
|
||||
@@ -237,6 +240,9 @@ static const Rect ROUND_END_NUM_HANDS_RECT = {88, 116, UNDEFINED, UNDEF
|
||||
static const Rect HAND_REWARD_RECT = {168, UNDEFINED, UNDEFINED, UNDEFINED };
|
||||
static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEFINED };
|
||||
static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFINED };
|
||||
static const Rect GAME_LOSE_MSG_TEXT_RECT = {104, 72, UNDEFINED, UNDEFINED};
|
||||
// 1 character to the right oF GAME_LOSE
|
||||
static const Rect GAME_WIN_MSG_TEXT_RECT = {112, 72, UNDEFINED, UNDEFINED};
|
||||
|
||||
static const BG_POINT HELD_JOKERS_POS = {108, 10};
|
||||
static const BG_POINT JOKER_DISCARD_TARGET = {240, 30};
|
||||
@@ -245,6 +251,7 @@ static const BG_POINT JOKER_DISCARD_TARGET = {240, 30};
|
||||
|
||||
//TODO: Properly define and use
|
||||
#define MENU_POP_OUT_ANIM_FRAMES 20
|
||||
#define GAME_OVER_ANIM_FRAMES 15
|
||||
|
||||
#define SCORED_CARD_TEXT_Y 48
|
||||
|
||||
@@ -516,7 +523,7 @@ void change_background(int id)
|
||||
obj_unhide(blind_select_tokens[BIG_BLIND]->obj, 0);
|
||||
obj_unhide(blind_select_tokens[BOSS_BLIND]->obj, 0);
|
||||
|
||||
const int default_y = 89 + (TILE_SIZE * 12); // Default y position for the blind select tokens. 8 is the size of a tile and 12 is the amound of tiles the background is shifted down by
|
||||
const int default_y = 89 + (TILE_SIZE * 12); // Default y position for the blind select tokens. 12 is the amound of tiles the background is shifted down by
|
||||
sprite_position(blind_select_tokens[SMALL_BLIND], 80, default_y);
|
||||
sprite_position(blind_select_tokens[BIG_BLIND], 120, default_y);
|
||||
sprite_position(blind_select_tokens[BOSS_BLIND], 160, default_y);
|
||||
@@ -632,7 +639,7 @@ void display_temp_score(int value)
|
||||
{
|
||||
int x_offset = 40 - get_digits_even(value) * TILE_SIZE;
|
||||
tte_erase_rect_wrapper(TEMP_SCORE_RECT);
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}%d", x_offset, TEMP_SCORE_RECT.top, value);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d", x_offset, TEMP_SCORE_RECT.top, TTE_WHITE_PB, value);
|
||||
}
|
||||
|
||||
void display_score(int value)
|
||||
@@ -661,14 +668,14 @@ void display_score(int value)
|
||||
int rect_width = SCORE_RECT.right - SCORE_RECT.left;
|
||||
int x_offset = SCORE_RECT.left + (rect_width - text_width) / 2;
|
||||
|
||||
tte_printf("#{P:%d,48; cx:0xF000}%d%c", x_offset, display_value, score_suffix);
|
||||
tte_printf("#{P:%d,48; cx:0x%X000}%d%c", x_offset, TTE_WHITE_PB, display_value, score_suffix);
|
||||
}
|
||||
|
||||
void display_money(int value)
|
||||
{
|
||||
int x_offset = 32 - get_digits_odd(value) * TILE_SIZE;
|
||||
tte_erase_rect_wrapper(MONEY_TEXT_RECT);
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}$%d", x_offset, MONEY_TEXT_RECT.top, value);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}$%d", x_offset, MONEY_TEXT_RECT.top, TTE_YELLOW_PB, value);
|
||||
}
|
||||
|
||||
void display_chips(int value)
|
||||
@@ -676,19 +683,19 @@ void display_chips(int value)
|
||||
Rect chips_text_rect = CHIPS_TEXT_RECT;
|
||||
tte_erase_rect_wrapper(CHIPS_TEXT_RECT);
|
||||
update_text_rect_to_right_align_num(&chips_text_rect, value, OVERFLOW_LEFT);
|
||||
tte_printf("#{P:%d,%d; cx:0xF000;}%d", chips_text_rect.left, chips_text_rect.top, value);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000;}%d", chips_text_rect.left, chips_text_rect.top, TTE_WHITE_PB, value);
|
||||
}
|
||||
|
||||
void display_mult(int value)
|
||||
{
|
||||
tte_erase_rect_wrapper(MULT_TEXT_RECT);
|
||||
tte_printf("#{P:%d,%d; cx:0xF000;}%d", MULT_TEXT_RECT.left, MULT_TEXT_RECT.top, value); // Mult
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000;}%d", MULT_TEXT_RECT.left, MULT_TEXT_RECT.top, TTE_WHITE_PB, value); // Mult
|
||||
}
|
||||
|
||||
void display_round(int value)
|
||||
{
|
||||
//tte_erase_rect_wrapper(ROUND_TEXT_RECT);
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}%d", ROUND_TEXT_RECT.left, ROUND_TEXT_RECT.top, round);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d", ROUND_TEXT_RECT.left, ROUND_TEXT_RECT.top, TTE_YELLOW_PB, round);
|
||||
}
|
||||
|
||||
void display_ante(int value)
|
||||
@@ -712,7 +719,7 @@ static void print_hand_type(const char* hand_type_str)
|
||||
{
|
||||
if (hand_type_str == NULL)
|
||||
return; // NULL-checking paranoia
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}%s", HAND_TYPE_RECT.left, HAND_TYPE_RECT.top, hand_type_str);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%s", HAND_TYPE_RECT.left, HAND_TYPE_RECT.top, TTE_WHITE_PB, hand_type_str);
|
||||
}
|
||||
|
||||
void set_hand()
|
||||
@@ -922,7 +929,7 @@ void increment_blind(enum BlindState increment_reason)
|
||||
}
|
||||
}
|
||||
|
||||
void game_round_init()
|
||||
static void game_round_init()
|
||||
{
|
||||
// once we have a main menu, move the seed set there. this is only here now because there isn't a way to set the seed to a psudorandom value unless there is something to wait on
|
||||
set_seed(rng_seed);
|
||||
@@ -968,13 +975,35 @@ void game_round_init()
|
||||
blind_req_text_rect.left -= TILE_SIZE; // Move left by one character width to make room for 'k'
|
||||
}
|
||||
|
||||
tte_printf("#{P:%d,%d; cx:0xE000}%d%c", blind_req_text_rect.left, blind_req_text_rect.top, blind_requirement, score_suffix); // Blind requirement
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}$%d", BLIND_REWARD_RECT.left, BLIND_REWARD_RECT.top, blind_get_reward(current_blind)); // Blind reward
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d%c", blind_req_text_rect.left, blind_req_text_rect.top, TTE_RED_PB, blind_requirement, score_suffix); // Blind requirement
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}$%d", BLIND_REWARD_RECT.left, BLIND_REWARD_RECT.top, TTE_YELLOW_PB, blind_get_reward(current_blind)); // Blind reward
|
||||
|
||||
deck_shuffle(); // Shuffle the deck at the start of the round
|
||||
}
|
||||
|
||||
void init_game_state(enum GameState game_state_to_init)
|
||||
static void game_over_init()
|
||||
{
|
||||
// Clears the round end menu
|
||||
main_bg_se_clear_rect(POP_MENU_ANIM_RECT);
|
||||
main_bg_se_copy_expand_3x3_rect(GAME_OVER_DIALOG_DEST_RECT, GAME_OVER_SRC_RECT_3X3_POS);
|
||||
}
|
||||
|
||||
static void game_lose_init()
|
||||
{
|
||||
game_over_init();
|
||||
// Using the text color to match the "Game Over" text
|
||||
affine_background_set_color(TEXT_CLR_RED);
|
||||
|
||||
}
|
||||
|
||||
static void game_win_init()
|
||||
{
|
||||
game_over_init();
|
||||
// Using the text color to match the "You Win" text
|
||||
affine_background_set_color(TEXT_CLR_BLUE);
|
||||
}
|
||||
|
||||
static void init_game_state(enum GameState game_state_to_init)
|
||||
{
|
||||
// Switch written out, add init for states as needed
|
||||
switch (game_state_to_init)
|
||||
@@ -989,6 +1018,10 @@ void init_game_state(enum GameState game_state_to_init)
|
||||
case GAME_BLIND_SELECT:
|
||||
break;
|
||||
case GAME_LOSE:
|
||||
game_lose_init();
|
||||
break;
|
||||
case GAME_WIN:
|
||||
game_win_init();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -996,7 +1029,7 @@ void init_game_state(enum GameState game_state_to_init)
|
||||
}
|
||||
|
||||
// Game functions
|
||||
void game_set_state(enum GameState new_game_state)
|
||||
static void game_set_state(enum GameState new_game_state)
|
||||
{
|
||||
timer = 0; // Reset the timer
|
||||
init_game_state(new_game_state);
|
||||
@@ -1048,7 +1081,7 @@ void game_init()
|
||||
|
||||
change_background(BG_ID_BLIND_SELECT);
|
||||
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, deck_get_size(), deck_get_max_size()); // Deck size/max size
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, TTE_WHITE_PB, deck_get_size(), deck_get_max_size()); // Deck size/max size
|
||||
|
||||
display_round(round); // Set the round display
|
||||
display_score(score); // Set the score display
|
||||
@@ -1059,10 +1092,9 @@ void game_init()
|
||||
display_hands(hands); // Hand
|
||||
display_discards(discards); // Discard
|
||||
|
||||
//tte_printf("#{P:24,120; cx:0xC000}$%d", money); // Money
|
||||
display_money(money); // Set the money display
|
||||
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}%d#{cx:0xF000}/%d", ANTE_TEXT_RECT.left, ANTE_TEXT_RECT.top, ante, MAX_ANTE); // Ante
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d#{cx:0x%X000}/%d", ANTE_TEXT_RECT.left, ANTE_TEXT_RECT.top, TTE_YELLOW_PB, ante, TTE_WHITE_PB, MAX_ANTE); // Ante
|
||||
}
|
||||
|
||||
static void game_playing_process_hand_select_input()
|
||||
@@ -1136,7 +1168,7 @@ static void game_playing_process_hand_select_input()
|
||||
selection_y = 0;
|
||||
display_hands(--discards);
|
||||
set_hand();
|
||||
tte_printf("#{P:%d,%d; cx:0xE000}%d", DISCARDS_TEXT_RECT.left, DISCARDS_TEXT_RECT.top, discards);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d", DISCARDS_TEXT_RECT.left, DISCARDS_TEXT_RECT.top, TTE_RED_PB, discards);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1236,6 +1268,37 @@ static void game_playing_process_card_draw()
|
||||
}
|
||||
}
|
||||
|
||||
static bool game_round_is_over()
|
||||
{
|
||||
return hands == 0 || score >= blind_get_requirement(current_blind, ante);
|
||||
}
|
||||
|
||||
static void game_playing_handle_round_over()
|
||||
{
|
||||
enum GameState next_state = GAME_ROUND_END;
|
||||
|
||||
if (score >= blind_get_requirement(current_blind, ante))
|
||||
{
|
||||
if (current_blind == BOSS_BLIND)
|
||||
{
|
||||
if (ante < MAX_ANTE)
|
||||
{
|
||||
display_ante(++ante);
|
||||
}
|
||||
else
|
||||
{
|
||||
next_state = GAME_WIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hands == 0)
|
||||
{
|
||||
next_state = GAME_LOSE;
|
||||
}
|
||||
|
||||
game_set_state(next_state);
|
||||
}
|
||||
|
||||
static void game_playing_discarded_cards_loop()
|
||||
{
|
||||
// Discarded cards loop (mainly for shuffling)
|
||||
@@ -1274,26 +1337,97 @@ static void game_playing_discarded_cards_loop()
|
||||
|
||||
if (discard_top == -1 && discarded_card_object == NULL) // If there are no more discarded cards, stop shuffling
|
||||
{
|
||||
game_set_state(GAME_ROUND_END); // Set the game state back to playing
|
||||
// After HAND_SHUFFLING the round is over
|
||||
game_playing_handle_round_over();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const int HAND_SPACING_LUT[MAX_HAND_SIZE] = { 28, 28, 28, 28, 27, 21, 18, 15, 13, 12, 10, 9, 9, 8, 8, 7 }; // This is a stupid way to do this but I don't care
|
||||
|
||||
void card_in_hand_loop_handle_discard_and_shuffling(int card_idx, bool* discarded_card, FIXED* hand_x, FIXED* hand_y, bool* sound_played, bool* break_loop)
|
||||
{
|
||||
if (hand_state != HAND_DISCARD && hand_state != HAND_SHUFFLING)
|
||||
{
|
||||
// Assumes hand_state is one of these
|
||||
return;
|
||||
}
|
||||
|
||||
*break_loop = false;
|
||||
if (card_object_is_selected(hand[card_idx]) || hand_state == HAND_SHUFFLING)
|
||||
{
|
||||
if (!*discarded_card)
|
||||
{
|
||||
*hand_x = int2fx(240);
|
||||
*hand_y = int2fx(70);
|
||||
|
||||
if (!*sound_played)
|
||||
{
|
||||
play_sfx(SFX_CARD_DRAW, MM_BASE_PITCH_RATE + cards_drawn * PITCH_STEP_DISCARD_SFX);
|
||||
*sound_played = true;
|
||||
}
|
||||
|
||||
if (hand[card_idx]->sprite_object->x >= *hand_x)
|
||||
{
|
||||
discard_push(hand[card_idx]->card);
|
||||
card_object_destroy(&hand[card_idx]);
|
||||
sort_cards();
|
||||
|
||||
hand_top--;
|
||||
cards_drawn++; // This technically isn't drawing cards, I'm just reusing the variable
|
||||
*sound_played = false;
|
||||
timer = 0;
|
||||
|
||||
*hand_y = hand[card_idx]->sprite_object->y;
|
||||
*hand_x = hand[card_idx]->sprite_object->x;
|
||||
}
|
||||
|
||||
*discarded_card = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hand_state == HAND_DISCARD)
|
||||
{
|
||||
*hand_y -= int2fx(15); // Don't raise the card if we're mass discarding, it looks stupid.
|
||||
}
|
||||
else // hand_state == HAND_SHUFFLING
|
||||
{
|
||||
*hand_y += int2fx(24);
|
||||
}
|
||||
*hand_x = *hand_x + (int2fx(card_idx) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*hand_x = *hand_x + (int2fx(card_idx) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top];
|
||||
}
|
||||
|
||||
if (card_idx == 0 && *discarded_card == false && timer % FRAMES(10) == 0)
|
||||
{
|
||||
// This is never reached in the case of HAND_SHUFFLING. // Not sure why but that's how it's supposed to be.
|
||||
hand_state = HAND_DRAW;
|
||||
*sound_played = false;
|
||||
cards_drawn = 0;
|
||||
hand_selections = 0;
|
||||
timer = 0;
|
||||
*break_loop = true;
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
static void cards_in_hand_update_loop(bool* discarded_card, int* played_selections, bool* sound_played)
|
||||
{
|
||||
for (int i = hand_top + 1; i >= 0; i--) // Start from the end of the hand and work backwards because that's how Balatro does it
|
||||
{
|
||||
if (hand[i] != NULL)
|
||||
{
|
||||
const int spacing_lut[MAX_HAND_SIZE] = { 28, 28, 28, 28, 27, 21, 18, 15, 13, 12, 10, 9, 9, 8, 8, 7 }; // This is a stupid way to do this but I don't care
|
||||
|
||||
FIXED hand_x = int2fx(120);
|
||||
FIXED hand_y = int2fx(90);
|
||||
|
||||
switch (hand_state)
|
||||
{
|
||||
case HAND_DRAW:
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top];
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top];
|
||||
break;
|
||||
case HAND_SELECT:
|
||||
bool is_focused = (i == selection_x && selection_y == 0);
|
||||
@@ -1317,72 +1451,18 @@ static void cards_in_hand_update_loop(bool* discarded_card, int* played_selectio
|
||||
hand[i]->sprite_object->vy = 0;
|
||||
}
|
||||
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top]; // TODO: Change this later to reference a 2D LUT of positions
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top]; // TODO: Change this later to reference a 2D LUT of positions
|
||||
break;
|
||||
case HAND_SHUFFLING:
|
||||
/* FALL THROUGH */
|
||||
case HAND_DISCARD: // TODO: Add sound
|
||||
if (card_object_is_selected(hand[i]) || hand_state == HAND_SHUFFLING)
|
||||
{
|
||||
if (!*discarded_card)
|
||||
{
|
||||
hand_x = int2fx(240);
|
||||
hand_y = int2fx(70);
|
||||
|
||||
if (!*sound_played)
|
||||
{
|
||||
play_sfx(SFX_CARD_DRAW, MM_BASE_PITCH_RATE + cards_drawn*PITCH_STEP_DISCARD_SFX);
|
||||
*sound_played = true;
|
||||
}
|
||||
|
||||
if (hand[i]->sprite_object->x >= hand_x)
|
||||
{
|
||||
discard_push(hand[i]->card);
|
||||
card_object_destroy(&hand[i]);
|
||||
sort_cards();
|
||||
|
||||
hand_top--;
|
||||
cards_drawn++; // This technically isn't drawing cards, I'm just reusing the variable
|
||||
*sound_played = false;
|
||||
timer = 0;
|
||||
|
||||
hand_y = hand[i]->sprite_object->y;
|
||||
hand_x = hand[i]->sprite_object->x;
|
||||
}
|
||||
|
||||
*discarded_card = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hand_state == HAND_DISCARD)
|
||||
{
|
||||
hand_y -= int2fx(15); // Don't raise the card if we're mass discarding, it looks stupid.
|
||||
}
|
||||
else
|
||||
{
|
||||
hand_y += int2fx(24);
|
||||
}
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top];
|
||||
}
|
||||
|
||||
if (i == 0 && *discarded_card == false && timer % FRAMES(10) == 0)
|
||||
{
|
||||
hand_state = HAND_DRAW;
|
||||
*sound_played = false;
|
||||
cards_drawn = 0;
|
||||
hand_selections = 0;
|
||||
timer = 0;
|
||||
break;
|
||||
}
|
||||
bool break_loop;
|
||||
card_in_hand_loop_handle_discard_and_shuffling(i, discarded_card, &hand_x, &hand_y, sound_played, &break_loop);
|
||||
if (break_loop) break;
|
||||
|
||||
break;
|
||||
case HAND_PLAY:
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top];
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top];
|
||||
hand_y += int2fx(24);
|
||||
|
||||
if (card_object_is_selected(hand[i]) && *discarded_card == false && timer % FRAMES(10) == 0)
|
||||
@@ -1556,7 +1636,7 @@ static void cards_in_hand_update_loop(bool* discarded_card, int* played_selectio
|
||||
|
||||
break;
|
||||
case HAND_PLAYING: // Don't need to do anything here, just wait for the player to select cards
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -spacing_lut[hand_top];
|
||||
hand_x = hand_x + (int2fx(i) - int2fx(hand_top) / 2) * -HAND_SPACING_LUT[hand_top];
|
||||
hand_y += int2fx(24);
|
||||
break;
|
||||
}
|
||||
@@ -1744,14 +1824,9 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
|
||||
if (i == played_top)
|
||||
{
|
||||
if (score >= blind_get_requirement(current_blind, ante))
|
||||
if (game_round_is_over())
|
||||
{
|
||||
hand_state = HAND_SHUFFLING;
|
||||
|
||||
if (current_blind == BOSS_BLIND)
|
||||
{
|
||||
display_ante(++ante);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1782,55 +1857,6 @@ static void played_cards_update_loop(bool* discarded_card, int* played_selection
|
||||
}
|
||||
}
|
||||
|
||||
static void discarded_jokers_update_loop()
|
||||
{
|
||||
if (discarded_jokers == NULL)
|
||||
return;
|
||||
|
||||
// Iterating backwards because of removal within loop
|
||||
for (int i = list_get_size(discarded_jokers) - 1; i >= 0; i--)
|
||||
{
|
||||
JokerObject* joker_object = list_get(discarded_jokers, i);
|
||||
joker_object_update(joker_object);
|
||||
if (joker_object->sprite_object->x == joker_object->sprite_object->tx
|
||||
&& joker_object->sprite_object->y == joker_object->sprite_object->ty)
|
||||
{
|
||||
list_remove_by_idx(discarded_jokers, i);
|
||||
joker_object_destroy(&joker_object);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void held_jokers_update_loop()
|
||||
{
|
||||
const int spacing_lut[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] =
|
||||
{
|
||||
{0, 0, 0, 0, 0},
|
||||
{13, -13, 0, 0, 0},
|
||||
{26, 0, -26, 0, 0},
|
||||
{39, 13, -13, -39, 0},
|
||||
{40, 20, 0, -20, -40}
|
||||
};
|
||||
|
||||
FIXED hand_x = int2fx(HELD_JOKERS_POS.x);
|
||||
|
||||
int jokers_top = list_get_size(jokers) - 1;
|
||||
for (int i = jokers_top; i >= 0; i--)
|
||||
{
|
||||
JokerObject *joker = list_get(jokers, i);
|
||||
joker->sprite_object->tx = hand_x - int2fx(spacing_lut[jokers_top][i]);
|
||||
|
||||
joker_object_update(joker);
|
||||
}
|
||||
}
|
||||
|
||||
static void jokers_update_loop()
|
||||
{
|
||||
held_jokers_update_loop();
|
||||
discarded_jokers_update_loop();
|
||||
}
|
||||
|
||||
static void game_playing_ui_text_update()
|
||||
{
|
||||
static int last_hand_size = 0;
|
||||
@@ -1840,14 +1866,14 @@ static void game_playing_ui_text_update()
|
||||
{
|
||||
if (background == BG_ID_CARD_SELECTING)
|
||||
{
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", HAND_SIZE_RECT_SELECT.left, HAND_SIZE_RECT_SELECT.top, hand_get_size(), hand_get_max_size()); // Hand size/max size
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d/%d", HAND_SIZE_RECT_SELECT.left, HAND_SIZE_RECT_SELECT.top, TTE_WHITE_PB, hand_get_size(), hand_get_max_size()); // Hand size/max size
|
||||
}
|
||||
else if (background == BG_ID_CARD_PLAYING)
|
||||
{
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", HAND_SIZE_RECT_PLAYING.left, HAND_SIZE_RECT_PLAYING.top, hand_get_size(), hand_get_max_size()); // Hand size/max size
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d/%d", HAND_SIZE_RECT_PLAYING.left, HAND_SIZE_RECT_PLAYING.top, TTE_WHITE_PB, hand_get_size(), hand_get_max_size()); // Hand size/max size
|
||||
}
|
||||
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, deck_get_size(), deck_get_max_size()); // Deck size/max size
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d/%d", DECK_SIZE_RECT.left, DECK_SIZE_RECT.top, TTE_WHITE_PB, deck_get_size(), deck_get_max_size()); // Deck size/max size
|
||||
|
||||
last_hand_size = hand_get_size();
|
||||
last_deck_size = deck_get_size();
|
||||
@@ -1870,13 +1896,6 @@ static void game_round_end_cashout()
|
||||
|
||||
void game_playing()
|
||||
{
|
||||
// TODO: Blind rect sliding into view animation...
|
||||
if (hand_state == HAND_SELECT && hands == 0)
|
||||
{
|
||||
// TODO: Check if it's safe to change to game_set_state() without side effects
|
||||
game_state = GAME_LOSE;
|
||||
}
|
||||
|
||||
// Background logic (thissss might be moved to the card'ssss logic later. I'm a sssssnake)
|
||||
if (hand_state == HAND_DRAW || hand_state == HAND_DISCARD || hand_state == HAND_SELECT)
|
||||
{
|
||||
@@ -1956,7 +1975,7 @@ void game_round_end()
|
||||
int blind_req = blind_get_requirement(current_blind, current_ante);
|
||||
update_text_rect_to_right_align_num(&blind_req_rect, blind_req, OVERFLOW_RIGHT);
|
||||
|
||||
tte_printf("#{P:%d,%d; cx:0xE000}%d", blind_req_rect.left, blind_req_rect.top, blind_req);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d", blind_req_rect.left, blind_req_rect.top, TTE_RED_PB, blind_req);
|
||||
|
||||
if (timer == 1)
|
||||
{
|
||||
@@ -2001,8 +2020,8 @@ void game_round_end()
|
||||
if (blind_reward > 0)
|
||||
{
|
||||
blind_reward--;
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}$%d", BLIND_REWARD_RECT.left , BLIND_REWARD_RECT.top, blind_reward);
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}$%d", ROUND_END_BLIND_REWARD_RECT.left, ROUND_END_BLIND_REWARD_RECT.top, blind_get_reward(current_blind) - blind_reward);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}$%d", BLIND_REWARD_RECT.left , BLIND_REWARD_RECT.top, TTE_YELLOW_PB, blind_reward);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}$%d", ROUND_END_BLIND_REWARD_RECT.left, ROUND_END_BLIND_REWARD_RECT.top, TTE_YELLOW_PB, blind_get_reward(current_blind) - blind_reward);
|
||||
}
|
||||
else if (timer > FRAMES(20))
|
||||
{
|
||||
@@ -2083,7 +2102,7 @@ void game_round_end()
|
||||
int x = (8 + timer) * TILE_SIZE;
|
||||
int y = (13) * TILE_SIZE;
|
||||
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}.", x, y);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}.", x, y, TTE_WHITE_PB);
|
||||
}
|
||||
else if (timer >= 30 && hand_reward > 0) // Wait an additional 15 frames since the last sequenced action
|
||||
{
|
||||
@@ -2094,13 +2113,13 @@ void game_round_end()
|
||||
single_line_rect.bottom = single_line_rect.top + 1;
|
||||
main_bg_se_copy_rect_1_tile_vert(single_line_rect, SE_DOWN);
|
||||
|
||||
tte_printf("#{P:%d,%d; cx:0xD000}%d #{cx:0xF000}Hands", ROUND_END_NUM_HANDS_RECT.left, ROUND_END_NUM_HANDS_RECT.top, hand_reward); // Print the hand reward
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}%d #{cx:0x%X000}Hands", ROUND_END_NUM_HANDS_RECT.left, ROUND_END_NUM_HANDS_RECT.top, TTE_BLUE_PB, hand_reward, TTE_WHITE_PB); // Print the hand reward
|
||||
}
|
||||
else if (timer > 45 && timer % FRAMES(20) == 0) // After 15 frames, every 20 frames, increment the hand reward text until the hand reward variable is depleted
|
||||
{
|
||||
int y = (13 + hand_y) * TILE_SIZE;
|
||||
hand_reward--;
|
||||
tte_printf("#{P:%d, %d; cx:0xC000}$%d", HAND_REWARD_RECT.left, y, hands - hand_reward); // Print the hand reward
|
||||
tte_printf("#{P:%d, %d; cx:0x%X000}$%d", HAND_REWARD_RECT.left, y, TTE_YELLOW_PB, hands - hand_reward); // Print the hand reward
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2120,17 +2139,17 @@ void game_round_end()
|
||||
|
||||
Rect top_rect = {11, 8, 22, 8};
|
||||
BG_POINT top_point = {6, 29};
|
||||
main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(top_point), top_rect);
|
||||
main_bg_se_fill_rect_with_se(main_bg_se_get_se(top_point), top_rect);
|
||||
|
||||
Rect middle_rect = {11, 9, 22, 9};
|
||||
BG_POINT middle_point = {6, 30};
|
||||
main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(middle_point), middle_rect);
|
||||
main_bg_se_fill_rect_with_se(main_bg_se_get_se(middle_point), middle_rect);
|
||||
|
||||
Rect bottom_rect = {11, 10, 22, 10};
|
||||
BG_POINT bottom_point = {6, 31};
|
||||
main_bg_se_copy_tile_to_rect(main_bg_se_get_tile(bottom_point), bottom_rect);
|
||||
main_bg_se_fill_rect_with_se(main_bg_se_get_se(bottom_point), bottom_rect);
|
||||
|
||||
tte_printf("#{P:%d, %d; cx:0xF000}Cash Out: $%d", CASHOUT_RECT.left, CASHOUT_RECT.top, hands + blind_get_reward(current_blind)); // Print the cash out amount
|
||||
tte_printf("#{P:%d, %d; cx:0x%X000}Cash Out: $%d", CASHOUT_RECT.left, CASHOUT_RECT.top, TTE_WHITE_PB, hands + blind_get_reward(current_blind)); // Print the cash out amount
|
||||
}
|
||||
else if (timer > FRAMES(40) && key_hit(SELECT_CARD)) // Wait until the player presses A to cash out
|
||||
{
|
||||
@@ -2186,7 +2205,7 @@ void print_price_under_sprite_object(SpriteObject *sprite_object, int price)
|
||||
{
|
||||
int x = fx2int(sprite_object->tx) + TILE_SIZE - (get_digits_even(price) - 1) * TILE_SIZE;
|
||||
int y = fx2int(sprite_object->ty) + CARD_SPRITE_SIZE + TILE_SIZE; // TODO: Should probably extract the sprite size
|
||||
tte_printf("#{P:%d,%d; cx:0xC000}$%d", x, y, price);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}$%d", x, y, TTE_YELLOW_PB, price);
|
||||
}
|
||||
|
||||
void erase_price_under_sprite_object(SpriteObject *sprite_object)
|
||||
@@ -2296,7 +2315,7 @@ static void game_shop_reroll(int *reroll_cost)
|
||||
}
|
||||
|
||||
(*reroll_cost)++;
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, *reroll_cost);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, TTE_WHITE_PB, *reroll_cost);
|
||||
}
|
||||
|
||||
static int jokers_sel_row_get_size()
|
||||
@@ -2503,7 +2522,7 @@ static void game_shop_process_user_input()
|
||||
// to trigger the selection change so the initial selection is visible
|
||||
shop_selection_grid.selection = SHOP_INIT_SEL;
|
||||
selection_grid_move_selection_horz(&shop_selection_grid, 1);
|
||||
tte_printf("#{P:%d,%d; cx:0xF000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, reroll_cost);
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}$%d", SHOP_REROLL_RECT.left, SHOP_REROLL_RECT.top, TTE_WHITE_PB, reroll_cost);
|
||||
}
|
||||
|
||||
// Shop input logic
|
||||
@@ -2805,6 +2824,84 @@ void game_blind_select()
|
||||
}
|
||||
}
|
||||
|
||||
static void discarded_jokers_update_loop()
|
||||
{
|
||||
if (discarded_jokers == NULL)
|
||||
return;
|
||||
|
||||
// Iterating backwards because of removal within loop
|
||||
for (int i = list_get_size(discarded_jokers) - 1; i >= 0; i--)
|
||||
{
|
||||
JokerObject* joker_object = list_get(discarded_jokers, i);
|
||||
joker_object_update(joker_object);
|
||||
if (joker_object->sprite_object->x == joker_object->sprite_object->tx
|
||||
&& joker_object->sprite_object->y == joker_object->sprite_object->ty)
|
||||
{
|
||||
list_remove_by_idx(discarded_jokers, i);
|
||||
joker_object_destroy(&joker_object);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void held_jokers_update_loop()
|
||||
{
|
||||
const int spacing_lut[MAX_JOKERS_HELD_SIZE][MAX_JOKERS_HELD_SIZE] =
|
||||
{
|
||||
{0, 0, 0, 0, 0},
|
||||
{13, -13, 0, 0, 0},
|
||||
{26, 0, -26, 0, 0},
|
||||
{39, 13, -13, -39, 0},
|
||||
{40, 20, 0, -20, -40}
|
||||
};
|
||||
|
||||
FIXED hand_x = int2fx(HELD_JOKERS_POS.x);
|
||||
|
||||
int jokers_top = list_get_size(jokers) - 1;
|
||||
for (int i = jokers_top; i >= 0; i--)
|
||||
{
|
||||
JokerObject *joker = list_get(jokers, i);
|
||||
joker->sprite_object->tx = hand_x - int2fx(spacing_lut[jokers_top][i]);
|
||||
|
||||
joker_object_update(joker);
|
||||
}
|
||||
}
|
||||
|
||||
static void jokers_update_loop()
|
||||
{
|
||||
held_jokers_update_loop();
|
||||
discarded_jokers_update_loop();
|
||||
}
|
||||
|
||||
static void game_over_anim_frame()
|
||||
{
|
||||
main_bg_se_move_rect_1_tile_vert(GAME_OVER_ANIM_RECT, SE_UP);
|
||||
}
|
||||
|
||||
static void game_lose()
|
||||
{
|
||||
if (timer < GAME_OVER_ANIM_FRAMES)
|
||||
{
|
||||
game_over_anim_frame();
|
||||
}
|
||||
else if (timer == GAME_OVER_ANIM_FRAMES)
|
||||
{
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}GAME OVER", GAME_LOSE_MSG_TEXT_RECT.left, GAME_LOSE_MSG_TEXT_RECT.top, TTE_RED_PB);
|
||||
}
|
||||
}
|
||||
|
||||
static void game_win()
|
||||
{
|
||||
if (timer < GAME_OVER_ANIM_FRAMES)
|
||||
{
|
||||
game_over_anim_frame();
|
||||
}
|
||||
else if (timer == GAME_OVER_ANIM_FRAMES)
|
||||
{
|
||||
tte_printf("#{P:%d,%d; cx:0x%X000}YOU WIN", GAME_WIN_MSG_TEXT_RECT.left, GAME_WIN_MSG_TEXT_RECT.top, TTE_BLUE_PB);
|
||||
}
|
||||
}
|
||||
|
||||
void game_update()
|
||||
{
|
||||
timer++;
|
||||
@@ -2835,7 +2932,10 @@ void game_update()
|
||||
game_blind_select();
|
||||
break;
|
||||
case GAME_LOSE:
|
||||
// Handle lose logic here
|
||||
game_lose();
|
||||
break;
|
||||
case GAME_WIN:
|
||||
game_win();
|
||||
break;
|
||||
}
|
||||
}
|
||||
+99
-16
@@ -24,7 +24,7 @@ static void clip_se_rect_to_screenblock(Rect* rect)
|
||||
clip_se_rect_to_bounding_rect(rect, &FULL_SCREENBLOCK_RECT);
|
||||
}
|
||||
|
||||
u16 main_bg_se_get_tile(BG_POINT pos)
|
||||
SE main_bg_se_get_se(BG_POINT pos)
|
||||
{
|
||||
return se_mat[MAIN_BG_SBB][pos.y][pos.x];
|
||||
}
|
||||
@@ -59,9 +59,8 @@ void main_bg_se_clear_rect(Rect se_rect)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Internal static function to merge implementation of move/copy functions.
|
||||
static void main_bg_se_copy_or_move_rect_1_tile_vert(Rect se_rect, int direction, bool move)
|
||||
static void bg_se_copy_or_move_rect_1_tile_vert(u16 bg_sbb, Rect se_rect, int direction, bool move)
|
||||
{
|
||||
if (se_rect.left > se_rect.right
|
||||
|| (direction != SE_UP && direction != SE_DOWN))
|
||||
@@ -77,17 +76,32 @@ static void main_bg_se_copy_or_move_rect_1_tile_vert(Rect se_rect, int direction
|
||||
|
||||
for (int y = start; y != end - direction; y -= direction)
|
||||
{
|
||||
memcpy16(&(se_mat[MAIN_BG_SBB][y + direction][se_rect.left]),
|
||||
&se_mat[MAIN_BG_SBB][y][se_rect.left],
|
||||
memcpy16(&(se_mat[bg_sbb][y + direction][se_rect.left]),
|
||||
&se_mat[bg_sbb][y][se_rect.left],
|
||||
rect_width(&se_rect));
|
||||
}
|
||||
|
||||
if (move)
|
||||
{
|
||||
memset16(&se_mat[MAIN_BG_SBB][end][se_rect.left], 0x0000, rect_width(&se_rect));
|
||||
memset16(&se_mat[bg_sbb][end][se_rect.left], 0x0000, rect_width(&se_rect));
|
||||
}
|
||||
}
|
||||
|
||||
static void main_bg_se_copy_or_move_rect_1_tile_vert(Rect se_rect, int direction, bool move)
|
||||
{
|
||||
bg_se_copy_or_move_rect_1_tile_vert(MAIN_BG_SBB, se_rect, direction, move);
|
||||
}
|
||||
|
||||
void bg_se_copy_rect_1_tile_vert(u16 bg_sbb, Rect se_rect, int direction)
|
||||
{
|
||||
bg_se_copy_or_move_rect_1_tile_vert(MAIN_BG_SBB, se_rect, direction, false);
|
||||
}
|
||||
|
||||
void bg_se_move_rect_1_tile_vert(u16 bg_sbb, Rect se_rect, int direction)
|
||||
{
|
||||
bg_se_copy_or_move_rect_1_tile_vert(MAIN_BG_SBB, se_rect, direction, true);
|
||||
}
|
||||
|
||||
void main_bg_se_copy_rect_1_tile_vert(Rect se_rect, int direction)
|
||||
{
|
||||
main_bg_se_copy_or_move_rect_1_tile_vert(se_rect, direction, false);
|
||||
@@ -108,20 +122,18 @@ void main_bg_se_copy_rect(Rect se_rect, BG_POINT pos)
|
||||
|
||||
int width = rect_width(&se_rect);
|
||||
int height = rect_height(&se_rect);
|
||||
u16 tile_map[height][width];
|
||||
SE tile_map[height][width];
|
||||
|
||||
// Copy the rect to the tile map
|
||||
for (int sy = 0; sy < height; sy++)
|
||||
{
|
||||
for (int sx = 0; sx < width; sx++)
|
||||
{
|
||||
BG_POINT pt;
|
||||
pt.x = se_rect.left + sx;
|
||||
pt.y = se_rect.top + sy;
|
||||
tile_map[sy][sx] = main_bg_se_get_tile(pt);
|
||||
}
|
||||
memcpy16(&tile_map[sy][0],
|
||||
&se_mat[MAIN_BG_SBB][se_rect.top + sy][se_rect.left],
|
||||
width);
|
||||
}
|
||||
|
||||
// TODO: Avoid overflow
|
||||
// Copy the tilemap to the new rect position
|
||||
for (int sy = 0; sy < height; sy++)
|
||||
{
|
||||
memcpy16(&se_mat[MAIN_BG_SBB][pos.y + sy][pos.x],
|
||||
@@ -130,7 +142,7 @@ void main_bg_se_copy_rect(Rect se_rect, BG_POINT pos)
|
||||
}
|
||||
}
|
||||
|
||||
void main_bg_se_copy_tile_to_rect(u16 tile, Rect se_rect)
|
||||
void main_bg_se_fill_rect_with_se(SE se, Rect se_rect)
|
||||
{
|
||||
if (se_rect.left > se_rect.right || se_rect.top > se_rect.bottom)
|
||||
return;
|
||||
@@ -143,7 +155,78 @@ void main_bg_se_copy_tile_to_rect(u16 tile, Rect se_rect)
|
||||
|
||||
for (int sy = 0; sy < height; sy++)
|
||||
{
|
||||
memset16(&se_mat[MAIN_BG_SBB][se_rect.top + sy][se_rect.left], tile, width);
|
||||
memset16(&se_mat[MAIN_BG_SBB][se_rect.top + sy][se_rect.left], se, width);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: Copy the corners of a 3x3 tile block
|
||||
static void main_bg_se_expand_3x3_copy_corners(const Rect* se_dest_rect, const BG_POINT* src_top_left_pnt, int dest_rect_width, int dest_rect_height)
|
||||
{
|
||||
SE top_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y][src_top_left_pnt->x];
|
||||
se_mat[MAIN_BG_SBB][se_dest_rect->top][se_dest_rect->left] = top_left_se;
|
||||
|
||||
SE top_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y][src_top_left_pnt->x + 2];
|
||||
se_mat[MAIN_BG_SBB][se_dest_rect->top][se_dest_rect->left + dest_rect_width - 1] = top_right_se;
|
||||
|
||||
SE bottom_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 2][src_top_left_pnt->x];
|
||||
se_mat[MAIN_BG_SBB][se_dest_rect->top + dest_rect_height - 1][se_dest_rect->left] = bottom_left_se;
|
||||
|
||||
SE bottom_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 2][src_top_left_pnt->x + 2];
|
||||
se_mat[MAIN_BG_SBB][se_dest_rect->top + dest_rect_height - 1][se_dest_rect->left + dest_rect_width - 1] = bottom_right_se;
|
||||
}
|
||||
|
||||
// Helper: Copy the top and bottom sides of a 3x3 tile block
|
||||
static void main_bg_se_expand_3x3_copy_top_bottom(const Rect* se_dest_rect, const BG_POINT* src_top_left_pnt, int dest_rect_width)
|
||||
{
|
||||
if (dest_rect_width > 2)
|
||||
{
|
||||
SE top_middle_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y][src_top_left_pnt->x + 1];
|
||||
SE bottom_middle_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 2][src_top_left_pnt->x + 1];
|
||||
memset16(&se_mat[MAIN_BG_SBB][se_dest_rect->top][se_dest_rect->left + 1], top_middle_se, dest_rect_width - 2);
|
||||
memset16(&se_mat[MAIN_BG_SBB][se_dest_rect->bottom][se_dest_rect->left + 1], bottom_middle_se, dest_rect_width - 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper: Copy the left and right sides of a 3x3 tile block
|
||||
static void main_bg_se_expand_3x3_copy_left_right(const Rect* se_dest_rect, const BG_POINT* src_top_left_pnt, int dest_rect_width, int dest_rect_height)
|
||||
{
|
||||
SE middle_left_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 1][src_top_left_pnt->x];
|
||||
SE middle_right_se = se_mat[MAIN_BG_SBB][src_top_left_pnt->y + 1][src_top_left_pnt->x + 2];
|
||||
for (int y = 1; y < dest_rect_height - 1; y++)
|
||||
{
|
||||
se_mat[MAIN_BG_SBB][se_dest_rect->top + y][se_dest_rect->left] = middle_left_se;
|
||||
se_mat[MAIN_BG_SBB][se_dest_rect->top + y][se_dest_rect->left + dest_rect_width - 1] = middle_right_se;
|
||||
}
|
||||
}
|
||||
|
||||
void main_bg_se_copy_expand_3x3_rect(Rect se_dest_rect, BG_POINT src_top_left_pnt)
|
||||
{
|
||||
clip_se_rect_to_screenblock(&se_dest_rect);
|
||||
|
||||
int dest_rect_width = rect_width(&se_dest_rect);
|
||||
int dest_rect_height = rect_height(&se_dest_rect);
|
||||
|
||||
// Verify the dest rect is at least 2x2
|
||||
if (dest_rect_width < 2 || dest_rect_height < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy the corners
|
||||
main_bg_se_expand_3x3_copy_corners(&se_dest_rect, &src_top_left_pnt, dest_rect_width, dest_rect_height);
|
||||
|
||||
// Copy top and bottom sides
|
||||
main_bg_se_expand_3x3_copy_top_bottom(&se_dest_rect, &src_top_left_pnt, dest_rect_width);
|
||||
|
||||
// Copy left and right sides
|
||||
main_bg_se_expand_3x3_copy_left_right(&se_dest_rect, &src_top_left_pnt, dest_rect_width, dest_rect_height);
|
||||
|
||||
// Fill the center if needed
|
||||
if (dest_rect_width > 2 && dest_rect_height > 2)
|
||||
{
|
||||
SE middle_fill_se = se_mat[MAIN_BG_SBB][src_top_left_pnt.y + 1][src_top_left_pnt.x + 1];
|
||||
Rect dest_inner_fill_rect = {se_dest_rect.left + 1, se_dest_rect.top + 1, se_dest_rect.right - 1, se_dest_rect.bottom - 1};
|
||||
main_bg_se_fill_rect_with_se(middle_fill_se, dest_inner_fill_rect);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -28,15 +28,15 @@ void init()
|
||||
mmStart(MOD_MAIN_THEME, MM_PLAY_LOOP);
|
||||
|
||||
// Initialize text engine
|
||||
tte_init_se(0, BG_CBB(TTE_CBB) | BG_SBB(TTE_SBB), 0, CLR_WHITE, 14, NULL, NULL);
|
||||
tte_init_se(0, BG_CBB(TTE_CBB) | BG_SBB(TTE_SBB), 0, CLR_WHITE, TTE_BIT_UNPACK_OFFSET, NULL, NULL);
|
||||
tte_erase_screen();
|
||||
tte_init_con();
|
||||
|
||||
// TTE palette setup
|
||||
pal_bg_bank[12][15] = 0x029F; // Yellow. honestly fuck libtonc because i cannot figure out how you're supposed to select a color from the palette index so i'm doing it like this
|
||||
pal_bg_bank[13][15] = 0x7E40; // Blue
|
||||
pal_bg_bank[14][15] = 0x213F; // Red
|
||||
pal_bg_bank[15][15] = CLR_WHITE;
|
||||
pal_bg_bank[TTE_YELLOW_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_YELLOW;
|
||||
pal_bg_bank[TTE_BLUE_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_BLUE;
|
||||
pal_bg_bank[TTE_RED_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_RED;
|
||||
pal_bg_bank[TTE_WHITE_PB][TTE_BIT_ON_CLR_IDX] = TEXT_CLR_WHITE;
|
||||
|
||||
// Set up the video mode
|
||||
// BG0 is the TTE text layer
|
||||
|
||||
Reference in New Issue
Block a user