Refactored scenes into separate files, added game end, added title logo

This commit is contained in:
Jon Thysell 2021-10-31 15:13:51 -07:00
parent 866dadb28d
commit 66794a2241
21 changed files with 488 additions and 285 deletions

BIN
img/title.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

36
src/GameEndScene.c Normal file
View File

@ -0,0 +1,36 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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);
}

13
src/GameEndScene.h Normal file
View File

@ -0,0 +1,13 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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

51
src/LevelEndScene.c Normal file
View File

@ -0,0 +1,51 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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);
}

13
src/LevelEndScene.h Normal file
View File

@ -0,0 +1,13 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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;

Binary file not shown.

Binary file not shown.

151
src/PlayScene.c Normal file
View File

@ -0,0 +1,151 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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
}
}

13
src/PlayScene.h Normal file
View File

@ -0,0 +1,13 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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

29
src/Scenes.h Normal file
View File

@ -0,0 +1,29 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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

64
src/TitleScene.c Normal file
View File

@ -0,0 +1,64 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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);
}

13
src/TitleScene.h Normal file
View File

@ -0,0 +1,13 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// 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