Main menu prototype

This commit is contained in:
cellos51
2025-08-09 21:49:37 -04:00
parent 8a905907fc
commit 164f58aa1e
11 changed files with 200 additions and 30 deletions
@@ -0,0 +1 @@
-gt -gB8 -mLa -mRa
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

+1
View File
@@ -0,0 +1 @@
-gB8 -mR8 -mLs -mRtf
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

+9 -2
View File
@@ -5,13 +5,20 @@
#include "graphic_utils.h"
#define AFFINE_BG_PAL_LEN 5
#define AFFINE_BG_PB (PAL_ROW_LEN * 15) // This isn't really a palette bank, just the starting index of the palette
#define AFFINE_BG_PAL_LEN 16
#define AFFINE_BG_PB (PAL_ROW_LEN * 10) // This isn't really a palette bank, just the starting index of the palette
enum AffineBackgroundID
{
AFFINE_BG_MAIN_MENU,
AFFINE_BG_GAME,
};
void affine_background_init();
void affine_background_update();
void affine_background_set_color(COLOR color);
// Must be called with an array of size at least AFFINE_BG_PAL_LEN
void affine_background_load_palette(const u16 *src);
void affine_background_change_background(enum AffineBackgroundID new_bg);
#endif // AFFINE_BACKGROUND_H
+2
View File
@@ -16,6 +16,7 @@
#define BG_ID_ROUND_END 3
#define BG_ID_SHOP 4
#define BG_ID_BLIND_SELECT 5
#define BG_ID_MAIN_MENU 6
// Input bindings
#define SELECT_CARD KEY_A
@@ -26,6 +27,7 @@
enum GameState
{
GAME_MAIN_MENU,
GAME_PLAYING,
GAME_ROUND_END,
GAME_SHOP,
+6
View File
@@ -138,4 +138,10 @@ void memcpy16_tile8_with_palette_offset(u16* dst, const u16* src, uint hwcount,
*/
void memcpy32_tile8_with_palette_offset(u32* dst, const u32* src, uint wcount, u8 palette_offset);
/* Toggles the visibility of the window layers.
* win0 and win1 are the visibility states for the two windows.
* These windows are primarily used for the shadows on held jokers, consumables and cards.
*/
void toggle_windows(bool win0, bool win1);
#endif //GRAPHIC_UTILS_H
+56 -13
View File
@@ -1,16 +1,17 @@
#include "affine_background.h"
#include "affine_background_gfx.h"
#include "affine_main_menu_background_gfx.h"
#include "graphic_utils.h"
BG_AFFINE bgaff;
AFF_SRC_EX asx = {32<<8, 64<<8, 120, 80, 0x0100, 0x0100, 0};
AFF_SRC_EX asx = {0};
enum AffineBackgroundID background = AFFINE_BG_MAIN_MENU;
void affine_background_init()
{
memcpy32_tile8_with_palette_offset((u32*)&tile8_mem[AFFINE_BG_CBB], (const u32*)affine_background_gfxTiles, affine_background_gfxTilesLen/4, AFFINE_BG_PB);
GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_background_gfxMap);
affine_background_load_palette(affine_background_gfxPal);
{
affine_background_change_background(background);
bgaff = bg_aff_default;
}
@@ -20,20 +21,37 @@ void affine_background_update()
static uint timer = 0;
timer++;
// These values are not permament, just the current configuration for the affine background
asx.tex_x += 5;
asx.tex_y += 12;
asx.sx = (lu_sin(timer * 100)) >> 8; // Scale the sine value to fit in a s16
asx.sx += 256; // Add 256 to the sine value to make it positive
asx.sy = (lu_sin(timer * 100 + 0x4000)) >> 8; // Scale the sine value to fit in a s16
asx.sy += 256; // Add 256 to the sine value to make it positive
switch (background)
{
case AFFINE_BG_MAIN_MENU:
asx.scr_x = SCREEN_WIDTH / 2;
asx.scr_y = SCREEN_HEIGHT / 2;
asx.tex_x = 16560;
asx.tex_y = 14400;
asx.sx = 128;
asx.sy = 128;
asx.alpha = 1000; // This slightly rotates it which increases the percieved resolution of the background
break;
case AFFINE_BG_GAME:
asx.scr_x = 0;
asx.scr_y = 0;
asx.tex_x += 5;
asx.tex_y += 12;
asx.sx = (lu_sin(timer * 100)) >> 8; // Scale the sine value to fit in a s16
asx.sx += 256; // Add 256 to the sine value to make it positive
asx.sy = (lu_sin(timer * 100 + 0x4000)) >> 8; // Scale the sine value to fit in a s16
asx.sy += 256; // Add 256 to the sine value to make it positive
asx.alpha = 0;
break;
}
bg_rotscale_ex(&bgaff, &asx);
REG_BG_AFFINE[2] = bgaff;
}
void affine_background_set_color(COLOR color)
{
memcpy16(&pal_bg_mem[AFFINE_BG_PB], affine_background_gfxPal, AFFINE_BG_PAL_LEN);
memcpy16(&pal_bg_mem[AFFINE_BG_PB], affine_main_menu_background_gfxPal, AFFINE_BG_PAL_LEN);
for (int i = 0; i < AFFINE_BG_PAL_LEN; i++)
{
clr_rgbscale(&pal_bg_mem[AFFINE_BG_PB] + i, &pal_bg_mem[AFFINE_BG_PB] + i, 1, color);
@@ -43,4 +61,29 @@ void affine_background_set_color(COLOR color)
void affine_background_load_palette(const u16 *src)
{
memcpy16(&pal_bg_mem[AFFINE_BG_PB], src, AFFINE_BG_PAL_LEN);
}
void affine_background_change_background(enum AffineBackgroundID new_bg)
{
background = new_bg;
switch (background)
{
case AFFINE_BG_MAIN_MENU:
REG_BG2CNT &= ~BG_AFF_32x32;
REG_BG2CNT |= BG_AFF_16x16;
memcpy32_tile8_with_palette_offset((u32*)&tile8_mem[AFFINE_BG_CBB], (const u32*)affine_main_menu_background_gfxTiles, affine_main_menu_background_gfxTilesLen/4, AFFINE_BG_PB);
GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_main_menu_background_gfxMap);
affine_background_load_palette(affine_main_menu_background_gfxPal);
break;
case AFFINE_BG_GAME:
REG_BG2CNT &= ~BG_AFF_16x16;
REG_BG2CNT |= BG_AFF_32x32;
memcpy32_tile8_with_palette_offset((u32*)&tile8_mem[AFFINE_BG_CBB], (const u32*)affine_background_gfxTiles, affine_background_gfxTilesLen/4, AFFINE_BG_PB);
GRIT_CPY(&se_mem[AFFINE_BG_SBB], affine_background_gfxMap);
affine_background_load_palette(affine_background_gfxPal);
break;
}
}
+94 -14
View File
@@ -20,6 +20,8 @@
#include "background_shop_gfx.h"
#include "background_blind_select_gfx.h"
#include "affine_background_gfx.h"
#include "background_main_menu_gfx.h"
#include "affine_main_menu_background_gfx.h"
#include "soundbank.h"
@@ -33,7 +35,7 @@ static uint timer = 0; // This might already exist in libtonc but idk so i'm jus
static int game_speed = 1;
static int background = 0;
static enum GameState game_state = GAME_BLIND_SELECT; // The current game state, this is used to determine what the game is doing at any given time
static enum GameState game_state = GAME_MAIN_MENU; // The current game state, this is used to determine what the game is doing at any given time
static enum HandState hand_state = HAND_DRAW;
static enum PlayState play_state = PLAY_PLAYING;
static int state = 0; // General state variable, used for switch statements in each game state related function
@@ -241,6 +243,8 @@ static const Rect CASHOUT_RECT = {88, 72, UNDEFINED, UNDEF
static const Rect SHOP_REROLL_RECT = {88, 96, UNDEFINED, UNDEFINED };
//TODO: Properly define and use
#define MAIN_MENU_BUTTONS 4
#define MENU_POP_OUT_ANIM_FRAMES 20
#define SCORED_CARD_TEXT_Y 48
@@ -429,7 +433,8 @@ void change_background(int id)
}
else
{
REG_DISPCNT |= DCNT_WIN0; // Enable window 0 to make hand background transparent
toggle_windows(true, true); // Enable window 0 for the hand shadow
// Load the tiles and palette
// Background
memcpy(pal_bg_mem, background_gfxPal, 64); // This '64" isn't a specific number, I'm just using it to prevent the text colors from being overridden
@@ -484,16 +489,16 @@ void change_background(int id)
background = BG_ID_ROUND_END;
}
REG_DISPCNT &= ~DCNT_WIN0; // Disable window 0 so it doesn't make the cashout menu transparent
toggle_windows(false, true); // Disable window 0 so it doesn't make the cashout menu transparent
main_bg_se_clear_rect(ROUND_END_MENU_RECT);
tte_erase_rect_wrapper(HAND_SIZE_RECT);
}
else if (id == BG_ID_SHOP)
{
REG_DISPCNT &= ~DCNT_WIN0;
toggle_windows(false, true);
memcpy(pal_bg_mem, background_shop_gfxPal, 64);
memcpy16(pal_bg_mem, background_shop_gfxPal, 64);
GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_shop_gfxTiles);
GRIT_CPY(&se_mem[MAIN_BG_SBB], background_shop_gfxMap);
@@ -520,7 +525,7 @@ void change_background(int id)
sprite_position(blind_select_tokens[BIG_BLIND], 120, default_y);
sprite_position(blind_select_tokens[BOSS_BLIND], 160, default_y);
REG_DISPCNT &= ~DCNT_WIN0;
toggle_windows(false, true);
memcpy16(pal_bg_mem, background_blind_select_gfxPal, 64);
GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_blind_select_gfxTiles);
@@ -619,6 +624,21 @@ void change_background(int id)
}
}
}
else if (id == BG_ID_MAIN_MENU)
{
toggle_windows(false, false);
tte_erase_screen();
memcpy16(pal_bg_mem, background_main_menu_gfxPal, PAL_ROW_LEN * 9);
GRIT_CPY(&tile_mem[MAIN_BG_CBB], background_main_menu_gfxTiles);
GRIT_CPY(&se_mem[MAIN_BG_SBB], background_main_menu_gfxMap);
// Disable the button highlight colors
// Select button PID is 5 and the outline is 3
memcpy16(&pal_bg_mem[3], &pal_bg_mem[5], 1);
affine_background_change_background(AFFINE_BG_MAIN_MENU);
}
else
{
return; // Invalid background ID
@@ -1015,10 +1035,7 @@ void jokers_avialable_to_shop_init()
void game_init()
{
jokers_avialable_to_shop_init();
hands = max_hands;
discards = max_discards;
change_background(BG_ID_MAIN_MENU);
blind_select_tokens[SMALL_BLIND] = blind_token_new(SMALL_BLIND, 8, 18, MAX_SELECTION_SIZE + MAX_HAND_SIZE + 3);
blind_select_tokens[BIG_BLIND] = blind_token_new(BIG_BLIND, 8, 18, MAX_SELECTION_SIZE + MAX_HAND_SIZE + 4);
@@ -1037,8 +1054,26 @@ void game_init()
deck_push(card);
}
}
}
change_background(BG_ID_BLIND_SELECT);
void game_start()
{
affine_background_change_background(AFFINE_BG_GAME);
jokers_avialable_to_shop_init();
hands = max_hands;
discards = max_discards;
// Fill the deck with all the cards. Later on this can be replaced with a more dynamic system that allows for different decks and card types.
for (int suit = 0; suit < NUM_SUITS; suit++)
{
for (int rank = 0; rank < NUM_RANKS; rank++)
{
Card *card = card_new(suit, rank);
deck_push(card);
}
}
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
@@ -1055,6 +1090,9 @@ void game_init()
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
change_background(BG_ID_BLIND_SELECT);
game_set_state(GAME_BLIND_SELECT);
}
static void game_playing_process_hand_select_input()
@@ -2375,7 +2413,6 @@ static void game_shop_lights_anim_frame()
memcpy16(&pal_bg_mem[8], &shifted_palette[3], 1);
}
void game_shop()
{
change_background(BG_ID_SHOP);
@@ -2473,8 +2510,6 @@ void game_shop()
}
}
void game_blind_select()
{
switch (state) // I'm only using magic numbers here for the sake of simplicity since it's just sequential, but you can replace them with named constants or enums if it makes it clearer
@@ -2639,6 +2674,48 @@ void game_blind_select()
}
}
void game_main_menu()
{
change_background(BG_ID_MAIN_MENU);
if (key_hit(KEY_LEFT))
{
if (selection_x > 0)
{
selection_x--;
}
}
else if (key_hit(KEY_RIGHT))
{
// TODO: Don't allow cursor on sold items
if (selection_x < MAIN_MENU_BUTTONS)
{
selection_x++;
}
else if (selection_x < MAIN_MENU_BUTTONS)
{
selection_x++;
}
}
if (selection_x == 0) // Play button
{
// Select button PID is 5 and the outline is 3
memset16(&pal_bg_mem[3], CLR_WHITE, 1);
if (key_hit(KEY_A))
{
// Start the game
game_start();
}
}
else
{
// Select button PID is 5 and the outline is 3
memcpy16(&pal_bg_mem[3], &pal_bg_mem[5], 1);
}
}
void game_update()
{
timer++;
@@ -2656,6 +2733,9 @@ void game_update()
switch (game_state)
{
case GAME_MAIN_MENU:
game_main_menu();
break;
case GAME_PLAYING:
game_playing();
break;
+30
View File
@@ -186,4 +186,34 @@ void memcpy32_tile8_with_palette_offset(u32* dst, const u32* src, uint wcount, u
// Copying u8 data 4 times across u32 data
dst[i] = src[i] + offset;
}
}
void toggle_windows(bool win0, bool win1)
{
if (win0)
{
REG_DISPCNT |= DCNT_WIN0;
}
else
{
REG_DISPCNT &= ~DCNT_WIN0;
}
if (win1)
{
REG_DISPCNT |= DCNT_WIN1;
}
else
{
REG_DISPCNT &= ~DCNT_WIN1;
}
if (win0 || win1)
{
REG_BLDCNT = BLD_BUILD(BLD_BG1, BLD_BG2, 1);
}
else
{
REG_BLDCNT = 0;
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ void init()
// BG1 is the main background layer
REG_BG1CNT = BG_PRIO(1) | BG_CBB(MAIN_BG_CBB) | BG_SBB(MAIN_BG_SBB) | BG_8BPP;
// BG2 is the affine background layer
REG_BG2CNT = BG_PRIO(2) | BG_CBB(AFFINE_BG_CBB) | BG_SBB(AFFINE_BG_CBB) | BG_8BPP | BG_WRAP | BG_AFF_32x32;
REG_BG2CNT = BG_PRIO(2) | BG_CBB(AFFINE_BG_CBB) | BG_SBB(AFFINE_BG_CBB) | BG_8BPP | BG_WRAP | BG_AFF_16x16;
int win1_left = 72;
int win1_top = 44;