Extracted pop menu animation to a rect copying function for shop

This commit is contained in:
MeirGavish
2025-07-10 16:37:43 +03:00
parent 83af67c3ed
commit fb7b60431c
3 changed files with 123 additions and 62 deletions
+19 -6
View File
@@ -4,6 +4,11 @@
/* This file contains general utils and wrappers that relate to /* This file contains general utils and wrappers that relate to
* graphics/video/vram and generally displaying things on the screen. * graphics/video/vram and generally displaying things on the screen.
* Mostly wrappers and defines for using tonc. * Mostly wrappers and defines for using tonc.
*
* Note: the code here assumes we're working with a single screenblock
* which should be true for this entire game since a screenblock
* is enough to contain a full screen (and more)
* and there isn't any scrolling etc.
*/ */
/* Reminder: /* Reminder:
@@ -17,13 +22,14 @@
#define AFFINE_BG_SBB 2 #define AFFINE_BG_SBB 2
#define AFFINE_BG_CBB 2 #define AFFINE_BG_CBB 2
/* A 1024 size screenblock is arranged in a grid of 32x32 block entries /* 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 * Interestingly since each block is 8x8 pixels, the 240x160 GBA screen
* is smaller than the screenblock, only the top left part of the screenblock * is smaller than the screenblock, only the top left part of the screenblock
* is displayed on the screen. * is displayed on the screen.
*/ */
#define SCREENBLOCK_ROW_LEN 32 #define SE_ROW_LEN 32
#define SE_COL_LEN 32
typedef struct typedef struct
{ {
@@ -35,10 +41,17 @@ typedef struct
#define UNDEFINED -1 #define UNDEFINED -1
/* Clears a rect in the main background screenblock. /* Clears a rect in the main background.
* The rect needs to be in screenblocks * The se_rect dimensions need to be in number of tiles.
*/ */
void main_bg_se_clear_rect(Rect rect); void main_bg_se_clear_rect(Rect se_rect);
/* Copies a rect in the main background a single tile up.
* The se_rect dimensions need to be in number of tiles.
* This is for the pop menu animation, can later be generalized to more tiles
* or other directions
*/
void main_bg_se_copy_rect_1_tile_up(Rect se_rect);
// A wrapper for tte_erase_rect that would use the rect struct // A wrapper for tte_erase_rect that would use the rect struct
void tte_erase_rect_wrapper(Rect rect); void tte_erase_rect_wrapper(Rect rect);
+39 -34
View File
@@ -108,36 +108,46 @@ static inline Card *discard_pop()
// Consts // Consts
static const Rect ROUND_END_MENU_RECT = { 9, 7, 25, 21 }; // In screenblocks
// Rects for TTE // Rects left top right bottom
static const Rect HAND_SIZE_RECT = { 128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING // Screenblock rects
static const Rect HAND_SIZE_RECT_SELECT = { 128, 128, 152, 136 }; static const Rect ROUND_END_MENU_RECT = {9, 7, 25, 21 };
static const Rect HAND_SIZE_RECT_PLAYING = { 128, 152, 152, 160 };
static const Rect HAND_TYPE_RECT = { 8, 64, 64, 72 }; static const Rect POP_MENU_ANIM_RECT = {9, 7, 25, 32 };
// The rect for popping menu animations - includes both the target and source position
// rects. The source position extends beyond the visible screen to the end
// of the screenblock
// The target position is blank so we just animate the whole thing so we don't
// have to track its position
// Rects for TTE (in pixels)
static const Rect HAND_SIZE_RECT = {128, 128, 152, 160 }; // Seems to include both SELECT and PLAYING
static const Rect HAND_SIZE_RECT_SELECT = {128, 128, 152, 136 };
static const Rect HAND_SIZE_RECT_PLAYING = {128, 152, 152, 160 };
static const Rect HAND_TYPE_RECT = {8, 64, 64, 72 };
// Score displayed in the same place as the hand type // Score displayed in the same place as the hand type
static const Rect TEMP_SCORE_RECT = { 8, 64, 64, 72 }; static const Rect TEMP_SCORE_RECT = {8, 64, 64, 72 };
static const Rect PLAYED_CARDS_SCORES_RECT = { 72, 48, 240, 56 }; static const Rect PLAYED_CARDS_SCORES_RECT = {72, 48, 240, 56 };
static const Rect BLIND_TOKEN_TEXT_RECT = { 80, 72, 200, 160 }; static const Rect BLIND_TOKEN_TEXT_RECT = {80, 72, 200, 160 };
static const Rect MONEY_TEXT_RECT = { 8, 120, 64, 120 }; static const Rect MONEY_TEXT_RECT = {8, 120, 64, 120 };
static const Rect CHIPS_TEXT_RECT = { 8, 80, 32, 88 }; static const Rect CHIPS_TEXT_RECT = {8, 80, 32, 88 };
static const Rect MULT_TEXT_RECT = { 40, 80, 64, 88 }; static const Rect MULT_TEXT_RECT = {40, 80, 64, 88 };
static const Rect BLIND_REWARD_RECT = { 40, 32, 64, 40 }; static const Rect BLIND_REWARD_RECT = {40, 32, 64, 40 };
// Rects with UNDEFINED are only used in tte_printf, they need to be fully defined // Rects with UNDEFINED are only used in tte_printf, they need to be fully defined
// to be used with tte_erase_rect_wrapper() // to be used with tte_erase_rect_wrapper()
static const Rect HANDS_TEXT_RECT = { 16, 104, UNDEFINED, UNDEFINED }; static const Rect HANDS_TEXT_RECT = {16, 104, UNDEFINED, UNDEFINED };
static const Rect DISCARDS_TEXT_RECT = { 48, 104, UNDEFINED, UNDEFINED }; static const Rect DISCARDS_TEXT_RECT = {48, 104, UNDEFINED, UNDEFINED };
static const Rect BLIND_REQUIREMENT_TEXT_RECT = { 40, 24, UNDEFINED, UNDEFINED }; static const Rect BLIND_REQ_TEXT_RECT = {40, 24, UNDEFINED, UNDEFINED };
static const Rect DECK_SIZE_RECT = { 200, 152, UNDEFINED, UNDEFINED }; static const Rect DECK_SIZE_RECT = {200, 152, UNDEFINED, UNDEFINED };
static const Rect ROUND_TEXT_RECT = { 48, 144, UNDEFINED, UNDEFINED }; static const Rect ROUND_TEXT_RECT = {48, 144, UNDEFINED, UNDEFINED };
static const Rect ANTE_TEXT_RECT = { 8, 144, UNDEFINED, UNDEFINED }; static const Rect ANTE_TEXT_RECT = {8, 144, UNDEFINED, UNDEFINED };
static const Rect ROUND_END_BLIND_REQUIREMENT_RECT = { 112, 96, UNDEFINED, UNDEFINED }; static const Rect ROUND_END_BLIND_REQ_RECT = {112, 96, UNDEFINED, UNDEFINED };
static const Rect ROUND_END_BLIND_REWARD_RECT = { 168, 96, UNDEFINED, UNDEFINED }; static const Rect ROUND_END_BLIND_REWARD_RECT = { 168, 96, UNDEFINED, UNDEFINED };
static const Rect ROUND_END_NUM_HANDS_RECT = { 88, 116, UNDEFINED, UNDEFINED }; static const Rect ROUND_END_NUM_HANDS_RECT = {88, 116, UNDEFINED, UNDEFINED };
static const Rect HAND_REWARD_RECT = { 168, UNDEFINED, UNDEFINED, UNDEFINED }; static const Rect HAND_REWARD_RECT = {168, UNDEFINED, UNDEFINED, UNDEFINED };
static const Rect CASHOUT_RECT = { 88, 72, UNDEFINED, UNDEFINED }; static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEFINED };
// General functions // General functions
void sort_hand_by_suit() void sort_hand_by_suit()
@@ -172,7 +182,6 @@ void sort_hand_by_rank()
} }
} }
void sort_cards() void sort_cards()
{ {
if (sort_by_suit) if (sort_by_suit)
@@ -656,7 +665,7 @@ void game_init()
tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", HAND_SIZE_RECT.left, HAND_SIZE_RECT.top, hand_get_size(), hand_get_max_size()); // Hand size/max size tte_printf("#{P:%d,%d; cx:0xF000}%d/%d", HAND_SIZE_RECT.left, HAND_SIZE_RECT.top, 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: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:0xE000}%d", BLIND_REQUIREMENT_TEXT_RECT.left, BLIND_REQUIREMENT_TEXT_RECT.top, blind_get_requirement(current_blind, ante)); // Blind requirement tte_printf("#{P:%d,%d; cx:0xE000}%d", BLIND_REQ_TEXT_RECT.left, BLIND_REQ_TEXT_RECT.top, blind_get_requirement(current_blind, ante)); // 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:0xC000}$%d", BLIND_REWARD_RECT.left, BLIND_REWARD_RECT.top, blind_get_reward(current_blind)); // Blind reward
set_score(score); // Set the score display set_score(score); // Set the score display
@@ -1427,7 +1436,7 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa
{ {
obj_unhide(round_end_blind_token->obj, 0); obj_unhide(round_end_blind_token->obj, 0);
tte_printf("#{P:%d,%d; cx:0xE000}%d", ROUND_END_BLIND_REQUIREMENT_RECT.left, ROUND_END_BLIND_REQUIREMENT_RECT.top, blind_get_requirement(current_blind, ante)); tte_printf("#{P:%d,%d; cx:0xE000}%d", ROUND_END_BLIND_REQ_RECT.left, ROUND_END_BLIND_REQ_RECT.top, blind_get_requirement(current_blind, ante));
int y = 13; int y = 13;
@@ -1469,7 +1478,7 @@ void game_round_end() // Writing this kind a made me want to kms. If somewone wa
blind_reward--; 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", 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_REQUIREMENT_RECT.top, blind_get_reward(current_blind) - blind_reward); tte_printf("#{P:%d,%d; cx:0xC000}$%d", ROUND_END_BLIND_REWARD_RECT.left, ROUND_END_BLIND_REQ_RECT.top, blind_get_reward(current_blind) - blind_reward);
if (blind_reward <= 0) if (blind_reward <= 0)
{ {
@@ -1741,11 +1750,7 @@ void game_shop()
if (timer < 13) if (timer < 13)
{ {
for (int y = 7; y < 40; y++) main_bg_se_copy_rect_1_tile_up(POP_MENU_ANIM_RECT);
{
int x = 9;
memcpy16(&se_mem[MAIN_BG_SBB][x + 32 * (y - 1)], &se_mem[MAIN_BG_SBB][x + 32 * y], 16);
}
if (timer >= 7) if (timer >= 7)
{ {
@@ -1763,7 +1768,7 @@ void game_shop()
// { // {
// int y_from = 26; // int y_from = 26;
// int y_to = 0; // int y_to = 0;
// memcpy16(&se_mem[MAIN_BG_SE_BASE][32 * y_to], &se_mem[MAIN_BG_SE_BASE][32 * y_from], 9); // memcpy16(&se_mem[MAIN_BG_SBB][32 * y_to], &se_mem[MAIN_BG_SBB][32 * y_from], 9);
// } // }
} }
} }
+65 -22
View File
@@ -1,22 +1,65 @@
#include <tonc_core.h> #include <tonc_core.h>
#include <tonc_tte.h> #include <tonc_tte.h>
#include <tonc_math.h>
#include "graphic_utils.h"
#include "graphic_utils.h"
void main_bg_se_clear_rect(Rect rect)
{ /*
for (int y = rect.top; y < rect.bottom; y++) *
{ */
for (int x = rect.left; x < rect.right; x++) const Rect FULL_SCREENBLOCK_RECT = { 0, 0, SE_ROW_LEN, SE_COL_LEN };
{
// I also tried to use se_mat and it didn't work
memset16(&se_mem[MAIN_BG_SBB][x + SCREENBLOCK_ROW_LEN * y], 0x000, 1); // Clips a rect of screenblock entries to a specified rect
} static void clip_se_rect_to_bounding_rect(Rect* rect, const Rect* bounding_rect)
} {
} rect->right = min(rect->right, SE_ROW_LEN);
rect->bottom = min(rect->bottom, SE_COL_LEN);
void tte_erase_rect_wrapper(Rect rect) rect->left = max(rect->left, 0);
{ rect->top = max(rect->top, 0);
tte_erase_rect(rect.left, rect.top, rect.right, rect.bottom); }
}
// Can be unstaticed if needed
// Clips a rect of screenblock entries to screenblock boundaries
// The bounding rect is not required to be within screenblock boundaries
static void clip_se_rect_to_screenblock(Rect* rect)
{
clip_se_rect_to_bounding_rect(rect, &FULL_SCREENBLOCK_RECT);
}
void main_bg_se_clear_rect(Rect se_rect)
{
if (se_rect.left > se_rect.right)
return;
// Just to make sure we're not overflowing the boundaries
clip_se_rect_to_screenblock(&se_rect);
for (int y = se_rect.top; y < se_rect.bottom; y++)
{
memset16(&(se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * y]), 0x0000, se_rect.right - se_rect.left);
}
}
void main_bg_se_copy_rect_1_tile_up(Rect se_rect)
{
if (se_rect.left > se_rect.right)
return;
Rect bounding_rect = FULL_SCREENBLOCK_RECT;
bounding_rect.top = 1; // Since we're going up, need to clip to 1 to not overflow
clip_se_rect_to_bounding_rect(&se_rect, &bounding_rect);
for (int y = se_rect.top; y < se_rect.bottom; y++)
{
memcpy16(&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * (y - 1)],
&se_mem[MAIN_BG_SBB][se_rect.left + SE_ROW_LEN * y],
se_rect.right - se_rect.left);
}
}
void tte_erase_rect_wrapper(Rect rect)
{
tte_erase_rect(rect.left, rect.top, rect.right, rect.bottom);
}