diff --git a/warehouse/main.c b/warehouse/main.c index 2252dce..ab7311d 100644 --- a/warehouse/main.c +++ b/warehouse/main.c @@ -53,6 +53,26 @@ segment "warehouse"; #define TILE_CRATE_ON_GOAL 7 #define TILE_COUNT 8 +#define AVATAR_UP 0 +#define AVATAR_RIGHT 1 +#define AVATAR_DOWN 2 +#define AVATAR_LEFT 3 +#define AVATAR_PUSH_UP 4 +#define AVATAR_PUSH_LOOP_UP 5 +#define AVATAR_PUSH_RIGHT 6 +#define AVATAR_PUSH_LOOP_RIGHT 7 +#define AVATAR_PUSH_DOWN 8 +#define AVATAR_PUSH_LOOP_DOWN 9 +#define AVATAR_PUSH_LEFT 10 +#define AVATAR_PUSH_LOOP_LEFT 11 +#define AVATAR_IDLE 12 +#define AVATAR_NO 13 +#define AVATAR_COUNT 14 +#define AVATAR_MAX_FRAMES 8 + +#define AVATAR_X_ON_SCREEN (((avatarX << 1) + puzzle.offsetX) << 3) - 8 +#define AVATAR_Y_ON_SCREEN (((avatarY << 1) + puzzle.offsetY) << 3) - 8 + typedef struct PuzzleS { byte offsetX; @@ -69,8 +89,8 @@ typedef struct SaveS { } SaveT; typedef struct CoordS { - byte x; - byte y; + jint16 x; + jint16 y; } CoordT; @@ -99,6 +119,8 @@ static jlImgT *helpI = NULL; static jlImgT *savedScreen1 = NULL; static jlImgT *savedScreen2 = NULL; +static jlStnT *tilesS = NULL; + static jint16 puzzleCount; static jint16 puzzleCurrent; static jint16 puzzleLast; @@ -118,6 +140,7 @@ static byte avatarXLast; static byte avatarYLast; static byte avatarXStart; static byte avatarYStart; +static byte avatarFacing = AVATAR_RIGHT; // 0=Up, 1=Right, 2=Down, 3=Left static byte crateCount; static byte crateInitialCount; @@ -126,19 +149,43 @@ static byte cratesInitiallyOnTarget; //static char puzzleChars[] = { "_# .$@+*" }; + +static CoordT avatar[AVATAR_COUNT][AVATAR_MAX_FRAMES] = { // These are sprite numbers and get converted later to tile coordinates. + { { 1, 0 }, { 2, 0 }, { 3, 0 }, { 2, 0 }, { 1, 0 }, { 4, 0 }, { 5, 0 }, { 4, 0 } }, // AVATAR_UP + { { 21, 0 }, { 22, 0 }, { 23, 0 }, { 24, 0 }, { 25, 0 }, { 26, 0 }, { 27, 0 }, { 0, 0 } }, // AVATAR_RIGHT + { { 6, 0 }, { 7, 0 }, { 8, 0 }, { 7, 0 }, { 6, 0 }, { 8, 0 }, { 9, 0 }, { 8, 0 } }, // AVATAR_DOWN + { { 11, 0 }, { 12, 0 }, { 13, 0 }, { 14, 0 }, { 15, 0 }, { 16, 0 }, { 17, 0 }, { 0, 0 } }, // AVATAR_LEFT + { { 31, 0 }, { 32, 0 }, { 33, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_PUSH_UP + { { 34, 0 }, { 35, 0 }, { 36, 0 }, { 37, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_PUSH_LOOP_UP + { { 61, 0 }, { 62, 0 }, { 63, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_PUSH_RIGHT + { { 64, 0 }, { 65, 0 }, { 66, 0 }, { 67, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_PUSH_LOOP_RIGHT + { { 41, 0 }, { 42, 0 }, { 43, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_PUSH_DOWN + { { 44, 0 }, { 45, 0 }, { 46, 0 }, { 47, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_PUSH_LOOP_DOWN + { { 51, 0 }, { 52, 0 }, { 53, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_PUSH_LEFT + { { 54, 0 }, { 55, 0 }, { 56, 0 }, { 57, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_PUSH_LOOP_LEFT + { { 11, 0 }, { 19, 0 }, { 20, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, // AVATAR_IDLE + { { 28, 0 }, { 29, 0 }, { 28, 0 }, { 29, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } } // AVATAR_NO +}; + static CoordT tileLookup[TILE_COUNT] = { - { 10 * 8, 0 }, - { 0 * 8, 0 }, - { 2 * 8, 0 }, - { 4 * 8, 0 }, - { 6 * 8, 0 }, - { 8 * 8, 0 }, - { 8 * 8, 0 }, - { 6 * 8, 0 } + { 8, 23 }, // Nothing + { 2, 23 }, // Wall + { 6, 23 }, // Floor + { 4, 23 }, // Goal + { 0, 23 }, // Crate + { 17, 3 }, // Player + { 17, 3 }, // Player on Goal + { 0, 23 } // Crate on Goal }; -void avatarDraw(void); +void avatarCrateHide(byte x1, byte y1, bool pushing); +void avatarCrateShow(void); +void avatarDraw(jint16 x1, jint16 y1, jint16 sequence, jint16 frame); +void avatarWalkDown(bool pushing); +void avatarWalkLeft(bool pushing); +void avatarWalkRight(bool pushing); +void avatarWalkUp(bool pushing); void crateMove(byte sx, byte sy, byte dx, byte dy); void fontPrint(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...); void gamePlay(void); @@ -158,22 +205,262 @@ void puzzleReset(void); void puzzleSelect(void); void solvedCount(void); void tickerUpdate(void); +void tileDraw(byte tile, jint16 x1, jint16 y1); void titleShow(void); -void avatarDraw(void) { - jint16 x = 0; // Screen (tile) coordinates. - jint16 y = 0; - CoordT t; +void avatarCrateHide(byte x1, byte y1, bool pushing) { + byte save = 0; - x = ((avatarX << 1) + puzzle.offsetX) << 3; - y = ((avatarY << 1) + puzzle.offsetY) << 3; - t = tileLookup[TILE_PLAYER]; + // Erase the avatar from the playfield. + puzzleBefore[avatarX][avatarY] = TILE_NOTHING; + puzzleBefore[avatarX - 1][avatarY] = TILE_NOTHING; + puzzleBefore[avatarX + 1][avatarY] = TILE_NOTHING; + puzzleBefore[avatarX][avatarY - 1] = TILE_NOTHING; - jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x, t.y, x, y ); - jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x + 8, t.y, x + 8, y ); - jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x, t.y + 8, x, y + 8); - jlDrawBlit8x8(jlImgSurfaceGet(tilesI), t.x + 8, t.y + 8, x + 8, y + 8); + // Erase crate if we're pushing. + if (pushing) { + save = puzzleNow[x1][y1]; + if (puzzleNow[x1][y1] == TILE_CRATE_ON_GOAL) { + puzzleNow[x1][y1] = TILE_GOAL; + } else { + puzzleNow[x1][y1] = TILE_FLOOR; + } + } + + puzzleDraw(); + jlImgCreate(savedScreen1); + + if (pushing) { + // Put the crate data back in the puzzle. + puzzleNow[x1][y1] = save; + } +} + + +void avatarCrateShow(void) { + jlImgDisplay(savedScreen1); + avatarDraw(AVATAR_X_ON_SCREEN, AVATAR_Y_ON_SCREEN, avatarFacing, 0); +} + + +void avatarDraw(jint16 x1, jint16 y1, jint16 sequence, jint16 frame) { + jint16 x2 = x1 + 8; + jint16 x3 = x2 + 8; + jint16 x4 = x3 + 8; + jint16 y2 = y1 + 8; + jint16 y3 = y2 + 8; + CoordT t = avatar[sequence][frame]; + jint16 tx1 = t.x; + jint16 tx2 = tx1 + 8; + jint16 tx3 = tx2 + 8; + jint16 tx4 = tx3 + 8; + jint16 ty1 = t.y; + jint16 ty2 = ty1 + 8; + jint16 ty3 = ty2 + 8; + + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx1, ty1, x1, y1); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx2, ty1, x2, y1); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx3, ty1, x3, y1); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx4, ty1, x4, y1); + + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx1, ty2, x1, y2); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx2, ty2, x2, y2); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx3, ty2, x3, y2); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx4, ty2, x4, y2); + + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx1, ty3, x1, y3); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx2, ty3, x2, y3); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx3, ty3, x3, y3); + jlDrawBlit8x8a(jlImgSurfaceGet(tilesI), tilesS, tx4, ty3, x4, y3); +} + + +void avatarWalkDown(bool pushing) { + jint16 i = 0; + jint16 x = AVATAR_X_ON_SCREEN; + jint16 y = AVATAR_Y_ON_SCREEN; + jint16 tx = x + 8; + jint16 frame = 0; + jint16 seq = pushing ? AVATAR_PUSH_DOWN : AVATAR_DOWN; + jint16 seq2 = pushing ? AVATAR_PUSH_LOOP_DOWN : AVATAR_DOWN; + + avatarCrateHide(avatarX, avatarY + 1, pushing); + + avatarFacing = AVATAR_DOWN; + + for (i=y; i= AVATAR_MAX_FRAMES) { + frame = 0; + seq = seq2; + } else { + if (avatar[seq][frame].x == -1) { + frame = 0; + seq = seq2; + } + } + + tickerUpdate(); + } + + avatarY++; + avatarCrateShow(); + + if (pushing) { + // Move crate. + crateMove(avatarX, avatarY, avatarX, avatarY + 1); + } +} + + +void avatarWalkLeft(bool pushing) { + jint16 i = 0; + jint16 x = AVATAR_X_ON_SCREEN; + jint16 y = AVATAR_Y_ON_SCREEN; + jint16 ty = y + 8; + jint16 frame = 0; + jint16 seq = pushing ? AVATAR_PUSH_LEFT : AVATAR_LEFT; + jint16 seq2 = pushing ? AVATAR_PUSH_LOOP_LEFT : AVATAR_LEFT; + + avatarCrateHide(avatarX - 1, avatarY, pushing); + + avatarFacing = AVATAR_LEFT; + + for (i=x; i>x-16; i--) { + + jlImgDisplay(savedScreen1); + avatarDraw(i, y, seq, frame); + if (pushing) { + tileDraw(TILE_CRATE, i - 8, ty); + } + jlDisplayPresent(); + jlUtilSleep(1); + + frame++; + if (frame >= AVATAR_MAX_FRAMES) { + frame = 0; + seq = seq2; + } else { + if (avatar[seq][frame].x == -1) { + frame = 0; + seq = seq2; + } + } + + tickerUpdate(); + } + + avatarX--; + avatarCrateShow(); + + if (pushing) { + // Move crate. + crateMove(avatarX, avatarY, avatarX - 1, avatarY); + } +} + + +void avatarWalkRight(bool pushing) { + jint16 i = 0; + jint16 x = AVATAR_X_ON_SCREEN; + jint16 y = AVATAR_Y_ON_SCREEN; + jint16 ty = y + 8; + jint16 frame = 0; + jint16 seq = pushing ? AVATAR_PUSH_RIGHT : AVATAR_RIGHT; + jint16 seq2 = pushing ? AVATAR_PUSH_LOOP_RIGHT : AVATAR_RIGHT; + + avatarCrateHide(avatarX + 1, avatarY, pushing); + + avatarFacing = AVATAR_RIGHT; + + for (i=x; i= AVATAR_MAX_FRAMES) { + frame = 0; + seq = seq2; + } else { + if (avatar[seq][frame].x == -1) { + frame = 0; + seq = seq2; + } + } + + tickerUpdate(); + } + + avatarX++; + avatarCrateShow(); + + if (pushing) { + // Move crate. + crateMove(avatarX, avatarY, avatarX + 1, avatarY); + } +} + + +void avatarWalkUp(bool pushing) { + jint16 i = 0; + jint16 x = AVATAR_X_ON_SCREEN; + jint16 y = AVATAR_Y_ON_SCREEN; + jint16 tx = x + 8; + jint16 frame = 0; + jint16 seq = pushing ? AVATAR_PUSH_UP : AVATAR_UP; + jint16 seq2 = pushing ? AVATAR_PUSH_LOOP_UP : AVATAR_UP; + + avatarCrateHide(avatarX, avatarY - 1, pushing); + + avatarFacing = AVATAR_UP; + + for (i=y; i>y-16; i--) { + + jlImgDisplay(savedScreen1); + if (pushing) { + tileDraw(TILE_CRATE, tx, i - 8); + } + avatarDraw(x, i, seq, frame); + jlDisplayPresent(); + jlUtilSleep(1); + + frame++; + if (frame >= AVATAR_MAX_FRAMES) { + frame = 0; + seq = seq2; + } else { + if (avatar[seq][frame].x == -1) { + frame = 0; + seq = seq2; + } + } + + tickerUpdate(); + } + + avatarY--; + avatarCrateShow(); + + if (pushing) { + // Move crate. + crateMove(avatarX, avatarY, avatarX, avatarY - 1); + } } @@ -256,14 +543,13 @@ void gamePlay(void) { // Can we move up? tile = puzzleNow[avatarX][avatarY - 1]; if ((tile == TILE_FLOOR) || (tile == TILE_GOAL)) { - avatarY--; + avatarWalkUp(false); } // Can we push up? if ((tile == TILE_CRATE) || (tile == TILE_CRATE_ON_GOAL)) { tile = puzzleNow[avatarX][avatarY - 2]; if ((tile == TILE_FLOOR) || (tile == TILE_GOAL)) { - avatarY--; - crateMove(avatarX, avatarY, avatarX, avatarY - 1); + avatarWalkUp(true); } } break; @@ -273,14 +559,13 @@ void gamePlay(void) { // Can we move left? tile = puzzleNow[avatarX - 1][avatarY]; if ((tile == TILE_FLOOR) || (tile == TILE_GOAL)) { - avatarX--; + avatarWalkLeft(false); } // Can we push left? if ((tile == TILE_CRATE) || (tile == TILE_CRATE_ON_GOAL)) { tile = puzzleNow[avatarX - 2][avatarY]; if ((tile == TILE_FLOOR) || (tile == TILE_GOAL)) { - avatarX--; - crateMove(avatarX, avatarY, avatarX - 1, avatarY); + avatarWalkLeft(true); } } break; @@ -290,14 +575,13 @@ void gamePlay(void) { // Can we move right? tile = puzzleNow[avatarX + 1][avatarY]; if ((tile == TILE_FLOOR) || (tile == TILE_GOAL)) { - avatarX++; + avatarWalkRight(false); } // Can we push right? if ((tile == TILE_CRATE) || (tile == TILE_CRATE_ON_GOAL)) { tile = puzzleNow[avatarX + 2][avatarY]; if ((tile == TILE_FLOOR) || (tile == TILE_GOAL)) { - avatarX++; - crateMove(avatarX, avatarY, avatarX + 1, avatarY); + avatarWalkRight(true); } } break; @@ -307,14 +591,13 @@ void gamePlay(void) { // Can we move down? tile = puzzleNow[avatarX][avatarY + 1]; if ((tile == TILE_FLOOR) || (tile == TILE_GOAL)) { - avatarY++; + avatarWalkDown(false); } // Can we push down? if ((tile == TILE_CRATE) || (tile == TILE_CRATE_ON_GOAL)) { tile = puzzleNow[avatarX][avatarY + 2]; if ((tile == TILE_FLOOR) || (tile == TILE_GOAL)) { - avatarY++; - crateMove(avatarX, avatarY, avatarX, avatarY + 1); + avatarWalkDown(true); } } break; @@ -330,7 +613,10 @@ void gamePlay(void) { } // Redraw? if ((avatarX != avatarXLast) || (avatarY != avatarYLast)) { - puzzleBefore[avatarXLast][avatarYLast] = TILE_NOTHING; + puzzleBefore[avatarXLast][avatarYLast] = TILE_NOTHING; + puzzleBefore[avatarXLast - 1][avatarYLast] = TILE_NOTHING; + puzzleBefore[avatarXLast + 1][avatarYLast] = TILE_NOTHING; + puzzleBefore[avatarXLast][avatarYLast - 1] = TILE_NOTHING; puzzleRedraw(); } tickerUpdate(); @@ -344,7 +630,7 @@ void gameSave(void) { saveGameData.lastPuzzle = puzzleCurrent; // Save game. - out = fopen("data/save.dat", "wb"); + out = fopen(jlUtilMakePathname("save", "dat"), "wb"); if (out) { fwrite(&puzzleCount, sizeof(jint16), 1, out); fwrite(&saveGameData.lastPuzzle, sizeof(jint16), 1, out); @@ -628,11 +914,11 @@ void puzzleComplete(void) { // Is the game complete? if (puzzleSolved == puzzleCount) { // They did them all! - //***TODO*** + //***TODO*** Game Complete! return; } - //***TODO*** + //***TODO*** Level Complete. } @@ -641,7 +927,6 @@ void puzzleDraw(void) { byte by = 0; jint16 x = 0; // Screen (tile) coordinates. jint16 y = 0; - CoordT t; for (by=0; by 0) { + x = ((avatar[i][j].x - 1) % 10) * 32; + y = ((avatar[i][j].x - 1) / 10) * 24; + avatar[i][j].x = x; + avatar[i][j].y = y; + } else { + avatar[i][j].x = -1; + avatar[i][j].y = -1; + } + } + } + // Force tile palette jlImgDisplay(tilesI); jlDrawClear(); @@ -1067,6 +1389,7 @@ int main(void) { jlImgFree(savedScreen1); jlImgFree(helpI); jlImgFree(aboutI); + jlStnFree(tilesS); jlImgFree(tilesI); jlImgFree(fontI);