Added saving of progress to the application's 'SAVE' resource

This commit is contained in:
Jon Thysell 2021-12-12 15:45:28 -08:00
parent 5a4928ba39
commit cdf67289a9
14 changed files with 174 additions and 5 deletions

View File

@ -48,8 +48,7 @@ void GameEngine_Init(GameEngine *pGameEngine)
for (level = 0; level < LevelCount; level++)
{
// TODO: Load actual scores
pGameEngine->ScoresA[level] = 1;
pGameEngine->ScoresA[level] = 0;
pGameEngine->ScoresB[level] = 0;
}

80
src/GameSave.c Normal file
View File

@ -0,0 +1,80 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// Licensed under the MIT License.
/**
* @file GameSave.c
*
* This file provides implementations for GameSave.h.
*/
#include "GameSave.h"
#include "MacCommon.h"
/** The save resource type. */
#define SaveResType 'SAVE'
/** The save resource ID. */
#define SaveResID 128
/** The save resource ID. */
#define SaveResSize (sizeof(uint8_t) * SetCount * LevelCount)
void GameSave_Init(GameSave *pGameSave)
{
pGameSave->Save = GetOrAddResource(SaveResType, SaveResID, SaveResSize, EmptyString);
if (pGameSave->Save == nil)
{
ShowError("\pGame's SAVE resource couldn't be created!", true);
}
}
void GameSave_LoadData(const GameSave *pSaveGame, GameEngine *pGameEngine)
{
int8_t level, scoreA, scoreB;
bool resetA, resetB;
HLock(pSaveGame->Save);
resetA = false;
resetB = false;
for (level = 0; level < LevelCount; level++)
{
scoreA = min(MaxHalfStars, (*pSaveGame->Save)[level]);
resetA = resetA || (scoreA < MinHalfStars);
pGameEngine->ScoresA[level] = resetA ? 0 : scoreA;
scoreB = min(MaxHalfStars, (*pSaveGame->Save)[LevelCount + level]);
resetB = resetB || (scoreB < MinHalfStars);
pGameEngine->ScoresB[level] = resetB ? 0 : scoreB;
}
HUnlock(pSaveGame->Save);
}
void GameSave_SaveData(GameSave *pSaveGame, const GameEngine *pGameEngine)
{
int8_t level;
bool dataChanged;
HLock(pSaveGame->Save);
dataChanged = false;
for (level = 0; level < LevelCount; level++)
{
dataChanged = dataChanged
|| ((*pSaveGame->Save)[level] != pGameEngine->ScoresA[level])
|| ((*pSaveGame->Save)[LevelCount + level] != pGameEngine->ScoresB[level]);
(*pSaveGame->Save)[level] = pGameEngine->ScoresA[level];
(*pSaveGame->Save)[LevelCount + level] = pGameEngine->ScoresB[level];
}
HUnlock(pSaveGame->Save);
if (dataChanged)
{
ChangedResource(pSaveGame->Save);
WriteResource(pSaveGame->Save);
}
}

41
src/GameSave.h Normal file
View File

@ -0,0 +1,41 @@
// Copyright (c) Jon Thysell <http://jonthysell.com>
// Licensed under the MIT License.
/**
* @file GameSave.h
*
* This file provides a GameSave type which manages saving scores to disk.
*/
#ifndef GAMESAVE_H
#define GAMESAVE_H
#include "GameEngine.h"
/** Struct containing handle to the save resource. */
typedef struct sGameSave
{
Handle Save;
} GameSave;
/**
* Initializes the GameSave.
* @param pGameSave The GameSave.
*/
void GameSave_Init(GameSave *pSaveGame);
/**
* Loads data from the GameSave into the GameEngine.
* @param pGameSave The GameSave.
* @param pGameEngine The GameEngine.
*/
void GameSave_LoadData(const GameSave *pSaveGame, GameEngine *pGameEngine);
/**
* Saves data from the GameEngine into the GameSave.
* @param pGameSave The GameSave.
* @param pGameEngine The GameEngine.
*/
void GameSave_SaveData(GameSave *pSaveGame, const GameEngine *pGameEngine);
#endif

View File

@ -34,6 +34,9 @@ void GameWindow_Init(GameWindow *pGameWindow)
// Initialize game engine
GameEngine_Init(&(pGameWindow->Engine));
// Initialize game save
GameSave_Init(&(pGameWindow->GameSave));
// Load PICT resources
Bitmaps_Init(&(pGameWindow->Bitmaps));
@ -44,6 +47,9 @@ void GameWindow_Init(GameWindow *pGameWindow)
SetPort(pGameWindow->Window);
FillRect(&(pGameWindow->Window->portRect), WindowPattern);
// Load data from saved game
GameSave_LoadData(&(pGameWindow->GameSave), &(pGameWindow->Engine));
GameWindow_SetScene(pGameWindow, Title);
}
@ -144,6 +150,7 @@ void GameWindow_ClearScores(GameWindow *pGameWindow)
if (ShowConfirm("\pAre you sure you want to clear all scores?"))
{
GameEngine_ResetGame(&(pGameWindow->Engine));
GameSave_SaveData(&(pGameWindow->GameSave), &(pGameWindow->Engine));
GameWindow_SetScene(pGameWindow, Title);
}
}

View File

@ -17,6 +17,7 @@
#include "MacCommon.h"
#include "WindowBuffer.h"
#include "GameEngine.h"
#include "GameSave.h"
#include "Bitmaps.h"
#include "Sounds.h"
#include "Scenes.h"
@ -30,6 +31,7 @@ typedef struct sGameWindow
WindowPtr Window;
WindowBuffer WindowBuffer;
GameEngine Engine;
GameSave GameSave;
Bitmaps Bitmaps;
Sounds Sounds;
SceneId CurrentSceneId;

View File

@ -18,6 +18,9 @@
/** The number of levels in each set. */
#define LevelCount 50
/** The number of sets. */
#define SetCount 2
/**
* Gets the lights for a given set and level number.
* @param level The level number.

View File

@ -164,3 +164,28 @@ void DrawScaledPic(const PicHandle pic, const uint8_t scale)
DrawPicture(pic, &destRect);
MoveTo(destRect.right, destRect.top);
}
Handle GetOrAddResource(ResType resType, uint16_t resID, Size byteCount, Str255 resName)
{
Handle result;
result = GetResource(resType, resID);
if (result != nil && GetHandleSize(result) != byteCount)
{
// Resource was the wrong size, delete it
RmveResource(result);
ReleaseResource(result);
result = nil;
}
if (result == nil)
{
// Resource didn't exist, create it
result = NewHandleClear(byteCount);
HNoPurge(result);
AddResource(result, resType, resID, resName);
}
return result;
}

View File

@ -122,4 +122,14 @@ void GetScaledPicFrame(const PicHandle picHandle, const uint8_t scale, Rect *pDe
*/
void DrawScaledPic(const PicHandle pic, const uint8_t scale);
/**
* Gets the specified resource or creates it if it doesn't exist.
* @param resType The resource type.
* @param resID The resource ID.
* @param byteCount The size of the resource if it needs to be created.
* @param resName The resource name if it needs to be created.
* @return Handle to the resource.
*/
Handle GetOrAddResource(ResType resType, uint16_t resID, Size byteCount, Str255 resName);
#endif

View File

@ -313,5 +313,6 @@ void MacLO_Quit()
if (ShowConfirm("\pAre you sure you want to quit MacLO?"))
{
gExitApp = true;
GameSave_SaveData(&(gGameWindow.GameSave), &(gGameWindow.Engine));
}
}

Binary file not shown.

Binary file not shown.

View File

@ -218,6 +218,7 @@ void PlayScene_Click(GameWindow *pGameWindow, const Point *pPosition)
// Level was completed in the last click
GameEngine_CompleteLevel(&(pGameWindow->Engine));
GameWindow_Draw(pGameWindow, false);
GameSave_SaveData(&(pGameWindow->GameSave), &(pGameWindow->Engine));
GameWindow_SetScene(pGameWindow, LevelEnd);
Sounds_PlayDoneSnd(&(pGameWindow->Sounds));
}

View File

@ -10,10 +10,10 @@
#include "Sounds.h"
/** The first snd resource ID. */
#define SndBaseResId 8192
#define SndBaseResID 8192
/** The click snd resource ID. */
#define ClickSndResID SndBaseResId
#define ClickSndResID SndBaseResID
/** The retry snd resource ID. */
#define RetrySndResID (ClickSndResID + 1)

View File

@ -38,4 +38,4 @@ void WindowBuffer_StartDraw(const WindowBuffer *pWindowBuffer);
*/
void WindowBuffer_EndDraw(const WindowBuffer *pWindowBuffer);
#endif
#endif