mirror of
https://github.com/jeremysrand/apple2048.git
synced 2024-06-08 21:29:30 +00:00
Add a bunch of animations and sounds
This commit is contained in:
parent
2e0a001c1c
commit
f2cfbc6a34
382
apple2048.c
382
apple2048.c
|
@ -8,8 +8,10 @@
|
||||||
|
|
||||||
#include <apple2enh.h>
|
#include <apple2enh.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
|
@ -17,6 +19,50 @@
|
||||||
#define TILE_WIDTH 10
|
#define TILE_WIDTH 10
|
||||||
#define TILE_HEIGHT 5
|
#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;
|
||||||
|
|
||||||
|
void shortDelay(uint16_t howMuch)
|
||||||
|
{
|
||||||
|
while (howMuch > 0) {
|
||||||
|
howMuch--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void playSound(int8_t freq, int16_t duration)
|
||||||
|
{
|
||||||
|
while (duration > 0) {
|
||||||
|
if (gPlaySounds)
|
||||||
|
asm ("STA %w", 0xc030);
|
||||||
|
while (freq > 0) {
|
||||||
|
freq--;
|
||||||
|
}
|
||||||
|
duration--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void printInstructions(void)
|
void printInstructions(void)
|
||||||
{
|
{
|
||||||
int seed = 0;
|
int seed = 0;
|
||||||
|
@ -40,11 +86,12 @@ void printInstructions(void)
|
||||||
"\n"
|
"\n"
|
||||||
"PRESS ESCAPE OR Q TO QUIT AT ANY TIME.\n"
|
"PRESS ESCAPE OR Q TO QUIT AT ANY TIME.\n"
|
||||||
"PRESS R TO START A NEW GAME.\n"
|
"PRESS R TO START A NEW GAME.\n"
|
||||||
|
"PRESS S TO TOGGLE SOUND.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
" PRESS ANY KEY TO START");
|
" PRESS ANY KEY TO START");
|
||||||
|
|
||||||
// The amount of time the user waits to read the in
|
// The amount of time the user waits to read the in
|
||||||
while (!kbhit())
|
while (!kbhit())
|
||||||
|
@ -57,36 +104,313 @@ void printInstructions(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void printBoard(void)
|
void printGrid(void)
|
||||||
{
|
{
|
||||||
tPos x;
|
tPos x;
|
||||||
tPos y;
|
tPos y;
|
||||||
|
|
||||||
for (x = 1; x <= BOARD_SIZE; x++) {
|
for (x = 1; x <= BOARD_SIZE; x++) {
|
||||||
for (y = 1; y <= BOARD_SIZE; y++) {
|
for (y = 1; y <= BOARD_SIZE; y++) {
|
||||||
textframexy((x - 1) * TILE_WIDTH,
|
textframexy(TILE_X_TO_SCREEN_X(x),
|
||||||
(y - 1) * TILE_HEIGHT,
|
TILE_Y_TO_SCREEN_Y(y),
|
||||||
TILE_WIDTH,
|
TILE_WIDTH,
|
||||||
TILE_HEIGHT,
|
TILE_HEIGHT,
|
||||||
TEXTFRAME_WIDE);
|
TEXTFRAME_WIDE);
|
||||||
cputsxy((x - 1) * TILE_WIDTH + 1,
|
}
|
||||||
(y - 1) * TILE_HEIGHT + 2,
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
tileStringForPos(x, y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void printScore(void)
|
||||||
|
{
|
||||||
gotoxy(0,20);
|
gotoxy(0,20);
|
||||||
printf("CURRENT SCORE: %ld\nTRY TO GET THE %ld TILE!", currentScore(),
|
printf("CURRENT SCORE: %ld\nTRY TO GET THE %ld TILE!", currentScore(),
|
||||||
nextTarget());
|
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;
|
||||||
|
|
||||||
|
do {
|
||||||
|
animInProgress = false;
|
||||||
|
|
||||||
|
for (pos = 0; pos < gNumAnims; pos++) {
|
||||||
|
tileAnim = &(gTileAnims[pos]);
|
||||||
|
if (tileAnim->tileString == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x = tileAnim->fromX;
|
||||||
|
y = tileAnim->fromY;
|
||||||
|
if ((x % TILE_WIDTH) != (TILE_WIDTH - 1)) {
|
||||||
|
x += TILE_WIDTH;
|
||||||
|
if (x < 40) {
|
||||||
|
cputcxy(x, y + 1, ' ');
|
||||||
|
cputcxy(x, y + 2, ' ');
|
||||||
|
cputcxy(x, y + 3, ' ');
|
||||||
|
}
|
||||||
|
x -= TILE_WIDTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
x--;
|
||||||
|
|
||||||
|
textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE);
|
||||||
|
|
||||||
|
if (x == tileAnim->toX) {
|
||||||
|
tileAnim->tileString = NULL;
|
||||||
|
printValueAt(x, y, tileAnim->endTileString);
|
||||||
|
} else {
|
||||||
|
tileAnim->fromX = x;
|
||||||
|
animInProgress = true;
|
||||||
|
printValueAt(x, y, tileAnim->tileString);
|
||||||
|
}
|
||||||
|
playSound(200, 2);
|
||||||
|
}
|
||||||
|
} while (animInProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void performAnimationsRight(void)
|
||||||
|
{
|
||||||
|
bool animInProgress;
|
||||||
|
tPos pos;
|
||||||
|
tTileAnim *tileAnim;
|
||||||
|
tPos x;
|
||||||
|
tPos y;
|
||||||
|
|
||||||
|
do {
|
||||||
|
animInProgress = false;
|
||||||
|
|
||||||
|
for (pos = 0; pos < gNumAnims; pos++) {
|
||||||
|
tileAnim = &(gTileAnims[pos]);
|
||||||
|
if (tileAnim->tileString == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x = tileAnim->fromX;
|
||||||
|
y = tileAnim->fromY;
|
||||||
|
if ((x % TILE_WIDTH) != 0) {
|
||||||
|
cputcxy(x, y + 1, ' ');
|
||||||
|
cputcxy(x, y + 2, ' ');
|
||||||
|
cputcxy(x, y + 3, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
x++;
|
||||||
|
|
||||||
|
textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE);
|
||||||
|
|
||||||
|
if (x == tileAnim->toX) {
|
||||||
|
tileAnim->tileString = NULL;
|
||||||
|
printValueAt(x, y, tileAnim->endTileString);
|
||||||
|
} else {
|
||||||
|
tileAnim->fromX = x;
|
||||||
|
animInProgress = true;
|
||||||
|
printValueAt(x, y, tileAnim->tileString);
|
||||||
|
}
|
||||||
|
playSound(200, 2);
|
||||||
|
}
|
||||||
|
} while (animInProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void performAnimationsUp(void)
|
||||||
|
{
|
||||||
|
bool animInProgress;
|
||||||
|
tPos pos;
|
||||||
|
tTileAnim *tileAnim;
|
||||||
|
tPos x;
|
||||||
|
tPos y;
|
||||||
|
|
||||||
|
do {
|
||||||
|
animInProgress = false;
|
||||||
|
|
||||||
|
for (pos = 0; pos < gNumAnims; pos++) {
|
||||||
|
tileAnim = &(gTileAnims[pos]);
|
||||||
|
if (tileAnim->tileString == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x = tileAnim->fromX;
|
||||||
|
y = tileAnim->fromY;
|
||||||
|
|
||||||
|
switch ((y % TILE_HEIGHT)) {
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
cputsxy(x, y + TILE_HEIGHT, " ");
|
||||||
|
if (y < TILE_Y_TO_SCREEN_Y(BOARD_SIZE))
|
||||||
|
textframexy(x, ((y / TILE_HEIGHT) + 1) * TILE_HEIGHT,
|
||||||
|
TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
y--;
|
||||||
|
|
||||||
|
textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE);
|
||||||
|
|
||||||
|
if (y == tileAnim->toY) {
|
||||||
|
tileAnim->tileString = NULL;
|
||||||
|
printValueAt(x, y, tileAnim->endTileString);
|
||||||
|
} else {
|
||||||
|
tileAnim->fromY = y;
|
||||||
|
animInProgress = true;
|
||||||
|
printValueAt(x, y, tileAnim->tileString);
|
||||||
|
}
|
||||||
|
playSound(200, 2);
|
||||||
|
}
|
||||||
|
} while (animInProgress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void performAnimationsDown(void)
|
||||||
|
{
|
||||||
|
bool animInProgress;
|
||||||
|
tPos pos;
|
||||||
|
tTileAnim *tileAnim;
|
||||||
|
tPos x;
|
||||||
|
tPos y;
|
||||||
|
|
||||||
|
do {
|
||||||
|
animInProgress = false;
|
||||||
|
|
||||||
|
for (pos = 0; pos < gNumAnims; pos++) {
|
||||||
|
tileAnim = &(gTileAnims[pos]);
|
||||||
|
if (tileAnim->tileString == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
x = tileAnim->fromX;
|
||||||
|
y = tileAnim->fromY;
|
||||||
|
|
||||||
|
switch ((y % TILE_HEIGHT)) {
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
cputsxy(x, y, " ");
|
||||||
|
textframexy(x, (y / TILE_HEIGHT) * TILE_HEIGHT,
|
||||||
|
TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
y++;
|
||||||
|
|
||||||
|
textframexy(x, y, TILE_WIDTH, TILE_HEIGHT, TEXTFRAME_WIDE);
|
||||||
|
|
||||||
|
if (y == tileAnim->toY) {
|
||||||
|
tileAnim->tileString = NULL;
|
||||||
|
printValueAt(x, y, tileAnim->endTileString);
|
||||||
|
} else {
|
||||||
|
tileAnim->fromY = y;
|
||||||
|
animInProgress = true;
|
||||||
|
printValueAt(x, y, tileAnim->tileString);
|
||||||
|
}
|
||||||
|
playSound(200, 2);
|
||||||
|
}
|
||||||
|
} 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)
|
void gameWon(void)
|
||||||
{
|
{
|
||||||
gotoxy(0, 22);
|
gotoxy(0, 22);
|
||||||
printf("YOU HAVE WON THE GAME! PRESS ANY KEY...\n");
|
printf("YOU HAVE WON THE GAME! PRESS ANY KEY...\n");
|
||||||
cgetc();
|
cgetc();
|
||||||
initGame();
|
clrscr();
|
||||||
|
newGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,7 +419,8 @@ void gameLost(void)
|
||||||
gotoxy(0, 22);
|
gotoxy(0, 22);
|
||||||
printf("SORRY, NO MORE MOVES. PRESS ANY KEY...");
|
printf("SORRY, NO MORE MOVES. PRESS ANY KEY...");
|
||||||
cgetc();
|
cgetc();
|
||||||
initGame();
|
clrscr();
|
||||||
|
newGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -137,18 +462,55 @@ void handleNextEvent(void)
|
||||||
|
|
||||||
case 'r':
|
case 'r':
|
||||||
case 'R':
|
case 'R':
|
||||||
initGame();
|
clrscr();
|
||||||
|
newGame();
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
gPlaySounds = !gPlaySounds;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
printInstructions();
|
printInstructions();
|
||||||
|
|
||||||
initGame();
|
initGameEngine(tileMoved, newTile);
|
||||||
|
newGame();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
printBoard();
|
printBoard();
|
||||||
|
|
35
game.c
35
game.c
|
@ -8,20 +8,12 @@
|
||||||
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
||||||
|
|
||||||
// A 4x4 board is actually represented as a 6x6 board internally. This gives
|
|
||||||
// us special tiles around the whole board which can have a value which
|
|
||||||
// prevents tiles from scrolling beyond the bounds of the board. Also, this
|
|
||||||
// is why the values of DIR_DOWN and DIR_UP in the game.h file is a bit
|
|
||||||
// strange.
|
|
||||||
#define NUM_TILES ((BOARD_SIZE + 2) * (BOARD_SIZE + 2))
|
|
||||||
|
|
||||||
#define POS_TO_X(pos) ((pos) % (BOARD_SIZE + 2))
|
|
||||||
#define POS_TO_Y(pos) ((pos) / (BOARD_SIZE + 2))
|
|
||||||
#define X_Y_TO_POS(x, y) (((y) * (BOARD_SIZE + 2)) + (x))
|
|
||||||
#define POS_IN_DIR(pos, dir) ((pos) + (dir))
|
#define POS_IN_DIR(pos, dir) ((pos) + (dir))
|
||||||
|
|
||||||
// The maximum which the game supports in any one tile is 2^19 because that is
|
// The maximum which the game supports in any one tile is 2^19 because that is
|
||||||
|
@ -79,7 +71,19 @@ static uint8_t gNumEmptyTiles;
|
||||||
void addRandomTile(void);
|
void addRandomTile(void);
|
||||||
|
|
||||||
|
|
||||||
void initGame(void)
|
static tTileMoveCallback gTileMoveCallback = NULL;
|
||||||
|
static tNewTileCallback gNewTileCallback = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
void initGameEngine(tTileMoveCallback tileMoveCallback,
|
||||||
|
tNewTileCallback newTileCallback)
|
||||||
|
{
|
||||||
|
gTileMoveCallback = tileMoveCallback;
|
||||||
|
gNewTileCallback = newTileCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void newGame(void)
|
||||||
{
|
{
|
||||||
tPos pos;
|
tPos pos;
|
||||||
tPos x;
|
tPos x;
|
||||||
|
@ -173,6 +177,7 @@ void slideInDirection(tDir dir)
|
||||||
} else {
|
} else {
|
||||||
gTileValues[destPos] = gTileValues[pos];
|
gTileValues[destPos] = gTileValues[pos];
|
||||||
}
|
}
|
||||||
|
gTileMoveCallback(pos, destPos, gValueStrings[gTileValues[pos]]);
|
||||||
gTileValues[pos] = 0; // Empty the old position
|
gTileValues[pos] = 0; // Empty the old position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +211,7 @@ void addRandomTile(void)
|
||||||
else
|
else
|
||||||
gTileValues[pos] = 1; // This creates a 2
|
gTileValues[pos] = 1; // This creates a 2
|
||||||
gNumEmptyTiles--;
|
gNumEmptyTiles--;
|
||||||
|
gNewTileCallback(pos, gValueStrings[gTileValues[pos]]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
randTile--;
|
randTile--;
|
||||||
|
@ -270,5 +276,10 @@ bool isGameLost(void)
|
||||||
|
|
||||||
char *tileStringForPos(tPos x, tPos y)
|
char *tileStringForPos(tPos x, tPos y)
|
||||||
{
|
{
|
||||||
return gValueStrings[gTileValues[X_Y_TO_POS(x, y)]];
|
tTileValue value = gTileValues[X_Y_TO_POS(x, y)];
|
||||||
|
|
||||||
|
if (value < 0)
|
||||||
|
value *= -1;
|
||||||
|
|
||||||
|
return gValueStrings[value];
|
||||||
}
|
}
|
||||||
|
|
30
game.h
30
game.h
|
@ -13,6 +13,17 @@
|
||||||
|
|
||||||
#define BOARD_SIZE 4
|
#define BOARD_SIZE 4
|
||||||
|
|
||||||
|
// A 4x4 board is actually represented as a 6x6 board internally. This gives
|
||||||
|
// us special tiles around the whole board which can have a value which
|
||||||
|
// prevents tiles from scrolling beyond the bounds of the board. Also, this
|
||||||
|
// is why the values of DIR_DOWN and DIR_UP in the game.h file is a bit
|
||||||
|
// strange.
|
||||||
|
#define NUM_TILES ((BOARD_SIZE + 2) * (BOARD_SIZE + 2))
|
||||||
|
|
||||||
|
#define POS_TO_X(pos) ((pos) % (BOARD_SIZE + 2))
|
||||||
|
#define POS_TO_Y(pos) ((pos) / (BOARD_SIZE + 2))
|
||||||
|
#define X_Y_TO_POS(x, y) (((y) * (BOARD_SIZE + 2)) + (x))
|
||||||
|
|
||||||
#define DIR_DOWN (BOARD_SIZE + 2)
|
#define DIR_DOWN (BOARD_SIZE + 2)
|
||||||
#define DIR_UP (-(DIR_DOWN))
|
#define DIR_UP (-(DIR_DOWN))
|
||||||
#define DIR_RIGHT 1
|
#define DIR_RIGHT 1
|
||||||
|
@ -23,19 +34,24 @@ typedef int8_t tDir;
|
||||||
typedef int8_t tPos;
|
typedef int8_t tPos;
|
||||||
typedef uint32_t tScore;
|
typedef uint32_t tScore;
|
||||||
|
|
||||||
|
typedef void (*tTileMoveCallback)(tPos from, tPos to, char *tileString);
|
||||||
|
typedef void (*tNewTileCallback)(tPos at, char *tileString);
|
||||||
|
|
||||||
void initGame(void);
|
extern void initGameEngine(tTileMoveCallback tileMoveCallback,
|
||||||
|
tNewTileCallback newTileCallback);
|
||||||
|
|
||||||
void slideInDirection(tDir dir);
|
extern void newGame(void);
|
||||||
|
|
||||||
tScore currentScore(void);
|
extern void slideInDirection(tDir dir);
|
||||||
|
|
||||||
tScore nextTarget(void);
|
extern tScore currentScore(void);
|
||||||
|
|
||||||
bool isGameWon(void);
|
extern tScore nextTarget(void);
|
||||||
|
|
||||||
bool isGameLost(void);
|
extern bool isGameWon(void);
|
||||||
|
|
||||||
|
extern bool isGameLost(void);
|
||||||
|
|
||||||
// Positions are 1 based so the top-left corner is (1, 1) and the bottom-right
|
// Positions are 1 based so the top-left corner is (1, 1) and the bottom-right
|
||||||
// corner is (BOARD_SIZE, BOARD_SIZE).
|
// corner is (BOARD_SIZE, BOARD_SIZE).
|
||||||
char *tileStringForPos(tPos x, tPos y);
|
extern char *tileStringForPos(tPos x, tPos y);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user