diff --git a/img/0.gif b/assets/0.gif similarity index 100% rename from img/0.gif rename to assets/0.gif diff --git a/img/1.gif b/assets/1.gif similarity index 100% rename from img/1.gif rename to assets/1.gif diff --git a/img/2.gif b/assets/2.gif similarity index 100% rename from img/2.gif rename to assets/2.gif diff --git a/img/3.gif b/assets/3.gif similarity index 100% rename from img/3.gif rename to assets/3.gif diff --git a/img/4.gif b/assets/4.gif similarity index 100% rename from img/4.gif rename to assets/4.gif diff --git a/img/5.gif b/assets/5.gif similarity index 100% rename from img/5.gif rename to assets/5.gif diff --git a/img/6.gif b/assets/6.gif similarity index 100% rename from img/6.gif rename to assets/6.gif diff --git a/img/7.gif b/assets/7.gif similarity index 100% rename from img/7.gif rename to assets/7.gif diff --git a/img/8.gif b/assets/8.gif similarity index 100% rename from img/8.gif rename to assets/8.gif diff --git a/img/9.gif b/assets/9.gif similarity index 100% rename from img/9.gif rename to assets/9.gif diff --git a/img/a.gif b/assets/a.gif similarity index 100% rename from img/a.gif rename to assets/a.gif diff --git a/img/b.gif b/assets/b.gif similarity index 100% rename from img/b.gif rename to assets/b.gif diff --git a/assets/click.wav b/assets/click.wav new file mode 100644 index 0000000..91aab73 Binary files /dev/null and b/assets/click.wav differ diff --git a/assets/done.wav b/assets/done.wav new file mode 100644 index 0000000..31d38c2 Binary files /dev/null and b/assets/done.wav differ diff --git a/img/next.gif b/assets/next.gif similarity index 100% rename from img/next.gif rename to assets/next.gif diff --git a/img/retry.gif b/assets/retry.gif similarity index 100% rename from img/retry.gif rename to assets/retry.gif diff --git a/assets/retry.wav b/assets/retry.wav new file mode 100644 index 0000000..28fd57f Binary files /dev/null and b/assets/retry.wav differ diff --git a/img/slash.gif b/assets/slash.gif similarity index 100% rename from img/slash.gif rename to assets/slash.gif diff --git a/img/sound0.gif b/assets/sound0.gif similarity index 100% rename from img/sound0.gif rename to assets/sound0.gif diff --git a/img/sound1.gif b/assets/sound1.gif similarity index 100% rename from img/sound1.gif rename to assets/sound1.gif diff --git a/img/star0.gif b/assets/star0.gif similarity index 100% rename from img/star0.gif rename to assets/star0.gif diff --git a/img/star1.gif b/assets/star1.gif similarity index 100% rename from img/star1.gif rename to assets/star1.gif diff --git a/img/star2.gif b/assets/star2.gif similarity index 100% rename from img/star2.gif rename to assets/star2.gif diff --git a/img/title.gif b/assets/title.gif similarity index 100% rename from img/title.gif rename to assets/title.gif diff --git a/src/Bitmaps.c b/src/Bitmaps.c index 68b099e..296cb37 100644 --- a/src/Bitmaps.c +++ b/src/Bitmaps.c @@ -11,6 +11,8 @@ #define StarPictBaseResID (SlashCharPictResID + 1) #define NextButtonPictResID (StarPictBaseResID + StarPictCount) #define RetryButtonPictResID (NextButtonPictResID + 1) +#define SoundOffPictResID (RetryButtonPictResID + 1) +#define SoundOnPictResID (SoundOffPictResID + 1) #define StarRectPadding 2 @@ -66,7 +68,7 @@ void Bitmaps_Init(Bitmaps *pBitmaps) } } - // Load next button + // Load slash char pBitmaps->SlashCharPict = GetPicture(SlashCharPictResID); if (pBitmaps->SlashCharPict == nil) { @@ -86,6 +88,20 @@ void Bitmaps_Init(Bitmaps *pBitmaps) { ShowError("\pRetry button PICT resource missing!", true); } + + // Load sound off + pBitmaps->SoundOffPict = GetPicture(SoundOffPictResID); + if (pBitmaps->SoundOffPict == nil) + { + ShowError("\pSound off PICT resource missing!", true); + } + + // Load sound on + pBitmaps->SoundOnPict = GetPicture(SoundOnPictResID); + if (pBitmaps->SoundOnPict == nil) + { + ShowError("\pSound on PICT resource missing!", true); + } } void Bitmaps_GetNumberRect(const Bitmaps *pBitmaps, const uint32_t number, const uint8_t scale, Rect *pDestRect) @@ -216,6 +232,35 @@ void Bitmaps_DrawHalfStars(const Bitmaps *pBitmaps, const uint8_t halfStars, con for (; drawn < maxStars; drawn++) { DrawScaledPic(pBitmaps->StarPicts[0], scale); + GetPen(&penPosition); MoveTo(penPosition.h + (StarRectPadding * scale), penPosition.v); } } + +void Bitmaps_GetSoundRect(const Bitmaps *pBitmaps, const bool enabled, const uint8_t scale, Rect *pDestRect) +{ + Rect r; + + GetScaledPicFrame(pBitmaps->SoundOffPict, scale, pDestRect); + GetScaledPicFrame(pBitmaps->SoundOnPict, scale, &r); + ConcatenateRect(pDestRect, &r, pDestRect); +} + +void Bitmaps_DrawSound(const Bitmaps *pBitmaps, const bool enabled, const uint8_t scale) +{ + Point penPosition; + Rect r; + + DrawScaledPic(pBitmaps->SoundOffPict, scale); + if (enabled) + { + DrawScaledPic(pBitmaps->SoundOnPict, scale); + } + else + { + GetScaledPicFrame(pBitmaps->SoundOnPict, scale, &r); + GetPen(&penPosition); + OffsetRect(&r, penPosition.h, penPosition.v); + FillRect(&r, black); + } +} diff --git a/src/Bitmaps.h b/src/Bitmaps.h index 408a27f..5431773 100644 --- a/src/Bitmaps.h +++ b/src/Bitmaps.h @@ -35,4 +35,7 @@ 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); +void Bitmaps_GetSoundRect(const Bitmaps *pBitmaps, const bool enabled, const uint8_t scale, Rect *pDestRect); +void Bitmaps_DrawSound(const Bitmaps *pBitmaps, const bool enabled, const uint8_t scale); + #endif diff --git a/src/GameEndScene.c b/src/GameEndScene.c index 02ca7d6..2252648 100644 --- a/src/GameEndScene.c +++ b/src/GameEndScene.c @@ -32,6 +32,9 @@ void GameEndScene_Init(GameWindow *pGameWindow) GetBoxRect(pContentRect, Bottom, &r); GetBoxRect(&r, Top, &r); CenterRect(&r, &(pGameWindow->GameEndScene.ScoreRect)); + + // Play done sound + Sounds_PlayDoneSnd(&(pGameWindow->Sounds)); } void GameEndScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) diff --git a/src/GameWindow.c b/src/GameWindow.c index 235306f..6a86a8d 100644 --- a/src/GameWindow.c +++ b/src/GameWindow.c @@ -24,6 +24,9 @@ void GameWindow_Init(GameWindow *pGameWindow) // Load PICT resources Bitmaps_Init(&(pGameWindow->Bitmaps)); + // Load snd resources + Sounds_Init(&(pGameWindow->Sounds)); + GameWindow_SetScene(pGameWindow, Title); } diff --git a/src/GameWindow.h b/src/GameWindow.h index 44c0286..367e8c2 100644 --- a/src/GameWindow.h +++ b/src/GameWindow.h @@ -7,6 +7,7 @@ #include "MacCommon.h" #include "GameEngine.h" #include "Bitmaps.h" +#include "Sounds.h" #include "Scenes.h" #define WindowPattern black @@ -16,6 +17,7 @@ typedef struct sGameWindow WindowPtr Window; GameEngine Engine; Bitmaps Bitmaps; + Sounds Sounds; SceneId CurrentSceneId; TitleScene TitleScene; PlayScene PlayScene; diff --git a/src/LevelEndScene.c b/src/LevelEndScene.c index c788b06..6152c8a 100644 --- a/src/LevelEndScene.c +++ b/src/LevelEndScene.c @@ -48,6 +48,9 @@ void LevelEndScene_Init(GameWindow *pGameWindow) GetBoxRect(pContentRect, BottomRight, &r); CenterRect(&r, &(pGameWindow->LevelEndScene.NextButtonRect)); + + // Play done sound + Sounds_PlayDoneSnd(&(pGameWindow->Sounds)); } void LevelEndScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) @@ -85,11 +88,13 @@ void LevelEndScene_Click(GameWindow *pGameWindow, const Point *pPosition) { if (PtInRect(*pPosition, &(pGameWindow->LevelEndScene.RetryButtonRect))) { + Sounds_PlayRetrySnd(&(pGameWindow->Sounds)); GameEngine_ResetLevel(&(pGameWindow->Engine)); GameWindow_SetScene(pGameWindow, Play); } else if (PtInRect(*pPosition, &(pGameWindow->LevelEndScene.NextButtonRect))) { + Sounds_PlayClickSnd(&(pGameWindow->Sounds)); GameEngine_NextLevel(&(pGameWindow->Engine)); GameWindow_SetScene(pGameWindow, GameEngine_IsGameOver(&(pGameWindow->Engine)) ? GameEnd : Play); } diff --git a/src/MacLO.c b/src/MacLO.c index 4863ef9..8a89295 100644 --- a/src/MacLO.c +++ b/src/MacLO.c @@ -199,7 +199,7 @@ void MacLO_HandleAppleMenuChoice(const int16_t item) void MacLO_ShowAboutDialog() { DialogPtr dialog; - int itemHit; + int32_t itemHit; dialog = GetNewDialog(AboutDialogResID, nil, MoveToFront); @@ -222,7 +222,6 @@ void MacLO_LaunchAppleMenuItem(const int16_t item) appleMenu = GetMHandle(AppleMenuResID); GetItem(appleMenu, item, accName); OpenDeskAcc(accName); - } void MacLO_HandleGameMenuChoice(const int16_t item) diff --git a/src/MacLO.pi.bin b/src/MacLO.pi.bin index 829953b..ff7f326 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 cf1de4c..99d58e0 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 7ca1738..e265aee 100644 --- a/src/PlayScene.c +++ b/src/PlayScene.c @@ -9,11 +9,9 @@ #define LightMargin 6 #define LightSize 50 #define LightCornerSize 12 -#define PlayfieldPattern ltGray #define HUDMargin PlayfieldMargin #define HUDCornerSize PlayfieldCornerSize -#define HUDPattern PlayfieldPattern #define LevelTextScale 3 #define HalfStarScale 2 @@ -66,6 +64,11 @@ void PlayScene_Init(GameWindow *pGameWindow) GetBoxRect(&(pGameWindow->PlayScene.HUDRect), BottomLeft, &r); CenterRect(&r, &(pGameWindow->PlayScene.RetryButtonRect)); + + // Setup sound button + Bitmaps_GetSoundRect(&(pGameWindow->Bitmaps), pGameWindow->Sounds.Enabled, 1, &(pGameWindow->PlayScene.SoundButtonRect)); + GetBoxRect(&(pGameWindow->PlayScene.HUDRect), BottomRight, &r); + CenterRect(&r, &(pGameWindow->PlayScene.SoundButtonRect)); } void PlayScene_SetLightRect(const GameWindow *pGameWindow, Rect *pRect, const int8_t c, const int8_t r) @@ -86,7 +89,6 @@ void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) // Fill backgrounds ForeColor(whiteColor); FrameRoundRect(&(pGameWindow->PlayScene.PlayfieldRect), PlayfieldCornerSize, PlayfieldCornerSize); - FrameRoundRect(&(pGameWindow->PlayScene.HUDRect), HUDCornerSize, HUDCornerSize); ForeColor(blackColor); } @@ -138,6 +140,11 @@ void PlayScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) // Draw retry button DrawPicture(pGameWindow->Bitmaps.RetryButtonPict, &(pGameWindow->PlayScene.RetryButtonRect)); + + // Draw sound button + MoveTo(pGameWindow->PlayScene.SoundButtonRect.left, pGameWindow->PlayScene.SoundButtonRect.top); + Bitmaps_DrawSound(&(pGameWindow->Bitmaps), pGameWindow->Sounds.Enabled, 1); + } void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition) @@ -156,6 +163,7 @@ void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition) if (PtInRect(*pPosition, &lightRect)) { + Sounds_PlayClickSnd(&(pGameWindow->Sounds)); GameEngine_ToggleLights(&(pGameWindow->Engine), c, r); GameWindow_Draw(pGameWindow, false); break; @@ -176,8 +184,14 @@ void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition) if (PtInRect(*pPosition, &(pGameWindow->PlayScene.RetryButtonRect))) { + Sounds_PlayRetrySnd(&(pGameWindow->Sounds)); GameEngine_ResetLevel(&(pGameWindow->Engine)); GameWindow_Draw(pGameWindow, false); } + else if (PtInRect(*pPosition, &(pGameWindow->PlayScene.SoundButtonRect))) + { + pGameWindow->Sounds.Enabled = !pGameWindow->Sounds.Enabled; + GameWindow_Draw(pGameWindow, false); + } } } diff --git a/src/Scenes.h b/src/Scenes.h index f712b83..597de22 100644 --- a/src/Scenes.h +++ b/src/Scenes.h @@ -19,6 +19,7 @@ typedef struct sTitleScene Rect TitleRect; Rect SetARect; Rect SetBRect; + Rect SoundButtonRect; } TitleScene; typedef struct sPlayScene @@ -29,6 +30,7 @@ typedef struct sPlayScene Rect HalfStarsRect; Rect ScoreRect; Rect RetryButtonRect; + Rect SoundButtonRect; } PlayScene; typedef struct sLevelEndScene diff --git a/src/Sounds.c b/src/Sounds.c new file mode 100644 index 0000000..00c2731 --- /dev/null +++ b/src/Sounds.c @@ -0,0 +1,60 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#include "Sounds.h" + +#define ClickSndResID BaseResID +#define RetrySndResID (ClickSndResID + 1) +#define DoneSndResID (RetrySndResID + 1) + +#define DefaultEnabled true +#define PlaySoundsAsync true + +void Sounds_Init(Sounds *pSounds) +{ + pSounds->Enabled = DefaultEnabled; + + SndNewChannel(&(pSounds->SndChannel), 0, 0, nil); + + pSounds->ClickSnd = GetResource('snd ', ClickSndResID); + if (pSounds->ClickSnd == nil) + { + ShowError("\pClick snd resource missing!", true); + } + + pSounds->RetrySnd = GetResource('snd ', RetrySndResID); + if (pSounds->RetrySnd == nil) + { + ShowError("\pRetry snd resource missing!", true); + } + + pSounds->DoneSnd = GetResource('snd ', DoneSndResID); + if (pSounds->DoneSnd == nil) + { + ShowError("\pDone snd resource missing!", true); + } +} + +void Sounds_PlayClickSnd(const Sounds *pSounds) +{ + if (pSounds->Enabled) + { + SndPlay(pSounds->SndChannel, pSounds->ClickSnd, PlaySoundsAsync); + } +} + +void Sounds_PlayRetrySnd(const Sounds *pSounds) +{ + if (pSounds->Enabled) + { + SndPlay(pSounds->SndChannel, pSounds->RetrySnd, PlaySoundsAsync); + } +} + +void Sounds_PlayDoneSnd(const Sounds *pSounds) +{ + if (pSounds->Enabled) + { + SndPlay(pSounds->SndChannel, pSounds->DoneSnd, PlaySoundsAsync); + } +} diff --git a/src/Sounds.h b/src/Sounds.h new file mode 100644 index 0000000..67cc9f4 --- /dev/null +++ b/src/Sounds.h @@ -0,0 +1,26 @@ +// Copyright (c) Jon Thysell +// Licensed under the MIT License. + +#ifndef SOUNDS_H +#define SOUNDS_H + +#include + +#include "MacCommon.h" + +typedef struct sSounds +{ + bool Enabled; + SndChannelPtr SndChannel; + Handle ClickSnd; + Handle RetrySnd; + Handle DoneSnd; +} Sounds; + +void Sounds_Init(Sounds *pSounds); + +void Sounds_PlayClickSnd(const Sounds *pSounds); +void Sounds_PlayRetrySnd(const Sounds *pSounds); +void Sounds_PlayDoneSnd(const Sounds *pSounds); + +#endif diff --git a/src/TitleScene.c b/src/TitleScene.c index 1b3a283..ee3ebc9 100644 --- a/src/TitleScene.c +++ b/src/TitleScene.c @@ -12,17 +12,24 @@ void TitleScene_Init(GameWindow *pGameWindow) const Rect *pContentRect = &(pGameWindow->Window->portRect); - // Setup rects + // Setup Title GetPictureRect(pGameWindow->Bitmaps.TitlePict, &(pGameWindow->TitleScene.TitleRect)); CenterRect(pContentRect, &(pGameWindow->TitleScene.TitleRect)); - GetBoxRect(pContentRect, BottomLeft, &r); + // Setup Set A GetScaledPicFrame(pGameWindow->Bitmaps.ACharPict, TitleTextScale, &(pGameWindow->TitleScene.SetARect)); + GetBoxRect(pContentRect, BottomLeft, &r); CenterRect(&r, &(pGameWindow->TitleScene.SetARect)); - GetBoxRect(pContentRect, BottomRight, &r); + // Setup Set B GetScaledPicFrame(pGameWindow->Bitmaps.BCharPict, TitleTextScale, &(pGameWindow->TitleScene.SetBRect)); + GetBoxRect(pContentRect, BottomRight, &r); CenterRect(&r, &(pGameWindow->TitleScene.SetBRect)); + + // Setup sound button + Bitmaps_GetSoundRect(&(pGameWindow->Bitmaps), pGameWindow->Sounds.Enabled, TitleTextScale, &(pGameWindow->TitleScene.SoundButtonRect)); + GetBoxRect(pContentRect, Bottom, &r); + CenterRect(&r, &(pGameWindow->TitleScene.SoundButtonRect)); } void TitleScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) @@ -37,18 +44,29 @@ void TitleScene_Draw(const GameWindow *pGameWindow, bool fullRefresh) // Draw Set B MoveTo(pGameWindow->TitleScene.SetBRect.left, pGameWindow->TitleScene.SetBRect.top); Bitmaps_DrawBChar(&(pGameWindow->Bitmaps), TitleTextScale); + + // Draw sound button + MoveTo(pGameWindow->TitleScene.SoundButtonRect.left, pGameWindow->TitleScene.SoundButtonRect.top); + Bitmaps_DrawSound(&(pGameWindow->Bitmaps), pGameWindow->Sounds.Enabled, TitleTextScale); } void TitleScene_Click(GameWindow *pGameWindow, const Point *pPosition) { if (PtInRect(*pPosition, &(pGameWindow->TitleScene.SetARect))) { + Sounds_PlayClickSnd(&(pGameWindow->Sounds)); GameEngine_NewGame(&(pGameWindow->Engine), false); GameWindow_SetScene(pGameWindow, Play); } else if (PtInRect(*pPosition, &(pGameWindow->TitleScene.SetBRect))) { + Sounds_PlayClickSnd(&(pGameWindow->Sounds)); GameEngine_NewGame(&(pGameWindow->Engine), true); GameWindow_SetScene(pGameWindow, Play); } + else if (PtInRect(*pPosition, &(pGameWindow->TitleScene.SoundButtonRect))) + { + pGameWindow->Sounds.Enabled = !pGameWindow->Sounds.Enabled; + GameWindow_Draw(pGameWindow, false); + } }