diff --git a/img/next.gif b/img/next.gif new file mode 100644 index 0000000..bb8ff14 Binary files /dev/null and b/img/next.gif differ diff --git a/img/retry.gif b/img/retry.gif new file mode 100644 index 0000000..1b2694a Binary files /dev/null and b/img/retry.gif differ diff --git a/img/sound0.gif b/img/sound0.gif new file mode 100644 index 0000000..c90735c Binary files /dev/null and b/img/sound0.gif differ diff --git a/img/sound1.gif b/img/sound1.gif new file mode 100644 index 0000000..68c4399 Binary files /dev/null and b/img/sound1.gif differ diff --git a/img/star0.gif b/img/star0.gif new file mode 100644 index 0000000..f4d04d0 Binary files /dev/null and b/img/star0.gif differ diff --git a/img/star1.gif b/img/star1.gif new file mode 100644 index 0000000..8f54131 Binary files /dev/null and b/img/star1.gif differ diff --git a/img/star2.gif b/img/star2.gif new file mode 100644 index 0000000..5110590 Binary files /dev/null and b/img/star2.gif differ diff --git a/src/Bitmaps.c b/src/Bitmaps.c index c1f8256..68b099e 100644 --- a/src/Bitmaps.c +++ b/src/Bitmaps.c @@ -5,11 +5,14 @@ #define TitlePictResID BaseResID #define NumCharPictBaseResID (TitlePictResID + 1) -#define ACharPictResID (NumCharPictBaseResID + NumChars) +#define ACharPictResID (NumCharPictBaseResID + NumCharPictCount) #define BCharPictResID (ACharPictResID + 1) #define SlashCharPictResID (BCharPictResID + 1) +#define StarPictBaseResID (SlashCharPictResID + 1) +#define NextButtonPictResID (StarPictBaseResID + StarPictCount) +#define RetryButtonPictResID (NextButtonPictResID + 1) -void Bitmaps_DrawScaledPic(const PicHandle pic, const uint8_t scale); +#define StarRectPadding 2 void Bitmaps_Init(Bitmaps *pBitmaps) { @@ -23,7 +26,7 @@ void Bitmaps_Init(Bitmaps *pBitmaps) } // Load number chars - for (i = 0; i < NumChars; i++) + for (i = 0; i < NumCharPictCount; i++) { pBitmaps->NumCharPicts[i] = GetPicture(NumCharPictBaseResID + i); if (pBitmaps->NumCharPicts[i] == nil) @@ -52,20 +55,37 @@ void Bitmaps_Init(Bitmaps *pBitmaps) { ShowError("\pSlash char PICT resource missing!", true); } -} - -void Bitmaps_DrawScaledPic(const PicHandle pic, const uint8_t scale) -{ - Point penPosition; - Rect destRect; - GetPen(&penPosition); - GetScaledPicFrame(pic, scale, &destRect); + // Load half-stars + for (i = 0; i < StarPictCount; i++) + { + pBitmaps->StarPicts[i] = GetPicture(StarPictBaseResID + i); + if (pBitmaps->StarPicts[i] == nil) + { + ShowError("\pStar PICT resource missing!", true); + } + } - OffsetRect(&destRect, penPosition.h, penPosition.v); + // Load next button + pBitmaps->SlashCharPict = GetPicture(SlashCharPictResID); + if (pBitmaps->SlashCharPict == nil) + { + ShowError("\pSlash char PICT resource missing!", true); + } - DrawPicture(pic, &destRect); - MoveTo(destRect.right, destRect.top); + // Load next button + pBitmaps->NextButtonPict = GetPicture(NextButtonPictResID); + if (pBitmaps->NextButtonPict == nil) + { + ShowError("\pNext button PICT resource missing!", true); + } + + // Load retry button + pBitmaps->RetryButtonPict = GetPicture(RetryButtonPictResID); + if (pBitmaps->RetryButtonPict == nil) + { + ShowError("\pRetry button PICT resource missing!", true); + } } void Bitmaps_GetNumberRect(const Bitmaps *pBitmaps, const uint32_t number, const uint8_t scale, Rect *pDestRect) @@ -110,7 +130,7 @@ void Bitmaps_DrawNumber(const Bitmaps *pBitmaps, const uint32_t number, const ui if (number == 0) { - Bitmaps_DrawScaledPic(pBitmaps->NumCharPicts[0], scale); + DrawScaledPic(pBitmaps->NumCharPicts[0], scale); return; } @@ -124,7 +144,7 @@ void Bitmaps_DrawNumber(const Bitmaps *pBitmaps, const uint32_t number, const ui if (started || (digit > 0 && digit < 10)) { - Bitmaps_DrawScaledPic(pBitmaps->NumCharPicts[digit], scale); + DrawScaledPic(pBitmaps->NumCharPicts[digit], scale); started = true; } } @@ -132,15 +152,70 @@ void Bitmaps_DrawNumber(const Bitmaps *pBitmaps, const uint32_t number, const ui void Bitmaps_DrawAChar(const Bitmaps *pBitmaps, const uint8_t scale) { - Bitmaps_DrawScaledPic(pBitmaps->ACharPict, scale); + DrawScaledPic(pBitmaps->ACharPict, scale); } void Bitmaps_DrawBChar(const Bitmaps *pBitmaps, const uint8_t scale) { - Bitmaps_DrawScaledPic(pBitmaps->BCharPict, scale); + DrawScaledPic(pBitmaps->BCharPict, scale); } void Bitmaps_DrawSlashChar(const Bitmaps *pBitmaps, const uint8_t scale) { - Bitmaps_DrawScaledPic(pBitmaps->SlashCharPict, scale); + DrawScaledPic(pBitmaps->SlashCharPict, scale); +} + +void Bitmaps_GetHalfStarsRect(const Bitmaps *pBitmaps, const uint8_t halfStars, const uint8_t maxStars, const uint8_t scale, Rect *pDestRect) +{ + uint8_t stars; + Rect starRect, paddingRect; + + pDestRect->top = 0; + pDestRect->left = 0; + pDestRect->bottom = 0; + pDestRect->right = 0; + + if (maxStars == 0) + { + return; + } + + GetScaledPicFrame(pBitmaps->StarPicts[0], scale, &starRect); + paddingRect = starRect; + paddingRect.right = paddingRect.left + (StarRectPadding * scale); + + ConcatenateRect(pDestRect, &starRect, pDestRect); + + for (stars = 1; stars < maxStars; stars++) + { + ConcatenateRect(pDestRect, &paddingRect, pDestRect); + ConcatenateRect(pDestRect, &starRect, pDestRect); + } +} + +void Bitmaps_DrawHalfStars(const Bitmaps *pBitmaps, const uint8_t halfStars, const uint8_t maxStars, const uint8_t scale) +{ + Point penPosition; + uint8_t i, progress, drawn; + + progress = halfStars; + drawn = 0; + + for (i = StarPictCount - 1; i > 0; i--) + { + while (drawn < maxStars && progress >= i) + { + DrawScaledPic(pBitmaps->StarPicts[i], scale); + GetPen(&penPosition); + MoveTo(penPosition.h + (StarRectPadding * scale), penPosition.v); + progress -= i; + drawn++; + } + } + + for (; drawn < maxStars; drawn++) + { + DrawScaledPic(pBitmaps->StarPicts[0], scale); + MoveTo(penPosition.h + (StarRectPadding * scale), penPosition.v); + } } diff --git a/src/Bitmaps.h b/src/Bitmaps.h index bb8e0e5..408a27f 100644 --- a/src/Bitmaps.h +++ b/src/Bitmaps.h @@ -6,15 +6,21 @@ #include "MacCommon.h" -#define NumChars 10 +#define NumCharPictCount 10 +#define StarPictCount 3 typedef struct sBitmaps { PicHandle TitlePict; - PicHandle NumCharPicts[NumChars]; + PicHandle NumCharPicts[NumCharPictCount]; PicHandle ACharPict; PicHandle BCharPict; PicHandle SlashCharPict; + PicHandle StarPicts[StarPictCount]; + PicHandle NextButtonPict; + PicHandle RetryButtonPict; + PicHandle SoundOffPict; + PicHandle SoundOnPict; } Bitmaps; void Bitmaps_Init(Bitmaps *pBitmaps); @@ -26,4 +32,7 @@ void Bitmaps_DrawAChar(const Bitmaps *pBitmaps, const uint8_t scale); void Bitmaps_DrawBChar(const Bitmaps *pBitmaps, const uint8_t scale); void Bitmaps_DrawSlashChar(const Bitmaps *pBitmaps, const uint8_t scale); +void Bitmaps_GetHalfStarsRect(const Bitmaps *pBitmaps, const uint8_t halfStars, const uint8_t maxStars, const uint8_t scale, Rect *pDestRect); +void Bitmaps_DrawHalfStars(const Bitmaps *pBitmaps, const uint8_t halfStars, const uint8_t maxStars, const uint8_t scale); + #endif diff --git a/src/GameEndScene.c b/src/GameEndScene.c index d596cab..02ca7d6 100644 --- a/src/GameEndScene.c +++ b/src/GameEndScene.c @@ -3,32 +3,60 @@ #include "GameEndScene.h" +#define SetTextScale 6 +#define ScoreTextScale 3 + void GameEndScene_Init(GameWindow *pGameWindow) { + Rect r; + + const Rect *pContentRect = &(pGameWindow->Window->portRect); + + // Setup set + GetScaledPicFrame(pGameWindow->Bitmaps.StarPicts[StarPictCount - 1], SetTextScale, &r); + GetScaledPicFrame(pGameWindow->Engine.SetB ? pGameWindow->Bitmaps.BCharPict : pGameWindow->Bitmaps.ACharPict, SetTextScale, &(pGameWindow->GameEndScene.SetRect)); + ConcatenateRect(&r, &(pGameWindow->GameEndScene.SetRect), &(pGameWindow->GameEndScene.SetRect)); + ConcatenateRect(&(pGameWindow->GameEndScene.SetRect), &r, &(pGameWindow->GameEndScene.SetRect)); + + GetBoxRect(pContentRect, Top, &r); + GetBoxRect(&r, Bottom, &r); + CenterRect(&r, &(pGameWindow->GameEndScene.SetRect)); + + // Setup score + Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), pGameWindow->Engine.Score, ScoreTextScale, &(pGameWindow->GameEndScene.ScoreRect)); + GetScaledPicFrame(pGameWindow->Bitmaps.SlashCharPict, ScoreTextScale, &r); + ConcatenateRect(&(pGameWindow->GameEndScene.ScoreRect), &r, &(pGameWindow->GameEndScene.ScoreRect)); + Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), PerfectScore, ScoreTextScale, &r); + ConcatenateRect(&(pGameWindow->GameEndScene.ScoreRect), &r, &(pGameWindow->GameEndScene.ScoreRect)); + + GetBoxRect(pContentRect, Bottom, &r); + GetBoxRect(&r, Top, &r); + CenterRect(&r, &(pGameWindow->GameEndScene.ScoreRect)); } void GameEndScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) { - Str255 scoreStr; - - // TODO: Proper level end - if (fullRefresh) + // Draw set + MoveTo(pGameWindow->GameEndScene.SetRect.left, pGameWindow->GameEndScene.SetRect.top); + DrawScaledPic(pGameWindow->Bitmaps.StarPicts[StarPictCount - 1], SetTextScale); + if (pGameWindow->Engine.SetB) { + Bitmaps_DrawBChar(&(pGameWindow->Bitmaps), SetTextScale); } + else + { + Bitmaps_DrawAChar(&(pGameWindow->Bitmaps), SetTextScale); + } + DrawScaledPic(pGameWindow->Bitmaps.StarPicts[StarPictCount - 1], SetTextScale); - MoveTo(100, 100); - DrawString("\pGame complete! Click to continue."); - - MoveTo(100, 125); - DrawString("\pScore: "); - NumToString((int32_t)(pGameWindow->Engine.Score), &scoreStr); - DrawString(scoreStr); - DrawString("\p/300"); + // Draw score + MoveTo(pGameWindow->GameEndScene.ScoreRect.left, pGameWindow->GameEndScene.ScoreRect.top); + Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), pGameWindow->Engine.Score, ScoreTextScale); + Bitmaps_DrawSlashChar(&(pGameWindow->Bitmaps), ScoreTextScale); + Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), PerfectScore, ScoreTextScale); } void GameEndScene_Click(GameWindow *pGameWindow, const Point *pPosition) { - // TODO: Proper click handling - - GameWindow_SetScene(pGameWindow, Title); + // Do nothing } diff --git a/src/GameWindow.c b/src/GameWindow.c index 98d7380..235306f 100644 --- a/src/GameWindow.c +++ b/src/GameWindow.c @@ -77,25 +77,20 @@ void GameWindow_Click(GameWindow *pGameWindow, const Point *pPosition) void GameWindow_SetScene(GameWindow *pGameWindow, const SceneId sceneId) { - GameWindow_Draw(pGameWindow, false); - if (!(pGameWindow->SceneIsInitialized[sceneId])) + switch (sceneId) { - switch (sceneId) - { - case Title: - TitleScene_Init(pGameWindow); - break; - case Play: - PlayScene_Init(pGameWindow); - break; - case LevelEnd: - LevelEndScene_Init(pGameWindow); - break; - case GameEnd: - GameEndScene_Init(pGameWindow); - break; - } - pGameWindow->SceneIsInitialized[sceneId] = true; + case Title: + TitleScene_Init(pGameWindow); + break; + case Play: + PlayScene_Init(pGameWindow); + break; + case LevelEnd: + LevelEndScene_Init(pGameWindow); + break; + case GameEnd: + GameEndScene_Init(pGameWindow); + break; } pGameWindow->CurrentSceneId = sceneId; GameWindow_Draw(pGameWindow, true); diff --git a/src/GameWindow.h b/src/GameWindow.h index 7e9ef54..44c0286 100644 --- a/src/GameWindow.h +++ b/src/GameWindow.h @@ -17,7 +17,6 @@ typedef struct sGameWindow GameEngine Engine; Bitmaps Bitmaps; SceneId CurrentSceneId; - bool SceneIsInitialized[NumScenes]; TitleScene TitleScene; PlayScene PlayScene; LevelEndScene LevelEndScene; diff --git a/src/LevelEndScene.c b/src/LevelEndScene.c index 16f90c7..c788b06 100644 --- a/src/LevelEndScene.c +++ b/src/LevelEndScene.c @@ -3,47 +3,94 @@ #include "LevelEndScene.h" +#define LevelTextScale 4 +#define HalfStarScale 3 +#define ScoreTextScale 1 + void LevelEndScene_Init(GameWindow *pGameWindow) { + Rect r; + + const Rect *pContentRect = &(pGameWindow->Window->portRect); + + // Setup level + GetScaledPicFrame(pGameWindow->Engine.SetB ? pGameWindow->Bitmaps.BCharPict : pGameWindow->Bitmaps.ACharPict, LevelTextScale, &(pGameWindow->LevelEndScene.LevelRect)); + Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), 1 + pGameWindow->Engine.Level, LevelTextScale, &r); + ConcatenateRect(&(pGameWindow->LevelEndScene.LevelRect), &r, &(pGameWindow->LevelEndScene.LevelRect)); + + GetBoxRect(pContentRect, Top, &r); + CenterRect(&r, &(pGameWindow->LevelEndScene.LevelRect)); + + // Setup half-stars + Bitmaps_GetHalfStarsRect(&(pGameWindow->Bitmaps), GameEngine_GetHalfStars(&(pGameWindow->Engine)), MaxStars, HalfStarScale, &(pGameWindow->LevelEndScene.HalfStarsRect)); + + GetBoxRect(pContentRect, Center, &r); + CenterRect(&r, &(pGameWindow->LevelEndScene.HalfStarsRect)); + + // Setup score + Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), pGameWindow->Engine.Score, ScoreTextScale, &(pGameWindow->LevelEndScene.ScoreRect)); + GetScaledPicFrame(pGameWindow->Bitmaps.SlashCharPict, ScoreTextScale, &r); + ConcatenateRect(&(pGameWindow->LevelEndScene.ScoreRect), &r, &(pGameWindow->LevelEndScene.ScoreRect)); + Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), PerfectScore, ScoreTextScale, &r); + ConcatenateRect(&(pGameWindow->LevelEndScene.ScoreRect), &r, &(pGameWindow->LevelEndScene.ScoreRect)); + + GetBoxRect(pContentRect, Bottom, &r); + CenterRect(&r, &(pGameWindow->LevelEndScene.ScoreRect)); + + // Setup retry button + GetPictureRect(pGameWindow->Bitmaps.RetryButtonPict, &(pGameWindow->LevelEndScene.RetryButtonRect)); + + GetBoxRect(pContentRect, BottomLeft, &r); + CenterRect(&r, &(pGameWindow->LevelEndScene.RetryButtonRect)); + + // Setup next button + GetPictureRect(pGameWindow->Bitmaps.NextButtonPict, &(pGameWindow->LevelEndScene.NextButtonRect)); + + GetBoxRect(pContentRect, BottomRight, &r); + CenterRect(&r, &(pGameWindow->LevelEndScene.NextButtonRect)); } void LevelEndScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) { - Str255 halfStarsStr; - - // TODO: Proper level end - if (fullRefresh) + // Draw level + MoveTo(pGameWindow->LevelEndScene.LevelRect.left, pGameWindow->LevelEndScene.LevelRect.top); + if (pGameWindow->Engine.SetB) { + Bitmaps_DrawBChar(&(pGameWindow->Bitmaps), LevelTextScale); } + else + { + Bitmaps_DrawAChar(&(pGameWindow->Bitmaps), LevelTextScale); + } + Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), 1 + pGameWindow->Engine.Level, LevelTextScale); - MoveTo(100, 100); - DrawString("\pLevel complete! Click to continue."); + // Draw half-stars + MoveTo(pGameWindow->LevelEndScene.HalfStarsRect.left, pGameWindow->LevelEndScene.HalfStarsRect.top); + Bitmaps_DrawHalfStars(&(pGameWindow->Bitmaps), GameEngine_GetHalfStars(&(pGameWindow->Engine)), MaxStars, HalfStarScale); - MoveTo(100, 125); - DrawString("\pReceived "); - NumToString((int32_t)GameEngine_GetHalfStars(&(pGameWindow->Engine)), &halfStarsStr); - DrawString(halfStarsStr); - DrawString("\p/6 half-stars."); + // Draw score + MoveTo(pGameWindow->LevelEndScene.ScoreRect.left, pGameWindow->LevelEndScene.ScoreRect.top); + Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), pGameWindow->Engine.Score, ScoreTextScale); + Bitmaps_DrawSlashChar(&(pGameWindow->Bitmaps), ScoreTextScale); + Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), PerfectScore, ScoreTextScale); - MoveTo(100, 200); - DrawString("\pRetry level."); + // Draw retry button + DrawPicture(pGameWindow->Bitmaps.RetryButtonPict, &(pGameWindow->LevelEndScene.RetryButtonRect)); - MoveTo(350, 200); - DrawString("\pNext level."); + // Draw next button + DrawPicture(pGameWindow->Bitmaps.NextButtonPict, &(pGameWindow->LevelEndScene.NextButtonRect)); } void LevelEndScene_Click(GameWindow *pGameWindow, const Point *pPosition) { - // TODO: Proper click handling - - if (pPosition->h < ((pGameWindow->Window->portRect.right - pGameWindow->Window->portRect.left) / 2)) + if (PtInRect(*pPosition, &(pGameWindow->LevelEndScene.RetryButtonRect))) { GameEngine_ResetLevel(&(pGameWindow->Engine)); + GameWindow_SetScene(pGameWindow, Play); } - else + else if (PtInRect(*pPosition, &(pGameWindow->LevelEndScene.NextButtonRect))) { GameEngine_NextLevel(&(pGameWindow->Engine)); + GameWindow_SetScene(pGameWindow, GameEngine_IsGameOver(&(pGameWindow->Engine)) ? GameEnd : Play); } - - GameWindow_SetScene(pGameWindow, GameEngine_IsGameOver(&(pGameWindow->Engine)) ? GameEnd : Play); } diff --git a/src/MacCommon.c b/src/MacCommon.c index c0f7c95..bb1e189 100644 --- a/src/MacCommon.c +++ b/src/MacCommon.c @@ -47,6 +47,7 @@ void ConcatenateRect(const Rect *pLeftRect, const Rect *pRightRect, Rect *pDestR void GetBoxRect(const Rect *pOuterRect, const BoxAlignment boxAlignment, Rect *pBoxRect) { int32_t boxWidth, boxHeight; + Rect resultRect; boxWidth = (pOuterRect->right - pOuterRect->left) / 3; boxHeight = (pOuterRect->bottom - pOuterRect->top) / 3; @@ -54,66 +55,87 @@ void GetBoxRect(const Rect *pOuterRect, const BoxAlignment boxAlignment, Rect *p switch (boxAlignment) { case Top: - pBoxRect->top = pOuterRect->top; - pBoxRect->left = pOuterRect->left + boxWidth; - pBoxRect->bottom = pOuterRect->top + boxHeight; - pBoxRect->right = pOuterRect->right - boxWidth; + resultRect.top = pOuterRect->top; + resultRect.left = pOuterRect->left + boxWidth; + resultRect.bottom = pOuterRect->top + boxHeight; + resultRect.right = pOuterRect->right - boxWidth; break; case TopLeft: - pBoxRect->top = pOuterRect->top; - pBoxRect->left = pOuterRect->left; - pBoxRect->bottom = pOuterRect->top + boxHeight; - pBoxRect->right = pOuterRect->left + boxWidth; + resultRect.top = pOuterRect->top; + resultRect.left = pOuterRect->left; + resultRect.bottom = pOuterRect->top + boxHeight; + resultRect.right = pOuterRect->left + boxWidth; break; case Left: - pBoxRect->top = pOuterRect->top + boxHeight; - pBoxRect->left = pOuterRect->left; - pBoxRect->bottom = pOuterRect->bottom - boxHeight; - pBoxRect->right = pOuterRect->left + boxWidth; + resultRect.top = pOuterRect->top + boxHeight; + resultRect.left = pOuterRect->left; + resultRect.bottom = pOuterRect->bottom - boxHeight; + resultRect.right = pOuterRect->left + boxWidth; break; case BottomLeft: - pBoxRect->top = pOuterRect->bottom - boxHeight; - pBoxRect->left = pOuterRect->left; - pBoxRect->bottom = pOuterRect->bottom; - pBoxRect->right = pOuterRect->left + boxWidth; + resultRect.top = pOuterRect->bottom - boxHeight; + resultRect.left = pOuterRect->left; + resultRect.bottom = pOuterRect->bottom; + resultRect.right = pOuterRect->left + boxWidth; break; case Bottom: - pBoxRect->top = pOuterRect->bottom - boxHeight; - pBoxRect->left = pOuterRect->left + boxWidth; - pBoxRect->bottom = pOuterRect->bottom; - pBoxRect->right = pOuterRect->right - boxWidth; + resultRect.top = pOuterRect->bottom - boxHeight; + resultRect.left = pOuterRect->left + boxWidth; + resultRect.bottom = pOuterRect->bottom; + resultRect.right = pOuterRect->right - boxWidth; break; case BottomRight: - pBoxRect->top = pOuterRect->bottom - boxHeight; - pBoxRect->left = pOuterRect->right - boxWidth; - pBoxRect->bottom = pOuterRect->bottom; - pBoxRect->right = pOuterRect->right; + resultRect.top = pOuterRect->bottom - boxHeight; + resultRect.left = pOuterRect->right - boxWidth; + resultRect.bottom = pOuterRect->bottom; + resultRect.right = pOuterRect->right; break; case Right: - pBoxRect->top = pOuterRect->top + boxHeight; - pBoxRect->left = pOuterRect->right - boxWidth; - pBoxRect->bottom = pOuterRect->bottom - boxHeight; - pBoxRect->right = pOuterRect->right; + resultRect.top = pOuterRect->top + boxHeight; + resultRect.left = pOuterRect->right - boxWidth; + resultRect.bottom = pOuterRect->bottom - boxHeight; + resultRect.right = pOuterRect->right; break; case TopRight: - pBoxRect->top = pOuterRect->top; - pBoxRect->left = pOuterRect->right - boxWidth; - pBoxRect->bottom = pOuterRect->top + boxHeight; - pBoxRect->right = pOuterRect->right; + resultRect.top = pOuterRect->top; + resultRect.left = pOuterRect->right - boxWidth; + resultRect.bottom = pOuterRect->top + boxHeight; + resultRect.right = pOuterRect->right; break; case Center: - pBoxRect->top = pOuterRect->top + boxHeight; - pBoxRect->left = pOuterRect->left + boxWidth; - pBoxRect->bottom = pOuterRect->bottom - boxHeight; - pBoxRect->right = pOuterRect->right - boxWidth; + resultRect.top = pOuterRect->top + boxHeight; + resultRect.left = pOuterRect->left + boxWidth; + resultRect.bottom = pOuterRect->bottom - boxHeight; + resultRect.right = pOuterRect->right - boxWidth; break; } + + *pBoxRect = resultRect; +} + +void GetPictureRect(const PicHandle picHandle, Rect *pDestRect) +{ + *pDestRect = (**(picHandle)).picFrame; } void GetScaledPicFrame(const PicHandle picHandle, const uint8_t scale, Rect *pDestRect) { - *pDestRect = (**(picHandle)).picFrame; + GetPictureRect(picHandle, pDestRect); pDestRect->right = pDestRect->left + ((pDestRect->right - pDestRect->left) * max(scale, 1)); pDestRect->bottom = pDestRect->top + ((pDestRect->bottom - pDestRect->top) * max(scale, 1)); } + +void DrawScaledPic(const PicHandle pic, const uint8_t scale) +{ + Point penPosition; + Rect destRect; + + GetPen(&penPosition); + GetScaledPicFrame(pic, scale, &destRect); + + OffsetRect(&destRect, penPosition.h, penPosition.v); + + DrawPicture(pic, &destRect); + MoveTo(destRect.right, destRect.top); +} diff --git a/src/MacCommon.h b/src/MacCommon.h index 58c5a4c..a87be46 100644 --- a/src/MacCommon.h +++ b/src/MacCommon.h @@ -39,6 +39,9 @@ void ConcatenateRect(const Rect *pLeftRect, const Rect *pRightRect, Rect *pDestR void GetBoxRect(const Rect *pOuterRect, const BoxAlignment boxAlignment, Rect *pBoxRect); +void GetPictureRect(const PicHandle picHandle, Rect *pDestRect); + void GetScaledPicFrame(const PicHandle picHandle, const uint8_t scale, Rect *pDestRect); +void DrawScaledPic(const PicHandle pic, const uint8_t scale); #endif diff --git a/src/MacLO.pi.bin b/src/MacLO.pi.bin index bdb822f..829953b 100644 Binary files a/src/MacLO.pi.bin and b/src/MacLO.pi.bin differ diff --git a/src/MacLO.pi.rsrc.bin b/src/MacLO.pi.rsrc.bin index 35d86e7..cf1de4c 100644 Binary files a/src/MacLO.pi.rsrc.bin and b/src/MacLO.pi.rsrc.bin differ diff --git a/src/PlayScene.c b/src/PlayScene.c index 679db09..7ca1738 100644 --- a/src/PlayScene.c +++ b/src/PlayScene.c @@ -8,39 +8,64 @@ #define PlayfieldCornerSize 12 #define LightMargin 6 #define LightSize 50 -#define LightCornerSize 8 +#define LightCornerSize 12 #define PlayfieldPattern ltGray #define HUDMargin PlayfieldMargin #define HUDCornerSize PlayfieldCornerSize #define HUDPattern PlayfieldPattern -#define LevelTextScale 2 +#define LevelTextScale 3 +#define HalfStarScale 2 +#define ScoreTextScale 1 void PlayScene_Init(GameWindow *pGameWindow) { - Rect r1, r2; + Rect r; + + const Rect *pContentRect = &(pGameWindow->Window->portRect); // Setup Playfield pGameWindow->PlayScene.PlayfieldRect.top = PlayfieldMargin; - pGameWindow->PlayScene.PlayfieldRect.bottom = pGameWindow->Window->portRect.bottom - PlayfieldMargin; + pGameWindow->PlayScene.PlayfieldRect.bottom = pContentRect->bottom - PlayfieldMargin; pGameWindow->PlayScene.PlayfieldRect.left = pGameWindow->PlayScene.PlayfieldRect.top; pGameWindow->PlayScene.PlayfieldRect.right = pGameWindow->PlayScene.PlayfieldRect.bottom; // Setup HUD pGameWindow->PlayScene.HUDRect.top = HUDMargin; - pGameWindow->PlayScene.HUDRect.bottom = pGameWindow->Window->portRect.bottom - HUDMargin; + pGameWindow->PlayScene.HUDRect.bottom = pContentRect->bottom - HUDMargin; pGameWindow->PlayScene.HUDRect.left = pGameWindow->PlayScene.PlayfieldRect.right + HUDMargin; - pGameWindow->PlayScene.HUDRect.right = pGameWindow->Window->portRect.right - HUDMargin; + pGameWindow->PlayScene.HUDRect.right = pContentRect->right - HUDMargin; - // Setup Level - GetScaledPicFrame(pGameWindow->Engine.SetB ? pGameWindow->Bitmaps.BCharPict : pGameWindow->Bitmaps.ACharPict, LevelTextScale, &r1); - Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), 1 + pGameWindow->Engine.Level, LevelTextScale, &r2); - ConcatenateRect(&r1, &r2, &(pGameWindow->PlayScene.LevelRect)); + // Setup level + GetScaledPicFrame(pGameWindow->Engine.SetB ? pGameWindow->Bitmaps.BCharPict : pGameWindow->Bitmaps.ACharPict, LevelTextScale, &(pGameWindow->PlayScene.LevelRect)); + Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), 1 + pGameWindow->Engine.Level, LevelTextScale, &r); + ConcatenateRect(&(pGameWindow->PlayScene.LevelRect), &r, &(pGameWindow->PlayScene.LevelRect)); + + GetBoxRect(&(pGameWindow->PlayScene.HUDRect), Top, &r); + CenterRect(&r, &(pGameWindow->PlayScene.LevelRect)); + + // Setup half-stars + Bitmaps_GetHalfStarsRect(&(pGameWindow->Bitmaps), GameEngine_GetHalfStars(&(pGameWindow->Engine)), MaxStars, HalfStarScale, &(pGameWindow->PlayScene.HalfStarsRect)); - GetBoxRect(&(pGameWindow->PlayScene.HUDRect), Top, &r1); - GetBoxRect(&r1, Bottom, &r2); - CenterRect(&r2, &(pGameWindow->PlayScene.LevelRect)); + GetBoxRect(&(pGameWindow->PlayScene.HUDRect), Center, &r); + CenterRect(&r, &(pGameWindow->PlayScene.HalfStarsRect)); + + // Setup score + Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), pGameWindow->Engine.Score, ScoreTextScale, &(pGameWindow->PlayScene.ScoreRect)); + GetScaledPicFrame(pGameWindow->Bitmaps.SlashCharPict, ScoreTextScale, &r); + ConcatenateRect(&(pGameWindow->PlayScene.ScoreRect), &r, &(pGameWindow->PlayScene.ScoreRect)); + Bitmaps_GetNumberRect(&(pGameWindow->Bitmaps), PerfectScore, ScoreTextScale, &r); + ConcatenateRect(&(pGameWindow->PlayScene.ScoreRect), &r, &(pGameWindow->PlayScene.ScoreRect)); + + GetBoxRect(&(pGameWindow->PlayScene.HUDRect), Bottom, &r); + CenterRect(&r, &(pGameWindow->PlayScene.ScoreRect)); + + // Setup retry button + GetPictureRect(pGameWindow->Bitmaps.RetryButtonPict, &(pGameWindow->PlayScene.RetryButtonRect)); + + GetBoxRect(&(pGameWindow->PlayScene.HUDRect), BottomLeft, &r); + CenterRect(&r, &(pGameWindow->PlayScene.RetryButtonRect)); } void PlayScene_SetLightRect(const GameWindow *pGameWindow, Rect *pRect, const int8_t c, const int8_t r) @@ -59,8 +84,10 @@ void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) if (fullRefresh) { // Fill backgrounds - FillRoundRect(&(pGameWindow->PlayScene.PlayfieldRect), PlayfieldCornerSize, PlayfieldCornerSize, PlayfieldPattern); - //FillRoundRect(&(pGameWindow->PlayScene.HUDRect), HUDCornerSize, HUDCornerSize, HUDPattern); + ForeColor(whiteColor); + FrameRoundRect(&(pGameWindow->PlayScene.PlayfieldRect), PlayfieldCornerSize, PlayfieldCornerSize); + FrameRoundRect(&(pGameWindow->PlayScene.HUDRect), HUDCornerSize, HUDCornerSize); + ForeColor(blackColor); } // Draw Playfield @@ -80,14 +107,14 @@ void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) else { // Draw OFF light - FillRoundRect(&lightRect, LightCornerSize, LightCornerSize, black); + FillRoundRect(&lightRect, LightCornerSize, LightCornerSize, dkGray); } } } // Draw HUD - // Draw Level + // Draw level MoveTo(pGameWindow->PlayScene.LevelRect.left, pGameWindow->PlayScene.LevelRect.top); if (pGameWindow->Engine.SetB) { @@ -99,7 +126,18 @@ void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) } Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), 1 + pGameWindow->Engine.Level, LevelTextScale); - // Draw Stars + // Draw half-stars + MoveTo(pGameWindow->PlayScene.HalfStarsRect.left, pGameWindow->PlayScene.HalfStarsRect.top); + Bitmaps_DrawHalfStars(&(pGameWindow->Bitmaps), GameEngine_GetHalfStars(&(pGameWindow->Engine)), MaxStars, HalfStarScale); + + // Draw score + MoveTo(pGameWindow->PlayScene.ScoreRect.left, pGameWindow->PlayScene.ScoreRect.top); + Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), pGameWindow->Engine.Score, ScoreTextScale); + Bitmaps_DrawSlashChar(&(pGameWindow->Bitmaps), ScoreTextScale); + Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), PerfectScore, ScoreTextScale); + + // Draw retry button + DrawPicture(pGameWindow->Bitmaps.RetryButtonPict, &(pGameWindow->PlayScene.RetryButtonRect)); } void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition) @@ -128,11 +166,18 @@ void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition) if (GameEngine_IsCompleted(&(pGameWindow->Engine))) { // Level was completed in the last click + GameWindow_Draw(pGameWindow, false); GameWindow_SetScene(pGameWindow, LevelEnd); } } else if (PtInRect(*pPosition, &(pGameWindow->PlayScene.HUDRect))) { // Click within HUD + + if (PtInRect(*pPosition, &(pGameWindow->PlayScene.RetryButtonRect))) + { + GameEngine_ResetLevel(&(pGameWindow->Engine)); + GameWindow_Draw(pGameWindow, false); + } } } diff --git a/src/Scenes.h b/src/Scenes.h index 9d05482..f712b83 100644 --- a/src/Scenes.h +++ b/src/Scenes.h @@ -26,16 +26,24 @@ typedef struct sPlayScene Rect PlayfieldRect; Rect HUDRect; Rect LevelRect; + Rect HalfStarsRect; + Rect ScoreRect; + Rect RetryButtonRect; } PlayScene; typedef struct sLevelEndScene { - Rect temp; + Rect LevelRect; + Rect HalfStarsRect; + Rect ScoreRect; + Rect RetryButtonRect; + Rect NextButtonRect; } LevelEndScene; typedef struct sGameEndScene { - Rect temp; + Rect SetRect; + Rect ScoreRect; } GameEndScene; #endif diff --git a/src/TitleScene.c b/src/TitleScene.c index 8437d2b..1b3a283 100644 --- a/src/TitleScene.c +++ b/src/TitleScene.c @@ -13,7 +13,7 @@ void TitleScene_Init(GameWindow *pGameWindow) const Rect *pContentRect = &(pGameWindow->Window->portRect); // Setup rects - GetScaledPicFrame(pGameWindow->Bitmaps.TitlePict, 1, &(pGameWindow->TitleScene.TitleRect)); + GetPictureRect(pGameWindow->Bitmaps.TitlePict, &(pGameWindow->TitleScene.TitleRect)); CenterRect(pContentRect, &(pGameWindow->TitleScene.TitleRect)); GetBoxRect(pContentRect, BottomLeft, &r); @@ -27,11 +27,6 @@ void TitleScene_Init(GameWindow *pGameWindow) void TitleScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) { - // TODO: Proper title - if (fullRefresh) - { - } - // Draw Title DrawPicture(pGameWindow->Bitmaps.TitlePict, &(pGameWindow->TitleScene.TitleRect));