mirror of
https://github.com/jeremysrand/a2bejwld.git
synced 2024-06-02 05:41:31 +00:00
Add support for saving and loading a game in progress.
This commit is contained in:
parent
b1716ce5ee
commit
66e6295cf7
|
@ -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__) */
|
|
@ -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;
|
||||
}
|
|
@ -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__) */
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
int main(void)
|
||||
{
|
||||
initUI();
|
||||
|
||||
printInstructions();
|
||||
|
||||
while (true) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__) */
|
||||
|
|
Loading…
Reference in New Issue
Block a user