| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014 |
- #include "draw.h"
- #include <gui/gui.h>
- #include <gui/icon.h>
- #include <gui/elements.h>
- #include <gui/icon_i.h>
- #include "fonts.h"
- #include "game_vexed_icons.h"
- #include "ui.h"
- #include "move.h"
- #include "utils.h"
- //-----------------------------------------------------------------------------
- u_int32_t frameNo = 0;
- int r1 = 0, r2 = 0;
- //-----------------------------------------------------------------------------
- void draw_app(Canvas* canvas, Game* game) {
- canvas_clear(canvas);
- if((game->state == MAIN_MENU) || (game->state == RESET_PROMPT)) {
- draw_main_menu(canvas, game);
- }
- if(game->state == ABOUT) {
- draw_about(canvas, game, frameNo);
- }
- if(game->state == INTRO) {
- draw_intro(canvas, game, frameNo);
- }
- if(game->state == RESET_PROMPT) {
- draw_reset_prompt(canvas, game);
- }
- if(game->state == INVALID_PROMPT) {
- draw_invalid_prompt(canvas, game);
- }
- if(game->state >= SELECT_BRICK) {
- draw_playground(canvas, game);
- switch(game->state) {
- case SELECT_BRICK:
- draw_movable(canvas, game, frameNo);
- break;
- case SOLUTION_SELECT:
- draw_direction_solution(canvas, game, frameNo);
- break;
- case SELECT_DIRECTION:
- draw_direction(canvas, game, frameNo);
- break;
- case MOVE_SIDES:
- draw_ani_sides(canvas, game);
- break;
- case MOVE_GRAVITY:
- draw_ani_gravity(canvas, game);
- break;
- case EXPLODE:
- draw_ani_explode(canvas, game);
- break;
- default:
- break;
- }
- draw_scores(canvas, game, frameNo);
- draw_playfield_hint(canvas, game);
- switch(game->state) {
- case PAUSED:
- draw_paused(canvas, game);
- break;
- case HISTOGRAM:
- draw_histogram(canvas, game->stats);
- break;
- case SOLUTION_PROMPT:
- draw_solution_prompt(canvas, game);
- break;
- case GAME_OVER:
- draw_game_over(canvas, game->gameOverReason);
- break;
- case LEVEL_FINISHED:
- draw_level_finished(canvas, game);
- break;
- default:
- break;
- }
- }
- frameNo++;
- }
- //-----------------------------------------------------------------------------
- void draw_intro(Canvas* canvas, Game* game, uint32_t frameNo) {
- if(frameNo % 2 == 1) {
- if(game->move.frameNo < 100) game->move.frameNo++;
- }
- canvas_set_color(canvas, ColorBlack);
- if((game->move.frameNo < 12)) {
- uint8_t x, y;
- for(y = 0; y < SIZE_Y_BG; y++) {
- for(x = 0; x < SIZE_X_BG; x++) {
- canvas_draw_icon(
- canvas, x * TILE_SIZE, y * TILE_SIZE, tile_to_icon(game->bg[y][x], false));
- }
- }
- }
- if((game->move.frameNo < 4)) {
- gray_canvas(canvas);
- }
- if(game->move.frameNo > 7) {
- canvas_set_color(canvas, ColorXOR);
- canvas_draw_box(canvas, 0, 0, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT);
- canvas_draw_icon(canvas, 0, 0, &I_logo_vexed_big);
- }
- if(game->move.frameNo > 11) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_icon(canvas, 0, 0, &I_logo_vexed_big);
- }
- if(game->move.frameNo == 24) {
- game->state = MAIN_MENU;
- }
- }
- void draw_about(Canvas* canvas, Game* game, uint32_t frameNo) {
- if(frameNo % 10 == 9) {
- randomize_bg(&game->bg);
- }
- if(frameNo % 50 == 49) {
- r1 = rand();
- r2 = rand();
- randomize_bg(&game->bg);
- }
- uint8_t sx, sy;
- for(sy = 0; sy < SIZE_Y_BG; sy++) {
- for(sx = 0; sx < SIZE_X_BG; sx++) {
- canvas_draw_icon(
- canvas,
- (sx * TILE_SIZE) - (r1 % 7),
- sy * TILE_SIZE - (r2 % 7),
- tile_to_icon(game->bg[sy][sx], false));
- }
- }
- //gray_canvas(canvas);
- // back for os buttons
- canvas_set_color(canvas, ColorWhite);
- canvas_draw_rbox(canvas, 44, 50, GUI_DISPLAY_WIDTH, GUI_DISPLAY_HEIGHT, 3);
- const uint8_t y = dialog_frame(canvas, 92, 43, false, true, "Exit game?");
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r6_tr);
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_WIDTH / 2, y + 2, AlignCenter, AlignTop, "(c) 2024 Dominik Dzienia");
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_WIDTH / 2, y + 13, AlignCenter, AlignTop, "based on Vexed 2.2");
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_WIDTH / 2, y + 21, AlignCenter, AlignTop, "(c) 2006 Vexed Dev Team");
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontSecondary);
- elements_button_center(canvas, "Exit");
- elements_button_right_back(canvas, "Back");
- }
- void draw_set_info(Canvas* canvas, Game* game) {
- BoundingBox box;
- const uint8_t w = 118;
- const uint8_t h = 46;
- const uint8_t x = (GUI_DISPLAY_WIDTH - w) / 2;
- const uint8_t y =
- dialog_frame(canvas, w, h, false, false, furi_string_get_cstr(game->levelSet->title));
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r6_tr);
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_str_aligned(
- canvas,
- GUI_DISPLAY_WIDTH / 2,
- y,
- AlignCenter,
- AlignTop,
- furi_string_get_cstr(game->levelSet->author));
- canvas_draw_str_aligned(
- canvas,
- GUI_DISPLAY_WIDTH / 2,
- y + 8,
- AlignCenter,
- AlignTop,
- furi_string_get_cstr(game->levelSet->url));
- canvas_draw_hline_dotted(canvas, x, y + 16, w);
- set_bounding_box(&box, x + 3, y + 16, w - 6, 16);
- elements_multiline_text_aligned_limited(
- canvas,
- &box,
- box.width / 2,
- box.height / 2,
- 2,
- AlignCenter,
- AlignCenter,
- furi_string_get_cstr(game->levelSet->description));
- }
- //-----------------------------------------------------------------------------
- void draw_level_info(Canvas* canvas, Game* game) {
- int bufSize = 80;
- char buf[bufSize];
- memset(buf, 0, bufSize);
- snprintf(
- buf,
- sizeof(buf),
- "%s #%u",
- furi_string_get_cstr(game->levelSet->title),
- game->selectedLevel + 1);
- const uint8_t x = (GUI_DISPLAY_WIDTH - 100) / 2;
- const uint8_t y = dialog_frame(canvas, 100, 40, false, false, buf);
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_vline_dotted(canvas, GUI_DISPLAY_CENTER_X, y, 30);
- canvas_set_font(canvas, FontSecondary);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- canvas_draw_str_aligned(canvas, x + 25, y + 4, AlignCenter, AlignTop, "Moves/Par");
- memset(buf, 0, bufSize);
- if(game->levelSet->scores[game->selectedLevel].moves == 0) {
- snprintf(
- buf,
- sizeof(buf),
- "??? / %u",
- game->levelSet->pars[game->selectedLevel]);
- } else {
- snprintf(
- buf,
- sizeof(buf),
- "%u / %u",
- game->levelSet->scores[game->selectedLevel].moves,
- game->levelSet->pars[game->selectedLevel]);
- }
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str_aligned(canvas, x + 25, y + 22, AlignCenter, AlignBottom, buf);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- canvas_draw_str_aligned(canvas, x + 75, y + 4, AlignCenter, AlignTop, "Score");
- memset(buf, 0, bufSize);
- if(game->score == 0) {
- snprintf(buf, sizeof(buf), "on par");
- } else {
- snprintf(buf, sizeof(buf), "%+d", game->score);
- }
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str_aligned(canvas, x + 75, y + 22, AlignCenter, AlignBottom, buf);
- }
- //-----------------------------------------------------------------------------
- void draw_main_menu_new_game(Canvas* canvas, Game* game) {
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontSecondary);
- elements_button_center(canvas, "Start");
- if(game->hasContinue) {
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- elements_button_right(canvas, "Continue");
- canvas_draw_str_aligned(
- canvas,
- GUI_DISPLAY_CENTER_X,
- 37,
- AlignCenter,
- AlignTop,
- "!!! Forgets all progress and scores !!!");
- }
- }
- //-----------------------------------------------------------------------------
- void draw_main_menu_continue(Canvas* canvas, Game* game) {
- int bufSize = 80;
- char buf[bufSize];
- int scorebufSize = 10;
- char scorebufSet[scorebufSize];
- bool hasNext = (game->continueLevel + 1) < game->levelSet->maxLevel;
- memset(scorebufSet, 0, scorebufSize);
- if(game->score == 0) {
- snprintf(scorebufSet, sizeof(scorebufSet), "par");
- } else {
- snprintf(scorebufSet, sizeof(scorebufSet), "%+d", game->score);
- }
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontSecondary);
- elements_button_left(canvas, "New");
- elements_button_center(canvas, "Start");
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- elements_button_right(canvas, "Custom");
- memset(buf, 0, bufSize);
- if(hasNext) {
- snprintf(
- buf,
- sizeof(buf),
- "%s (%s), #%d",
- furi_string_get_cstr(game->continueSet),
- scorebufSet,
- game->continueLevel + 2);
- } else {
- snprintf(buf, sizeof(buf), "%s finished!", furi_string_get_cstr(game->continueSet));
- }
- canvas_draw_str_aligned(canvas, GUI_DISPLAY_CENTER_X, 37, AlignCenter, AlignTop, buf);
- }
- //-----------------------------------------------------------------------------
- void draw_main_menu_custom(Canvas* canvas, Game* game) {
- int bufSize = 80;
- char buf[bufSize];
- int scorebufSize = 10;
- char scorebuf[scorebufSize];
- canvas_set_color(canvas, ColorBlack);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- main_menu_pill(
- canvas,
- 35,
- 90,
- game->mainMenuBtn == LEVELSET_BTN,
- game->setPos > 0,
- game->setPos < game->setCount - 1,
- furi_string_get_cstr(game->selectedSet));
- memset(scorebuf, 0, scorebufSize);
- score_for_level(game, game->selectedLevel, scorebuf, scorebufSize);
- canvas_set_font(canvas, FontSecondary);
- memset(buf, 0, bufSize);
- snprintf(
- buf,
- sizeof(buf),
- "%u of %u (%s)",
- game->selectedLevel + 1,
- game->levelSet->maxLevel,
- scorebuf);
- main_menu_pill(
- canvas,
- 50,
- 90,
- game->mainMenuBtn == LEVELNO_BTN,
- game->selectedLevel > 0,
- game->selectedLevel < game->levelSet->maxLevel - 1,
- buf);
- }
- //-----------------------------------------------------------------------------
- void draw_main_menu(Canvas* canvas, Game* game) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(canvas, 0, 6, GUI_DISPLAY_WIDTH, 6);
- canvas_draw_line(canvas, 0, 9, GUI_DISPLAY_WIDTH, 9);
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_rbox(canvas, GUI_DISPLAY_CENTER_X - 16 - 6, 1, 32 + 12, 14, 3);
- canvas_set_color(canvas, ColorWhite);
- canvas_draw_icon(canvas, GUI_DISPLAY_CENTER_X - 16, 2, &I_logo_vexed_mini);
- canvas_set_font(canvas, FontSecondary);
- main_menu_pill(
- canvas,
- 20,
- 90,
- game->mainMenuBtn == MODE_BTN,
- game->mainMenuMode != NEW_GAME,
- game->mainMenuMode != CUSTOM,
- game_mode_label(game->mainMenuMode));
- switch(game->mainMenuMode) {
- case CONTINUE:
- draw_main_menu_continue(canvas, game);
- break;
- case CUSTOM:
- draw_main_menu_custom(canvas, game);
- break;
- case NEW_GAME:
- default:
- draw_main_menu_new_game(canvas, game);
- break;
- }
- if(game->mainMenuInfo) {
- gray_canvas(canvas);
- if(game->mainMenuBtn == LEVELSET_BTN) {
- draw_set_info(canvas, game);
- } else if(game->mainMenuBtn == LEVELNO_BTN) {
- draw_level_info(canvas, game);
- }
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontSecondary);
- elements_button_center(canvas, "Start");
- elements_button_right_back(canvas, "Back");
- }
- }
- //-----------------------------------------------------------------------------
- void draw_playground(Canvas* canvas, Game* game) {
- Neighbors tiles;
- uint8_t tile, x, y, sx, sy, ex, ey;
- bool whiteB = (game->state == LEVEL_FINISHED) || (game->solutionMode);
- for(y = 0; y < SIZE_Y; y++) {
- for(x = 0; x < SIZE_X; x++) {
- tile = game->board[y][x];
- sx = x * TILE_SIZE;
- sy = y * TILE_SIZE;
- ex = ((x + 1) * TILE_SIZE) - 1;
- ey = ((y + 1) * TILE_SIZE) - 1;
- if(tile > 0) {
- if((game->state == MOVE_SIDES) && (x == game->move.x) && (y == game->move.y))
- continue;
- if(((game->state == MOVE_GRAVITY) || (game->state == EXPLODE)) &&
- (game->toAnimate[y][x] == 1))
- continue;
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_icon(canvas, sx, sy, tile_to_icon(tile, game->state == GAME_OVER));
- }
- if(tile == WALL_TILE) {
- tiles = find_neighbors(&game->board, x, y);
- // UP
- if(tiles.u != WALL_TILE) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(canvas, sx, sy + 1, ex, sy + 1);
- canvas_set_color(canvas, ColorWhite);
- canvas_draw_line(canvas, sx, sy, ex, sy);
- if(whiteB) canvas_draw_line(canvas, sx, sy + 2, ex, sy + 2);
- }
- // DOWN
- if(tiles.d != WALL_TILE) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(canvas, sx, ey, ex, ey);
- canvas_set_color(canvas, ColorWhite);
- if(whiteB) canvas_draw_line(canvas, sx, ey - 1, ex, ey - 1);
- }
- // LEFT
- if(tiles.l != WALL_TILE) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(
- canvas, sx + 1, sy + ((tiles.u != WALL_TILE) ? 1 : 0), sx + 1, ey);
- canvas_set_color(canvas, ColorWhite);
- canvas_draw_line(canvas, sx, sy, sx, ey);
- if(whiteB)
- canvas_draw_line(
- canvas,
- sx + 2,
- sy + ((tiles.u != WALL_TILE) ? 2 : 0),
- sx + 2,
- ey - ((tiles.d != WALL_TILE) ? 2 : 0));
- }
- // RIGHT
- if(tiles.r != WALL_TILE) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(canvas, ex, (sy) + ((tiles.u != WALL_TILE) ? 1 : 0), ex, ey);
- canvas_set_color(canvas, ColorWhite);
- if(whiteB)
- canvas_draw_line(
- canvas,
- ex - 1,
- sy + ((tiles.u != WALL_TILE) ? 2 : 0),
- ex - 1,
- ey - ((tiles.d != WALL_TILE) ? 2 : 0));
- }
- if((tiles.dl != WALL_TILE) && (tiles.l == WALL_TILE)) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(canvas, sx, ey, sx + 1, ey);
- canvas_set_color(canvas, ColorWhite);
- if(whiteB) canvas_draw_line(canvas, sx, ey - 1, sx + 2, ey - 1);
- }
- if((tiles.ur != WALL_TILE) && (tiles.u == WALL_TILE)) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(canvas, ex, sy, ex, sy + 1);
- canvas_set_color(canvas, ColorWhite);
- if(whiteB) canvas_draw_line(canvas, ex - 1, sy, ex - 1, sy + 2);
- }
- if(tiles.ul != WALL_TILE) {
- canvas_set_color(canvas, ColorWhite);
- canvas_draw_dot(canvas, sx, sy);
- if(whiteB) canvas_draw_dot(canvas, sx + 2, sy + 2);
- if(tiles.l == WALL_TILE) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(canvas, sx, sy + 1, sx + 1, sy + 1);
- canvas_set_color(canvas, ColorWhite);
- if(whiteB) canvas_draw_line(canvas, sx, sy + 2, sx + 1, sy + 2);
- }
- if(tiles.u == WALL_TILE) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_line(canvas, sx + 1, sy, sx + 1, sy + 1);
- canvas_set_color(canvas, ColorWhite);
- if(whiteB) canvas_draw_line(canvas, sx + 2, sy, sx + 2, sy + 1);
- }
- }
- if((tiles.dr != WALL_TILE) && (tiles.r == WALL_TILE) && (tiles.d == WALL_TILE)) {
- canvas_set_color(canvas, ColorWhite);
- if(whiteB) canvas_draw_line(canvas, ex - 1, ey - 1, ex - 1, ey);
- }
- }
- }
- }
- }
- //-----------------------------------------------------------------------------
- void draw_movable(Canvas* canvas, Game* game, uint32_t frameNo) {
- bool oddFrame = (frameNo % 20 < 10);
- if(game->currentMovable != MOVABLE_NOT_FOUND) {
- canvas_set_color(canvas, ColorBlack);
- uint8_t x = coord_x(game->currentMovable);
- uint8_t y = coord_y(game->currentMovable);
- uint8_t how_movable = game->movables[y][x];
- if((how_movable & MOVABLE_LEFT) != 0) {
- canvas_draw_icon(
- canvas, (x - 1) * TILE_SIZE + (oddFrame ? 0 : 1), y * TILE_SIZE, &I_arr_l);
- }
- if((how_movable & MOVABLE_RIGHT) != 0) {
- canvas_draw_icon(
- canvas, (x + 1) * TILE_SIZE + (oddFrame ? 1 : 0), y * TILE_SIZE, &I_arr_r);
- }
- canvas_draw_frame(
- canvas, x * TILE_SIZE - 1, y * TILE_SIZE - 1, TILE_SIZE + 3, TILE_SIZE + 3);
- if(oddFrame) {
- canvas_draw_frame(
- canvas, x * TILE_SIZE - 2, y * TILE_SIZE - 2, TILE_SIZE + 5, TILE_SIZE + 5);
- } else {
- canvas_draw_frame(canvas, x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE + 1, TILE_SIZE + 1);
- }
- }
- }
- //-----------------------------------------------------------------------------
- void draw_direction(Canvas* canvas, Game* game, uint32_t frameNo) {
- bool oddFrame = (frameNo % 20 < 10);
- if(game->currentMovable != MOVABLE_NOT_FOUND) {
- canvas_set_color(canvas, ColorBlack);
- uint8_t x = coord_x(game->currentMovable);
- uint8_t y = coord_y(game->currentMovable);
- if(oddFrame) {
- canvas_draw_icon(canvas, (x - 1) * TILE_SIZE, y * TILE_SIZE, &I_mov_l);
- canvas_draw_icon(canvas, ((x + 1) * TILE_SIZE) + 1, y * TILE_SIZE, &I_mov_r);
- }
- }
- }
- //-----------------------------------------------------------------------------
- void draw_direction_solution(Canvas* canvas, Game* game, uint32_t frameNo) {
- bool oddFrame = (frameNo % 20 < 10);
- if(game->currentMovable != MOVABLE_NOT_FOUND) {
- canvas_set_color(canvas, ColorBlack);
- uint8_t x = coord_x(game->currentMovable);
- uint8_t y = coord_y(game->currentMovable);
- uint8_t how_movable = game->movables[y][x];
- if((how_movable & MOVABLE_LEFT) != 0) {
- canvas_draw_icon(
- canvas, (x - 1) * TILE_SIZE + (oddFrame ? 0 : 1), y * TILE_SIZE, &I_arr_l);
- }
- if((how_movable & MOVABLE_RIGHT) != 0) {
- canvas_draw_icon(
- canvas, (x + 1) * TILE_SIZE + (oddFrame ? 1 : 0), y * TILE_SIZE, &I_mov_r);
- }
- canvas_draw_frame(
- canvas, x * TILE_SIZE - 1, y * TILE_SIZE - 1, TILE_SIZE + 3, TILE_SIZE + 3);
- if(oddFrame) {
- canvas_draw_frame(
- canvas, x * TILE_SIZE - 2, y * TILE_SIZE - 2, TILE_SIZE + 5, TILE_SIZE + 5);
- } else {
- canvas_draw_frame(canvas, x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE + 1, TILE_SIZE + 1);
- }
- }
- game->move.frameNo--;
- if(game->move.frameNo == 0) {
- solution_move(game);
- }
- }
- //-----------------------------------------------------------------------------
- void draw_ani_sides(Canvas* canvas, Game* game) {
- uint8_t tile, sx, sy, deltaX;
- if(game->state == MOVE_SIDES) {
- tile = game->board[game->move.y][game->move.x];
- deltaX = ((game->move.dir & MOVABLE_LEFT) != 0) ? -1 : 1;
- sx = (game->move.x * TILE_SIZE) + (deltaX * game->move.frameNo);
- sy = game->move.y * TILE_SIZE;
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_icon(canvas, sx, sy, tile_to_icon(tile, game->state == GAME_OVER));
- game->move.frameNo++;
- if(game->move.frameNo > TILE_SIZE) {
- stop_move(game);
- }
- }
- }
- //-----------------------------------------------------------------------------
- void draw_ani_gravity(Canvas* canvas, Game* game) {
- uint8_t tile, x, y, sx, sy;
- if(game->state == MOVE_GRAVITY) {
- for(y = 0; y < SIZE_Y; y++) {
- for(x = 0; x < SIZE_X; x++) {
- tile = game->board[y][x];
- sx = x * TILE_SIZE;
- sy = y * TILE_SIZE;
- if((tile > 0) && (game->toAnimate[y][x] == 1)) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_icon(
- canvas,
- sx,
- sy + game->move.frameNo,
- tile_to_icon(tile, game->state == GAME_OVER));
- }
- }
- }
- if(game->move.delay > 0) {
- game->move.delay--;
- return;
- }
- game->move.frameNo++;
- if(game->move.frameNo > TILE_SIZE) {
- stop_gravity(game);
- }
- }
- }
- //-----------------------------------------------------------------------------
- void draw_ani_explode(Canvas* canvas, Game* game) {
- uint8_t tile, x, y, sx, sy, cx, cy, s, o;
- if(game->state == EXPLODE) {
- for(y = 0; y < SIZE_Y; y++) {
- for(x = 0; x < SIZE_X; x++) {
- tile = game->board[y][x];
- if((tile > 0) && (game->toAnimate[y][x] == 1)) {
- sx = x * TILE_SIZE;
- sy = y * TILE_SIZE;
- cx = sx + 4;
- cy = sy + 4;
- if((game->move.delay % 4 < 2) || (game->move.delay > 8)) {
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_icon(
- canvas, sx, sy, tile_to_icon(tile, game->state == GAME_OVER));
- }
- if(game->move.frameNo > 0) {
- canvas_set_color(canvas, ColorXOR);
- o = MIN(((game->move.frameNo - 1) / 2), (uint8_t)4);
- s = (o * 2) + 1;
- canvas_draw_box(canvas, cx - o, cy - o, s, s);
- }
- }
- }
- }
- if(game->move.delay > 0) {
- game->move.delay--;
- return;
- }
- game->move.frameNo++;
- if(game->move.frameNo > 10) {
- stop_explosion(game);
- }
- }
- }
- //-----------------------------------------------------------------------------
- void draw_scores(Canvas* canvas, Game* game, uint32_t frameNo) {
- BoundingBox box;
- int bufSize = 80;
- char buf[bufSize];
- bool showScore = (frameNo % 200) < 100;
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_rbox(canvas, 82, 1, 46, 17, 2);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r6_tr);
- canvas_set_color(canvas, ColorWhite);
- set_bounding_box(&box, 82, 1, 46, 17);
- elements_multiline_text_aligned_limited(
- canvas,
- &box,
- box.width / 2,
- box.height / 2,
- 2,
- AlignCenter,
- AlignCenter,
- furi_string_get_cstr(game->levelData->title));
- if(game->solutionMode) {
- canvas_set_color(canvas, ColorBlack);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_wedge_tr);
- canvas_draw_str_aligned(canvas, 104, 27, AlignCenter, AlignTop, "Solution");
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_tom_thumb_4x6_mr);
- memset(buf, 0, bufSize);
- snprintf(buf, sizeof(buf), "%d of %d", game->solutionStep + 1, game->solutionTotal);
- canvas_draw_str_aligned(canvas, 104, 34, AlignCenter, AlignTop, buf);
- } else {
- canvas_set_color(canvas, ColorBlack);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_wedge_tr);
- canvas_draw_str_aligned(
- canvas, 104, 20, AlignCenter, AlignTop, showScore ? "Score" : "Level");
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_tom_thumb_4x6_mr);
- memset(buf, 0, bufSize);
- if(showScore) {
- if(game->score == 0) {
- snprintf(buf, sizeof(buf), "on par");
- } else {
- snprintf(buf, sizeof(buf), "%+d", game->score);
- }
- } else {
- snprintf(buf, sizeof(buf), "%u/%u", game->currentLevel + 1, game->levelSet->maxLevel);
- }
- canvas_draw_str_aligned(canvas, 104, 27, AlignCenter, AlignTop, buf);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_wedge_tr);
- canvas_draw_str_aligned(
- canvas, 104, 34, AlignCenter, AlignTop, showScore ? "Best" : "Moves");
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_tom_thumb_4x6_mr);
- memset(buf, 0, bufSize);
- if(showScore) {
- snprintf(buf, sizeof(buf), "%s", game->parLabel);
- } else {
- snprintf(buf, sizeof(buf), "%u/%u", game->gameMoves, game->levelData->gamePar);
- }
- canvas_draw_str_aligned(canvas, 104, 41, AlignCenter, AlignTop, buf);
- }
- }
- //-----------------------------------------------------------------------------
- void draw_paused(Canvas* canvas, Game* game) {
- gray_canvas(canvas);
- menu_pill(
- canvas,
- 0,
- MENU_PAUSED_COUNT,
- ((game->menuPausedPos == 0) && (game->undoMovable != MOVABLE_NOT_FOUND)),
- game->undoMovable == MOVABLE_NOT_FOUND,
- "Undo",
- &I_ico_undo);
- menu_pill(
- canvas, 1, MENU_PAUSED_COUNT, game->menuPausedPos == 1, false, "Restart", &I_ico_restart);
- menu_pill(canvas, 2, MENU_PAUSED_COUNT, game->menuPausedPos == 2, false, "Menu", &I_ico_home);
- menu_pill(canvas, 3, MENU_PAUSED_COUNT, game->menuPausedPos == 3, false, "Skip", &I_ico_skip);
- menu_pill(canvas, 4, MENU_PAUSED_COUNT, game->menuPausedPos == 4, false, "Count", &I_ico_hist);
- menu_pill(
- canvas, 5, MENU_PAUSED_COUNT, game->menuPausedPos == 5, false, "Solve", &I_ico_check);
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontSecondary);
- elements_button_right_back(canvas, "Back to game");
- }
- //-----------------------------------------------------------------------------
- void draw_histogram(Canvas* canvas, Stats* stats) {
- gray_canvas(canvas);
- panel_histogram(canvas, furi_string_get_cstr(stats->bricksNonZero), stats->statsNonZero);
- }
- void draw_playfield_hint(Canvas* canvas, Game* game) {
- if(game->state == SELECT_BRICK) {
- if((game->currentMovable != MOVABLE_NOT_FOUND) &&
- (movable_dir(&game->movables, game->currentMovable) == MOVABLE_BOTH)) {
- hint_pill_double(canvas, "Select", "Choose", &I_hint_2);
- } else {
- hint_pill_double(canvas, "Select", "Move", &I_hint_1);
- }
- }
- if(game->state == SELECT_DIRECTION) {
- hint_pill_double(canvas, "Move", "Cancel", &I_hint_3);
- }
- if(game->state == SOLUTION_SELECT || game->solutionMode) {
- hint_pill_double(canvas, "ANY", "CANCEL", &I_hint_4);
- } else {
- if(game->state == MOVE_SIDES) {
- hint_pill_single(canvas, "moving..");
- }
- if(game->state == MOVE_GRAVITY) {
- hint_pill_single(canvas, "falling..");
- }
- if(game->state == EXPLODE) {
- hint_pill_single(canvas, "BOOM!");
- }
- }
- }
- //-----------------------------------------------------------------------------
- void draw_game_over(Canvas* canvas, GameOver gameOverReason) {
- gray_canvas(canvas);
- const uint8_t y = dialog_frame(canvas, 100, 38, true, false, "Game Over!");
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontSecondary);
- if(gameOverReason == CANNOT_MOVE) {
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 8, AlignCenter, AlignTop, "Cannot move");
- } else if(gameOverReason == BRICKS_LEFT) {
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 8, AlignCenter, AlignTop, "Unpaired bricks left");
- }
- elements_button_left(canvas, "Retry");
- elements_button_center(canvas, "Menu");
- elements_button_right_back(canvas, "Undo");
- }
- //-----------------------------------------------------------------------------
- void draw_level_finished(Canvas* canvas, Game* game) {
- int bufSize = 80;
- char buf[bufSize];
- bool hasNext = game->currentLevel < game->levelSet->maxLevel - 1;
- gray_canvas(canvas);
- const uint8_t x = (GUI_DISPLAY_WIDTH - 100) / 2;
- const uint8_t y =
- dialog_frame(canvas, 100, 40, true, false, hasNext ? "Level finished!" : "Pack finished!");
- canvas_set_color(canvas, ColorBlack);
- canvas_draw_vline_dotted(canvas, GUI_DISPLAY_CENTER_X, y, 30);
- canvas_set_font(canvas, FontSecondary);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- canvas_draw_str_aligned(canvas, x + 25, y + 4, AlignCenter, AlignTop, "Moves/Par");
- memset(buf, 0, bufSize);
- snprintf(buf, sizeof(buf), "%u / %u", game->gameMoves, game->levelData->gamePar);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str_aligned(canvas, x + 25, y + 22, AlignCenter, AlignBottom, buf);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- canvas_draw_str_aligned(canvas, x + 75, y + 4, AlignCenter, AlignTop, "Score");
- memset(buf, 0, bufSize);
- if(game->score == 0) {
- snprintf(buf, sizeof(buf), "on par");
- } else {
- snprintf(buf, sizeof(buf), "%+d", game->score);
- }
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str_aligned(canvas, x + 75, y + 22, AlignCenter, AlignBottom, buf);
- canvas_set_font(canvas, FontSecondary);
- if(hasNext) {
- elements_button_center(canvas, "Next");
- elements_button_right_back(canvas, "Menu");
- } else {
- elements_button_center(canvas, "Menu");
- }
- }
- //-----------------------------------------------------------------------------
- void draw_solution_prompt(Canvas* canvas, Game* game) {
- gray_canvas(canvas);
- const uint8_t y = dialog_frame(canvas, 100, 40, true, false, "Show solution?");
- const bool penalty = solution_will_have_penalty(game);
- canvas_set_color(canvas, ColorBlack);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- if(penalty) {
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 4, AlignCenter, AlignTop, "It has one-time penalty");
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 15, AlignCenter, AlignTop, "of additional 5 point");
- } else {
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 4, AlignCenter, AlignTop, "Show solution?");
- }
- elements_button_center(canvas, "Show");
- elements_button_right_back(canvas, "Resign");
- }
- //-----------------------------------------------------------------------------
- void draw_reset_prompt(Canvas* canvas, Game* game) {
- UNUSED(game);
- gray_canvas(canvas);
- const uint8_t y = dialog_frame(canvas, 110, 45, true, false, "Reset game?");
- canvas_set_color(canvas, ColorBlack);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 2, AlignCenter, AlignTop, "Starting new game will reset");
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 10, AlignCenter, AlignTop, "all progress and scores!");
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 21, AlignCenter, AlignTop, "Are you sure?");
- canvas_set_font(canvas, FontSecondary);
- elements_button_center(canvas, "Confirm");
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- elements_button_right_back(canvas, "Back");
- }
- //-----------------------------------------------------------------------------
- void draw_invalid_prompt(Canvas* canvas, Game* game) {
- UNUSED(game);
- gray_canvas(canvas);
- const uint8_t y = dialog_frame(canvas, 110, 45, true, false, "Invalid level");
- canvas_set_color(canvas, ColorBlack);
- canvas_set_custom_u8g2_font(canvas, app_u8g2_font_squeezed_r7_tr);
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 2, AlignCenter, AlignTop, "Cannot load/parse level!");
- canvas_draw_str_aligned(
- canvas,
- GUI_DISPLAY_CENTER_X,
- y + 10,
- AlignCenter,
- AlignTop,
- furi_string_get_cstr(game->errorMsg));
- canvas_draw_str_aligned(
- canvas, GUI_DISPLAY_CENTER_X, y + 21, AlignCenter, AlignTop, "Repair or remove file!");
- canvas_set_font(canvas, FontSecondary);
- elements_button_center(canvas, "Understood");
- }
|