From 82cae1f613cdc0641f1b8a82c90e1c3c047cf9a2 Mon Sep 17 00:00:00 2001 From: Jeremy Rand Date: Sat, 20 Aug 2016 00:08:29 -0400 Subject: [PATCH] Add the ability to set options in the game and save/load those options. Some general code cleanup. --- a2bejwld/mouseWrapper.c | 9 +- a2bejwld/mouseWrapper.h | 2 +- a2bejwld/types.h | 10 +- a2bejwld/ui.c | 535 ++++++++++++++++++++-------------------- 4 files changed, 285 insertions(+), 271 deletions(-) diff --git a/a2bejwld/mouseWrapper.c b/a2bejwld/mouseWrapper.c index 3df4ea3..8c36e9c 100644 --- a/a2bejwld/mouseWrapper.c +++ b/a2bejwld/mouseWrapper.c @@ -26,13 +26,16 @@ static tMouseCallbacks *gMouseCallbacks = NULL; static bool gMouseInstalled = false; -void initMouse(tMouseCallbacks *callbacks) +bool initMouse(tMouseCallbacks *callbacks) { - if (mouse_install(&mouse_def_callbacks, &a2e_stdmou_mou) == 0) { - gMouseInstalled = true; + if (!gMouseInstalled) { + if (mouse_install(&mouse_def_callbacks, &a2e_stdmou_mou) == 0) { + gMouseInstalled = true; + } } gMouseCallbacks = callbacks; + return gMouseInstalled; } diff --git a/a2bejwld/mouseWrapper.h b/a2bejwld/mouseWrapper.h index 27d3380..fe3ba8b 100644 --- a/a2bejwld/mouseWrapper.h +++ b/a2bejwld/mouseWrapper.h @@ -25,7 +25,7 @@ typedef struct tMouseCallbacks { // API -extern void initMouse(tMouseCallbacks *callbacks); +extern bool initMouse(tMouseCallbacks *callbacks); extern void shutdownMouse(void); extern bool pollMouse(void); diff --git a/a2bejwld/types.h b/a2bejwld/types.h index 605fd13..4fd2cbb 100644 --- a/a2bejwld/types.h +++ b/a2bejwld/types.h @@ -15,10 +15,12 @@ // Defines -#define DIR_UP 0 -#define DIR_DOWN 1 -#define DIR_LEFT 2 -#define DIR_RIGHT 3 +#define DIR_NONE 0 +#define DIR_UP 1 +#define DIR_DOWN 2 +#define DIR_LEFT 3 +#define DIR_RIGHT 4 + #define GEM_NONE 0 #define GEM_GREEN 1 diff --git a/a2bejwld/ui.c b/a2bejwld/ui.c index c77a5e8..535a341 100644 --- a/a2bejwld/ui.c +++ b/a2bejwld/ui.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "ui.h" #include "anim.h" @@ -19,9 +20,15 @@ #include "mouseWrapper.h" +// Defines + +#define SAVE_OPTIONS_FILE "a2bejwld.options" + + // Typedefs typedef struct tGameOptions { + bool optionsSaved; bool enableJoystick; bool enableMouse; bool enableSound; @@ -84,6 +91,7 @@ static tMouseCallbacks gMouseCallbacks = { static bool gShouldSave = false; static tGameOptions gGameOptions = { + false, false, true, true, @@ -125,6 +133,117 @@ static void showAndClearDblLoRes(void) } +void saveOptions(void) +{ + FILE *optionsFile = fopen(SAVE_OPTIONS_FILE, "wb"); + if (optionsFile != NULL) { + gGameOptions.optionsSaved = true; + fwrite(&gGameOptions, sizeof(gGameOptions), 1, optionsFile); + fclose(optionsFile); + } +} + + +bool loadOptions(void) +{ + FILE *optionsFile = fopen(SAVE_OPTIONS_FILE, "rb"); + + if (optionsFile == NULL) { + return false; + } + + if (fread(&gGameOptions, sizeof(gGameOptions), 1, optionsFile) != 1) { + fclose(optionsFile); + return false; + } + + fclose(optionsFile); + + return true; +} + + +void applyNewOptions(tGameOptions *newOptions) +{ + bool oldEnableMouse = gGameOptions.enableMouse; + + // If there is no change in game options, then nothing to do. + if (memcmp(newOptions, &gGameOptions, sizeof(gGameOptions)) == 0) { + return; + } + + memcpy(&gGameOptions, newOptions, sizeof(gGameOptions)); + gGameOptions.optionsSaved = false; + if (oldEnableMouse != gGameOptions.enableMouse) { + if (gGameOptions.enableMouse) { + gGameOptions.enableMouse = initMouse(&gMouseCallbacks); + } else { + shutdownMouse(); + } + } + saveOptions(); +} + + +void selectOptions(void) +{ + tGameOptions newOptions; + + unshowDblLoRes(); + videomode(VIDEOMODE_80x24); + clrscr(); + + memcpy(&newOptions, &gGameOptions, sizeof(newOptions)); + + while (true) { + clrscr(); + printf( + // 0000000001111111111222222222233333333334444444444555555555566666666667 + // 1234567890123456789012345678901234567890123456789012345678901234567890 + " Apple Jeweled\n" + " Options\n" + "\n" + " J - Joystick control - %s\n" + " M - Mouse control - %s\n" + " S - Sound - %s\n" + "\n" + " Type a letter to toggle a setting or any other key to save settings\n" + " and continue", + (newOptions.enableJoystick ? "Enable" : "Disabled"), + (newOptions.enableMouse ? "Enable" : "Disabled"), + (newOptions.enableSound ? "Enable" : "Disabled")); + + switch (cgetc()) { + case 'j': + case 'J': + newOptions.enableJoystick = !newOptions.enableJoystick; + if (newOptions.enableJoystick) { + newOptions.enableMouse = false; + } + break; + + case 'm': + case 'M': + newOptions.enableMouse = !newOptions.enableMouse; + if (newOptions.enableMouse) { + newOptions.enableJoystick = false; + } + break; + + case 's': + case 'S': + newOptions.enableSound = !newOptions.enableSound; + break; + + default: + applyNewOptions(&newOptions); + clrscr(); + return; + } + } +} + + void printInstructions(void) { int seed = 0; @@ -164,22 +283,17 @@ void printInstructions(void) while (!kbhit()) seed++; - cgetc(); srand(seed); - clrscr(); -} - - -void selectOptions(void) -{ - unshowDblLoRes(); - videomode(VIDEOMODE_80x24); - clrscr(); - - printf("Options go here..."); - - cgetc(); + switch (cgetc()) { + case 'o': + case 'O': + selectOptions(); + break; + + default: + break; + } clrscr(); } @@ -218,246 +332,132 @@ static void quitGame(void) } -static void moveUp(void) +static void moveDir(tDirection dir) { tSquare oldSquare = gSelectedSquare; tPos x = SQUARE_TO_X(gSelectedSquare); tPos y = SQUARE_TO_Y(gSelectedSquare); - if (y == 0) - y = BOARD_SIZE - 1; - else - y--; - - gSelectedSquare = XY_TO_SQUARE(x, y); - - refreshSquare(oldSquare); - selectSquare(gSelectedSquare); -} - - -static void moveUpLeft(void) -{ - tSquare oldSquare = gSelectedSquare; - tPos x = SQUARE_TO_X(gSelectedSquare); - tPos y = SQUARE_TO_Y(gSelectedSquare); - - if (y == 0) - y = BOARD_SIZE - 1; - else - y--; - - if (x == 0) - x = BOARD_SIZE - 1; - else - x--; - - gSelectedSquare = XY_TO_SQUARE(x, y); - - refreshSquare(oldSquare); - selectSquare(gSelectedSquare); -} - - - -static void moveUpRight(void) -{ - tSquare oldSquare = gSelectedSquare; - tPos x = SQUARE_TO_X(gSelectedSquare); - tPos y = SQUARE_TO_Y(gSelectedSquare); - - if (y == 0) - y = BOARD_SIZE - 1; - else - y--; - - if (x == BOARD_SIZE - 1) - x = 0; - else - x++; - - gSelectedSquare = XY_TO_SQUARE(x, y); - - refreshSquare(oldSquare); - selectSquare(gSelectedSquare); -} - - -static void moveDown(void) -{ - tSquare oldSquare = gSelectedSquare; - tPos x = SQUARE_TO_X(gSelectedSquare); - tPos y = SQUARE_TO_Y(gSelectedSquare); - - if (y == BOARD_SIZE - 1) - y = 0; - else - y++; - - gSelectedSquare = XY_TO_SQUARE(x, y); - - refreshSquare(oldSquare); - selectSquare(gSelectedSquare); -} - - -static void moveDownLeft(void) -{ - tSquare oldSquare = gSelectedSquare; - tPos x = SQUARE_TO_X(gSelectedSquare); - tPos y = SQUARE_TO_Y(gSelectedSquare); - - if (y == BOARD_SIZE - 1) - y = 0; - else - y++; - - if (x == 0) - x = BOARD_SIZE - 1; - else - x--; - - gSelectedSquare = XY_TO_SQUARE(x, y); - - refreshSquare(oldSquare); - selectSquare(gSelectedSquare); -} - - -static void moveDownRight(void) -{ - tSquare oldSquare = gSelectedSquare; - tPos x = SQUARE_TO_X(gSelectedSquare); - tPos y = SQUARE_TO_Y(gSelectedSquare); - - if (y == BOARD_SIZE - 1) - y = 0; - else - y++; - - if (x == BOARD_SIZE - 1) - x = 0; - else - x++; - - gSelectedSquare = XY_TO_SQUARE(x, y); - - refreshSquare(oldSquare); - selectSquare(gSelectedSquare); -} - - -static void moveLeft(void) -{ - tSquare oldSquare = gSelectedSquare; - tPos x = SQUARE_TO_X(gSelectedSquare); - tPos y = SQUARE_TO_Y(gSelectedSquare); - - if (x == 0) - x = BOARD_SIZE - 1; - else - x--; - - gSelectedSquare = XY_TO_SQUARE(x, y); - - refreshSquare(oldSquare); - selectSquare(gSelectedSquare); -} - - -static void moveRight(void) -{ - tSquare oldSquare = gSelectedSquare; - tPos x = SQUARE_TO_X(gSelectedSquare); - tPos y = SQUARE_TO_Y(gSelectedSquare); - - if (x == BOARD_SIZE - 1) - x = 0; - else - x++; - - gSelectedSquare = XY_TO_SQUARE(x, y); - - refreshSquare(oldSquare); - selectSquare(gSelectedSquare); -} - - -static bool swapUp(void) -{ - bool result = false; - tPos y = SQUARE_TO_Y(gSelectedSquare); - - if (y == 0) { - badThingHappened(); - return result; + switch (dir) { + case DIR_UP: + if (y == 0) + y = BOARD_SIZE - 1; + else + y--; + break; + + case DIR_DOWN: + if (y == BOARD_SIZE - 1) + y = 0; + else + y++; + break; + + case DIR_LEFT: + if (x == 0) + x = BOARD_SIZE - 1; + else + x--; + break; + + case DIR_RIGHT: + if (x == BOARD_SIZE - 1) + x = 0; + else + x++; + break; } - resetStarAnim(); - result = moveSquareInDir(gSelectedSquare, DIR_UP); + gSelectedSquare = XY_TO_SQUARE(x, y); + + refreshSquare(oldSquare); selectSquare(gSelectedSquare); - - if (result) - gShouldSave = true; - - return result; } -static bool swapDown(void) +static void moveTwoDirs(tDirection dir1, tDirection dir2) { - bool result = false; + tSquare oldSquare = gSelectedSquare; + tPos x = SQUARE_TO_X(gSelectedSquare); tPos y = SQUARE_TO_Y(gSelectedSquare); - if (y == BOARD_SIZE - 1) { - badThingHappened(); - return result; + switch (dir1) { + case DIR_UP: + if (y == 0) + y = BOARD_SIZE - 1; + else + y--; + break; + + case DIR_DOWN: + if (y == BOARD_SIZE - 1) + y = 0; + else + y++; + break; } - resetStarAnim(); - result = moveSquareInDir(gSelectedSquare, DIR_DOWN); + switch (dir2) { + case DIR_LEFT: + if (x == 0) + x = BOARD_SIZE - 1; + else + x--; + break; + + case DIR_RIGHT: + if (x == BOARD_SIZE - 1) + x = 0; + else + x++; + break; + } + + gSelectedSquare = XY_TO_SQUARE(x, y); + + refreshSquare(oldSquare); selectSquare(gSelectedSquare); - - if (result) - gShouldSave = true; - - return result; } -static bool swapLeft(void) +static bool swapDir(tDirection dir) { bool result = false; tPos x = SQUARE_TO_X(gSelectedSquare); + tPos y = SQUARE_TO_Y(gSelectedSquare); - if (x == 0) { - badThingHappened(); - return result; + switch (dir) { + case DIR_UP: + if (y == 0) { + badThingHappened(); + return result; + } + break; + + case DIR_DOWN: + if (y == BOARD_SIZE - 1) { + badThingHappened(); + return result; + } + break; + + case DIR_LEFT: + if (x == 0) { + badThingHappened(); + return result; + } + break; + + case DIR_RIGHT: + if (x == BOARD_SIZE - 1) { + badThingHappened(); + return result; + } + break; } resetStarAnim(); - result = moveSquareInDir(gSelectedSquare, DIR_LEFT); - selectSquare(gSelectedSquare); - - if (result) - gShouldSave = true; - - return result; -} - - -static bool swapRight(void) -{ - bool result = false; - tPos x = SQUARE_TO_X(gSelectedSquare); - - if (x == BOARD_SIZE - 1) { - badThingHappened(); - return result; - } - - resetStarAnim(); - result = moveSquareInDir(gSelectedSquare, DIR_RIGHT); + result = moveSquareInDir(gSelectedSquare, dir); selectSquare(gSelectedSquare); if (result) @@ -551,10 +551,33 @@ static void getHint(void) void initUI(void) { + bool optionsLoaded; + + optionsLoaded = loadOptions(); + initGameEngine(&gCallbacks); animInit(); + + if ((!optionsLoaded) || + (gGameOptions.enableMouse)) { + // If we didn't load any options or the saved options had the mouse enabled, then try to init a mouse. + gGameOptions.enableMouse = initMouse(&gMouseCallbacks); + if (!gGameOptions.enableMouse) { + // If we didn't init a mouse, then let's mark the options as not saved. + gGameOptions.optionsSaved = false; + + // If we didn't load an options file, then let's turn on the joystick instead. + if (!optionsLoaded) { + gGameOptions.enableJoystick = true; + } + } + } + initJoystick(&gJoyCallbacks); - initMouse(&gMouseCallbacks); + + if (!gGameOptions.optionsSaved) { + saveOptions(); + } } @@ -576,21 +599,7 @@ static bool mouseSwapSquare(tSquare square, tDirection dir) selectSquare(gSelectedSquare); } - switch (dir) { - case DIR_UP: - return swapUp(); - - case DIR_DOWN: - return swapDown(); - - case DIR_LEFT: - return swapLeft(); - - case DIR_RIGHT: - return swapRight(); - } - - return false; + return swapDir(dir); } @@ -598,35 +607,35 @@ static void joystickMove(tJoyPos position) { switch (position) { case JOY_POS_DOWN: - moveDown(); + moveDir(DIR_DOWN); break; case JOY_POS_DOWN_LEFT: - moveDownLeft(); + moveTwoDirs(DIR_DOWN, DIR_LEFT); break; case JOY_POS_LEFT: - moveLeft(); + moveDir(DIR_LEFT); break; case JOY_POS_UP_LEFT: - moveUpLeft(); + moveTwoDirs(DIR_UP, DIR_LEFT); break; case JOY_POS_UP: - moveUp(); + moveDir(DIR_UP); break; case JOY_POS_UP_RIGHT: - moveUpRight(); + moveTwoDirs(DIR_UP, DIR_RIGHT); break; case JOY_POS_RIGHT: - moveRight(); + moveDir(DIR_RIGHT); break; case JOY_POS_DOWN_RIGHT: - moveDownRight(); + moveTwoDirs(DIR_DOWN, DIR_RIGHT); break; default: @@ -646,16 +655,16 @@ static bool joystickChangedCallback(tJoyState *oldState, tJoyState *newState) (newState->button1)) { switch (newState->position) { case JOY_POS_UP: - return swapUp(); + return swapDir(DIR_UP); case JOY_POS_DOWN: - return swapDown(); + return swapDir(DIR_DOWN); case JOY_POS_LEFT: - return swapLeft(); + return swapDir(DIR_LEFT); case JOY_POS_RIGHT: - return swapRight(); + return swapDir(DIR_RIGHT); default: break; @@ -696,48 +705,48 @@ static bool pollKeyboard(void) case 'I': case CH_CURS_UP: if (!isAppleButtonPressed()) { - moveUp(); + moveDir(DIR_UP); break; } // Fallthrough... case 139: - result = swapUp(); + result = swapDir(DIR_UP); break; case 'j': case 'J': case CH_CURS_LEFT: if (!isAppleButtonPressed()) { - moveLeft(); + moveDir(DIR_LEFT); break; } // Fallthrough... case 136: - result = swapLeft(); + result = swapDir(DIR_LEFT); break; case 'k': case 'K': case CH_CURS_RIGHT: if (!isAppleButtonPressed()) { - moveRight(); + moveDir(DIR_RIGHT); break; } // Fallthrough... case 149: - result = swapRight(); + result = swapDir(DIR_RIGHT); break; case 'm': case 'M': case CH_CURS_DOWN: if (!isAppleButtonPressed()) { - moveDown(); + moveDir(DIR_DOWN); break; } // Fallthrough... case 138: - result = swapDown(); + result = swapDir(DIR_DOWN); break; case CH_ESC: