From f88161d2c38936768c6e160df655e32606c26e21 Mon Sep 17 00:00:00 2001 From: sphericalice Date: Wed, 29 Dec 2021 17:54:08 +0000 Subject: [PATCH 1/4] Add sliding puzzles --- data/event_scripts.s | 1 + data/specials.inc | 1 + graphics/sliding_puzzle/bg.pal | 19 + graphics/sliding_puzzle/bg.png | Bin 0 -> 5349 bytes graphics/sliding_puzzle/cursor.png | Bin 0 -> 195 bytes graphics/sliding_puzzle/cursor_tiles.pal | 19 + graphics/sliding_puzzle/map.bin | Bin 0 -> 2048 bytes .../puzzles/aerodactyl/tiles.png | Bin 0 -> 8481 bytes .../sliding_puzzle/puzzles/ho_oh/tiles.png | Bin 0 -> 8481 bytes .../sliding_puzzle/puzzles/kabuto/tiles.png | Bin 0 -> 8481 bytes .../sliding_puzzle/puzzles/omanyte/tiles.png | Bin 0 -> 8481 bytes include/constants/sliding_puzzles.h | 11 + ld_script.txt | 2 + spritesheet_rules.mk | 14 + src/data/sliding_puzzles.h | 473 +++++++++++++++ src/sliding_puzzle.c | 539 ++++++++++++++++++ sym_ewram.txt | 1 + 17 files changed, 1080 insertions(+) create mode 100644 graphics/sliding_puzzle/bg.pal create mode 100644 graphics/sliding_puzzle/bg.png create mode 100644 graphics/sliding_puzzle/cursor.png create mode 100644 graphics/sliding_puzzle/cursor_tiles.pal create mode 100644 graphics/sliding_puzzle/map.bin create mode 100644 graphics/sliding_puzzle/puzzles/aerodactyl/tiles.png create mode 100644 graphics/sliding_puzzle/puzzles/ho_oh/tiles.png create mode 100644 graphics/sliding_puzzle/puzzles/kabuto/tiles.png create mode 100644 graphics/sliding_puzzle/puzzles/omanyte/tiles.png create mode 100644 include/constants/sliding_puzzles.h create mode 100644 src/data/sliding_puzzles.h create mode 100644 src/sliding_puzzle.c diff --git a/data/event_scripts.s b/data/event_scripts.s index 1f3db6aa2..278300e67 100644 --- a/data/event_scripts.s +++ b/data/event_scripts.s @@ -43,6 +43,7 @@ #include "constants/roulette.h" #include "constants/script_menu.h" #include "constants/secret_bases.h" +#include "constants/sliding_puzzles.h" #include "constants/songs.h" #include "constants/sound.h" #include "constants/species.h" diff --git a/data/specials.inc b/data/specials.inc index a863b6e13..7984ffa24 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -535,3 +535,4 @@ gSpecials:: def_special RemoveRecordsWindow def_special CloseDeptStoreElevatorWindow def_special TrySetBattleTowerLinkType + def_special DoSlidingPuzzle diff --git a/graphics/sliding_puzzle/bg.pal b/graphics/sliding_puzzle/bg.pal new file mode 100644 index 000000000..3b7bbeb74 --- /dev/null +++ b/graphics/sliding_puzzle/bg.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +255 0 0 +148 107 57 +165 123 66 +115 82 41 +74 57 41 +231 189 123 +198 156 90 +181 140 74 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 +0 0 0 diff --git a/graphics/sliding_puzzle/bg.png b/graphics/sliding_puzzle/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..34c5e1d4737be1f4eaead5673dc42d4c3866ac32 GIT binary patch literal 5349 zcmbuD&x;&I6vrzlg24oe8TO#JnY{!-oShNOF*6m+1__(6J)mB)huMn=LRdzKhv-f4 zs5dVj1WyWrM{nZ4Aove>@Q={%`&B=>t7c~L!AwI{`X`FF&)z@3|F3i3e0=wZ=gVhL?mWDE=kMR1|MA_2zkdA? z{Z)DG$9KO+$E%+{_~4myw|}SKjc?z){f2Ynk50qA^UwaeaW?+>A2!}zvTV9c*3#De z-)94iA##~4O#yNhv{ zL_pVNqenniDdGdd#kTX~RR&=DkV$5os)Au(34jo23^tudNQaV42elpmP?(cTD$^eA zUXKtWfD9Hr?I7yWCsUrx1%EuB&lfBFL7a|wjPY?fKm}5&0(4LVOh6!A7Q^Tu3816p zL*)R|H%=_02L(W)k^l>yLo~`ORe**y0WkmED6iK58fc#Z=1mu>0L^O-n73Rg0n-Tu zD;OYm70oKKm9Js2%#Fl$G^5hR&|B_|k(I!;0nnr2R9)EmKV~Ux%6`Dmrf3=S;583s&?67_NE<+g*9XkX@cuh9_EMi;lL;G@cMLp3zl#6_ z@Babd`e6VI5XC0KcWJqshgzC40?ViN6^#I)K?2(L z0))fI90u6Z2Y~F;3kO}~`(f!w1jLidO5a&{A;BY=LggGNAUTKQT~XFGO+gR$EdZZC zlNSa+PM5I8fGcT=Q;=;>&a(0FY8AW^(hL{0(dr(GvniqgF%J|Vr(WxgS8|>PAU;FT z#r6eYp$39Rzf}|{0LdfH#|n@l{qt^&9U#(h8_-llLx->eL2}7dY6RfpwsOZ&GyJT>FC1m0L#Te4YBd(|Qc_E|+Fk%?$w8`$tw!&U zu=Gl4=~mk*NZw283{zEXHNt)!BdtrQrCV*MYyl8cOR%b9t5MS}g}Tzxt+l_>y>tG{ S7oUGZeW&*yg`bvBzx)qlK356= literal 0 HcmV?d00001 diff --git a/graphics/sliding_puzzle/cursor.png b/graphics/sliding_puzzle/cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..6e3ac46eb22f3b22fa1caaf156fee821ade2a8a5 GIT binary patch literal 195 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 literal 0 HcmV?d00001 diff --git a/graphics/sliding_puzzle/puzzles/kabuto/tiles.png b/graphics/sliding_puzzle/puzzles/kabuto/tiles.png new file mode 100644 index 0000000000000000000000000000000000000000..2efbe2405a80209ae1e4f6d7729ecc8e131f1322 GIT binary patch literal 8481 zcmai)&x<5U6~}8^8E|D6v$L881?j4G=CYT`t~~8&YqJ_>K$e-I3*1{#r#YH<7!TqO z3xeWl4}!Pj7+D-5ce~vV1-L5RCb|6{HOjqQ18{u2-{q>@ zAeEUa0CLhwRXeEBmFtUC0*nEvplOyUXmHyg2^g2i?a!|Opg}2>2BF5ZenbG$Kt@kF zJvn##N`NS0Z2&e~Yc=Oj&Q|d#E2vk}E&)mr0LUcu<#2O#cHQS}k=w|OU36iGim+>a zShsyN$zlR<+eJ~f-WoeP@zHuu$w=o{$1vHl=LVqnfoPK??*J$a1faxn0|fz6QvlKe zrh;IXBw)bfI{><9z<{K_*|1BSKJp1+**015_zv|GfEx4#PA!1VCYsT04!Be)EwE~@ zn@7bZyjFzvv;`RVB91O-SgVpkI1Oml6#%|TfbarHB#gXF0ogwY-P~RU$YtTJ%aP-d zMqxl0k%`o%CPQPAwHY1d0Dwdt2P{R(HlG4SnI$tIBGIJ-0c=RIh5N*U07Q2w#Yn_- zrnEfMW{nA;c+iMWt!?@OfP~8csGJD#upsdaNW%Tp0u4-85957+qst?K*>S5iF?9hR z+zdAgq-|b2G#8@XQYsS&c*SKs16uUthSN9CwjQ%{-CCcn3+_%P2!IvM09Mmi1W-Tb zEAla&?Rpb-n%V;`r~zsT0Idg!Ad3Kwp-VQf4^u!#4*00pAKpE9_Sj;SMySfz)&S%e9-1@I@_+p(rW>`u~Rtx@3+hbJrRu{l7FrUhycR-i>}Z2-t30K$zn zC;^UiV#GLP32+N&lmNy79+hB{k}}({04JP*{Xt?M9{|`Zo%L-I{3ah@Dhx3QT{G%P z)2anr9gSX!Vg%G z0Z+J~U~v&}CVv88GUTkVL;zIb9$mnKu&p+; zdV8+TeOgx#QLCQcBmf{ezafMV_B)<0;;l!WEc)g3A21M5EiT&2Ck%wL4=Ach zO*D-bByVl1;bjQGD2wBW0zj8$Q*ANb&43 zjuTiZET{ooP&&mKo2dXka9nBF^h^Q)=qTd|VW-`h$9af5-lt%-2>ImTPNEHCCCcyeVMbfypE=w)WDDpLx=nziUwL8}u(@8xuMc#3 z1|%sCc5Yg^!;=FcnZ?k)9@_R*8BgGF_(MSkznKX8`$$0Em*&X$65(X~7%ykPuqHI|?TN z09zDq4G4+a0*K3z5C|9GrcvMqv}(~F!R#Wn6(=ZS7raBQsD=cA7B@GT0hXa{s8>S} zP|AQ1;qFQSRDvS_ch6(4Mty@{IFddrIJLWKh--j_bRO{Zb@P{Fa~^N=fx+#}2ZUk) z8!yKP)LWTX0P;4SMKD`?_8@nmSkF@h9Ev(9rc_nOBLE$1Qx~|VmLrq_NxQlik!!h7 zk>^o}NQ5w&xR!q^#e0uvSksI%Vh%{Ngi2VuPbP*#jL``IV@VDQ-4hf~9Mzu!z`h6i zFq+u{(D@Oq-RpwFxi%q0%dIwX1{fiAsTtMP!zkU{63|AWA5giZI zg^6i)Rsdjp?g;J707&&20Ff@hzDb8>C?e2#CjF{YiDe78wMle|yTdG0W`j{Gxn@Gf z7HD%-6TYYo6G&53*(*~xZPM?`+TJTbgrN^@bb!V%vfcr`#XJb81Gy!+t2&-KrxxcH z$aNEiR&pfZDZVJWNFzN3By|YLXf#_Dg?4=#dVejP`oI!H1YRxg&!zi)U8b*v0O*6I zK4#Xn^>g*THh-Q?pImuXE-6duGiuIJ>!mi9iwwZS9XCFl)=j8u=Fe81>{9sHj8g8I z>$;sRsgKb)Cspix)oZy!^KX-%*8ld4um1a+A20vM(&x9I?f&}d;miL6^fbDK literal 0 HcmV?d00001 diff --git a/graphics/sliding_puzzle/puzzles/omanyte/tiles.png b/graphics/sliding_puzzle/puzzles/omanyte/tiles.png new file mode 100644 index 0000000000000000000000000000000000000000..3e3e88f95d196339e40616000ad7dfe22dea702a GIT binary patch literal 8481 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 = __; + sSlidingPuzzle->puzzleId = gSpecialVar_0x8004; + sSlidingPuzzle->solved = gSpecialVar_0x8005; + LoadCompressedSpriteSheet(&sSpriteSheet_Tiles[sSlidingPuzzle->puzzleId]); + LoadSpritePalettes(sSpritePalettes_CursorTiles); + if (sSlidingPuzzle->solved) + DrawInstructionsBar(INSTRUCTION_CONTINUE); + else + DrawInstructionsBar(INSTRUCTION_NO_SELECTION); + CreateCursorSprite(); + CreateTileSprites(); + BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK); + EnableInterrupts(INTR_FLAG_VBLANK); + SetVBlankCallback(VBlankCB_SlidingPuzzle); + SetMainCallback2(CB2_SlidingPuzzle); + CreateTask(Task_SlidingPuzzle_WaitFadeIn, 0); +} + +static void CB2_SlidingPuzzle(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + DoScheduledBgTilemapCopiesToVram(); + UpdatePaletteFade(); +} + +static void VBlankCB_SlidingPuzzle(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void Task_SlidingPuzzle_WaitFadeIn(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (!sSlidingPuzzle->solved) + gTasks[taskId].func = Task_SlidingPuzzle_HandleInput; + else + gTasks[taskId].func = Task_SlidingPuzzle_Solved; + } +} + +static void Task_SlidingPuzzle_HandleInput(u8 taskId) +{ + // Prevent input if the puzzle has been solved + if (sSlidingPuzzle->solved) + { + gTasks[taskId].func = Task_SlidingPuzzle_Glow; + return; + } + + // Prevent input while the tile is rotating + if (sSlidingPuzzle->heldTile != __) + { + struct Sprite *sprite = &gSprites[sSlidingPuzzle->heldTile]; + + if (sprite->sAnimating && !sprite->affineAnimEnded) + return; + } + + if (JOY_NEW(B_BUTTON)) + ExitSlidingPuzzle(taskId); + else if (JOY_NEW(DPAD_LEFT)) + MoveCursor(-1, 0); + else if (JOY_NEW(DPAD_RIGHT)) + MoveCursor( 1, 0); + else if (JOY_NEW(DPAD_UP)) + MoveCursor( 0, -1); + else if (JOY_NEW(DPAD_DOWN)) + MoveCursor( 0, 1); + + if (sSlidingPuzzle->heldTile == __) + { + // Not holding a tile + if (CursorIsOnTile() && !CursorIsOnImmovableTile()) + { + DrawInstructionsBar(INSTRUCTION_PICK_UP); + if (JOY_NEW(A_BUTTON)) + SelectTile(); + } + else + { + DrawInstructionsBar(INSTRUCTION_NO_SELECTION); + } + } + else + { + // Currently holding a tile + if (CursorIsOnTile() && !CursorIsOnImmovableTile()) + { + DrawInstructionsBar(INSTRUCTION_SWAP); + if (JOY_NEW(A_BUTTON)) + SelectTile(); + } + else if (CursorIsOnImmovableTile()) + { + DrawInstructionsBar(INSTRUCTION_ROTATE); + } + else + { + DrawInstructionsBar(INSTRUCTION_PLACE); + if (JOY_NEW(A_BUTTON)) + PlaceTile(); + } + + if (JOY_NEW(L_BUTTON)) + RotateTile(ROTATE_ANTICLOCKWISE); + else if (JOY_NEW(R_BUTTON)) + RotateTile(ROTATE_CLOCKWISE); + } +} + +#define tState data[0] +#define tTimer data[1] +#define tGlow data[2] + +static void Task_SlidingPuzzle_Glow(u8 taskId) +{ + u16 color; + s16* data = gTasks[taskId].data; + switch (tState) + { + case 0: + DrawInstructionsBar(INSTRUCTION_CONTINUE); + tState++; + break; + case 1: + DestroySprite(&gSprites[sSlidingPuzzle->cursorSpriteId]); + PlayFanfare(MUS_LEVEL_UP); + tGlow = 22; + tState++; + break; + case 2: + tTimer++; + if ((tTimer % 4) == 0) + { + tGlow++; + if (tGlow == 31) + tState++; + color = RGB(tGlow, tGlow, tGlow); + LoadPalette(&color, 0x103, sizeof(color)); + } + break; + case 3: + tTimer++; + if ((tTimer % 4) == 0) + { + tGlow--; + if (tGlow > 22) + { + color = RGB(tGlow, tGlow, tGlow); + } + else + { + color = RGB(28, 22, 13); + tState++; + } + LoadPalette(&color, 0x103, sizeof(color)); + } + break; + default: + if (IsFanfareTaskInactive()) + { + tState = 0; + gTasks[taskId].func = Task_SlidingPuzzle_Solved; + } + break; + } +} + +static void Task_SlidingPuzzle_Solved(u8 taskId) +{ + u16 color; + s16* data = gTasks[taskId].data; + switch (tState) + { + case 0: + if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON)) + tState++; + break; + default: + ExitSlidingPuzzle(taskId); + break; + } +} + +#undef tState +#undef tTimer +#undef tGlow + +static void Task_SlidingPuzzle_Exit(u8 taskId) +{ + if (!gPaletteFade.active) + { + gSpecialVar_Result = sSlidingPuzzle->solved; + Free(sSlidingPuzzle); + FreeAllWindowBuffers(); + SetMainCallback2(gMain.savedCallback); + } +} + +static void DrawInstructionsBar(u8 stringId) +{ + const u8 color[3] = { TEXT_DYNAMIC_COLOR_6, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY }; + + FillWindowPixelBuffer(0, PIXEL_FILL(15)); + AddTextPrinterParameterized3(0, FONT_SMALL, 2, 1, color, 0, sInstructions[stringId]); + PutWindowTilemap(0); + CopyWindowToVram(0, COPYWIN_FULL); + ScheduleBgCopyTilemapToVram(0); +} + +static void CreateCursorSprite(void) +{ + u8 spriteId = SPRITE_NONE; + + if (!sSlidingPuzzle->solved) + { + spriteId = CreateSprite(&sSpriteTemplate_Cursor, + sColumnXCoords[0], + sRowYCoords[0], + 1); + gSprites[spriteId].sTimer = 0; + gSprites[spriteId].sAnimating = TRUE; + gSprites[spriteId].sRow = 0; + gSprites[spriteId].sCol = 0; + } + + sSlidingPuzzle->cursorSpriteId = spriteId; +} + +static void CreateTileSprites(void) +{ + u8 row, col, puzzleId, tile; + for (row = 0; row < NUM_ROWS; ++row) + { + for (col = 0; col < NUM_COLS; ++col) + { + if (sSlidingPuzzle->solved) + puzzleId = PUZZLE_SOLVED; + else + puzzleId = sSlidingPuzzle->puzzleId; + + tile = sPuzzleLayouts[puzzleId][row][col]; + if (tile != __) + { + u8 spriteId = CreateSprite(&sSpriteTemplate_Tiles, + sColumnXCoords[col], + sRowYCoords[row], + 2); + struct Sprite *sprite = &gSprites[spriteId]; + sprite->sAnimating = FALSE; + sprite->sRow = row; + sprite->sCol = col; + sprite->sTileId = tile; + sprite->sOrientation = sTileOrientations[puzzleId][row][col]; + if (sprite->sOrientation >= ORIENTATION_MAX) + sprite->sOrientation = ORIENTATION_0; + StartSpriteAnim(sprite, tile - 1); + StartSpriteAffineAnim(sprite, sprite->sOrientation); + tile = spriteId; + } + + sSlidingPuzzle->tiles[row][col] = tile; + } + } +} + +static void MoveCursor(s8 deltaX, s8 deltaY) +{ + MoveCursorSprite(deltaX, deltaY, sSlidingPuzzle->cursorSpriteId); + + if (sSlidingPuzzle->heldTile != __) + { + MoveCursorSprite(deltaX, deltaY, sSlidingPuzzle->heldTile); + PlaySE(SE_BALL_TRAY_ENTER); + } +} + +static void MoveCursorSprite(s8 deltaX, s8 deltaY, u8 spriteId) +{ + struct Sprite *sprite = &gSprites[spriteId]; + s8 row = sprite->sRow + deltaY; + s8 col = sprite->sCol + deltaX; + + if (row < FIRST_ROW) + row = FINAL_ROW; + else if (row > FINAL_ROW) + row = FIRST_ROW; + + if (col < FIRST_COL) + col = FINAL_COL; + else if (col > FINAL_COL) + col = FIRST_COL; + + sprite->sCol = col; + sprite->sRow = row; + sprite->x = sColumnXCoords[sprite->sCol]; + sprite->y = sRowYCoords[sprite->sRow]; + + sprite->invisible = FALSE; + sprite->sTimer = 0; +} + +static bool32 CursorIsOnTile(void) +{ + struct Sprite *cursor = &gSprites[sSlidingPuzzle->cursorSpriteId]; + + if (sSlidingPuzzle->tiles[cursor->sRow][cursor->sCol] != __) + return TRUE; + + return FALSE; +} + +static bool32 CursorIsOnImmovableTile(void) +{ + struct Sprite *cursor = &gSprites[sSlidingPuzzle->cursorSpriteId]; + + if (sTileOrientations[sSlidingPuzzle->puzzleId][cursor->sRow][cursor->sCol] == IMMOVABLE_TILE) + return TRUE; + + return FALSE; +} + +static void SelectTile(void) +{ + struct Sprite *cursor = &gSprites[sSlidingPuzzle->cursorSpriteId]; + + u8 tile = sSlidingPuzzle->heldTile; + if (tile != __) + gSprites[tile].subpriority = 2; + + sSlidingPuzzle->heldTile = sSlidingPuzzle->tiles[cursor->sRow][cursor->sCol]; + gSprites[sSlidingPuzzle->heldTile].subpriority = 0; + + sSlidingPuzzle->tiles[cursor->sRow][cursor->sCol] = tile; + + cursor->sAnimating = FALSE; + PlaySE(SE_SELECT); + CheckForSolution(); +} + +static void PlaceTile(void) +{ + struct Sprite *cursor = &gSprites[sSlidingPuzzle->cursorSpriteId]; + + sSlidingPuzzle->tiles[cursor->sRow][cursor->sCol] = sSlidingPuzzle->heldTile; + gSprites[sSlidingPuzzle->heldTile].subpriority = 2; + + sSlidingPuzzle->heldTile = __; + + cursor->sAnimating = TRUE; + PlaySE(SE_SELECT); + CheckForSolution(); +} + +static void RotateTile(u8 rotDir) +{ + struct Sprite *sprite = &gSprites[sSlidingPuzzle->heldTile]; + u8 affineAnimation; + + if (rotDir == ROTATE_ANTICLOCKWISE) + { + affineAnimation = sprite->sOrientation + 4; + if (sprite->sOrientation) + sprite->sOrientation--; + else + sprite->sOrientation = ORIENTATION_270; + } + else if (rotDir == ROTATE_CLOCKWISE) + { + affineAnimation = sprite->sOrientation + 8; + sprite->sOrientation++; + sprite->sOrientation = sprite->sOrientation % ORIENTATION_MAX; + } + + StartSpriteAffineAnim(sprite, affineAnimation); + sprite->sAnimating = TRUE; +} + +static void CheckForSolution(void) +{ + u8 row, col, tile; + for (row = 0; row < NUM_ROWS; row++) + { + for (col = 0; col < NUM_COLS; col++) + { + struct Sprite *tile = &gSprites[sSlidingPuzzle->tiles[row][col]]; + u8 tileId = sPuzzleLayouts[PUZZLE_SOLVED][row][col]; + + if (tile->sTileId != tileId || tile->sOrientation != ORIENTATION_0) + { + sSlidingPuzzle->solved = FALSE; + return; + } + } + } + + sSlidingPuzzle->solved = TRUE; +} + +static void ExitSlidingPuzzle(u8 taskId) +{ + BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 16, RGB_BLACK); + gTasks[taskId].func = Task_SlidingPuzzle_Exit; +} + +static void SpriteCB_Cursor(struct Sprite *sprite) +{ + if (++sprite->sTimer % 16 == 0) + { + sprite->sTimer = 0; + if (sprite->sAnimating) + sprite->invisible ^= 1; + else + sprite->invisible = FALSE; + } +} + +#undef __ +#undef sTimer +#undef sAnimating +#undef sRow +#undef sCol +#undef sTileId +#undef sOrientation diff --git a/sym_ewram.txt b/sym_ewram.txt index 414b7a3b2..776b41e2d 100644 --- a/sym_ewram.txt +++ b/sym_ewram.txt @@ -148,3 +148,4 @@ .include "src/faraway_island.o" .include "src/trainer_hill.o" .include "src/rayquaza_scene.o" + .include "src/sliding_puzzle.o" From 749042efe4f2043d376b7f23a7e6573a7378430c Mon Sep 17 00:00:00 2001 From: sphericalice Date: Thu, 30 Dec 2021 10:39:02 +0000 Subject: [PATCH 2/4] Simplify Task_SlidingPuzzle_Solved --- src/sliding_puzzle.c | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/sliding_puzzle.c b/src/sliding_puzzle.c index 160590b82..5bf38392b 100644 --- a/src/sliding_puzzle.c +++ b/src/sliding_puzzle.c @@ -273,26 +273,7 @@ static void Task_SlidingPuzzle_Glow(u8 taskId) break; default: if (IsFanfareTaskInactive()) - { - tState = 0; gTasks[taskId].func = Task_SlidingPuzzle_Solved; - } - break; - } -} - -static void Task_SlidingPuzzle_Solved(u8 taskId) -{ - u16 color; - s16* data = gTasks[taskId].data; - switch (tState) - { - case 0: - if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON)) - tState++; - break; - default: - ExitSlidingPuzzle(taskId); break; } } @@ -301,6 +282,12 @@ static void Task_SlidingPuzzle_Solved(u8 taskId) #undef tTimer #undef tGlow +static void Task_SlidingPuzzle_Solved(u8 taskId) +{ + if (JOY_NEW(A_BUTTON) || JOY_NEW(B_BUTTON)) + ExitSlidingPuzzle(taskId); +} + static void Task_SlidingPuzzle_Exit(u8 taskId) { if (!gPaletteFade.active) From abbd9dae96e338a7e570df53eb7d7bc5f368830b Mon Sep 17 00:00:00 2001 From: sphericalice Date: Fri, 15 Jul 2022 16:09:32 +0100 Subject: [PATCH 3/4] Bugfix and refactor sliding_puzzle.c --- include/constants/sliding_puzzles.h | 15 +- include/sliding_puzzle.h | 41 ++ src/data/sliding_puzzles.h | 462 ++--------------------- src/sliding_puzzle.c | 561 +++++++++++++++++++++++----- 4 files changed, 561 insertions(+), 518 deletions(-) create mode 100644 include/sliding_puzzle.h diff --git a/include/constants/sliding_puzzles.h b/include/constants/sliding_puzzles.h index b4ca16188..2b0dd18a2 100644 --- a/include/constants/sliding_puzzles.h +++ b/include/constants/sliding_puzzles.h @@ -1,11 +1,12 @@ #ifndef GUARD_SLIDING_PUZZLES_CONSTANTS_H #define GUARD_SLIDING_PUZZLES_CONSTANTS_H -#define PUZZLE_KABUTO 0 -#define PUZZLE_OMANYTE 1 -#define PUZZLE_AERODACTYL 2 -#define PUZZLE_HO_OH 3 -#define PUZZLE_SOLVED 4 -#define PUZZLE_COUNT 5 +#define SLIDING_PUZZLE_KABUTO 0 +#define SLIDING_PUZZLE_OMANYTE 1 +#define SLIDING_PUZZLE_AERODACTYL 2 +#define SLIDING_PUZZLE_HO_OH 3 +#define SLIDING_PUZZLE_SOLVED 4 -#endif //GUARD_SLIDING_PUZZLES_CONSTANTS_H +#define SLIDING_PUZZLE_COUNT 5 + +#endif // GUARD_SLIDING_PUZZLES_CONSTANTS_H diff --git a/include/sliding_puzzle.h b/include/sliding_puzzle.h new file mode 100644 index 000000000..8113e3cf0 --- /dev/null +++ b/include/sliding_puzzle.h @@ -0,0 +1,41 @@ +#ifndef GUARD_SLIDING_PUZZLE_H +#define GUARD_SLIDING_PUZZLE_H + +#include "constants/sliding_puzzles.h" + +enum +{ + ROTATE_NONE, + ROTATE_ANTICLOCKWISE, + ROTATE_CLOCKWISE, +}; + +enum +{ + ORIENTATION_0, + ORIENTATION_90, + ORIENTATION_180, + ORIENTATION_270, + ORIENTATION_MAX, +}; + +#define IMMOVABLE_TILE ORIENTATION_MAX + +#define NUM_SLIDING_PUZZLE_COLS 6 +#define NUM_SLIDING_PUZZLE_ROWS 4 + +#define FIRST_SLIDING_PUZZLE_COL 0 +#define FINAL_SLIDING_PUZZLE_COL (NUM_SLIDING_PUZZLE_COLS - 1) +#define FIRST_SLIDING_PUZZLE_ROW 0 +#define FINAL_SLIDING_PUZZLE_ROW (NUM_SLIDING_PUZZLE_ROWS - 1) + +struct SlidingPuzzle +{ + u8 tiles[NUM_SLIDING_PUZZLE_ROWS][NUM_SLIDING_PUZZLE_COLS]; + u8 puzzleId; + u8 cursorSpriteId; + u8 heldTile; + bool8 solved; +}; + +#endif // GUARD_SLIDING_PUZZLE_H diff --git a/src/data/sliding_puzzles.h b/src/data/sliding_puzzles.h index c2f69b62d..68f79304c 100644 --- a/src/data/sliding_puzzles.h +++ b/src/data/sliding_puzzles.h @@ -1,407 +1,48 @@ -static const u32 sSlidingPuzzle_Gfx[] = INCBIN_U32("graphics/sliding_puzzle/bg.4bpp.lz"); -static const u32 sSlidingPuzzle_Tilemap[] = INCBIN_U32("graphics/sliding_puzzle/map.bin.lz"); -static const u16 sSlidingPuzzle_Pal[] = INCBIN_U16("graphics/sliding_puzzle/bg.gbapal"); - -static const u32 sCursor_Gfx[] = INCBIN_U32("graphics/sliding_puzzle/cursor.4bpp.lz"); -static const u16 sCursorTiles_Pal[] = INCBIN_U16("graphics/sliding_puzzle/cursor_tiles.gbapal"); - static const u32 sKabutoPuzzle_Gfx[] = INCBIN_U32("graphics/sliding_puzzle/puzzles/kabuto/tiles.4bpp.lz"); static const u32 sOmanytePuzzle_Gfx[] = INCBIN_U32("graphics/sliding_puzzle/puzzles/omanyte/tiles.4bpp.lz"); static const u32 sAerodactylPuzzle_Gfx[] = INCBIN_U32("graphics/sliding_puzzle/puzzles/aerodactyl/tiles.4bpp.lz"); static const u32 sHoOhPuzzle_Gfx[] = INCBIN_U32("graphics/sliding_puzzle/puzzles/ho_oh/tiles.4bpp.lz"); -#define TAG_CURSOR 244 -#define GFXTAG_TILES 245 - -static const struct SpritePalette sSpritePalettes_CursorTiles[] = +static const struct CompressedSpriteSheet sSpriteSheet_Tiles[SLIDING_PUZZLE_COUNT] = { - { - .data = sCursorTiles_Pal, - .tag = TAG_CURSOR - }, - {}, + [SLIDING_PUZZLE_KABUTO] = {sKabutoPuzzle_Gfx, 0x400 * 16, GFXTAG_TILES}, + [SLIDING_PUZZLE_OMANYTE] = {sOmanytePuzzle_Gfx, 0x400 * 16, GFXTAG_TILES}, + [SLIDING_PUZZLE_AERODACTYL] = {sAerodactylPuzzle_Gfx, 0x400 * 16, GFXTAG_TILES}, + [SLIDING_PUZZLE_HO_OH] = {sHoOhPuzzle_Gfx, 0x400 * 16, GFXTAG_TILES}, + [SLIDING_PUZZLE_SOLVED] = {}, }; -static const struct CompressedSpriteSheet sSpriteSheet_Cursor = +static const u8 sPuzzleLayouts[SLIDING_PUZZLE_COUNT][NUM_SLIDING_PUZZLE_ROWS][NUM_SLIDING_PUZZLE_COLS] = { - .data = sCursor_Gfx, - .size = 0x400, - .tag = TAG_CURSOR, -}; - -static const struct OamData sOamData_Cursor = -{ - .y = 0, - .affineMode = ST_OAM_AFFINE_OFF, - .objMode = ST_OAM_OBJ_NORMAL, - .mosaic = 0, - .bpp = ST_OAM_4BPP, - .shape = SPRITE_SHAPE(32x32), - .x = 0, - .matrixNum = 0, - .size = SPRITE_SIZE(32x32), - .tileNum = 0, - .priority = 2, - .paletteNum = 0, - .affineParam = 0, -}; - -static const struct SpriteTemplate sSpriteTemplate_Cursor = -{ - .tileTag = TAG_CURSOR, - .paletteTag = TAG_CURSOR, - .oam = &sOamData_Cursor, - .anims = gDummySpriteAnimTable, - .images = NULL, - .affineAnims = gDummySpriteAffineAnimTable, - .callback = SpriteCB_Cursor, -}; - -static const struct CompressedSpriteSheet sSpriteSheet_Tiles[PUZZLE_COUNT] = -{ - [PUZZLE_KABUTO] = {sKabutoPuzzle_Gfx, 0x400 * 16, GFXTAG_TILES}, - [PUZZLE_OMANYTE] = {sOmanytePuzzle_Gfx, 0x400 * 16, GFXTAG_TILES}, - [PUZZLE_AERODACTYL] = {sAerodactylPuzzle_Gfx, 0x400 * 16, GFXTAG_TILES}, - [PUZZLE_HO_OH] = {sHoOhPuzzle_Gfx, 0x400 * 16, GFXTAG_TILES}, - [PUZZLE_SOLVED] = {}, -}; - -static const struct OamData sOamData_Tiles = -{ - .y = 0, - .affineMode = ST_OAM_AFFINE_NORMAL, - .objMode = ST_OAM_OBJ_NORMAL, - .mosaic = 0, - .bpp = ST_OAM_4BPP, - .shape = SPRITE_SHAPE(32x32), - .x = 0, - .matrixNum = 0, - .size = SPRITE_SIZE(32x32), - .tileNum = 0, - .priority = 2, - .paletteNum = 0, - .affineParam = 0, -}; - -static const union AnimCmd sAnim_Tile0[] = -{ - ANIMCMD_FRAME(0 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile1[] = -{ - ANIMCMD_FRAME(1 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile2[] = -{ - ANIMCMD_FRAME(2 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile3[] = -{ - ANIMCMD_FRAME(3 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile4[] = -{ - ANIMCMD_FRAME(4 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile5[] = -{ - ANIMCMD_FRAME(5 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile6[] = -{ - ANIMCMD_FRAME(6 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile7[] = -{ - ANIMCMD_FRAME(7 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile8[] = -{ - ANIMCMD_FRAME(8 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile9[] = -{ - ANIMCMD_FRAME(9 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile10[] = -{ - ANIMCMD_FRAME(10 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile11[] = -{ - ANIMCMD_FRAME(11 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile12[] = -{ - ANIMCMD_FRAME(12 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile13[] = -{ - ANIMCMD_FRAME(13 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile14[] = -{ - ANIMCMD_FRAME(14 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd sAnim_Tile15[] = -{ - ANIMCMD_FRAME(15 * 16, 30), - ANIMCMD_END, -}; - -static const union AnimCmd *const sAnims_Tiles[] = -{ - sAnim_Tile0, - sAnim_Tile1, - sAnim_Tile2, - sAnim_Tile3, - sAnim_Tile4, - sAnim_Tile5, - sAnim_Tile6, - sAnim_Tile7, - sAnim_Tile8, - sAnim_Tile9, - sAnim_Tile10, - sAnim_Tile11, - sAnim_Tile12, - sAnim_Tile13, - sAnim_Tile14, - sAnim_Tile15, -}; - -enum -{ - ROTATE_NONE, - ROTATE_ANTICLOCKWISE, - ROTATE_CLOCKWISE, -}; - -enum -{ - ORIENTATION_0, - ORIENTATION_90, - ORIENTATION_180, - ORIENTATION_270, - ORIENTATION_MAX, -}; - -#define IMMOVABLE_TILE ORIENTATION_MAX - -static const union AffineAnimCmd sSpriteAffineAnim_Rotated0[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd sSpriteAffineAnim_Rotated90[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd sSpriteAffineAnim_Rotated180[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd sSpriteAffineAnim_Rotated270[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), - AFFINEANIMCMD_JUMP(0), -}; - -static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0[] = -{ - AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), - AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), - AFFINEANIMCMD_END, -}; - -static const union AffineAnimCmd *const sSpriteAffineAnimTable_RotateTile[] = -{ - sSpriteAffineAnim_Rotated0, - sSpriteAffineAnim_Rotated90, - sSpriteAffineAnim_Rotated180, - sSpriteAffineAnim_Rotated270, - sSpriteAffineAnim_RotatingAnticlockwise360to270, - sSpriteAffineAnim_RotatingAnticlockwise90to0, - sSpriteAffineAnim_RotatingAnticlockwise180to90, - sSpriteAffineAnim_RotatingAnticlockwise270to180, - sSpriteAffineAnim_RotatingClockwise0to90, - sSpriteAffineAnim_RotatingClockwise90to180, - sSpriteAffineAnim_RotatingClockwise180to270, - sSpriteAffineAnim_RotatingClockwise270to360, -}; - -static const struct SpriteTemplate sSpriteTemplate_Tiles = -{ - .tileTag = GFXTAG_TILES, - .paletteTag = TAG_CURSOR, - .oam = &sOamData_Tiles, - .anims = sAnims_Tiles, - .images = NULL, - .affineAnims = sSpriteAffineAnimTable_RotateTile, - .callback = SpriteCallbackDummy, -}; - -enum -{ - INSTRUCTION_NO_SELECTION, - INSTRUCTION_PICK_UP, - INSTRUCTION_PLACE, - INSTRUCTION_SWAP, - INSTRUCTION_ROTATE, - INSTRUCTION_CONTINUE, -}; - -static const u8 sText_MoveQuit[] = _("{DPAD_NONE} Move {B_BUTTON} Quit"); -static const u8 sText_MovePickUpQuit[] = _("{DPAD_NONE} Move {A_BUTTON} Pick Up {B_BUTTON} Quit"); -static const u8 sText_MovePlaceRotateQuit[] = _("{DPAD_NONE} Move {A_BUTTON} Place {L_BUTTON}{R_BUTTON} Rotate {B_BUTTON} Quit"); -static const u8 sText_MoveSwapRotateQuit[] = _("{DPAD_NONE} Move {A_BUTTON} Swap {L_BUTTON}{R_BUTTON} Rotate {B_BUTTON} Quit"); -static const u8 sText_MoveRotateQuit[] = _("{DPAD_NONE} Move {L_BUTTON}{R_BUTTON} Rotate {B_BUTTON} Quit"); -static const u8 sText_Continue[] = _("{A_BUTTON}{B_BUTTON} Continue"); - -static const u8 *const sInstructions[] = -{ - [INSTRUCTION_NO_SELECTION] = sText_MoveQuit, - [INSTRUCTION_PICK_UP] = sText_MovePickUpQuit, - [INSTRUCTION_PLACE] = sText_MovePlaceRotateQuit, - [INSTRUCTION_SWAP] = sText_MoveSwapRotateQuit, - [INSTRUCTION_ROTATE] = sText_MoveRotateQuit, - [INSTRUCTION_CONTINUE] = sText_Continue, -}; - -static const u16 sColumnXCoords[] = -{ - 32, 72, 104, 136, 168, 208, -}; -static const u16 sRowYCoords[] = -{ - 40, - 72, - 104, - 136, -}; - -#define NUM_COLS (ARRAY_COUNT(sColumnXCoords)) -#define NUM_ROWS (ARRAY_COUNT(sRowYCoords)) - -#define FIRST_COL 0 -#define FINAL_COL (NUM_COLS - 1) -#define FIRST_ROW 0 -#define FINAL_ROW (NUM_ROWS - 1) - -static const u8 sPuzzleLayouts[PUZZLE_COUNT][NUM_ROWS][NUM_COLS] = -{ - [PUZZLE_KABUTO] = + [SLIDING_PUZZLE_KABUTO] = { { 6, 1,__, 3, 4,__}, {__, 5,__, 7, 8,11}, {__,__,10,__,12,__}, { 2,13,14,15,16, 9}, }, - [PUZZLE_OMANYTE] = + [SLIDING_PUZZLE_OMANYTE] = { { 9,__, 2, 3, 4,11}, {__, 5, 6,12,__,14}, { 8,__,__,__,__,13}, { 1, 7,__,15,16,10}, }, - [PUZZLE_AERODACTYL] = + [SLIDING_PUZZLE_AERODACTYL] = { {14,__,__, 3, 4,__}, {__,__,10, 7, 8,16}, { 2, 9,__,11,12, 5}, { 1,13,__,15,__, 6}, }, - [PUZZLE_HO_OH] = + [SLIDING_PUZZLE_HO_OH] = { {15,__,14, 3, 4, 1}, {13,__, 6, 7,__,10}, { 2,__,__,__,12, 9}, { 8,__, 5,__,16,11}, }, - [PUZZLE_SOLVED] = + [SLIDING_PUZZLE_SOLVED] = { {__, 1, 2, 3, 4,__}, {__, 5, 6, 7, 8,__}, @@ -410,64 +51,41 @@ static const u8 sPuzzleLayouts[PUZZLE_COUNT][NUM_ROWS][NUM_COLS] = }, }; -static const u8 sTileOrientations[PUZZLE_COUNT][NUM_ROWS][NUM_COLS] = +static const u8 sTileOrientations[SLIDING_PUZZLE_COUNT][NUM_SLIDING_PUZZLE_ROWS][NUM_SLIDING_PUZZLE_COLS] = { - [PUZZLE_KABUTO] = + [SLIDING_PUZZLE_KABUTO] = { - {ORIENTATION_90 , IMMOVABLE_TILE, ORIENTATION_0 , IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_0 }, - {ORIENTATION_0 , IMMOVABLE_TILE, ORIENTATION_0 , IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_180}, - {ORIENTATION_0 , ORIENTATION_0 , IMMOVABLE_TILE, ORIENTATION_0 , IMMOVABLE_TILE, ORIENTATION_0 }, - {ORIENTATION_270, IMMOVABLE_TILE, IMMOVABLE_TILE, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_90 }, + {ORIENTATION_90, IMMOVABLE_TILE, ORIENTATION_0, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_0}, + {ORIENTATION_0, IMMOVABLE_TILE, ORIENTATION_0, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_180}, + {ORIENTATION_0, ORIENTATION_0, IMMOVABLE_TILE, ORIENTATION_0, IMMOVABLE_TILE, ORIENTATION_0}, + {ORIENTATION_270, IMMOVABLE_TILE, IMMOVABLE_TILE, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_90}, }, - [PUZZLE_OMANYTE] = + [SLIDING_PUZZLE_OMANYTE] = { - {ORIENTATION_0 , ORIENTATION_0 , IMMOVABLE_TILE, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_90 }, - {ORIENTATION_0 , IMMOVABLE_TILE , IMMOVABLE_TILE, ORIENTATION_90, ORIENTATION_0 , ORIENTATION_180}, - {ORIENTATION_0 , ORIENTATION_0 , ORIENTATION_0 , ORIENTATION_0 , ORIENTATION_0 , ORIENTATION_270}, - {ORIENTATION_270, ORIENTATION_180, ORIENTATION_0 , IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_0 }, + {ORIENTATION_0, ORIENTATION_0, IMMOVABLE_TILE, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_90}, + {ORIENTATION_0, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_90, ORIENTATION_0, ORIENTATION_180}, + {ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_270}, + {ORIENTATION_270, ORIENTATION_180, ORIENTATION_0, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_0}, }, - [PUZZLE_AERODACTYL] = + [SLIDING_PUZZLE_AERODACTYL] = { - {ORIENTATION_180, ORIENTATION_0 , ORIENTATION_0 , IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_0 }, - {ORIENTATION_0 , ORIENTATION_0 , ORIENTATION_270, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_270}, - {ORIENTATION_270, IMMOVABLE_TILE, ORIENTATION_0 , IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_90 }, - {ORIENTATION_180, IMMOVABLE_TILE, ORIENTATION_0 , IMMOVABLE_TILE, ORIENTATION_0 , ORIENTATION_180}, + {ORIENTATION_180, ORIENTATION_0, ORIENTATION_0, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_0}, + {ORIENTATION_0, ORIENTATION_0, ORIENTATION_270, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_270}, + {ORIENTATION_270, IMMOVABLE_TILE, ORIENTATION_0, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_90}, + {ORIENTATION_180, IMMOVABLE_TILE, ORIENTATION_0, IMMOVABLE_TILE, ORIENTATION_0, ORIENTATION_180}, }, - [PUZZLE_HO_OH] = + [SLIDING_PUZZLE_HO_OH] = { - {ORIENTATION_180, ORIENTATION_180, ORIENTATION_90 , IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_270}, - {ORIENTATION_180, ORIENTATION_0 , IMMOVABLE_TILE , IMMOVABLE_TILE, ORIENTATION_0 , ORIENTATION_270}, - {ORIENTATION_270, ORIENTATION_0 , ORIENTATION_0 , ORIENTATION_0 , IMMOVABLE_TILE, ORIENTATION_0 }, - {ORIENTATION_90 , ORIENTATION_0 , ORIENTATION_180, ORIENTATION_0 , IMMOVABLE_TILE, ORIENTATION_270}, - }, -}; - -static const struct WindowTemplate sWindowTemplates[] = -{ - { - .bg = 0, - .tilemapLeft = 0, - .tilemapTop = 0, - .width = 30, - .height = 2, - .paletteNum = 13, - .baseBlock = 1, - }, - DUMMY_WIN_TEMPLATE, -}; - -static const struct BgTemplate sBgTemplates[] = -{ - { - .bg = 0, - .charBaseIndex = 1, - .mapBaseIndex = 29, - .priority = 3, - }, - { - .bg = 1, - .charBaseIndex = 0, - .mapBaseIndex = 7, - .priority = 3, + {ORIENTATION_180, ORIENTATION_180, ORIENTATION_90, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_270}, + {ORIENTATION_180, ORIENTATION_0, IMMOVABLE_TILE, IMMOVABLE_TILE, ORIENTATION_0, ORIENTATION_270}, + {ORIENTATION_270, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, IMMOVABLE_TILE, ORIENTATION_0}, + {ORIENTATION_90, ORIENTATION_0, ORIENTATION_180, ORIENTATION_0, IMMOVABLE_TILE, ORIENTATION_270}, + }, + [SLIDING_PUZZLE_SOLVED] = + { + {ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0}, + {ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0}, + {ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0}, + {ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0, ORIENTATION_0}, }, }; diff --git a/src/sliding_puzzle.c b/src/sliding_puzzle.c index 5bf38392b..02d2bf1d6 100644 --- a/src/sliding_puzzle.c +++ b/src/sliding_puzzle.c @@ -1,4 +1,5 @@ #include "global.h" +#include "sliding_puzzle.h" #include "bg.h" #include "decompress.h" #include "event_data.h" @@ -18,7 +19,6 @@ #include "window.h" #include "constants/rgb.h" #include "constants/songs.h" -#include "constants/sliding_puzzles.h" static void CB2_LoadSlidingPuzzle(void); static void CB2_SlidingPuzzle(void); @@ -42,26 +42,382 @@ static void CheckForSolution(void); static void ExitSlidingPuzzle(u8); static void SpriteCB_Cursor(struct Sprite *); +static EWRAM_DATA struct SlidingPuzzle *sSlidingPuzzle = NULL; + +static const u32 sSlidingPuzzle_Gfx[] = INCBIN_U32("graphics/sliding_puzzle/bg.4bpp.lz"); +static const u32 sSlidingPuzzle_Tilemap[] = INCBIN_U32("graphics/sliding_puzzle/map.bin.lz"); +static const u16 sSlidingPuzzle_Pal[] = INCBIN_U16("graphics/sliding_puzzle/bg.gbapal"); + +enum +{ + WIN_INSTRUCTIONS_BAR, + WIN_DUMMY, +}; + +static const struct WindowTemplate sWindowTemplates[] = +{ + [WIN_INSTRUCTIONS_BAR] = + { + .bg = 0, + .tilemapLeft = 0, + .tilemapTop = 0, + .width = 30, + .height = 2, + .paletteNum = 13, + .baseBlock = 1, + }, + [WIN_DUMMY] = DUMMY_WIN_TEMPLATE, +}; + +static const struct BgTemplate sBgTemplates[] = +{ + { + .bg = 0, + .charBaseIndex = 1, + .mapBaseIndex = 29, + .priority = 3, + }, + { + .bg = 1, + .charBaseIndex = 0, + .mapBaseIndex = 7, + .priority = 3, + }, +}; + +static const u16 sColumnXCoords[NUM_SLIDING_PUZZLE_COLS] = +{ + 32, 72, 104, 136, 168, 208, +}; + +static const u16 sRowYCoords[NUM_SLIDING_PUZZLE_ROWS] = +{ + 40, + 72, + 104, + 136, +}; + +static const u32 sCursor_Gfx[] = INCBIN_U32("graphics/sliding_puzzle/cursor.4bpp.lz"); +static const u16 sCursorTiles_Pal[] = INCBIN_U16("graphics/sliding_puzzle/cursor_tiles.gbapal"); + +#define TAG_CURSOR 244 +#define GFXTAG_TILES 245 + +static const struct SpritePalette sSpritePalettes_CursorTiles[] = +{ + { + .data = sCursorTiles_Pal, + .tag = TAG_CURSOR + }, + {}, +}; + +static const struct CompressedSpriteSheet sSpriteSheet_Cursor = +{ + .data = sCursor_Gfx, + .size = 0x400, + .tag = TAG_CURSOR, +}; + +static const struct OamData sOamData_Cursor = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(32x32), + .x = 0, + .matrixNum = 0, + .size = SPRITE_SIZE(32x32), + .tileNum = 0, + .priority = 2, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteTemplate sSpriteTemplate_Cursor = +{ + .tileTag = TAG_CURSOR, + .paletteTag = TAG_CURSOR, + .oam = &sOamData_Cursor, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_Cursor, +}; + +static const struct OamData sOamData_Tiles = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = SPRITE_SHAPE(32x32), + .x = 0, + .matrixNum = 0, + .size = SPRITE_SIZE(32x32), + .tileNum = 0, + .priority = 2, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd sAnim_Tile0[] = +{ + ANIMCMD_FRAME(0 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile1[] = +{ + ANIMCMD_FRAME(1 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile2[] = +{ + ANIMCMD_FRAME(2 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile3[] = +{ + ANIMCMD_FRAME(3 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile4[] = +{ + ANIMCMD_FRAME(4 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile5[] = +{ + ANIMCMD_FRAME(5 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile6[] = +{ + ANIMCMD_FRAME(6 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile7[] = +{ + ANIMCMD_FRAME(7 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile8[] = +{ + ANIMCMD_FRAME(8 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile9[] = +{ + ANIMCMD_FRAME(9 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile10[] = +{ + ANIMCMD_FRAME(10 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile11[] = +{ + ANIMCMD_FRAME(11 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile12[] = +{ + ANIMCMD_FRAME(12 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile13[] = +{ + ANIMCMD_FRAME(13 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile14[] = +{ + ANIMCMD_FRAME(14 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd sAnim_Tile15[] = +{ + ANIMCMD_FRAME(15 * 16, 30), + ANIMCMD_END, +}; + +static const union AnimCmd *const sAnims_Tiles[] = +{ + sAnim_Tile0, + sAnim_Tile1, + sAnim_Tile2, + sAnim_Tile3, + sAnim_Tile4, + sAnim_Tile5, + sAnim_Tile6, + sAnim_Tile7, + sAnim_Tile8, + sAnim_Tile9, + sAnim_Tile10, + sAnim_Tile11, + sAnim_Tile12, + sAnim_Tile13, + sAnim_Tile14, + sAnim_Tile15, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_RotateTile[] = +{ + sSpriteAffineAnim_Rotated0, + sSpriteAffineAnim_Rotated90, + sSpriteAffineAnim_Rotated180, + sSpriteAffineAnim_Rotated270, + sSpriteAffineAnim_RotatingAnticlockwise360to270, + sSpriteAffineAnim_RotatingAnticlockwise90to0, + sSpriteAffineAnim_RotatingAnticlockwise180to90, + sSpriteAffineAnim_RotatingAnticlockwise270to180, + sSpriteAffineAnim_RotatingClockwise0to90, + sSpriteAffineAnim_RotatingClockwise90to180, + sSpriteAffineAnim_RotatingClockwise180to270, + sSpriteAffineAnim_RotatingClockwise270to360, +}; + +static const struct SpriteTemplate sSpriteTemplate_Tiles = +{ + .tileTag = GFXTAG_TILES, + .paletteTag = TAG_CURSOR, + .oam = &sOamData_Tiles, + .anims = sAnims_Tiles, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotateTile, + .callback = SpriteCallbackDummy, +}; + #define __ 0 -#define sTimer data[0] -#define sAnimating data[1] -#define sRow data[2] -#define sCol data[3] -#define sTileId data[4] -#define sOrientation data[5] #include "data/sliding_puzzles.h" -struct SlidingPuzzle +enum { - u8 tiles[NUM_ROWS][NUM_COLS]; - u8 puzzleId; - u8 cursorSpriteId; - u8 heldTile; - bool8 solved; + INSTRUCTION_NO_SELECTION, + INSTRUCTION_PICK_UP, + INSTRUCTION_PLACE, + INSTRUCTION_SWAP, + INSTRUCTION_ROTATE, + INSTRUCTION_CONTINUE, }; -static EWRAM_DATA struct SlidingPuzzle *sSlidingPuzzle = NULL; +static const u8 sText_MoveQuit[] = _("{DPAD_NONE} Move {B_BUTTON} Quit"); +static const u8 sText_MovePickUpQuit[] = _("{DPAD_NONE} Move {A_BUTTON} Pick Up {B_BUTTON} Quit"); +static const u8 sText_MovePlaceRotateQuit[] = _("{DPAD_NONE} Move {A_BUTTON} Place {L_BUTTON}{R_BUTTON} Rotate {B_BUTTON} Quit"); +static const u8 sText_MoveSwapRotateQuit[] = _("{DPAD_NONE} Move {A_BUTTON} Swap {L_BUTTON}{R_BUTTON} Rotate {B_BUTTON} Quit"); +static const u8 sText_MoveRotateQuit[] = _("{DPAD_NONE} Move {L_BUTTON}{R_BUTTON} Rotate {B_BUTTON} Quit"); +static const u8 sText_Continue[] = _("{A_BUTTON}{B_BUTTON} Continue"); + +static const u8 *const sInstructions[] = +{ + [INSTRUCTION_NO_SELECTION] = sText_MoveQuit, + [INSTRUCTION_PICK_UP] = sText_MovePickUpQuit, + [INSTRUCTION_PLACE] = sText_MovePlaceRotateQuit, + [INSTRUCTION_SWAP] = sText_MoveSwapRotateQuit, + [INSTRUCTION_ROTATE] = sText_MoveRotateQuit, + [INSTRUCTION_CONTINUE] = sText_Continue, +}; void DoSlidingPuzzle(void) { @@ -71,59 +427,79 @@ void DoSlidingPuzzle(void) static void CB2_LoadSlidingPuzzle(void) { - SetVBlankCallback(NULL); - SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_MODE_0); - SetGpuReg(REG_OFFSET_BG3CNT, 0); - SetGpuReg(REG_OFFSET_BG2CNT, 0); - SetGpuReg(REG_OFFSET_BG1CNT, 0); - SetGpuReg(REG_OFFSET_BG0CNT, 0); - SetGpuReg(REG_OFFSET_BG3HOFS, 0); - SetGpuReg(REG_OFFSET_BG3VOFS, 0); - SetGpuReg(REG_OFFSET_BG2HOFS, 0); - SetGpuReg(REG_OFFSET_BG2VOFS, 0); - SetGpuReg(REG_OFFSET_BG1HOFS, 0); - SetGpuReg(REG_OFFSET_BG1VOFS, 0); - SetGpuReg(REG_OFFSET_BG0HOFS, 0); - SetGpuReg(REG_OFFSET_BG0VOFS, 0); - DmaFillLarge16(3, 0, (void *)VRAM, VRAM_SIZE, 0x1000); - DmaClear32(3, (void *)OAM, OAM_SIZE); - DmaClear16(3, (void *)PLTT, PLTT_SIZE); - ScanlineEffect_Stop(); - ResetTasks(); - ResetSpriteData(); - ResetPaletteFade(); - FreeAllSpritePalettes(); - LoadPalette(sSlidingPuzzle_Pal, 0, 32); - ResetBgsAndClearDma3BusyFlags(0); - InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); - SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_1D_MAP); - ShowBg(0); - ShowBg(1); - SetGpuReg(REG_OFFSET_BLDCNT, 0); - SetGpuReg(REG_OFFSET_BLDALPHA, 0); - SetGpuReg(REG_OFFSET_BLDY, 0); - LZ77UnCompVram(sSlidingPuzzle_Gfx, (void *)VRAM); - LZ77UnCompVram(sSlidingPuzzle_Tilemap, (u16 *)BG_SCREEN_ADDR(7)); - InitWindows(sWindowTemplates); - LoadPalette(GetTextWindowPalette(2), 0xD0, 32); - LoadCompressedSpriteSheet(&sSpriteSheet_Cursor); - sSlidingPuzzle = AllocZeroed(sizeof(sSlidingPuzzle)); - sSlidingPuzzle->heldTile = __; - sSlidingPuzzle->puzzleId = gSpecialVar_0x8004; - sSlidingPuzzle->solved = gSpecialVar_0x8005; - LoadCompressedSpriteSheet(&sSpriteSheet_Tiles[sSlidingPuzzle->puzzleId]); - LoadSpritePalettes(sSpritePalettes_CursorTiles); - if (sSlidingPuzzle->solved) - DrawInstructionsBar(INSTRUCTION_CONTINUE); - else - DrawInstructionsBar(INSTRUCTION_NO_SELECTION); - CreateCursorSprite(); - CreateTileSprites(); - BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK); - EnableInterrupts(INTR_FLAG_VBLANK); - SetVBlankCallback(VBlankCB_SlidingPuzzle); - SetMainCallback2(CB2_SlidingPuzzle); - CreateTask(Task_SlidingPuzzle_WaitFadeIn, 0); + switch (gMain.state) + { + case 0: + SetVBlankCallback(NULL); + SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_1D_MAP); + SetGpuReg(REG_OFFSET_BLDCNT, 0); + SetGpuReg(REG_OFFSET_BLDALPHA, 0); + SetGpuReg(REG_OFFSET_BLDY, 0); + SetGpuReg(REG_OFFSET_BG3CNT, 0); + SetGpuReg(REG_OFFSET_BG2CNT, 0); + SetGpuReg(REG_OFFSET_BG1CNT, 0); + SetGpuReg(REG_OFFSET_BG0CNT, 0); + SetGpuReg(REG_OFFSET_BG3HOFS, 0); + SetGpuReg(REG_OFFSET_BG3VOFS, 0); + SetGpuReg(REG_OFFSET_BG2HOFS, 0); + SetGpuReg(REG_OFFSET_BG2VOFS, 0); + SetGpuReg(REG_OFFSET_BG1HOFS, 0); + SetGpuReg(REG_OFFSET_BG1VOFS, 0); + SetGpuReg(REG_OFFSET_BG0HOFS, 0); + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + break; + case 1: + ScanlineEffect_Stop(); + ResetTasks(); + ResetSpriteData(); + FreeAllSpritePalettes(); + ResetPaletteFade(); + ResetBgsAndClearDma3BusyFlags(0); + break; + case 2: + InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates)); + InitWindows(sWindowTemplates); + break; + case 3: + sSlidingPuzzle = AllocZeroed(sizeof(*sSlidingPuzzle)); + sSlidingPuzzle->heldTile = __; + sSlidingPuzzle->puzzleId = gSpecialVar_0x8004; + sSlidingPuzzle->solved = gSpecialVar_0x8005; + break; + case 4: + LoadPalette(GetTextWindowPalette(2), 0xD0, 32); + if (sSlidingPuzzle->solved) + DrawInstructionsBar(INSTRUCTION_CONTINUE); + else + DrawInstructionsBar(INSTRUCTION_NO_SELECTION); + ShowBg(0); + break; + case 5: + LoadPalette(sSlidingPuzzle_Pal, 0, 32); + LZ77UnCompVram(sSlidingPuzzle_Gfx, (void *)(BG_CHAR_ADDR(0))); + LZ77UnCompVram(sSlidingPuzzle_Tilemap, (void *)(BG_SCREEN_ADDR(7))); + ShowBg(1); + break; + case 6: + LoadSpritePalettes(sSpritePalettes_CursorTiles); + BlendPalettes(PALETTES_ALL, 16, RGB_BLACK); + break; + case 7: + LoadCompressedSpriteSheet(&sSpriteSheet_Cursor); + CreateCursorSprite(); + break; + case 8: + LoadCompressedSpriteSheet(&sSpriteSheet_Tiles[sSlidingPuzzle->puzzleId]); + CreateTileSprites(); + break; + default: + BeginNormalPaletteFade(PALETTES_ALL, 0, 16, 0, RGB_BLACK); + CreateTask(Task_SlidingPuzzle_WaitFadeIn, 0); + SetVBlankCallback(VBlankCB_SlidingPuzzle); + SetMainCallback2(CB2_SlidingPuzzle); + return; + } + gMain.state++; } static void CB2_SlidingPuzzle(void) @@ -153,6 +529,13 @@ static void Task_SlidingPuzzle_WaitFadeIn(u8 taskId) } } +#define sTimer data[0] +#define sAnimating data[1] +#define sRow data[2] +#define sCol data[3] +#define sTileId data[4] +#define sOrientation data[5] + static void Task_SlidingPuzzle_HandleInput(u8 taskId) { // Prevent input if the puzzle has been solved @@ -247,8 +630,7 @@ static void Task_SlidingPuzzle_Glow(u8 taskId) tTimer++; if ((tTimer % 4) == 0) { - tGlow++; - if (tGlow == 31) + if (++tGlow == 31) tState++; color = RGB(tGlow, tGlow, tGlow); LoadPalette(&color, 0x103, sizeof(color)); @@ -303,10 +685,10 @@ static void DrawInstructionsBar(u8 stringId) { const u8 color[3] = { TEXT_DYNAMIC_COLOR_6, TEXT_COLOR_WHITE, TEXT_COLOR_DARK_GRAY }; - FillWindowPixelBuffer(0, PIXEL_FILL(15)); - AddTextPrinterParameterized3(0, FONT_SMALL, 2, 1, color, 0, sInstructions[stringId]); - PutWindowTilemap(0); - CopyWindowToVram(0, COPYWIN_FULL); + FillWindowPixelBuffer(WIN_INSTRUCTIONS_BAR, PIXEL_FILL(15)); + AddTextPrinterParameterized3(WIN_INSTRUCTIONS_BAR, FONT_SMALL, 2, 1, color, 0, sInstructions[stringId]); + PutWindowTilemap(WIN_INSTRUCTIONS_BAR); + CopyWindowToVram(WIN_INSTRUCTIONS_BAR, COPYWIN_FULL); ScheduleBgCopyTilemapToVram(0); } @@ -332,12 +714,12 @@ static void CreateCursorSprite(void) static void CreateTileSprites(void) { u8 row, col, puzzleId, tile; - for (row = 0; row < NUM_ROWS; ++row) + for (row = 0; row < NUM_SLIDING_PUZZLE_ROWS; ++row) { - for (col = 0; col < NUM_COLS; ++col) + for (col = 0; col < NUM_SLIDING_PUZZLE_COLS; ++col) { if (sSlidingPuzzle->solved) - puzzleId = PUZZLE_SOLVED; + puzzleId = SLIDING_PUZZLE_SOLVED; else puzzleId = sSlidingPuzzle->puzzleId; @@ -383,15 +765,15 @@ static void MoveCursorSprite(s8 deltaX, s8 deltaY, u8 spriteId) s8 row = sprite->sRow + deltaY; s8 col = sprite->sCol + deltaX; - if (row < FIRST_ROW) - row = FINAL_ROW; - else if (row > FINAL_ROW) - row = FIRST_ROW; + if (row < FIRST_SLIDING_PUZZLE_ROW) + row = FINAL_SLIDING_PUZZLE_ROW; + else if (row > FINAL_SLIDING_PUZZLE_ROW) + row = FIRST_SLIDING_PUZZLE_ROW; - if (col < FIRST_COL) - col = FINAL_COL; - else if (col > FINAL_COL) - col = FIRST_COL; + if (col < FIRST_SLIDING_PUZZLE_COL) + col = FINAL_SLIDING_PUZZLE_COL; + else if (col > FINAL_SLIDING_PUZZLE_COL) + col = FIRST_SLIDING_PUZZLE_COL; sprite->sCol = col; sprite->sRow = row; @@ -481,12 +863,12 @@ static void RotateTile(u8 rotDir) static void CheckForSolution(void) { u8 row, col, tile; - for (row = 0; row < NUM_ROWS; row++) + for (row = 0; row < NUM_SLIDING_PUZZLE_ROWS; row++) { - for (col = 0; col < NUM_COLS; col++) + for (col = 0; col < NUM_SLIDING_PUZZLE_COLS; col++) { struct Sprite *tile = &gSprites[sSlidingPuzzle->tiles[row][col]]; - u8 tileId = sPuzzleLayouts[PUZZLE_SOLVED][row][col]; + u8 tileId = sPuzzleLayouts[SLIDING_PUZZLE_SOLVED][row][col]; if (tile->sTileId != tileId || tile->sOrientation != ORIENTATION_0) { @@ -511,16 +893,17 @@ static void SpriteCB_Cursor(struct Sprite *sprite) { sprite->sTimer = 0; if (sprite->sAnimating) - sprite->invisible ^= 1; + sprite->invisible ^= TRUE; else sprite->invisible = FALSE; } } -#undef __ #undef sTimer #undef sAnimating #undef sRow #undef sCol #undef sTileId #undef sOrientation + +#undef __ From 5aafc5f53f26e169d7c24f35762ac14ecd19c345 Mon Sep 17 00:00:00 2001 From: Jaizu Date: Wed, 20 Dec 2023 12:49:16 +0100 Subject: [PATCH 4/4] Clear VRAM before loading puzzles --- src/sliding_puzzle.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sliding_puzzle.c b/src/sliding_puzzle.c index 02d2bf1d6..2f95f75bc 100644 --- a/src/sliding_puzzle.c +++ b/src/sliding_puzzle.c @@ -454,6 +454,7 @@ static void CB2_LoadSlidingPuzzle(void) ResetSpriteData(); FreeAllSpritePalettes(); ResetPaletteFade(); + CpuFill32(0, (void *)VRAM, VRAM_SIZE); ResetBgsAndClearDma3BusyFlags(0); break; case 2: