diff --git a/src/GameEngine.c b/src/GameEngine.c index ccb10ab..7357377 100644 --- a/src/GameEngine.c +++ b/src/GameEngine.c @@ -13,6 +13,7 @@ const uint8_t MinHalfStars = 1; const uint16_t PerfectScore = 300; // LevelCount * MaxHalfStars void GameEngine_LoadLevel(GameEngine *pGameEngine, const int8_t level, const bool setB); +uint8_t GameEngine_CalculateHalfStars(const uint16_t par, const uint16_t moves); void GameEngine_ToggleSingleLight(GameEngine *pGameEngine, const int8_t x, const int8_t y); void GameEngine_NewGame(GameEngine *pGameEngine, const bool setB) @@ -39,6 +40,7 @@ void GameEngine_LoadLevel(GameEngine *pGameEngine, const int8_t level, const boo { pGameEngine->Level = level; pGameEngine->SetB = setB; + pGameEngine->PreviousLights = pGameEngine->Lights; pGameEngine->Lights = Levels_GetLightsForLevel(pGameEngine->Level, setB); pGameEngine->Par = Levels_GetParForLevel(pGameEngine->Level); pGameEngine->Moves = 0; @@ -66,7 +68,12 @@ bool GameEngine_IsGameOver(const GameEngine *pGameEngine) uint8_t GameEngine_GetHalfStars(const GameEngine *pGameEngine) { - uint8_t halfStarsLost = pGameEngine->Moves <= pGameEngine->Par ? 0 : max(0, (1 + pGameEngine->Moves - pGameEngine->Par) / 2); + return GameEngine_CalculateHalfStars(pGameEngine->Par, pGameEngine->Moves); +} + +uint8_t GameEngine_CalculateHalfStars(const uint16_t par, const uint16_t moves) +{ + uint8_t halfStarsLost = moves <= par ? 0 : max(0, (1 + moves - par) / 2); return max(MinHalfStars, MaxHalfStars - halfStarsLost); } @@ -75,6 +82,8 @@ void GameEngine_ToggleLights(GameEngine *pGameEngine, const int8_t x, const int8 int8_t targetX = max(0, min(x, PuzzleSize - 1)); int8_t targetY = max(0, min(y, PuzzleSize - 1)); + pGameEngine->PreviousLights = pGameEngine->Lights; + GameEngine_ToggleSingleLight(pGameEngine, targetX, targetY); GameEngine_ToggleSingleLight(pGameEngine, targetX + 1, targetY); GameEngine_ToggleSingleLight(pGameEngine, targetX, targetY + 1); @@ -91,3 +100,19 @@ void GameEngine_ToggleSingleLight(GameEngine *pGameEngine, const int8_t x, const bitToggle(pGameEngine->Lights, y * PuzzleSize + x); } } + +bool GameEngine_LightChanged(const GameEngine *pGameEngine, const int8_t x, const int8_t y) +{ + if (x >= 0 && x < PuzzleSize && y >= 0 && y < PuzzleSize) + { + return bitRead(pGameEngine->Lights, y * PuzzleSize + x) != bitRead(pGameEngine->PreviousLights, y * PuzzleSize + x); + } + + return false; +} + +bool GameEngine_HalfStarsChanged(const GameEngine *pGameEngine) +{ + return pGameEngine->Moves == 0 || + GameEngine_CalculateHalfStars(pGameEngine->Par, pGameEngine->Moves - 1) != GameEngine_GetHalfStars(pGameEngine); +} diff --git a/src/GameEngine.h b/src/GameEngine.h index 124bfb2..2a2e3d4 100644 --- a/src/GameEngine.h +++ b/src/GameEngine.h @@ -20,6 +20,7 @@ typedef struct GameEngine int8_t Level; bool SetB; uint32_t Lights; + uint32_t PreviousLights; uint16_t Par; uint16_t Moves; } GameEngine; @@ -40,4 +41,8 @@ uint8_t GameEngine_GetHalfStars(const GameEngine *pGameEngine); void GameEngine_ToggleLights(GameEngine *pGameEngine, const int8_t x, const int8_t y); +bool GameEngine_LightChanged(const GameEngine *pGameEngine, const int8_t x, const int8_t y); + +bool GameEngine_HalfStarsChanged(const GameEngine *pGameEngine); + #endif diff --git a/src/GameWindow.c b/src/GameWindow.c index d59714d..e891366 100644 --- a/src/GameWindow.c +++ b/src/GameWindow.c @@ -110,8 +110,9 @@ void GameWindow_SetScene(GameWindow *pGameWindow, const SceneId sceneId) GameEndScene_Init(pGameWindow); break; } + pGameWindow->CurrentSceneId = sceneId; - GameWindow_Draw(pGameWindow, true); + GameWindow_Draw(pGameWindow, true); // Always force a full refresh when changing scenes } void GameWindow_Show(const GameWindow *pGameWindow) diff --git a/src/MacLO.pi.bin b/src/MacLO.pi.bin index 5b06658..c2bc12a 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 f1e7fef..5817b7c 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 69c42e4..c192029 100644 --- a/src/PlayScene.c +++ b/src/PlayScene.c @@ -98,17 +98,20 @@ void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) { for (c = 0; c < PuzzleSize; c++) { - PlayScene_SetLightRect(pGameWindow, &lightRect, c, r); - - if (GameEngine_GetLight(&(pGameWindow->Engine), c, r)) + if (fullRefresh || GameEngine_LightChanged(&(pGameWindow->Engine), c, r)) { - // Draw ON light - DrawPicture(pGameWindow->Bitmaps.LightOnPict, &lightRect); - } - else - { - // Draw OFF light - DrawPicture(pGameWindow->Bitmaps.LightOffPict, &lightRect); + PlayScene_SetLightRect(pGameWindow, &lightRect, c, r); + + if (GameEngine_GetLight(&(pGameWindow->Engine), c, r)) + { + // Draw ON light + DrawPicture(pGameWindow->Bitmaps.LightOnPict, &lightRect); + } + else + { + // Draw OFF light + DrawPicture(pGameWindow->Bitmaps.LightOffPict, &lightRect); + } } } } @@ -116,29 +119,41 @@ void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) // Draw HUD // Draw level - MoveTo(pGameWindow->PlayScene.LevelRect.left, pGameWindow->PlayScene.LevelRect.top); - if (pGameWindow->Engine.SetB) + if (fullRefresh) { - Bitmaps_DrawBChar(&(pGameWindow->Bitmaps), LevelTextScale); + MoveTo(pGameWindow->PlayScene.LevelRect.left, pGameWindow->PlayScene.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); } - else - { - Bitmaps_DrawAChar(&(pGameWindow->Bitmaps), LevelTextScale); - } - Bitmaps_DrawNumber(&(pGameWindow->Bitmaps), 1 + pGameWindow->Engine.Level, LevelTextScale); // Draw half-stars - MoveTo(pGameWindow->PlayScene.HalfStarsRect.left, pGameWindow->PlayScene.HalfStarsRect.top); - Bitmaps_DrawHalfStars(&(pGameWindow->Bitmaps), GameEngine_GetHalfStars(&(pGameWindow->Engine)), MaxStars, HalfStarScale); + if (fullRefresh || GameEngine_HalfStarsChanged(&(pGameWindow->Engine))) + { + 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); + if (fullRefresh) + { + 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)); + if (fullRefresh) + { + DrawPicture(pGameWindow->Bitmaps.RetryButtonPict, &(pGameWindow->PlayScene.RetryButtonRect)); + } // Draw sound button MoveTo(pGameWindow->PlayScene.SoundButtonRect.left, pGameWindow->PlayScene.SoundButtonRect.top);