diff --git a/img/title.png b/img/title.png new file mode 100644 index 0000000..ab096a1 Binary files /dev/null and b/img/title.png differ diff --git a/src/GameEndScene.c b/src/GameEndScene.c new file mode 100644 index 0000000..29a5900 --- /dev/null +++ b/src/GameEndScene.c @@ -0,0 +1,36 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#include "GameEndScene.h" + +void GameEndScene_Init(GameWindow *pGameWindow) +{ +} + +void GameEndScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) +{ + Str255 scoreStr; + + SetPort(pGameWindow->Window); + + // TODO: Proper level end + if (fullRefresh) + { + } + + MoveTo(100, 100); + DrawString("\pGame complete! Click to continue."); + + MoveTo(100, 125); + DrawString("\pScore: "); + NumToString((long)(pGameWindow->Engine.Score), &scoreStr); + DrawString(scoreStr); + DrawString("\p/300"); +} + +void GameEndScene_Click(GameWindow *pGameWindow, const Point *pPosition) +{ + // TODO: Proper click handling + + GameWindow_SetScene(pGameWindow, Title); +} diff --git a/src/GameEndScene.h b/src/GameEndScene.h new file mode 100644 index 0000000..fcfee87 --- /dev/null +++ b/src/GameEndScene.h @@ -0,0 +1,13 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#ifndef GAMEENDSCENE_H +#define GAMEENDSCENE_H + +#include "GameWindow.h" + +void GameEndScene_Init(GameWindow *pGameWindow); +void GameEndScene_Draw(const GameWindow *pGameWindow, bool fullRefresh); +void GameEndScene_Click(GameWindow *pGameWindow, const Point *pPosition); + +#endif diff --git a/src/GameEngine.c b/src/GameEngine.c index 17db1e9..ccb10ab 100644 --- a/src/GameEngine.c +++ b/src/GameEngine.c @@ -37,7 +37,7 @@ void GameEngine_ResetLevel(GameEngine *pGameEngine) void GameEngine_LoadLevel(GameEngine *pGameEngine, const int8_t level, const bool setB) { - pGameEngine->Level = Levels_BoundLevel(level); + pGameEngine->Level = level; pGameEngine->SetB = setB; pGameEngine->Lights = Levels_GetLightsForLevel(pGameEngine->Level, setB); pGameEngine->Par = Levels_GetParForLevel(pGameEngine->Level); @@ -59,6 +59,11 @@ bool GameEngine_IsCompleted(const GameEngine *pGameEngine) return pGameEngine->Lights == 0; } +bool GameEngine_IsGameOver(const GameEngine *pGameEngine) +{ + return pGameEngine->Level >= LevelCount; +} + uint8_t GameEngine_GetHalfStars(const GameEngine *pGameEngine) { uint8_t halfStarsLost = pGameEngine->Moves <= pGameEngine->Par ? 0 : max(0, (1 + pGameEngine->Moves - pGameEngine->Par) / 2); diff --git a/src/GameEngine.h b/src/GameEngine.h index b922306..124bfb2 100644 --- a/src/GameEngine.h +++ b/src/GameEngine.h @@ -34,6 +34,8 @@ bool GameEngine_GetLight(const GameEngine *pGameEngine, const int8_t x, const in bool GameEngine_IsCompleted(const GameEngine *pGameEngine); +bool GameEngine_IsGameOver(const GameEngine *pGameEngine); + uint8_t GameEngine_GetHalfStars(const GameEngine *pGameEngine); void GameEngine_ToggleLights(GameEngine *pGameEngine, const int8_t x, const int8_t y); diff --git a/src/GameWindow.c b/src/GameWindow.c index 57cacec..b929d52 100644 --- a/src/GameWindow.c +++ b/src/GameWindow.c @@ -2,16 +2,10 @@ // Licensed under the MIT License. #include "GameWindow.h" - -void GameWindow_SetLightRect(const GameWindow *pGameWindow, Rect *pRect, const int8_t c, const int8_t r); - -void GameWindow_DrawTitleMode(const GameWindow *pGameWindow, bool fullRefresh); -void GameWindow_DrawPlayMode(const GameWindow *pGameWindow, bool fullRefresh); -void GameWindow_DrawLevelCompleteMode(const GameWindow *pGameWindow, bool fullRefresh); - -void GameWindow_ClickTitleMode(GameWindow *pGameWindow, const Point *pPosition); -void GameWindow_ClickPlayMode(GameWindow *pGameWindow, const Point *pPosition); -void GameWindow_ClickLevelCompleteMode(GameWindow *pGameWindow, const Point *pPosition); +#include "TitleScene.h" +#include "PlayScene.h" +#include "LevelEndScene.h" +#include "GameEndScene.h" void GameWindow_Init(GameWindow *pGameWindow) { @@ -24,24 +18,10 @@ void GameWindow_Init(GameWindow *pGameWindow) if (pGameWindow->Window == nil) { - ShowError("\pGameWindow resource WIND BaseResID missing!", true); + ShowError("\pGameWindow WIND resource missing!", true); } - pGameWindow->GameMode = Title; - - // Setup rects - pGameWindow->PlayfieldRect.top = PlayfieldMargin; - pGameWindow->PlayfieldRect.bottom = pGameWindow->Window->portRect.bottom - PlayfieldMargin; - pGameWindow->PlayfieldRect.left = pGameWindow->PlayfieldRect.top; - pGameWindow->PlayfieldRect.right = pGameWindow->PlayfieldRect.bottom; - - pGameWindow->HUDRect.top = HUDMargin; - pGameWindow->HUDRect.bottom = pGameWindow->Window->portRect.bottom - HUDMargin; - pGameWindow->HUDRect.left = pGameWindow->PlayfieldRect.right + HUDMargin; - pGameWindow->HUDRect.right = pGameWindow->Window->portRect.right - HUDMargin; - - // Load first level - GameEngine_LoadLevel(&(pGameWindow->Engine), 0, false); + GameWindow_SetScene(pGameWindow, Title); } void GameWindow_Draw(const GameWindow *pGameWindow, bool fullRefresh) @@ -56,245 +36,69 @@ void GameWindow_Draw(const GameWindow *pGameWindow, bool fullRefresh) FillRect(pContentRect, WindowPattern); } - switch (pGameWindow->GameMode) + switch (pGameWindow->CurrentSceneId) { case Title: - GameWindow_DrawTitleMode(pGameWindow, fullRefresh); + TitleScene_Draw(pGameWindow, fullRefresh); break; case Play: - GameWindow_DrawPlayMode(pGameWindow, fullRefresh); + PlayScene_Draw(pGameWindow, fullRefresh); break; - case LevelComplete: - GameWindow_DrawLevelCompleteMode(pGameWindow, fullRefresh); + case LevelEnd: + LevelEndScene_Draw(pGameWindow, fullRefresh); + break; + case GameEnd: + GameEndScene_Draw(pGameWindow, fullRefresh); break; } } -void GameWindow_SetLightRect(const GameWindow *pGameWindow, Rect *pRect, const int8_t c, const int8_t r) +void GameWindow_Click(GameWindow *pGameWindow, const Point *pPosition) { - pRect->top = pGameWindow->PlayfieldRect.top + PlayfieldPadding + LightMargin + (r * (LightMargin + LightSize)); - pRect->bottom = pRect->top + LightSize; - pRect->left = pGameWindow->PlayfieldRect.left + PlayfieldPadding + LightMargin + (c * (LightMargin + LightSize)); - pRect->right = pRect->left + LightSize; + switch (pGameWindow->CurrentSceneId) + { + case Title: + TitleScene_Click(pGameWindow, pPosition); + break; + case Play: + PlayScene_Click(pGameWindow, pPosition); + break; + case LevelEnd: + LevelEndScene_Click(pGameWindow, pPosition); + break; + case GameEnd: + GameEndScene_Click(pGameWindow, pPosition); + break; + } } -void GameWindow_DrawTitleMode(const GameWindow *pGameWindow, bool fullRefresh) +void GameWindow_SetScene(GameWindow *pGameWindow, const SceneId sceneId) { - SetPort(pGameWindow->Window); - - // TODO: Proper title - if (fullRefresh) + GameWindow_Draw(pGameWindow, false); + if (!(pGameWindow->SceneIsInitialized[sceneId])) { - } - - ForeColor(blackColor); - TextFace(bold + outline); - - MoveTo(100, 100); - DrawString("\pMacLO! Click to continue."); - - MoveTo(25, 200); - DrawString("\pSet A."); - - MoveTo(250, 200); - DrawString("\pSet B."); -} - -void GameWindow_DrawPlayMode(const GameWindow *pGameWindow, bool fullRefresh) -{ - int8_t r, c; - Rect lightRect; - Str255 levelStr, parStr, movesStr, halfStarsStr, scoreStr; - - SetPort(pGameWindow->Window); - - if (fullRefresh) - { - // Fill backgrounds - FillRoundRect(&(pGameWindow->PlayfieldRect), PlayfieldCornerSize, PlayfieldCornerSize, PlayfieldPattern); - FillRoundRect(&(pGameWindow->HUDRect), HUDCornerSize, HUDCornerSize, HUDPattern); - } - - // Draw Playfield - - // Draw lights - for (r = 0; r < PuzzleSize; r++) - { - for (c = 0; c < PuzzleSize; c++) + switch (sceneId) { - GameWindow_SetLightRect(pGameWindow, &lightRect, c, r); - - if (GameEngine_GetLight(&(pGameWindow->Engine), c, r)) - { - // Draw ON light - FillRoundRect(&lightRect, LightCornerSize, LightCornerSize, white); - } - else - { - // Draw OFF light - FillRoundRect(&lightRect, LightCornerSize, LightCornerSize, black); - } + 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; } - - // Draw HUD - - ForeColor(blackColor); - TextFace(bold + outline); - - // Draw Level - MoveTo(pGameWindow->HUDRect.left + 10, pGameWindow->HUDRect.top + 20); - DrawString("\pLevel: "); - NumToString(1L + pGameWindow->Engine.Level, &levelStr); - DrawString(levelStr); - DrawString("\p/50"); - - // Draw Par - MoveTo(pGameWindow->HUDRect.left + 10, pGameWindow->HUDRect.top + 40); - DrawString("\pPar: "); - NumToString((long)(pGameWindow->Engine.Par), &parStr); - DrawString(parStr); - - // Draw Moves - MoveTo(pGameWindow->HUDRect.left + 10, pGameWindow->HUDRect.top + 60); - DrawString("\pMoves: "); - NumToString((long)(pGameWindow->Engine.Moves), &movesStr); - DrawString(movesStr); - DrawString("\p/"); - DrawString(parStr); - - // Draw Stars - MoveTo(pGameWindow->HUDRect.left + 10, pGameWindow->HUDRect.top + 80); - DrawString("\pStars: "); - NumToString((long)GameEngine_GetHalfStars(&(pGameWindow->Engine)), &halfStarsStr); - DrawString(halfStarsStr); - DrawString("\p/6"); - - // Draw Score - MoveTo(pGameWindow->HUDRect.left + 10, pGameWindow->HUDRect.top + 100); - DrawString("\pScore: "); - NumToString((long)(pGameWindow->Engine.Score), &scoreStr); - DrawString(scoreStr); - DrawString("\p/300"); -} - -void GameWindow_DrawLevelCompleteMode(const GameWindow *pGameWindow, bool fullRefresh) -{ - Str255 halfStarsStr; - - SetPort(pGameWindow->Window); - - // TODO: Proper level complete - if (fullRefresh) - { - } - - MoveTo(50, 100); - DrawString("\pLevel complete! Click to continue."); - - MoveTo(50, 125); - DrawString("\pReceived "); - NumToString((long)GameEngine_GetHalfStars(&(pGameWindow->Engine)), &halfStarsStr); - DrawString(halfStarsStr); - DrawString("\p/6 half-stars."); - - MoveTo(25, 200); - DrawString("\pRetry level."); - - MoveTo(250, 200); - DrawString("\pNext level."); + pGameWindow->CurrentSceneId = sceneId; + GameWindow_Draw(pGameWindow, true); } void GameWindow_Show(const GameWindow *pGameWindow) { ShowWindow(pGameWindow->Window); } - -void GameWindow_Click(GameWindow *pGameWindow, const Point *pPosition) -{ - switch (pGameWindow->GameMode) - { - case Title: - GameWindow_ClickTitleMode(pGameWindow, pPosition); - break; - case Play: - GameWindow_ClickPlayMode(pGameWindow, pPosition); - break; - case LevelComplete: - GameWindow_ClickLevelCompleteMode(pGameWindow, pPosition); - break; - } -} - -void GameWindow_ClickTitleMode(GameWindow *pGameWindow, const Point *pPosition) -{ - bool setB; - - // TODO: Proper click handling - - if (pPosition->h < ((pGameWindow->Window->portRect.right - pGameWindow->Window->portRect.left) / 2)) - { - setB = false; - } - else - { - setB = true; - } - - GameEngine_NewGame(&(pGameWindow->Engine), setB); - pGameWindow->GameMode = Play; - GameWindow_Draw(pGameWindow, true); -} - -void GameWindow_ClickPlayMode(GameWindow *pGameWindow, const Point *pPosition) -{ - int8_t r, c; - Rect lightRect; - - if (PtInRect(*pPosition, &(pGameWindow->PlayfieldRect))) - { - // Click within Playfield - for (r = 0; r < PuzzleSize; r++) - { - for (c = 0; c < PuzzleSize; c++) - { - GameWindow_SetLightRect(pGameWindow, &lightRect, c, r); - - if (PtInRect(*pPosition, &lightRect)) - { - GameEngine_ToggleLights(&(pGameWindow->Engine), c, r); - GameWindow_Draw(pGameWindow, false); - break; - } - } - } - - if (GameEngine_IsCompleted(&(pGameWindow->Engine))) - { - // Level was completed in the last click - pGameWindow->GameMode = LevelComplete; - GameWindow_Draw(pGameWindow, true); - } - } - else if (PtInRect(*pPosition, &(pGameWindow->HUDRect))) - { - // Click within HUD - } -} - -void GameWindow_ClickLevelCompleteMode(GameWindow *pGameWindow, const Point *pPosition) -{ - // TODO: Proper click handling - - if (pPosition->h < ((pGameWindow->Window->portRect.right - pGameWindow->Window->portRect.left) / 2)) - { - GameEngine_ResetLevel(&(pGameWindow->Engine)); - } - else - { - GameEngine_NextLevel(&(pGameWindow->Engine)); - } - - pGameWindow->GameMode = Play; - GameWindow_Draw(pGameWindow, true); -} diff --git a/src/GameWindow.h b/src/GameWindow.h index f6298c8..e8af4f2 100644 --- a/src/GameWindow.h +++ b/src/GameWindow.h @@ -6,43 +6,25 @@ #include "MacCommon.h" #include "GameEngine.h" +#include "Scenes.h" -#define WindowPattern black - -#define PlayfieldMargin 4 -#define PlayfieldPadding 2 -#define PlayfieldCornerSize 12 -#define LightMargin 6 -#define LightSize 50 -#define LightCornerSize 8 -#define PlayfieldPattern ltGray - -#define HUDMargin PlayfieldMargin -#define HUDCornerSize PlayfieldCornerSize -#define HUDPattern PlayfieldPattern - -typedef enum GameMode -{ - Title, - Play, - LevelComplete, - GameComplete -} GameMode; +#define WindowPattern black typedef struct GameWindow { WindowPtr Window; GameEngine Engine; - GameMode GameMode; - Rect PlayfieldRect; - Rect HUDRect; + SceneId CurrentSceneId; + bool SceneIsInitialized[NumScenes]; + TitleScene TitleScene; + PlayScene PlayScene; } GameWindow; void GameWindow_Init(GameWindow *pGameWindow); - void GameWindow_Draw(const GameWindow *pGameWindow, bool fullRefresh); -void GameWindow_Show(const GameWindow *pGameWindow); - void GameWindow_Click(GameWindow *pGameWindow, const Point *pPosition); +void GameWindow_SetScene(GameWindow *pGameWindow, const SceneId sceneId); +void GameWindow_Show(const GameWindow *pGameWindow); + #endif diff --git a/src/LevelEndScene.c b/src/LevelEndScene.c new file mode 100644 index 0000000..adfdaf5 --- /dev/null +++ b/src/LevelEndScene.c @@ -0,0 +1,51 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#include "LevelEndScene.h" + +void LevelEndScene_Init(GameWindow *pGameWindow) +{ +} + +void LevelEndScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) +{ + Str255 halfStarsStr; + + SetPort(pGameWindow->Window); + + // TODO: Proper level end + if (fullRefresh) + { + } + + MoveTo(100, 100); + DrawString("\pLevel complete! Click to continue."); + + MoveTo(100, 125); + DrawString("\pReceived "); + NumToString((long)GameEngine_GetHalfStars(&(pGameWindow->Engine)), &halfStarsStr); + DrawString(halfStarsStr); + DrawString("\p/6 half-stars."); + + MoveTo(100, 200); + DrawString("\pRetry level."); + + MoveTo(350, 200); + DrawString("\pNext level."); +} + +void LevelEndScene_Click(GameWindow *pGameWindow, const Point *pPosition) +{ + // TODO: Proper click handling + + if (pPosition->h < ((pGameWindow->Window->portRect.right - pGameWindow->Window->portRect.left) / 2)) + { + GameEngine_ResetLevel(&(pGameWindow->Engine)); + } + else + { + GameEngine_NextLevel(&(pGameWindow->Engine)); + } + + GameWindow_SetScene(pGameWindow, GameEngine_IsGameOver(&(pGameWindow->Engine)) ? GameEnd : Play); +} diff --git a/src/LevelEndScene.h b/src/LevelEndScene.h new file mode 100644 index 0000000..47becb5 --- /dev/null +++ b/src/LevelEndScene.h @@ -0,0 +1,13 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#ifndef LEVELENDSCENE_H +#define LEVELENDSCENE_H + +#include "GameWindow.h" + +void LevelEndScene_Init(GameWindow *pGameWindow); +void LevelEndScene_Draw(const GameWindow *pGameWindow, bool fullRefresh); +void LevelEndScene_Click(GameWindow *pGameWindow, const Point *pPosition); + +#endif diff --git a/src/Levels.c b/src/Levels.c index 1d8d68a..bbe790b 100644 --- a/src/Levels.c +++ b/src/Levels.c @@ -24,19 +24,22 @@ const uint32_t Levels_LightsB[] = { 0x1151151UL, 0x1F27C9FUL, 0x1F711DFUL, 0x04AFEA4UL, 0x1FFFFFFUL, }; -int8_t Levels_BoundLevel(const int8_t level) -{ - return max(level, 0) % LevelCount; -} - uint32_t Levels_GetLightsForLevel(const int8_t level, const bool setB) { - int8_t bLevel = Levels_BoundLevel(level); - return setB ? Levels_LightsB[bLevel] : Levels_LightsA[bLevel]; + if (level >= 0 && level < LevelCount) + { + return setB ? Levels_LightsB[level] : Levels_LightsA[level]; + } + + return 0; } uint16_t Levels_GetParForLevel(const int8_t level) { - return 6 + (Levels_BoundLevel(level) / 5); + if (level >= 0 && level < LevelCount) + { + return 6 + (level / 5); + } + + return 0; } - diff --git a/src/Levels.h b/src/Levels.h index 2c3498f..cd8a216 100644 --- a/src/Levels.h +++ b/src/Levels.h @@ -9,8 +9,6 @@ extern const int8_t LevelCount; -int8_t Levels_BoundLevel(const int8_t level); - uint32_t Levels_GetLightsForLevel(const int8_t level, const bool setB); uint16_t Levels_GetParForLevel(const int8_t level); diff --git a/src/MacCommon.c b/src/MacCommon.c index d919102..5d35cdf 100644 --- a/src/MacCommon.c +++ b/src/MacCommon.c @@ -13,3 +13,21 @@ void ShowError(Str255 message, Boolean isFatal) ExitToShell(); } } + +void CenterRect(const Rect *pOuterRect, Rect *pInnerRect) +{ + CenterRectH(pOuterRect, pInnerRect); + CenterRectV(pOuterRect, pInnerRect); +} + +void CenterRectH(const Rect *pOuterRect, Rect *pInnerRect) +{ + OffsetRect(pInnerRect, pOuterRect->left - pInnerRect->left, 0); + OffsetRect(pInnerRect, (pOuterRect->right - pInnerRect->right) / 2, 0); +} + +void CenterRectV(const Rect *pOuterRect, Rect *pInnerRect) +{ + OffsetRect(pInnerRect, 0, pOuterRect->top - pInnerRect->top); + OffsetRect(pInnerRect, 0, (pOuterRect->bottom - pInnerRect->bottom) / 2); +} \ No newline at end of file diff --git a/src/MacCommon.h b/src/MacCommon.h index 05a2bc3..40b6f4b 100644 --- a/src/MacCommon.h +++ b/src/MacCommon.h @@ -16,4 +16,8 @@ pascal OSErr SetDialogDefaultItem(DialogPtr theDialog, short newItem) = { 0x303C void ShowError(Str255 message, Boolean isFatal); +void CenterRect(const Rect *pOuterRect, Rect *pInnerRect); +void CenterRectH(const Rect *pOuterRect, Rect *pInnerRect); +void CenterRectV(const Rect *pOuterRect, Rect *pInnerRect); + #endif diff --git a/src/MacLO.c b/src/MacLO.c index 053bb62..31fb129 100644 --- a/src/MacLO.c +++ b/src/MacLO.c @@ -8,7 +8,8 @@ #define AboutMenuItemID 1 #define GameMenuResID BaseResID+1 -#define QuitMenuItemID 1 +#define NewMenuItemID 1 +#define QuitMenuItemID 3 #define AboutDialogResID BaseResID #define AboutDialogOKID 1 @@ -228,6 +229,9 @@ void MacLO_HandleGameMenuChoice(const short item) { switch (item) { + case NewMenuItemID: + GameWindow_SetScene(&gGameWindow, Title); + break; case QuitMenuItemID: gExitApp = true; break; diff --git a/src/MacLO.pi.bin b/src/MacLO.pi.bin index 743a81f..d2cafb7 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 7f5ddfb..0324b38 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 new file mode 100644 index 0000000..b8ac8a9 --- /dev/null +++ b/src/PlayScene.c @@ -0,0 +1,151 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#include "PlayScene.h" + +#define PlayfieldMargin 4 +#define PlayfieldPadding 2 +#define PlayfieldCornerSize 12 +#define LightMargin 6 +#define LightSize 50 +#define LightCornerSize 8 +#define PlayfieldPattern ltGray + +#define HUDMargin PlayfieldMargin +#define HUDCornerSize PlayfieldCornerSize +#define HUDPattern PlayfieldPattern + +void PlayScene_Init(GameWindow *pGameWindow) +{ + // Setup rects + pGameWindow->PlayScene.PlayfieldRect.top = PlayfieldMargin; + pGameWindow->PlayScene.PlayfieldRect.bottom = pGameWindow->Window->portRect.bottom - PlayfieldMargin; + pGameWindow->PlayScene.PlayfieldRect.left = pGameWindow->PlayScene.PlayfieldRect.top; + pGameWindow->PlayScene.PlayfieldRect.right = pGameWindow->PlayScene.PlayfieldRect.bottom; + + pGameWindow->PlayScene.HUDRect.top = HUDMargin; + pGameWindow->PlayScene.HUDRect.bottom = pGameWindow->Window->portRect.bottom - HUDMargin; + pGameWindow->PlayScene.HUDRect.left = pGameWindow->PlayScene.PlayfieldRect.right + HUDMargin; + pGameWindow->PlayScene.HUDRect.right = pGameWindow->Window->portRect.right - HUDMargin; +} + +void PlayScene_SetLightRect(const GameWindow *pGameWindow, Rect *pRect, const int8_t c, const int8_t r) +{ + pRect->top = pGameWindow->PlayScene.PlayfieldRect.top + PlayfieldPadding + LightMargin + (r * (LightMargin + LightSize)); + pRect->bottom = pRect->top + LightSize; + pRect->left = pGameWindow->PlayScene.PlayfieldRect.left + PlayfieldPadding + LightMargin + (c * (LightMargin + LightSize)); + pRect->right = pRect->left + LightSize; +} + +void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) +{ + int8_t r, c; + Rect lightRect; + Str255 levelStr, parStr, movesStr, halfStarsStr, scoreStr; + + SetPort(pGameWindow->Window); + + if (fullRefresh) + { + // Fill backgrounds + FillRoundRect(&(pGameWindow->PlayScene.PlayfieldRect), PlayfieldCornerSize, PlayfieldCornerSize, PlayfieldPattern); + FillRoundRect(&(pGameWindow->PlayScene.HUDRect), HUDCornerSize, HUDCornerSize, HUDPattern); + } + + // Draw Playfield + + // Draw lights + for (r = 0; r < PuzzleSize; r++) + { + for (c = 0; c < PuzzleSize; c++) + { + PlayScene_SetLightRect(pGameWindow, &lightRect, c, r); + + if (GameEngine_GetLight(&(pGameWindow->Engine), c, r)) + { + // Draw ON light + FillRoundRect(&lightRect, LightCornerSize, LightCornerSize, white); + } + else + { + // Draw OFF light + FillRoundRect(&lightRect, LightCornerSize, LightCornerSize, black); + } + } + } + + // Draw HUD + + ForeColor(blackColor); + TextFace(bold + outline); + + // Draw Level + MoveTo(pGameWindow->PlayScene.HUDRect.left + 10, pGameWindow->PlayScene.HUDRect.top + 20); + DrawString("\pLevel: "); + NumToString(1L + pGameWindow->Engine.Level, &levelStr); + DrawString(levelStr); + DrawString("\p/50"); + + // Draw Par + MoveTo(pGameWindow->PlayScene.HUDRect.left + 10, pGameWindow->PlayScene.HUDRect.top + 40); + DrawString("\pPar: "); + NumToString((long)(pGameWindow->Engine.Par), &parStr); + DrawString(parStr); + + // Draw Moves + MoveTo(pGameWindow->PlayScene.HUDRect.left + 10, pGameWindow->PlayScene.HUDRect.top + 60); + DrawString("\pMoves: "); + NumToString((long)(pGameWindow->Engine.Moves), &movesStr); + DrawString(movesStr); + DrawString("\p/"); + DrawString(parStr); + + // Draw Stars + MoveTo(pGameWindow->PlayScene.HUDRect.left + 10, pGameWindow->PlayScene.HUDRect.top + 80); + DrawString("\pStars: "); + NumToString((long)GameEngine_GetHalfStars(&(pGameWindow->Engine)), &halfStarsStr); + DrawString(halfStarsStr); + DrawString("\p/6"); + + // Draw Score + MoveTo(pGameWindow->PlayScene.HUDRect.left + 10, pGameWindow->PlayScene.HUDRect.top + 100); + DrawString("\pScore: "); + NumToString((long)(pGameWindow->Engine.Score), &scoreStr); + DrawString(scoreStr); + DrawString("\p/300"); +} + +void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition) +{ + int8_t r, c; + Rect lightRect; + + if (PtInRect(*pPosition, &(pGameWindow->PlayScene.PlayfieldRect))) + { + // Click within Playfield + for (r = 0; r < PuzzleSize; r++) + { + for (c = 0; c < PuzzleSize; c++) + { + PlayScene_SetLightRect(pGameWindow, &lightRect, c, r); + + if (PtInRect(*pPosition, &lightRect)) + { + GameEngine_ToggleLights(&(pGameWindow->Engine), c, r); + GameWindow_Draw(pGameWindow, false); + break; + } + } + } + + if (GameEngine_IsCompleted(&(pGameWindow->Engine))) + { + // Level was completed in the last click + GameWindow_SetScene(pGameWindow, LevelEnd); + } + } + else if (PtInRect(*pPosition, &(pGameWindow->PlayScene.HUDRect))) + { + // Click within HUD + } +} diff --git a/src/PlayScene.h b/src/PlayScene.h new file mode 100644 index 0000000..466d330 --- /dev/null +++ b/src/PlayScene.h @@ -0,0 +1,13 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#ifndef PLAYSCENE_H +#define PLAYSCENE_H + +#include "GameWindow.h" + +void PlayScene_Init(GameWindow *pGameWindow); +void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh); +void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition); + +#endif diff --git a/src/Scenes.h b/src/Scenes.h new file mode 100644 index 0000000..ef46def --- /dev/null +++ b/src/Scenes.h @@ -0,0 +1,29 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#ifndef SCENES_H +#define SCENES_H + +#define NumScenes 4 + +typedef enum SceneId +{ + Title, + Play, + LevelEnd, + GameEnd +} SceneId; + +typedef struct TitleScene +{ + PicHandle TitlePict; + Rect TitleRect; +} TitleScene; + +typedef struct PlayScene +{ + Rect PlayfieldRect; + Rect HUDRect; +} PlayScene; + +#endif diff --git a/src/TitleScene.c b/src/TitleScene.c new file mode 100644 index 0000000..cc2ef80 --- /dev/null +++ b/src/TitleScene.c @@ -0,0 +1,64 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#include "TitleScene.h" + +#define TitlePictResID BaseResID + +void TitleScene_Init(GameWindow *pGameWindow) +{ + const Rect *pContentRect = &(pGameWindow->Window->portRect); + + pGameWindow->TitleScene.TitlePict = GetPicture(TitlePictResID); + + if (pGameWindow->TitleScene.TitlePict == nil) + { + ShowError("\pTitle PICT resource missing!", true); + } + + // Setup rects + pGameWindow->TitleScene.TitleRect = (**(pGameWindow->TitleScene.TitlePict)).picFrame; + CenterRect(pContentRect, &(pGameWindow->TitleScene.TitleRect)); +} + +void TitleScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) +{ + SetPort(pGameWindow->Window); + + // TODO: Proper title + if (fullRefresh) + { + } + + // Draw Title PICT + DrawPicture(pGameWindow->TitleScene.TitlePict, &(pGameWindow->TitleScene.TitleRect)); + + ForeColor(blackColor); + TextFace(bold + outline); + + MoveTo(100, pGameWindow->TitleScene.TitleRect.bottom + 30); + DrawString("\pSet A"); + + MoveTo(350, pGameWindow->TitleScene.TitleRect.bottom + 30); + DrawString("\pSet B"); +} + +void TitleScene_Click(GameWindow *pGameWindow, const Point *pPosition) +{ + bool setB; + + // TODO: Proper click handling + + if (pPosition->h < ((pGameWindow->Window->portRect.right - pGameWindow->Window->portRect.left) / 2)) + { + setB = false; + } + else + { + setB = true; + } + + GameEngine_NewGame(&(pGameWindow->Engine), setB); + + GameWindow_SetScene(pGameWindow, Play); +} diff --git a/src/TitleScene.h b/src/TitleScene.h new file mode 100644 index 0000000..1ace401 --- /dev/null +++ b/src/TitleScene.h @@ -0,0 +1,13 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#ifndef TITLESCENE_H +#define TITLESCENE_H + +#include "GameWindow.h" + +void TitleScene_Init(GameWindow *pGameWindow); +void TitleScene_Draw(const GameWindow *pGameWindow, bool fullRefresh); +void TitleScene_Click(GameWindow *pGameWindow, const Point *pPosition); + +#endif