Add support for saving and loading a game in progress.

This commit is contained in:
Jeremy Rand 2016-07-22 00:11:36 -05:00
parent b1716ce5ee
commit 66e6295cf7
6 changed files with 180 additions and 39 deletions

View File

@ -12,27 +12,27 @@
#include "types.h"
void __fastcall__ showDblLoRes(void);
void __fastcall__ clearDblLoRes(void);
void __fastcall__ unshowDblLoRes(void);
void __fastcall__ mixedTextMode(void);
extern void __fastcall__ showDblLoRes(void);
extern void __fastcall__ clearDblLoRes(void);
extern void __fastcall__ unshowDblLoRes(void);
extern void __fastcall__ mixedTextMode(void);
void __fastcall__ drawBgSquare(tSquare square);
extern void __fastcall__ drawBgSquare(tSquare square);
void __fastcall__ drawBlueGem(tSquare square);
void __fastcall__ drawYellowGem(tSquare square);
void __fastcall__ drawRedGem(tSquare square);
void __fastcall__ drawGreenGem(tSquare square);
void __fastcall__ drawOrangeGem(tSquare square);
void __fastcall__ drawGreyGem(tSquare square);
void __fastcall__ drawPurpleGem(tSquare square);
void __fastcall__ drawSpecialGem(tSquare square);
extern void __fastcall__ drawBlueGem(tSquare square);
extern void __fastcall__ drawYellowGem(tSquare square);
extern void __fastcall__ drawRedGem(tSquare square);
extern void __fastcall__ drawGreenGem(tSquare square);
extern void __fastcall__ drawOrangeGem(tSquare square);
extern void __fastcall__ drawGreyGem(tSquare square);
extern void __fastcall__ drawPurpleGem(tSquare square);
extern void __fastcall__ drawSpecialGem(tSquare square);
void __fastcall__ starGem(tSquare square);
extern void __fastcall__ starGem(tSquare square);
void __fastcall__ selectSquare(tSquare square);
extern void __fastcall__ selectSquare(tSquare square);
void __fastcall__ drawScore(uint8_t score);
extern void __fastcall__ drawScore(uint8_t score);
#endif /* defined(__a2bejwld__dbllores__) */

View File

@ -27,6 +27,8 @@
#define GEM_TYPE_AT_SQUARE(square) gGameState.squareStates[square].gemType
#define GEM_STARRED_AT_SQUARE(square) gGameState.squareStates[square].isStarred
#define SAVE_GAME_FILE "a2bejwld.game"
typedef struct tSquareState {
tGemType gemType;
@ -36,12 +38,12 @@ typedef struct tSquareState {
typedef struct tGameState {
tSquareState squareStates[NUM_SQUARES];
tLevel level;
uint16_t numGemsCleared;
uint16_t targetGemsToClear;
uint8_t gemsPerPoint;
tScore score;
tSquare hintSquare;
tLevel level;
uint16_t numGemsCleared;
uint16_t targetGemsToClear;
uint8_t gemsPerPoint;
tScore score;
tSquare hintSquare;
} tGameState;
@ -214,7 +216,7 @@ static void initSquare(tSquare square)
}
void initGame(tGameCallbacks *gameCallbacks)
void initGameEngine(tGameCallbacks *gameCallbacks)
{
tSquare square;
@ -234,6 +236,24 @@ void initGame(tGameCallbacks *gameCallbacks)
}
void startNewGame(void)
{
tSquare square;
memset(&gGameState, 0, sizeof(gGameState));
gGameState.level = 1;
gGameState.numGemsCleared = 0;
gGameState.gemsPerPoint = STARTING_GEMS_PER_POINT;
gGameState.targetGemsToClear = STARTING_GEMS_PER_POINT * SCORE_PER_LEVEL;
gGameState.score = 0;
for (square = MIN_SQUARE; square <= MAX_SQUARE; square++) {
initSquare(square);
}
}
tGemType gemTypeAtSquare(tSquare square)
{
return GEM_TYPE_AT_SQUARE(square);
@ -671,3 +691,60 @@ void moveSquareInDir(tSquare square, tDirection dir)
checkForNextLevel();
}
}
void saveGame(void)
{
FILE *saveFile = fopen(SAVE_GAME_FILE, "wb");
if (saveFile != NULL) {
bool isValid = true;
fwrite(&isValid, sizeof(isValid), 1, saveFile);
fwrite(&gGameState, sizeof(gGameState), 1, saveFile);
fclose(saveFile);
}
}
static void deleteGame(void)
{
// So, I tried using unlink() from unistd.h but it seems it
// does nothing on an Apple // with cc65. Instead, I will
// just open the file for writing and close it again which
// will leave it empty. That way, there won't be a saved
// game in the file.
FILE *saveFile = fopen(SAVE_GAME_FILE, "wb");
if (saveFile != NULL) {
bool isValid = false;
fwrite(&isValid, sizeof(isValid), 1, saveFile);
fclose(saveFile);
}
}
bool loadGame(void)
{
bool isValid = false;
bool result = false;
FILE *saveFile= fopen(SAVE_GAME_FILE, "rb");
if (saveFile == NULL) {
return false;
}
if ((fread(&isValid, sizeof(isValid), 1, saveFile) != 1) ||
(!isValid)) {
fclose(saveFile);
return false;
}
if (fread(&gGameState, sizeof(gGameState), 1, saveFile) != 1) {
fclose(saveFile);
deleteGame();
return false;
}
fclose(saveFile);
deleteGame();
return true;
}

View File

@ -34,19 +34,24 @@ typedef struct tGameCallbacks {
} tGameCallbacks;
void initGame(tGameCallbacks *callbacks);
extern void initGameEngine(tGameCallbacks *callbacks);
extern void startNewGame(void);
void moveSquareInDir(tSquare square, tDirection dir);
extern void moveSquareInDir(tSquare square, tDirection dir);
tGemType gemTypeAtSquare(tSquare square);
bool gemIsStarredAtSquare(tSquare square);
extern tGemType gemTypeAtSquare(tSquare square);
extern bool gemIsStarredAtSquare(tSquare square);
tLevel getLevel(void);
tScore getScore(void);
extern tLevel getLevel(void);
extern tScore getScore(void);
tSquare getHintSquare(void);
extern tSquare getHintSquare(void);
bool gameIsOver(void);
extern bool gameIsOver(void);
extern void saveGame(void);
extern bool loadGame(void);
#endif /* defined(__a2bejwld__game__) */

View File

@ -15,6 +15,8 @@
int main(void)
{
initUI();
printInstructions();
while (true) {

View File

@ -35,7 +35,7 @@ static tGameCallbacks gCallbacks = {
};
static void initUI(void)
static void showAndClearDblLoRes(void)
{
showDblLoRes();
clearDblLoRes();
@ -93,7 +93,6 @@ void printInstructions(void)
srand(seed);
clrscr();
initUI();
}
@ -372,7 +371,7 @@ static void refreshLevel(tLevel level)
}
}
initUI();
showAndClearDblLoRes();
}
@ -385,16 +384,60 @@ static void getHint(void)
}
void initUI(void)
{
initGameEngine(&gCallbacks);
}
void playGame(void)
{
static bool firstGame = true;
bool shouldSave = false;
bool gameLoaded = false;
uint8_t ch;
gScoreBar = 0;
initGame(&gCallbacks);
if (firstGame) {
firstGame = false;
printf("\n\nChecking for a saved game...");
if (loadGame()) {
bool gotAnswer = false;
printf("\n\nYou have a saved game!\n Would you like to continue it (Y/N)");
while (!gotAnswer) {
ch = cgetc();
switch (ch) {
case 'y':
case 'Y':
printf("\n\nLoading your saved puzzle");
gotAnswer = true;
shouldSave = true;
gameLoaded = true;
break;
case 'n':
case 'N':
gotAnswer = true;
break;
default:
badThingHappened();
break;
}
}
}
}
initUI();
showAndClearDblLoRes();
if (!gameLoaded) {
startNewGame();
}
drawBoard();
while (true) {
uint8_t ch;
if (gameIsOver()) {
endGame();
@ -410,6 +453,7 @@ void playGame(void)
case 'i':
case 'I':
case CH_CURS_UP:
shouldSave = true;
if (isAppleButtonPressed())
swapUp();
else
@ -419,6 +463,7 @@ void playGame(void)
case 'j':
case 'J':
case CH_CURS_LEFT:
shouldSave = true;
if (isAppleButtonPressed())
swapLeft();
else
@ -428,6 +473,7 @@ void playGame(void)
case 'k':
case 'K':
case CH_CURS_RIGHT:
shouldSave = true;
if (isAppleButtonPressed())
swapRight();
else
@ -437,6 +483,7 @@ void playGame(void)
case 'm':
case 'M':
case CH_CURS_DOWN:
shouldSave = true;
if (isAppleButtonPressed())
swapDown();
else
@ -446,6 +493,13 @@ void playGame(void)
case CH_ESC:
case 'q':
case 'Q':
if (shouldSave) {
mixedTextMode();
videomode(VIDEOMODE_80x24);
gotoxy(0, 20);
cprintf("\n\nSaving your game so you can continue\r\n later...");
saveGame();
}
quitGame();
break;
@ -465,6 +519,7 @@ void playGame(void)
case '?':
printInstructions();
showAndClearDblLoRes();
drawBoard();
break;

View File

@ -10,9 +10,11 @@
#define __a2bejwld__ui__
void printInstructions(void);
extern void initUI(void);
void playGame(void);
extern void printInstructions(void);
extern void playGame(void);
#endif /* defined(__a2bejwld__ui__) */