diff --git a/anim.c b/anim.c new file mode 100644 index 0000000..f4d50a8 --- /dev/null +++ b/anim.c @@ -0,0 +1,445 @@ +/* + * File: anim.c + * Author: Jeremy Rand + * Date: July 23, 2014 + * + * This file is the implementation file the 2048 animations. + */ + + +#include +#include +#include +#include + +#include "game.h" +#include "textpage.h" +#include "ui.h" + + +typedef struct tTileAnim +{ + uint8_t fromX; + uint8_t fromY; + uint8_t toX; + uint8_t toY; + char *tileString; + char *endTileString; +} tTileAnim; + + +static tTileAnim gTileAnims[NUM_TILES]; +static tDir gAnimDir; +static uint8_t gNumAnims; +static char *gNewTileString = NULL; +static tPos gNewTilePos; + +static void (*gSwitchToPage2)(void) = switchToPage2; + + +static void shortDelay(uint16_t howMuch) +{ + while (howMuch > 0) { + howMuch--; + } +} + + +static void resetAnimations(void) +{ + memset(gTileAnims, 0, sizeof(gTileAnims)); + gNewTileString = NULL; + gAnimDir = 0; + gNumAnims = 0; +} + + +static void performAnimationsLeft(void) +{ + bool animInProgress; + tPos pos; + tTileAnim *tileAnim; + tPos x; + tPos y; + bool firstFrame = true; + uint8_t speed = 1; + + if (gNumAnims > BOARD_SIZE) + speed = 2; + + do { + animInProgress = false; + + gSwitchToPage2(); + for (pos = 0; pos < gNumAnims; pos++) { + tileAnim = &(gTileAnims[pos]); + if (tileAnim->tileString == NULL) + continue; + + x = tileAnim->fromX; + y = tileAnim->fromY; + + if (!firstFrame) { + if (speed == 1) { + switch (x % TILE_WIDTH) { + case 0: + break; + case 1: + textframexy(((x / TILE_WIDTH) + 1) * TILE_WIDTH, y, + TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + break; + default: + x += TILE_WIDTH - 1; + cputcxy(x, y + 1, ' '); + cputcxy(x, y + 2, ' '); + cputcxy(x, y + 3, ' '); + x -= TILE_WIDTH - 1; + break; + } + } else { + switch (x % TILE_WIDTH) { + case 0: + break; + case 1: + case 2: + x += TILE_WIDTH - 1; + cputcxy(x, y + 1, ' '); + cputcxy(x, y + 2, ' '); + cputcxy(x, y + 3, ' '); + x -= TILE_WIDTH - 1; + textframexy(((x / TILE_WIDTH) + 1) * TILE_WIDTH, y, + TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + break; + default: + x += TILE_WIDTH - 2; + cputsxy(x, y + 1, " "); + cputsxy(x, y + 2, " "); + cputsxy(x, y + 3, " "); + x -= TILE_WIDTH - 2; + break; + } + } + } + + x -= speed; + + + if (x <= tileAnim->toX) { + x = tileAnim->toX; + textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + tileAnim->tileString = NULL; + printValueAt(x, y, tileAnim->endTileString); + } else { + textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + tileAnim->fromX = x; + animInProgress = true; + printValueAt(x, y, tileAnim->tileString); + } + playSound(200, 1); + } + switchToPage1(); + firstFrame = false; + } while (animInProgress); +} + + +static void performAnimationsRight(void) +{ + bool animInProgress; + tPos pos; + tTileAnim *tileAnim; + tPos x; + tPos y; + bool firstFrame = true; + uint8_t speed = 1; + + if (gNumAnims > BOARD_SIZE) + speed = 2; + + do { + animInProgress = false; + + gSwitchToPage2(); + for (pos = 0; pos < gNumAnims; pos++) { + tileAnim = &(gTileAnims[pos]); + if (tileAnim->tileString == NULL) + continue; + + x = tileAnim->fromX; + y = tileAnim->fromY; + + if (!firstFrame) { + if (speed == 1) { + switch (x % TILE_WIDTH) { + case 0: + break; + case (TILE_WIDTH - 1): + textframexy((x / TILE_WIDTH) * TILE_WIDTH, y, + TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + break; + default: + cputcxy(x, y + 1, ' '); + cputcxy(x, y + 2, ' '); + cputcxy(x, y + 3, ' '); + break; + } + } else { + switch (x % TILE_WIDTH) { + case 0: + break; + case (TILE_WIDTH - 1): + case (TILE_WIDTH - 2): + textframexy((x / TILE_WIDTH) * TILE_WIDTH, y, + TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + cputcxy(x, y + 1, ' '); + cputcxy(x, y + 2, ' '); + cputcxy(x, y + 3, ' '); + break; + default: + cputsxy(x, y + 1, " "); + cputsxy(x, y + 2, " "); + cputsxy(x, y + 3, " "); + break; + } + } + } + + x += speed; + + + if (x >= tileAnim->toX) { + x = tileAnim->toX; + textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + tileAnim->tileString = NULL; + printValueAt(x, y, tileAnim->endTileString); + } else { + textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + tileAnim->fromX = x; + animInProgress = true; + printValueAt(x, y, tileAnim->tileString); + } + playSound(200, 1); + } + switchToPage1(); + firstFrame = false; + } while (animInProgress); +} + + +static void performAnimationsUp(void) +{ + bool animInProgress; + tPos pos; + tTileAnim *tileAnim; + tPos x; + tPos y; + bool firstFrame = true; + uint8_t speed = 1; + + if (gNumAnims > BOARD_SIZE) + speed = 2; + + do { + animInProgress = false; + + gSwitchToPage2(); + for (pos = 0; pos < gNumAnims; pos++) { + tileAnim = &(gTileAnims[pos]); + if (tileAnim->tileString == NULL) + continue; + + x = tileAnim->fromX; + y = tileAnim->fromY; + + if (!firstFrame) { + switch ((y % TILE_HEIGHT)) { + case 0: + break; + default: + cputsxy(x + 1, y + TILE_HEIGHT - 1, " "); + if (speed > 1) + cputsxy(x + 1, y + TILE_HEIGHT - 1, " "); + textframexy(x, ((y / TILE_HEIGHT) + 1) * TILE_HEIGHT, + TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + break; + } + } + + if (y < speed) + y = 0; + else + y -= speed;; + + if (y <= tileAnim->toY) { + y = tileAnim->toY; + textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + tileAnim->tileString = NULL; + printValueAt(x, y, tileAnim->endTileString); + } else { + textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + tileAnim->fromY = y; + animInProgress = true; + printValueAt(x, y, tileAnim->tileString); + } + playSound(200, 1); + } + switchToPage1(); + firstFrame = false; + } while (animInProgress); +} + + +static void performAnimationsDown(void) +{ + bool animInProgress; + tPos pos; + tTileAnim *tileAnim; + tPos x; + tPos y; + bool firstFrame = true; + uint8_t speed = 1; + + if (gNumAnims > BOARD_SIZE) + speed = 2; + + do { + animInProgress = false; + + gSwitchToPage2(); + for (pos = 0; pos < gNumAnims; pos++) { + tileAnim = &(gTileAnims[pos]); + if (tileAnim->tileString == NULL) + continue; + + x = tileAnim->fromX; + y = tileAnim->fromY; + + if (!firstFrame) { + switch ((y % TILE_HEIGHT)) { + case 0: + break; + default: + cputsxy(x + 1, y, " "); + if (speed > 1) + cputsxy(x + 1, y + 1, " "); + textframexy(x, (y / TILE_HEIGHT) * TILE_HEIGHT, + TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + break; + } + } + + y += speed; + + + if (y >= tileAnim->toY) { + y = tileAnim->toY; + textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + tileAnim->tileString = NULL; + printValueAt(x, y, tileAnim->endTileString); + } else { + textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + tileAnim->fromY = y; + animInProgress = true; + printValueAt(x, y, tileAnim->tileString); + } + playSound(200, 1); + } + switchToPage1(); + firstFrame = false; + } while (animInProgress); +} + + +static void performNewTileAnimation() +{ + uint8_t screenX; + uint8_t screenY; + + if (gNewTileString == NULL) + return; + + screenX = TILE_X_TO_SCREEN_X(POS_TO_X(gNewTilePos)); + screenY = TILE_Y_TO_SCREEN_Y(POS_TO_Y(gNewTilePos)); + + textframexy(screenX + 2, screenY + 1, TILE_WIDTH - 4, TILE_HEIGHT - 2, + TEXTFRAME_WIDE); + shortDelay(500); + + textframexy(screenX + 1, screenY + 1, TILE_WIDTH - 2, TILE_HEIGHT - 1, + TEXTFRAME_WIDE); + shortDelay(500); + + textframexy(screenX, screenY, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); + printValueAt(screenX, screenY, gNewTileString); +} + + +void performAnimations(void) +{ + switch (gAnimDir) { + case DIR_UP: + performAnimationsUp(); + break; + case DIR_DOWN: + performAnimationsDown(); + break; + + case DIR_LEFT: + performAnimationsLeft(); + break; + + case DIR_RIGHT: + performAnimationsRight(); + break; + } + + performNewTileAnimation(); + + resetAnimations(); +} + + +static void tileMoved(tPos from, tPos to, char *tileString) +{ + tTileAnim *anim = &(gTileAnims[gNumAnims]); + anim->tileString = tileString; + anim->endTileString = tileStringForPos(POS_TO_X(to), POS_TO_Y(to)); + anim->fromX = TILE_X_TO_SCREEN_X(POS_TO_X(from)); + anim->fromY = TILE_Y_TO_SCREEN_Y(POS_TO_Y(from)); + anim->toX = TILE_X_TO_SCREEN_X(POS_TO_X(to)); + anim->toY = TILE_Y_TO_SCREEN_Y(POS_TO_Y(to)); + gNumAnims++; + + if (anim->fromX > anim->toX) { + gAnimDir = DIR_LEFT; + } else if (anim->fromX < anim->toX) { + gAnimDir = DIR_RIGHT; + } else if (anim->fromY > anim->toY) { + gAnimDir = DIR_UP; + } else if (anim->fromY < anim->toY) { + gAnimDir = DIR_DOWN; + } +} + + +static void newTile(tPos at, char *tileString) +{ + gNewTileString = tileString; + gNewTilePos = at; +} + + +void initAnimations(void) +{ + switch (get_ostype()) { + case APPLE_IIGS: + case APPLE_IIGS1: + case APPLE_IIGS3: + gSwitchToPage2 = gsSwitchToPage2; + break; + } + + initGameEngine(tileMoved, newTile); +} + + diff --git a/anim.h b/anim.h new file mode 100644 index 0000000..2741d00 --- /dev/null +++ b/anim.h @@ -0,0 +1,12 @@ +/* + * File: anim.h + * Author: Jeremy Rand + * Date: July 23, 2014 + * + * This file is the header file the 2048 animations. + */ + + +extern void initAnimations(void); + +extern void performAnimations(void); diff --git a/apple2048.c b/apple2048.c index 6726bf6..3ed0a91 100644 --- a/apple2048.c +++ b/apple2048.c @@ -6,661 +6,17 @@ * This file contains the entry point for the 2048 game. */ -#include -#include -#include -#include -#include -#include +#include "anim.h" #include "game.h" -#include "textpage.h" - - -#define TILE_WIDTH 10 -#define TILE_HEIGHT 5 - -#define TILE_X_TO_SCREEN_X(x) (((x) - 1) * TILE_WIDTH) -#define TILE_Y_TO_SCREEN_Y(y) (((y) - 1) * TILE_HEIGHT) - - -typedef struct tTileAnim -{ - uint8_t fromX; - uint8_t fromY; - uint8_t toX; - uint8_t toY; - char *tileString; - char *endTileString; -} tTileAnim; - - -static tTileAnim gTileAnims[NUM_TILES]; -static tDir gAnimDir; -static uint8_t gNumAnims; -static char *gNewTileString = NULL; -static tPos gNewTilePos; - -static bool gPlaySounds = true; - -static void (*gSwitchToPage2)(void) = switchToPage2; - -void shortDelay(uint16_t howMuch) -{ - while (howMuch > 0) { - howMuch--; - } -} - - -void playSound(int8_t freq, int16_t duration) -{ - if (!gPlaySounds) - return; - - while (duration > 0) { - asm ("STA %w", 0xc030); - while (freq > 0) { - freq--; - } - duration--; - } -} - - -void quitGame(void) -{ - shutdownGameEngine(); - clrscr(); - exit(0); -} - - -void printInstructions(void) -{ - int seed = 0; - - clrscr(); - printf( -// 0000000001111111111222222222233333333334 -// 1234567890123456789012345678901234567890 - " APPLE 2048\n" - "\n" - "USE I-J-K-M OR THE ARROW KEYS TO SLIDE\n" - "ALL TILES IN A DIRECTION. MATCHING\n" - "TILES ARE ADDED TOGETHER TO MAKE A NEW\n" - "TILE. ON EVERY MOVE, ONE MORE TILE IS\n" - "ADDED WITH A RANDOM VALUE OF EITHER 2\n" - "OR 4.\n" - "\n" - "PLAY ENDS WHEN ALL TILES ARE OCCUPIED\n" - "AND NO MORE MOVES ARE POSSIBLE. TRY\n" - "TO GET THE LARGEST TILE YOU CAN!\n" - "\n" - "PRESS ESCAPE OR Q TO QUIT AT ANY TIME.\n" - "PRESS R TO START A NEW GAME.\n" - "PRESS S TO TOGGLE SOUND.\n" - "PRESS H TO SEE THIS INFO AGAIN.\n" - "\n" - "\n" - "\n" - " PRESS ANY KEY TO START"); - - // The amount of time the user waits to read the in - while (!kbhit()) - seed++; - - cgetc(); - srand(seed); - - clrscr(); -} - - -void printGrid(void) -{ - tPos x; - tPos y; - - for (x = 1; x <= BOARD_SIZE; x++) { - for (y = 1; y <= BOARD_SIZE; y++) { - textframexy(TILE_X_TO_SCREEN_X(x), - TILE_Y_TO_SCREEN_Y(y), - TILE_WIDTH, - TILE_HEIGHT, - TEXTFRAME_WIDE); - } - } -} - - -void printValueAt(uint8_t screenX, uint8_t screenY, char *tileString) -{ - screenX++; - screenY++; - - cputsxy(screenX, screenY, " "); - screenY++; - cputsxy(screenX, screenY, tileString); - screenY++; - cputsxy(screenX, screenY, " "); -} - - -void printValues(void) -{ - tPos x; - tPos y; - - for (x = 1; x <= BOARD_SIZE; x++) { - for (y = 1; y <= BOARD_SIZE; y++) { - printValueAt(TILE_X_TO_SCREEN_X(x), TILE_Y_TO_SCREEN_Y(y), - tileStringForPos(x, y)); - } - } -} - - -void printScore(void) -{ - tScore highestTile = highestTarget(); - - gotoxy(0,20); - printf("SCORE: %10ld HI-SCORE: %10ld\n", currentScore(), highScore()); - - if (highestTile == 0) { - printf("TRY TO GET THE %ld TILE!\n", nextTarget()); - } else { - printf("GOT %ld! NOW GET %ld!\n", highestTile, nextTarget()); - } -} - - -void resetAnimations(void) -{ - memset(gTileAnims, 0, sizeof(gTileAnims)); - gNewTileString = NULL; - gAnimDir = 0; - gNumAnims = 0; -} - - -void performAnimationsLeft(void) -{ - bool animInProgress; - tPos pos; - tTileAnim *tileAnim; - tPos x; - tPos y; - bool firstFrame = true; - uint8_t speed = 1; - - if (gNumAnims > BOARD_SIZE) - speed = 2; - - do { - animInProgress = false; - - gSwitchToPage2(); - for (pos = 0; pos < gNumAnims; pos++) { - tileAnim = &(gTileAnims[pos]); - if (tileAnim->tileString == NULL) - continue; - - x = tileAnim->fromX; - y = tileAnim->fromY; - - if (!firstFrame) { - if (speed == 1) { - switch (x % TILE_WIDTH) { - case 0: - break; - case 1: - textframexy(((x / TILE_WIDTH) + 1) * TILE_WIDTH, y, - TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - break; - default: - x += TILE_WIDTH - 1; - cputcxy(x, y + 1, ' '); - cputcxy(x, y + 2, ' '); - cputcxy(x, y + 3, ' '); - x -= TILE_WIDTH - 1; - break; - } - } else { - switch (x % TILE_WIDTH) { - case 0: - break; - case 1: - case 2: - x += TILE_WIDTH - 1; - cputcxy(x, y + 1, ' '); - cputcxy(x, y + 2, ' '); - cputcxy(x, y + 3, ' '); - x -= TILE_WIDTH - 1; - textframexy(((x / TILE_WIDTH) + 1) * TILE_WIDTH, y, - TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - break; - default: - x += TILE_WIDTH - 2; - cputsxy(x, y + 1, " "); - cputsxy(x, y + 2, " "); - cputsxy(x, y + 3, " "); - x -= TILE_WIDTH - 2; - break; - } - } - } - - x -= speed; - - - if (x <= tileAnim->toX) { - x = tileAnim->toX; - textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - tileAnim->tileString = NULL; - printValueAt(x, y, tileAnim->endTileString); - } else { - textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - tileAnim->fromX = x; - animInProgress = true; - printValueAt(x, y, tileAnim->tileString); - } - playSound(200, 1); - } - switchToPage1(); - firstFrame = false; - } while (animInProgress); -} - - -void performAnimationsRight(void) -{ - bool animInProgress; - tPos pos; - tTileAnim *tileAnim; - tPos x; - tPos y; - bool firstFrame = true; - uint8_t speed = 1; - - if (gNumAnims > BOARD_SIZE) - speed = 2; - - do { - animInProgress = false; - - gSwitchToPage2(); - for (pos = 0; pos < gNumAnims; pos++) { - tileAnim = &(gTileAnims[pos]); - if (tileAnim->tileString == NULL) - continue; - - x = tileAnim->fromX; - y = tileAnim->fromY; - - if (!firstFrame) { - if (speed == 1) { - switch (x % TILE_WIDTH) { - case 0: - break; - case (TILE_WIDTH - 1): - textframexy((x / TILE_WIDTH) * TILE_WIDTH, y, - TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - break; - default: - cputcxy(x, y + 1, ' '); - cputcxy(x, y + 2, ' '); - cputcxy(x, y + 3, ' '); - break; - } - } else { - switch (x % TILE_WIDTH) { - case 0: - break; - case (TILE_WIDTH - 1): - case (TILE_WIDTH - 2): - textframexy((x / TILE_WIDTH) * TILE_WIDTH, y, - TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - cputcxy(x, y + 1, ' '); - cputcxy(x, y + 2, ' '); - cputcxy(x, y + 3, ' '); - break; - default: - cputsxy(x, y + 1, " "); - cputsxy(x, y + 2, " "); - cputsxy(x, y + 3, " "); - break; - } - } - } - - x += speed; - - - if (x >= tileAnim->toX) { - x = tileAnim->toX; - textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - tileAnim->tileString = NULL; - printValueAt(x, y, tileAnim->endTileString); - } else { - textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - tileAnim->fromX = x; - animInProgress = true; - printValueAt(x, y, tileAnim->tileString); - } - playSound(200, 1); - } - switchToPage1(); - firstFrame = false; - } while (animInProgress); -} - - -void performAnimationsUp(void) -{ - bool animInProgress; - tPos pos; - tTileAnim *tileAnim; - tPos x; - tPos y; - bool firstFrame = true; - uint8_t speed = 1; - - if (gNumAnims > BOARD_SIZE) - speed = 2; - - do { - animInProgress = false; - - gSwitchToPage2(); - for (pos = 0; pos < gNumAnims; pos++) { - tileAnim = &(gTileAnims[pos]); - if (tileAnim->tileString == NULL) - continue; - - x = tileAnim->fromX; - y = tileAnim->fromY; - - if (!firstFrame) { - switch ((y % TILE_HEIGHT)) { - case 0: - break; - default: - cputsxy(x + 1, y + TILE_HEIGHT - 1, " "); - if (speed > 1) - cputsxy(x + 1, y + TILE_HEIGHT - 1, " "); - textframexy(x, ((y / TILE_HEIGHT) + 1) * TILE_HEIGHT, - TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - break; - } - } - - if (y < speed) - y = 0; - else - y -= speed;; - - if (y <= tileAnim->toY) { - y = tileAnim->toY; - textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - tileAnim->tileString = NULL; - printValueAt(x, y, tileAnim->endTileString); - } else { - textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - tileAnim->fromY = y; - animInProgress = true; - printValueAt(x, y, tileAnim->tileString); - } - playSound(200, 1); - } - switchToPage1(); - firstFrame = false; - } while (animInProgress); -} - - -void performAnimationsDown(void) -{ - bool animInProgress; - tPos pos; - tTileAnim *tileAnim; - tPos x; - tPos y; - bool firstFrame = true; - uint8_t speed = 1; - - if (gNumAnims > BOARD_SIZE) - speed = 2; - - do { - animInProgress = false; - - gSwitchToPage2(); - for (pos = 0; pos < gNumAnims; pos++) { - tileAnim = &(gTileAnims[pos]); - if (tileAnim->tileString == NULL) - continue; - - x = tileAnim->fromX; - y = tileAnim->fromY; - - if (!firstFrame) { - switch ((y % TILE_HEIGHT)) { - case 0: - break; - default: - cputsxy(x + 1, y, " "); - if (speed > 1) - cputsxy(x + 1, y + 1, " "); - textframexy(x, (y / TILE_HEIGHT) * TILE_HEIGHT, - TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - break; - } - } - - y += speed; - - - if (y >= tileAnim->toY) { - y = tileAnim->toY; - textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - tileAnim->tileString = NULL; - printValueAt(x, y, tileAnim->endTileString); - } else { - textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - tileAnim->fromY = y; - animInProgress = true; - printValueAt(x, y, tileAnim->tileString); - } - playSound(200, 1); - } - switchToPage1(); - firstFrame = false; - } while (animInProgress); -} - - -void performNewTileAnimation() -{ - uint8_t screenX; - uint8_t screenY; - - if (gNewTileString == NULL) - return; - - screenX = TILE_X_TO_SCREEN_X(POS_TO_X(gNewTilePos)); - screenY = TILE_Y_TO_SCREEN_Y(POS_TO_Y(gNewTilePos)); - - textframexy(screenX + 2, screenY + 1, TILE_WIDTH - 4, TILE_HEIGHT - 2, - TEXTFRAME_WIDE); - shortDelay(500); - - textframexy(screenX + 1, screenY + 1, TILE_WIDTH - 2, TILE_HEIGHT - 1, - TEXTFRAME_WIDE); - shortDelay(500); - - textframexy(screenX, screenY, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE); - printValueAt(screenX, screenY, gNewTileString); -} - - -void performAnimations(void) -{ - switch (gAnimDir) { - case DIR_UP: - performAnimationsUp(); - break; - case DIR_DOWN: - performAnimationsDown(); - break; - - case DIR_LEFT: - performAnimationsLeft(); - break; - - case DIR_RIGHT: - performAnimationsRight(); - break; - } - - performNewTileAnimation(); - - resetAnimations(); -} - - -void printBoard(void) -{ - performAnimations(); - printGrid(); - printValues(); - printScore(); -} - - -void gameWon(void) -{ - gotoxy(0, 22); - printf("YOU HAVE WON THE GAME! PRESS SPACE...\n"); - while (cgetc() != ' ') - ; - clrscr(); - newGame(); -} - - -void gameLost(void) -{ - gotoxy(0, 22); - printf("SORRY, NO MORE MOVES. PRESS SPACE..."); - while (cgetc() != ' ') - ; - clrscr(); - newGame(); -} - - -void handleNextEvent(void) -{ - char ch; - - while (true) { - ch = cgetc(); - switch (ch) { - case 'i': - case 'I': - case CH_CURS_UP: - slideInDirection(DIR_UP); - return; - - case 'j': - case 'J': - case CH_CURS_LEFT: - slideInDirection(DIR_LEFT); - return; - - case 'k': - case 'K': - case CH_CURS_RIGHT: - slideInDirection(DIR_RIGHT); - return; - - case 'm': - case 'M': - case CH_CURS_DOWN: - slideInDirection(DIR_DOWN); - return; - - case CH_ESC: - case 'q': - case 'Q': - quitGame(); - break; - - case 'r': - case 'R': - clrscr(); - newGame(); - return; - - case 's': - case 'S': - gPlaySounds = !gPlaySounds; - break; - - case 'h': - case 'H': - printInstructions(); - return; - } - } -} - - -void tileMoved(tPos from, tPos to, char *tileString) -{ - tTileAnim *anim = &(gTileAnims[gNumAnims]); - anim->tileString = tileString; - anim->endTileString = tileStringForPos(POS_TO_X(to), POS_TO_Y(to)); - anim->fromX = TILE_X_TO_SCREEN_X(POS_TO_X(from)); - anim->fromY = TILE_Y_TO_SCREEN_Y(POS_TO_Y(from)); - anim->toX = TILE_X_TO_SCREEN_X(POS_TO_X(to)); - anim->toY = TILE_Y_TO_SCREEN_Y(POS_TO_Y(to)); - gNumAnims++; - - if (anim->fromX > anim->toX) { - gAnimDir = DIR_LEFT; - } else if (anim->fromX < anim->toX) { - gAnimDir = DIR_RIGHT; - } else if (anim->fromY > anim->toY) { - gAnimDir = DIR_UP; - } else if (anim->fromY < anim->toY) { - gAnimDir = DIR_DOWN; - } -} - - -void newTile(tPos at, char *tileString) -{ - gNewTileString = tileString; - gNewTilePos = at; -} +#include "ui.h" int main(void) { - switch (get_ostype()) { - case APPLE_IIGS: - case APPLE_IIGS1: - case APPLE_IIGS3: - gSwitchToPage2 = gsSwitchToPage2; - break; - } - + initAnimations(); printInstructions(); - initGameEngine(tileMoved, newTile); newGame(); while (true) { diff --git a/game.c b/game.c index 53a915c..bf61d3f 100644 --- a/game.c +++ b/game.c @@ -83,7 +83,7 @@ static uint8_t gNumEmptyTiles; static bool gIsGameWon; -void addRandomTile(void); +static void addRandomTile(void); static tTileMoveCallback gTileMoveCallback = NULL; @@ -150,7 +150,7 @@ void newGame(void) } -tPos nextPosInDir(tPos pos, tDir dir) +static tPos nextPosInDir(tPos pos, tDir dir) { tPos result = pos; tPos nextPos; @@ -173,7 +173,7 @@ tPos nextPosInDir(tPos pos, tDir dir) } -void increaseScore(tScore value) +static void increaseScore(tScore value) { gScoreRecord.currentScore += value; if (gScoreRecord.currentScore > gScoreRecord.highScore) @@ -181,7 +181,7 @@ void increaseScore(tScore value) } -void updateMaxTile(tTileValue tileValue) +static void updateMaxTile(tTileValue tileValue) { if (gScoreRecord.highestTile < tileValue) gScoreRecord.highestTile = tileValue; @@ -247,7 +247,7 @@ void slideInDirection(tDir dir) } -void addRandomTile(void) +static void addRandomTile(void) { int8_t randTile; tPos pos; diff --git a/ui.c b/ui.c new file mode 100644 index 0000000..685ecf6 --- /dev/null +++ b/ui.c @@ -0,0 +1,231 @@ +/* + * File: ui.c + * Author: Jeremy Rand + * Date: July 23, 2014 + * + * This file contains the implementation for the 2048 UI. + */ + + +#include +#include +#include + +#include "anim.h" +#include "game.h" +#include "ui.h" + + +static bool gPlaySounds = true; + + +static void quitGame(void) +{ + shutdownGameEngine(); + clrscr(); + exit(0); +} + + +void playSound(int8_t freq, int16_t duration) +{ + if (!gPlaySounds) + return; + + while (duration > 0) { + asm ("STA %w", 0xc030); + while (freq > 0) { + freq--; + } + duration--; + } +} + + +void printInstructions(void) +{ + int seed = 0; + + clrscr(); + printf( +// 0000000001111111111222222222233333333334 +// 1234567890123456789012345678901234567890 + " APPLE 2048\n" + "\n" + "USE I-J-K-M OR THE ARROW KEYS TO SLIDE\n" + "ALL TILES IN A DIRECTION. MATCHING\n" + "TILES ARE ADDED TOGETHER TO MAKE A NEW\n" + "TILE. ON EVERY MOVE, ONE MORE TILE IS\n" + "ADDED WITH A RANDOM VALUE OF EITHER 2\n" + "OR 4.\n" + "\n" + "PLAY ENDS WHEN ALL TILES ARE OCCUPIED\n" + "AND NO MORE MOVES ARE POSSIBLE. TRY\n" + "TO GET THE LARGEST TILE YOU CAN!\n" + "\n" + "PRESS ESCAPE OR Q TO QUIT AT ANY TIME.\n" + "PRESS R TO START A NEW GAME.\n" + "PRESS S TO TOGGLE SOUND.\n" + "PRESS H TO SEE THIS INFO AGAIN.\n" + "\n" + "\n" + "\n" + " PRESS ANY KEY TO START"); + + // The amount of time the user waits to read the in + while (!kbhit()) + seed++; + + cgetc(); + srand(seed); + + clrscr(); +} + + +static void printGrid(void) +{ + tPos x; + tPos y; + + for (x = 1; x <= BOARD_SIZE; x++) { + for (y = 1; y <= BOARD_SIZE; y++) { + textframexy(TILE_X_TO_SCREEN_X(x), + TILE_Y_TO_SCREEN_Y(y), + TILE_WIDTH, + TILE_HEIGHT, + TEXTFRAME_WIDE); + } + } +} + + +void printValueAt(uint8_t screenX, uint8_t screenY, char *tileString) +{ + screenX++; + screenY++; + + cputsxy(screenX, screenY, " "); + screenY++; + cputsxy(screenX, screenY, tileString); + screenY++; + cputsxy(screenX, screenY, " "); +} + + +static void printValues(void) +{ + tPos x; + tPos y; + + for (x = 1; x <= BOARD_SIZE; x++) { + for (y = 1; y <= BOARD_SIZE; y++) { + printValueAt(TILE_X_TO_SCREEN_X(x), TILE_Y_TO_SCREEN_Y(y), + tileStringForPos(x, y)); + } + } +} + + +static void printScore(void) +{ + tScore highestTile = highestTarget(); + + gotoxy(0,20); + printf("SCORE: %10ld HI-SCORE: %10ld\n", currentScore(), highScore()); + + if (highestTile == 0) { + printf("TRY TO GET THE %ld TILE!\n", nextTarget()); + } else { + printf("GOT %ld! NOW GET %ld!\n", highestTile, nextTarget()); + } +} + + +void printBoard(void) +{ + performAnimations(); + printGrid(); + printValues(); + printScore(); +} + + +void gameWon(void) +{ + gotoxy(0, 22); + printf("YOU HAVE WON THE GAME! PRESS SPACE...\n"); + while (cgetc() != ' ') + ; + clrscr(); + newGame(); +} + + +void gameLost(void) +{ + gotoxy(0, 22); + printf("SORRY, NO MORE MOVES. PRESS SPACE..."); + while (cgetc() != ' ') + ; + clrscr(); + newGame(); +} + + +void handleNextEvent(void) +{ + char ch; + + while (true) { + ch = cgetc(); + switch (ch) { + case 'i': + case 'I': + case CH_CURS_UP: + slideInDirection(DIR_UP); + return; + + case 'j': + case 'J': + case CH_CURS_LEFT: + slideInDirection(DIR_LEFT); + return; + + case 'k': + case 'K': + case CH_CURS_RIGHT: + slideInDirection(DIR_RIGHT); + return; + + case 'm': + case 'M': + case CH_CURS_DOWN: + slideInDirection(DIR_DOWN); + return; + + case CH_ESC: + case 'q': + case 'Q': + quitGame(); + break; + + case 'r': + case 'R': + clrscr(); + newGame(); + return; + + case 's': + case 'S': + gPlaySounds = !gPlaySounds; + break; + + case 'h': + case 'H': + printInstructions(); + return; + } + } +} + diff --git a/ui.h b/ui.h new file mode 100644 index 0000000..9c8f571 --- /dev/null +++ b/ui.h @@ -0,0 +1,29 @@ +/* + * File: ui.h + * Author: Jeremy Rand + * Date: July 23, 2014 + * + * This file contains the header for the 2048 UI. + */ + + +#define TILE_WIDTH 10 +#define TILE_HEIGHT 5 + +#define TILE_X_TO_SCREEN_X(x) (((x) - 1) * TILE_WIDTH) +#define TILE_Y_TO_SCREEN_Y(y) (((y) - 1) * TILE_HEIGHT) + + +extern void printInstructions(void); + +extern void printBoard(void); + +extern void gameWon(void); + +extern void gameLost(void); + +extern void handleNextEvent(void); + +extern void printValueAt(uint8_t screenX, uint8_t screenY, char *tileString); + +extern void playSound(int8_t freq, int16_t duration);