| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- #include "../color_guess.h"
- #include "color_guess_icons.h"
- #include "../helpers/color_guess_colors.h"
- #include "../helpers/color_guess_haptic.h"
- #include "../helpers/color_guess_led.h"
- #include <furi.h>
- #include <furi_hal.h>
- #include <input/input.h>
- #include <gui/elements.h>
- #include <dolphin/dolphin.h>
- struct ColorGuessPlay {
- View* view;
- ColorGuessPlayCallback callback;
- void* context;
- };
- typedef struct {
- ColorGuessPlayStatus status;
- int cursorpos;
- int digit[6];
- int color;
- int time_spent;
- int timestamp_start;
- int prev_closeness;
- int closeness;
- int difficulty;
- int success;
- } ColorGuessPlayModel;
- void color_guess_play_set_callback(
- ColorGuessPlay* instance,
- ColorGuessPlayCallback callback,
- void* context) {
- furi_assert(instance);
- furi_assert(callback);
- instance->callback = callback;
- instance->context = context;
- }
- void play_haptic(void* context, ColorGuessPlayModel* model) {
- ColorGuess* app = context;
- if(model->success == 1) {
- color_guess_play_long_bump(app);
- } else if(model->closeness > model->prev_closeness) {
- color_guess_play_happy_bump(app);
- } else if(model->closeness < model->prev_closeness) {
- color_guess_play_bad_bump(app);
- }
- }
- void color_guess_play_new_round(void* context, ColorGuessPlayModel* model) {
- furi_assert(context);
- ColorGuess* app = context;
- //Reset timer
- FuriHalRtcDateTime date_time;
- furi_hal_rtc_get_datetime(&date_time);
- model->timestamp_start = furi_hal_rtc_datetime_to_timestamp(&date_time);
- model->success = 0;
- model->closeness = 0;
- model->prev_closeness = 0;
- if(model->difficulty == 0) {
- model->color = colorsEasy[rand() % ARR_SIZE(colorsEasy)];
- } else if(model->difficulty == 1) {
- model->color = colorsNormal[rand() % ARR_SIZE(colorsNormal)];
- } else if(model->difficulty == 2) {
- model->color = colorsHard[rand() % ARR_SIZE(colorsHard)];
- }
- color_guess_led_set_rgb(
- app, ((model->color >> 16) & 0xFF), ((model->color >> 8) & 0xFF), ((model->color) & 0xFF));
- }
- void color_guess_play_calculate_closeness(void* context, ColorGuessPlayModel* model) {
- furi_assert(context);
- ColorGuess* app = context;
- UNUSED(app);
- int userRed = (model->digit[0] * 16) + model->digit[1];
- int userGreen = (model->digit[2] * 16) + model->digit[3];
- int userBlue = (model->digit[4] * 16) + model->digit[5];
- int ledRed = ((model->color >> 16) & 0xFF);
- int ledGreen = ((model->color >> 8) & 0xFF);
- int ledBlue = ((model->color) & 0xFF);
- int distanceRed = abs(ledRed - userRed);
- int distanceGreen = abs(ledGreen - userGreen);
- int distanceBlue = abs(ledBlue - userBlue);
- float percentageRed = 100 - ((distanceRed / 255.0) *
- 100); //make sure one number is float, otherwise C will calc wrong
- float percentageGreen = 100 - ((distanceGreen / 255.0) * 100);
- float percentageBlue = 100 - ((distanceBlue / 255.0) * 100);
- if(percentageRed == 100 && percentageGreen == 100 && percentageBlue == 100) {
- model->success = 1;
- dolphin_deed(DolphinDeedPluginGameWin);
- }
- float fullPercentage = (percentageRed + percentageGreen + percentageBlue) / 3;
- model->prev_closeness = model->closeness;
- model->closeness = round(fullPercentage);
- }
- void parse_time_str(char* buffer, int32_t sec) {
- snprintf(
- buffer,
- TIMER_LENGHT,
- TIMER_FORMAT,
- (sec % (60 * 60)) / 60, // minute
- sec % 60); // second
- }
- void drawDifficulty(Canvas* canvas, ColorGuessPlayModel* model) {
- UNUSED(model);
- char* strDifficulty = malloc(7);
- if(model->difficulty == 0) {
- strcpy(strDifficulty, "Easy");
- } else if(model->difficulty == 1) {
- strcpy(strDifficulty, "Medium");
- } else if(model->difficulty == 2) {
- strcpy(strDifficulty, "Hard");
- }
- canvas_draw_box(canvas, 0, 52, 47, 12);
- canvas_invert_color(canvas);
- canvas_draw_icon(canvas, 2, 54, &I_ButtonCenter_7x7);
- canvas_draw_str_aligned(canvas, 11, 54, AlignLeft, AlignTop, strDifficulty);
- canvas_invert_color(canvas);
- free(strDifficulty);
- furi_thread_flags_wait(0, FuriFlagWaitAny, 10);
- }
- void color_guess_play_draw(Canvas* canvas, ColorGuessPlayModel* model) {
- char timer_string[TIMER_LENGHT];
- if(model->success == 1) {
- parse_time_str(timer_string, model->time_spent);
- canvas_clear(canvas);
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontPrimary);
- canvas_draw_str_aligned(canvas, 64, 2, AlignCenter, AlignTop, "You won!!");
- canvas_set_font(canvas, FontSecondary);
- elements_button_center(canvas, "New Round");
- canvas_set_font(canvas, FontBigNumbers);
- canvas_draw_str_aligned(canvas, 64, 16, AlignCenter, AlignTop, timer_string);
- canvas_draw_icon(canvas, 18, 32, digits[16]);
- canvas_draw_icon(canvas, 30, 32, digits[model->digit[0]]);
- canvas_draw_icon(canvas, 42, 32, digits[model->digit[1]]);
- canvas_draw_icon(canvas, 54, 32, digits[model->digit[2]]);
- canvas_draw_icon(canvas, 66, 32, digits[model->digit[3]]);
- canvas_draw_icon(canvas, 78, 32, digits[model->digit[4]]);
- canvas_draw_icon(canvas, 90, 32, digits[model->digit[5]]);
- return;
- }
- const int cursorOffset = 30;
- const int newCursorPos = (model->cursorpos * 12) + cursorOffset;
- FuriHalRtcDateTime date_time;
- furi_hal_rtc_get_datetime(&date_time);
- uint32_t timestamp = furi_hal_rtc_datetime_to_timestamp(&date_time);
- uint32_t time_elapsed = timestamp - model->timestamp_start;
- model->time_spent = time_elapsed;
- char closeness_string[4];
- parse_time_str(timer_string, time_elapsed);
- snprintf(closeness_string, CLOSENESS_LENGTH, CLOSENESS_FORMAT, model->closeness);
- canvas_clear(canvas);
- canvas_set_color(canvas, ColorBlack);
- canvas_set_font(canvas, FontSecondary);
- canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Time spent:");
- canvas_draw_str_aligned(canvas, 55, 0, AlignLeft, AlignTop, timer_string); // DRAW TIMER
- canvas_draw_str_aligned(canvas, 0, 9, AlignLeft, AlignTop, "You are this close:");
- canvas_draw_str_aligned(canvas, 105, 9, AlignLeft, AlignTop, closeness_string);
- canvas_draw_icon(canvas, newCursorPos, 20, &I_ButtonUp_10x5);
- canvas_draw_icon(canvas, newCursorPos, 43, &I_ButtonDown_10x5);
- canvas_draw_icon(canvas, 18, 27, digits[16]);
- canvas_draw_icon(canvas, 30, 27, digits[model->digit[0]]);
- canvas_draw_icon(canvas, 42, 27, digits[model->digit[1]]);
- canvas_draw_icon(canvas, 54, 27, digits[model->digit[2]]);
- canvas_draw_icon(canvas, 66, 27, digits[model->digit[3]]);
- canvas_draw_icon(canvas, 78, 27, digits[model->digit[4]]);
- canvas_draw_icon(canvas, 90, 27, digits[model->digit[5]]);
- elements_button_right(canvas, "Guess this color");
- drawDifficulty(canvas, model);
- }
- static void color_guess_play_model_init(ColorGuessPlayModel* const model) {
- model->cursorpos = 0;
- for(int i = 0; i < 6; i++) {
- model->digit[i] = 0;
- }
- model->closeness = 0;
- model->difficulty = 1;
- }
- bool color_guess_play_input(InputEvent* event, void* context) {
- furi_assert(context);
- ColorGuessPlay* instance = context;
- if(event->type == InputTypeRelease) {
- switch(event->key) {
- case InputKeyBack:
- with_view_model(
- instance->view,
- ColorGuessPlayModel * model,
- {
- UNUSED(model);
- instance->callback(ColorGuessCustomEventPlayBack, instance->context);
- },
- true);
- break;
- case InputKeyLeft:
- with_view_model(
- instance->view,
- ColorGuessPlayModel * model,
- {
- model->cursorpos--;
- if(model->cursorpos < 0) {
- model->cursorpos = 5;
- }
- },
- true);
- break;
- case InputKeyRight:
- with_view_model(
- instance->view,
- ColorGuessPlayModel * model,
- {
- model->cursorpos++;
- if(model->cursorpos > 5) {
- model->cursorpos = 0;
- }
- },
- true);
- break;
- case InputKeyUp:
- with_view_model(
- instance->view,
- ColorGuessPlayModel * model,
- {
- model->digit[model->cursorpos]++;
- if(model->digit[model->cursorpos] > 15) {
- model->digit[model->cursorpos] = 0;
- }
- color_guess_play_calculate_closeness(instance, model);
- play_haptic(instance->context, model);
- },
- true);
- break;
- case InputKeyDown:
- with_view_model(
- instance->view,
- ColorGuessPlayModel * model,
- {
- model->digit[model->cursorpos]--;
- if(model->digit[model->cursorpos] < 0) {
- model->digit[model->cursorpos] = 15;
- }
- color_guess_play_calculate_closeness(instance, model);
- play_haptic(instance->context, model);
- },
- true);
- break;
- case InputKeyOk:
- with_view_model(
- instance->view,
- ColorGuessPlayModel * model,
- {
- if(model->success == 1) {
- model->success = 0;
- } else {
- model->difficulty++;
- if(model->difficulty > 2) {
- model->difficulty = 0;
- }
- }
- color_guess_play_new_round(instance->context, model);
- },
- true);
- break;
- case InputKeyMAX:
- break;
- }
- }
- return true;
- }
- void color_guess_play_exit(void* context) {
- furi_assert(context);
- }
- void color_guess_play_enter(void* context) {
- furi_assert(context);
- ColorGuessPlay* instance = (ColorGuessPlay*)context;
- dolphin_deed(DolphinDeedPluginGameStart);
- with_view_model(
- instance->view,
- ColorGuessPlayModel * model,
- {
- color_guess_play_model_init(model);
- color_guess_play_new_round(instance->context, model);
- },
- true);
- }
- ColorGuessPlay* color_guess_play_alloc() {
- ColorGuessPlay* instance = malloc(sizeof(ColorGuessPlay));
- instance->view = view_alloc();
- view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(ColorGuessPlayModel));
- view_set_context(instance->view, instance); // furi_assert crashes in events without this
- view_set_draw_callback(instance->view, (ViewDrawCallback)color_guess_play_draw);
- view_set_input_callback(instance->view, color_guess_play_input);
- view_set_enter_callback(instance->view, color_guess_play_enter);
- //view_set_exit_callback(instance->view, color_guess_play_exit);
- with_view_model(
- instance->view, ColorGuessPlayModel * model, { color_guess_play_model_init(model); }, true);
- return instance;
- }
- void color_guess_play_free(ColorGuessPlay* instance) {
- furi_assert(instance);
- with_view_model(
- instance->view, ColorGuessPlayModel * model, { free(model->digit); }, true);
- view_free(instance->view);
- free(instance);
- }
- View* color_guess_play_get_view(ColorGuessPlay* instance) {
- furi_assert(instance);
- return instance->view;
- }
|