From 8bb1091352517aea442d26252cdce96ae95f1847 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Thu, 30 Jul 2020 19:54:36 -0500 Subject: [PATCH] Continued work on menus. Level selection almost works. --- warehouse/about.xcf | 3 + warehouse/build-IIgs.sh | 2 +- warehouse/main.c | 398 ++++++++++++++++++++++++++++++---------- warehouse/play.xcf | 3 + 4 files changed, 307 insertions(+), 99 deletions(-) create mode 100644 warehouse/about.xcf create mode 100644 warehouse/play.xcf diff --git a/warehouse/about.xcf b/warehouse/about.xcf new file mode 100644 index 0000000..c807415 --- /dev/null +++ b/warehouse/about.xcf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44a1c80f46ffc424f85b1a1791412d5a42d6a61e0953c452a1bf83979aebe1f1 +size 4327 diff --git a/warehouse/build-IIgs.sh b/warehouse/build-IIgs.sh index 2ad40d6..1dce9de 100755 --- a/warehouse/build-IIgs.sh +++ b/warehouse/build-IIgs.sh @@ -1,7 +1,7 @@ #!/bin/bash -e PROJECT=Warehouse -DATA=(font.img kanga.img tiles.img backgrnd.img ../puzzles.dat ../index.dat) +DATA=(font.img kanga.img tiles.img backgrnd.img about.img play.img ../puzzles.dat ../index.dat) #SOURCE=(*.c *.h) SOURCE=() diff --git a/warehouse/main.c b/warehouse/main.c index 1e911fe..7b6f6c1 100644 --- a/warehouse/main.c +++ b/warehouse/main.c @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -71,6 +72,7 @@ static jlImgT *fontI = NULL; static jlImgT *tilesI = NULL; static jint16 puzzleCount; +static jint16 puzzleCurrent; static jint32 *puzzleIndex = NULL; @@ -103,17 +105,23 @@ static CoordT tileLookup[TILE_COUNT] = { void drawAvatar(void); -byte drawMenu(char *menu[], byte width, byte *height, byte *offsetX, byte *offsetY); +byte drawMenu(char *title, char *menuItems[], byte requestedWidth, byte *height, byte *offsetX, byte *offsetY); void drawPuzzle(void); void forceFullRedraw(void); void loadPuzzle(jint16 number); -bool menu(void); +bool mainMenu(void); +char menu(char *title, char *menuItems[], char selected, byte width, byte offsetX, byte offsetY); void moveCrate(byte sx, byte sy, byte dx, byte dy); void play(void); void printPuzzle(char *message, byte which[MAX_WIDTH][MAX_HEIGHT]); void printAt(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...); +bool readInput(byte *key); void redraw(void); +void resetPuzzle(void); +void selectLevel(void); +void showImage(char *name); void showPalette(void); +void ticker(void); void title(void); @@ -133,33 +141,35 @@ void drawAvatar(void) { } -byte drawMenu(char *menu[], byte width, byte *height, byte *offsetX, byte *offsetY) { +byte drawMenu(char *title, char *menuItems[], byte requestedWidth, byte *height, byte *offsetX, byte *offsetY) { jint16 count = 0; - jint16 lx = ((byte)221 % 40) << 3; // Left-hand block ASCII - jint16 ly = ((byte)221 / 40) << 3; - jint16 rx = ((byte)222 % 40) << 3; // Right-hand block ASCII - jint16 ry = ((byte)222 / 40) << 3; - jint16 tx = ((byte)223 % 40) << 3; // Top-half block ASCII - jint16 ty = ((byte)223 / 40) << 3; - jint16 bx = ((byte)220 % 40) << 3; // Bottom-half block ASCII - jint16 by = ((byte)220 / 40) << 3; + jint16 lx = ((byte)221 % 40) << 3; // Left-hand block ASCII + jint16 ly = ((byte)221 / 40) << 3; + jint16 rx = ((byte)222 % 40) << 3; // Right-hand block ASCII + jint16 ry = ((byte)222 / 40) << 3; + jint16 tx = ((byte)223 % 40) << 3; // Top-half block ASCII + jint16 ty = ((byte)223 / 40) << 3; + jint16 bx = ((byte)220 % 40) << 3; // Bottom-half block ASCII + jint16 by = ((byte)220 / 40) << 3; jint16 x1; jint16 y1; jint16 x2; jint16 y2; jint16 y3; + byte width = requestedWidth; // 222 223 221 // 222 220 221 - // Calculate height and offsets from menu count. - while (menu[count]) { + // Calculate height, width, and offsets from menu count. + while (menuItems[count]) { + if (width < strlen(menuItems[count]) + 6) width = strlen(menuItems[count]) + 6; count++; } - *height = 13 + count; - *offsetX = 20 - width / 2; - *offsetY = 11 - *height / 2; + *height = 8 + count * 2; + if (*offsetX == 0) *offsetX = 20 - width / 2; + if (*offsetY == 0) *offsetY = 11 - *height / 2; // Clear area behind menu. Slightly higher and lower to add borders to the non-bordered ASCII characters. jlDrawBoxFilled(*offsetX * 8, *offsetY * 8 - 4, (*offsetX + width + 1) * 8, (*offsetY + *height) * 8 + 4); @@ -182,14 +192,15 @@ byte drawMenu(char *menu[], byte width, byte *height, byte *offsetX, byte *offse jlDrawBlit8x8(jlImgSurfaceGet(fontI), bx, by, x1, y3); } - printAt(fontI, 16, *offsetY + 2, "Main Menu"); + x1 = (width / 2 - strlen(title) / 2) + *offsetX; + printAt(fontI, x1, *offsetY + 2, title); // Draw menu. - x1 = *offsetX + 5; + x1 = *offsetX + 4; y1 = *offsetY + 7; count = 0; - while (menu[count]) { - printAt(fontI, x1, y1, menu[count]); + while (menuItems[count]) { + printAt(fontI, x1, y1, menuItems[count]); y1+=2; count++; } @@ -240,8 +251,9 @@ void loadPuzzle(jint16 number) { in = fopen("data/puzzles.dat", "rb"); if (!in) jlUtilDie("Unable to open puzzle database!"); - crateCount = 0; + crateCount = 0; cratesOnTarget = 0; + puzzleCurrent = number; // Skip to requested puzzle. fseek(in, puzzleIndex[number - 1], SEEK_SET); @@ -294,61 +306,96 @@ void loadPuzzle(jint16 number) { puzzle.offsetX = (10 - puzzle.width / 2) * 2; puzzle.offsetY = (6 - puzzle.height / 2) * 2; - // Make copy for our rendering array. - memcpy(&puzzleNow, puzzle.puzzle, sizeof(byte) * MAX_WIDTH * MAX_HEIGHT); - + resetPuzzle(); forceFullRedraw(); } -bool menu(void) { +bool mainMenu(void) { + char *options[] = { "Return to Game", "About", "How to Play", "Select Level", "Reset Level", "Exit", 0 }; + char *yesno[] = { "What? No!", "Yeah, I've had enough.", 0 }; + char *reset[] = { "No! I didn't mean it!", "Yes, let me try again.", 0 }; + bool running = true; + char choice = 0; - char *menu[] = { "About", "How to Play", "Select Level", "Reset Level", "Exit", 0 }; - byte count = 0; - byte height; - byte offsetX; - byte offsetY; - byte inMenuYOffset = 7; - byte key; - jint16 rx = ((byte)175 % 40) << 3; // Right Arrows ASCII - jint16 ry = ((byte)175 / 40) << 3; - jint16 sx = ((byte)32 % 40) << 3; // Space ASCII - jint16 sy = ((byte)32 / 40) << 3; - jint16 xpos; - jint16 ypos; - jint16 selected; - jint16 last; - jint16 lastY; - bool inMenu = true; - bool keepPlayingn = true; + while ((choice >= 0) && running && !jlUtilMustExit()) { + choice = menu("Main Menu", options, choice, 0, 0, 0); + switch (choice) { + case 0: // Return to Game + choice = -1; + break; - count = drawMenu(menu, 20, &height, &offsetX, &offsetY); + case 1: // About + showImage("about"); + break; - inMenuYOffset += offsetY; - xpos = (offsetX + 3) * 8; - ypos = inMenuYOffset * 8; + case 2: // How to Play + showImage("play"); + break; + + case 3: // Select Level + selectLevel(); + break; + + case 4: // Reset Level + if (1 == menu("Reset Level?", reset, 0, 0, 0, 0)) { + resetPuzzle(); + forceFullRedraw(); + choice = -1; + } + break; + + case 5: // Exit + running = (0 == menu("Exit Game?", yesno, 0, 0, 0, 0)); + break; + } + } + + return running; +} + + +char menu(char *title, char *menuItems[], char selected, byte width, byte offsetX, byte offsetY) { + byte count = 0; + byte inMenuYOffset = 7; + byte key; + byte height; + byte ox; + byte oy; + char result = -1; + bool inMenu = true; + jint16 rx = ((byte)175 % 40) << 3; // Right Arrows ASCII + jint16 ry = ((byte)175 / 40) << 3; + jint16 sx = ((byte)32 % 40) << 3; // Space ASCII + jint16 sy = ((byte)32 / 40) << 3; + jint16 xpos; + jint16 ypos; + jint16 last; + jint16 lastY; + jlImgT *screen = NULL; //***TODO*** Maybe re-use tilesI to save RAM? + + jlImgCreate(screen); + + ox = offsetX; + oy = offsetY; + + count = drawMenu(title, menuItems, width, &height, &ox, &oy); + + inMenuYOffset += oy; + xpos = (ox + 2) * 8; + ypos = (inMenuYOffset + (selected * 2)) * 8; lastY = ypos; - selected = 0; - last = 1; + last = (selected == 0 ? 1 : 0); while (inMenu && !jlUtilMustExit()) { - if (jlKeyPressed()) { - while (jlKeyPressed()) { - key = jlKeyRead(); - } + if (readInput(&key)) { switch (key) { case 27: inMenu = false; - forceFullRedraw(); - jlDrawClear(); break; case 13: - switch (selected) { - case 4: // Exit - inMenu = false; - keepPlayingn = false; - break; - } + result = selected; + inMenu = false; break; case 'I': @@ -381,10 +428,13 @@ bool menu(void) { lastY = ypos; last = selected; } + ticker(); } - // Return 'false' to exit the game. - return keepPlayingn; + jlImgDisplay(screen); + jlImgFree(screen); + + return result; } @@ -407,44 +457,41 @@ void moveCrate(byte sx, byte sy, byte dx, byte dy) { void play(void) { - jint16 current = 1; jint16 last = 0; - char key = 0; + byte key = 0; bool playing = true; byte tile = 0; + // Show menu on entry + playing = mainMenu(); + // Force tile palette jlImgDisplay(tilesI); - - // Show menu on entry - playing = menu(); + jlDrawClear(); while (playing && !jlUtilMustExit()) { - if (jlKeyPressed()) { - while (jlKeyPressed()) { - key = jlKeyRead(); - } + if (readInput(&key)) { avatarXLast = avatarX; avatarYLast = avatarY; switch (key) { case 27: - playing = menu(); + playing = mainMenu(); if (playing) redraw(); break; - case 'Q': + case 'Q': //***REMOVE*** case 'q': - current--; - if (current < 1) { - current = puzzleCount; + puzzleCurrent--; + if (puzzleCurrent < 1) { + puzzleCurrent = puzzleCount; } break; - case 'W': + case 'W'://***REMOVE*** case 'w': - current++; - if (current >= puzzleCount) { - current = 1; + puzzleCurrent++; + if (puzzleCurrent >= puzzleCount) { + puzzleCurrent = 1; } break; @@ -517,20 +564,20 @@ void play(void) { break; } } - // Load new level? - if (last != current) { - last = current; - loadPuzzle(current); + // Load new level? ***REMOVE*** + if (last != puzzleCurrent) { + last = puzzleCurrent; + loadPuzzle(puzzleCurrent); avatarXLast = -1; avatarYLast = -1; jlDrawClear(); - printAt(fontI, 0, 24, "%d puzzles. Showing #%d", puzzleCount, current); } // Redraw? if ((avatarX != avatarXLast) || (avatarY != avatarYLast)) { puzzleBefore[avatarXLast][avatarYLast] = TILE_NOTHING; redraw(); } + ticker(); } } @@ -557,7 +604,7 @@ void printAt(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...) { jint16 tx; jint16 ty; jint16 counter; - char msg[40]; // Very short messages (screen width). Be careful! + char msg[41]; // Very short messages (screen width). Be careful! va_list va; va_start(va, what); @@ -576,16 +623,153 @@ void printAt(jlImgT *font, jint16 cx, jint16 cy, const char *what, ...) { } +bool readInput(byte *key) { + if (jlKeyPressed()) { + while (jlKeyPressed()) { + *key = jlKeyRead(); + } + return true; + } + //***TODO*** Add joystick here. + return false; +} + + void redraw(void) { //printPuzzle("Now", puzzleNow); //printPuzzle("Before", puzzleBefore); drawPuzzle(); drawAvatar(); - printAt(fontI, 30, 24, "%d/%d ", cratesOnTarget, crateCount); jlDisplayPresent(); } +void resetPuzzle(void) { + // Make copy for our rendering array. + memcpy(&puzzleNow, puzzle.puzzle, sizeof(byte) * MAX_WIDTH * MAX_HEIGHT); +} + + +void selectLevel(void) { + jint16 x; + jint16 y; + jint16 lastX; + jint16 lastY; + jint16 p; + jint16 c = 0; + jint16 index = -1;; + jint16 marginX = 16; + jint16 marginY = 16; + jint16 spacingX; + jint16 spacingY; + jint16 cols = (jint16)(sqrt(puzzleCount) + 0.5f); + char bit = 0; + byte data; + bool inMenu = true; + + jlPaletteSet( 0, 0, 0, 0); + jlPaletteSet( 1, 0, 15, 0); + jlPaletteSet( 2, 15, 0, 0); + jlPaletteSet(15, 15, 15, 15); + + jlDrawColorSet(0); + jlDrawClear(); + + spacingX = (320 - (marginX * 2)) / cols; + spacingY = (200 - (marginY * 2)) / cols; + + // Y spacing needs corrected to be centered on the screen + marginY = (200 - (spacingY * cols)) / 2; + + x = marginX; + y = marginY; + + for (p=0; p= cols) { + x = marginX; + y += spacingY; + c = 0; + } else { + x += spacingX; + } + } + + p = puzzleCurrent; + lastX = -1; + lastY = -1; + + while (inMenu && !jlUtilMustExit()) { + if (readInput(&data)) { + avatarXLast = avatarX; + avatarYLast = avatarY; + switch (data) { + case 27: + inMenu = false; + break; + } + } + x = ((p - 1) % cols) * spacingX + marginX; + y = ((p - 1) / cols) * spacingY + marginY; + if ((x != lastX) || (y != lastY)) { + if (lastX > -1) { + jlDrawColorSet(0); + jlDrawBox(lastX - 1, lastY - 1, lastX + 2, lastY + 2); + } + jlDrawColorSet(15); + jlDrawBox(x - 1, y - 1, x + 2, y + 2); + lastX = x; + lastY = y; + } + } + + printAt(fontI, 5, 0, "Select Your Next Level: %d ", p); + printAt(fontI, 0, 24, "Green are Completed. Red are Unsolved."); + + jlDisplayPresent(); + jlKeyWaitForAny(); +} + + +void showImage(char *name) { + jlImgT *screen = NULL; + jlImgT *image = NULL; + byte key; + + //***TODO*** Maybe re-use tilesI to save RAM? + jlImgCreate(screen); + if (!jlImgLoad(image, name)) jlUtilDie("Unable to open %s!", name); + + jlImgDisplay(image); + jlDisplayPresent(); + + while (!readInput(&key) && !jlUtilMustExit()) { + // Do nothing + } + + jlImgDisplay(screen); + jlDisplayPresent(); + + jlImgFree(image); + jlImgFree(screen); +} + + void showPalette(void) { byte x; for (x=0; x<16; x++) { @@ -595,10 +779,26 @@ void showPalette(void) { } +void ticker(void) { + char *spinner = "/-\\|"; + static byte count = 0; + static jint16 last = 0; + + printAt(fontI, 0, 24, "%d puzzles. Showing #%d. %d/%d %c ", + puzzleCount, puzzleCurrent, cratesOnTarget, crateCount, spinner[count++]); + jlDisplayPresent(); + + if (jlUtilTimeSpan(last, jlUtilTimer()) > 3) { + if (count > 3) count = 0; + last = jlUtilTimer(); + } +} + + void title(void) { char *images[] = { "kanga", "backgrnd", 0 }; - byte count = 0; + byte count = 1; // CHANGE jlDrawColorSet(0); jlDisplayBorder(BORDER_BLACK); @@ -606,14 +806,16 @@ void title(void) { while (images[count] && !jlUtilMustExit()) { // For splash screens, reuse tilesI to save memory. - jlImgLoad(tilesI, images[count]); + if (!jlImgLoad(tilesI, images[count])) jlUtilDie("Unable to open %s!", images[count]); jlImgDisplay(tilesI); //showPalette(); jlDisplayPresent(); jlUtilSleep(20); - jlDrawClear(); - jlDisplayPresent(); - jlUtilSleep(3); + if (images[count+1] != 0) { + jlDrawClear(); + jlDisplayPresent(); + jlUtilSleep(3); + } count++; } } @@ -625,13 +827,11 @@ int main(void) { jlUtilStartup("Warehouse"); // Get something on the screen as quickly as possible. - //title(); + title(); // Load the rest of our data. - jlImgLoad(tilesI, "tiles"); - if (!tilesI) jlUtilDie("Unable to load tiles!"); - jlImgLoad(fontI, "font"); - if (!fontI) jlUtilDie("Unable to load font!"); + if (!jlImgLoad(tilesI, "tiles")) jlUtilDie("Unable to load tiles!"); + if (!jlImgLoad(fontI, "font")) jlUtilDie("Unable to load font!"); // Load the index. in = fopen("data/index.dat", "rb"); @@ -661,6 +861,8 @@ int main(void) { memset(saveGame.solved, 0, saveGame.solvedSize); } + loadPuzzle(saveGame.lastPuzzle); + play(); jlFree(saveGame.solved); diff --git a/warehouse/play.xcf b/warehouse/play.xcf new file mode 100644 index 0000000..8413184 --- /dev/null +++ b/warehouse/play.xcf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec2390912c91f1e82b3136b5c26c76772219409fa247cd68d6b99fec7d0142cb +size 3346