FInal code cleanup for hackfest entry

This commit is contained in:
Jeremy Rand 2014-07-25 14:55:41 -05:00
parent ae7930ddf1
commit 63132800ec
6 changed files with 725 additions and 652 deletions

445
anim.c Normal file
View File

@ -0,0 +1,445 @@
/*
* File: anim.c
* Author: Jeremy Rand
* Date: July 23, 2014
*
* This file is the implementation file the 2048 animations.
*/
#include <apple2enh.h>
#include <conio.h>
#include <stddef.h>
#include <string.h>
#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);
}

12
anim.h Normal file
View File

@ -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);

View File

@ -6,661 +6,17 @@
* This file contains the entry point for the 2048 game.
*/
#include <apple2enh.h>
#include <conio.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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) {

10
game.c
View File

@ -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;

231
ui.c Normal file
View File

@ -0,0 +1,231 @@
/*
* File: ui.c
* Author: Jeremy Rand
* Date: July 23, 2014
*
* This file contains the implementation for the 2048 UI.
*/
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}
}
}

29
ui.h Normal file
View File

@ -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);