diff options
| author | physick <mynameisgennadiy@vk.com> | 2026-08-31 17:16:44 +0500 |
|---|---|---|
| committer | physick <mynameisgennadiy@vk.com> | 2026-08-31 17:16:44 +0500 |
| commit | e4b96cc66d8c4269661745ce187cb58c852542d3 (patch) | |
| tree | 4268a1ee350a9d762694e1de8803493ba4237bb1 | |
| parent | b45620544427306854a28a5163fafd45b007acc2 (diff) | |
transitions
| -rwxr-xr-x | assets/textures/buttons_atlas.png | bin | 660 -> 1496 bytes | |||
| -rw-r--r-- | build.zig | 1 | ||||
| -rw-r--r-- | src/resources/TextruesAtlas.h | 35 | ||||
| -rw-r--r-- | src/scenes/collectionScene.c | 16 | ||||
| -rw-r--r-- | src/scenes/puzzlePreviewScene.c | 193 | ||||
| -rw-r--r-- | src/scenes/puzzleScene.c | 19 | ||||
| -rw-r--r-- | src/scenes/puzzleSelectionScene.c | 29 | ||||
| -rw-r--r-- | src/scenes/resultView.c | 3 | ||||
| -rw-r--r-- | src/scenes/scenes.h | 11 | ||||
| -rw-r--r-- | src/ui_elements/UI.h | 1 |
10 files changed, 298 insertions, 10 deletions
diff --git a/assets/textures/buttons_atlas.png b/assets/textures/buttons_atlas.png Binary files differindex 587b94e..ce4a4f1 100755 --- a/assets/textures/buttons_atlas.png +++ b/assets/textures/buttons_atlas.png @@ -16,6 +16,7 @@ const common_c_files = &[_][]const u8 { "src/scenes/sceneManager.c", "src/scenes/mainMenu.c", "src/scenes/resultView.c", + "src/scenes/puzzlePreviewScene.c", "src/scenes/puzzleScene.c", "src/scenes/distractionScene.c", "src/scenes/collectionScene.c", diff --git a/src/resources/TextruesAtlas.h b/src/resources/TextruesAtlas.h index 5fdafc3..97eb889 100644 --- a/src/resources/TextruesAtlas.h +++ b/src/resources/TextruesAtlas.h @@ -15,4 +15,39 @@ static const Rectangle SUBMIT_BUTTON_LOCATION = { .height = 32, }; +static const Rectangle UNKNOWN_BUTTON_LOCATION = { + .x = 32, + .y = 0, + .width = 32, + .height = 32, +}; + +static const Rectangle UNKNOWN_BUTTON_2_LOCATION = { + .x = 64, + .y = 0, + .width = 32, + .height = 32, +}; + +static const Rectangle BACK_BUTTON_SMALL_LOCATION = { + .x = 96, + .y = 0, + .width = 32, + .height = 32, +}; + +static const Rectangle BACK_BUTTON_WIDE_LOCATION = { + .x = 128, + .y = 0, + .width = 64, + .height = 32, +}; + +static const Rectangle PROCEED_BUTTON_WIDE_LOCATION = { + .x = 192, + .y = 0, + .width = 64, + .height = 32, +}; + #endif // TEXTURES_ATLAS_H diff --git a/src/scenes/collectionScene.c b/src/scenes/collectionScene.c index 508e4d5..cda6fd1 100644 --- a/src/scenes/collectionScene.c +++ b/src/scenes/collectionScene.c @@ -8,6 +8,7 @@ #include "../ui_elements/UI.h" #include "../resources/resources.h" #include "../utils/arena.h" +#include "../resources/TextruesAtlas.h" static const size_t ARENA_SIZE = 1024 * 64; @@ -29,8 +30,12 @@ void collectionElement_onSelect(CollectionElement *caller) { if (caller == NULL) return; TraceLog(LOG_INFO, "Selected element %s", caller->name); switch (caller->type) { - case COLLECTION_ELEMENT_PUZZLE: break; - case COLLECTION_ELEMENT_COLLECTION: AddScene(CreatePuzzleCollectionScene(caller)); break; + case COLLECTION_ELEMENT_PUZZLE: + AddScene(CreatePuzzlePreview(ReadPuzzleFromFile(caller->path))); + break; + case COLLECTION_ELEMENT_COLLECTION: + AddScene(CreatePuzzleCollectionScene(caller)); + break; default: TraceLog(LOG_WARNING, "Invalid CollectionElement type for %s", caller->path); break; @@ -125,12 +130,7 @@ Scene *CreatePuzzleCollectionScene(CollectionElement *el) { backButton->parent = outp; backButton->OnClick = backButton_onClick; backButton->atlas = GetButtonsAtlas(); - backButton->textrueLocation = (Rectangle) { - .x = 0, - .y = 0, - .width = 32, - .height = 32, - }; + backButton->textrueLocation = BACK_BUTTON_SMALL_LOCATION; } data->backButton = backButton; diff --git a/src/scenes/puzzlePreviewScene.c b/src/scenes/puzzlePreviewScene.c new file mode 100644 index 0000000..6ce3ba7 --- /dev/null +++ b/src/scenes/puzzlePreviewScene.c @@ -0,0 +1,193 @@ +#include <raylib.h> +#include <stdint.h> +#include <stdlib.h> +#include "scenes.h" +#include "../ui_elements/UI.h" +#include "../resources/resources.h" +#include "../resources/TextruesAtlas.h" + +static const uint8_t MAX_TINT = 96; +static const float BODY_BUTTON_RATIO = 0.9f; +static const float BUTTON_PADDING_RATIO = 0.015f; + +typedef struct { + Puzzle *puzzle; + Button *backButton; + Button *proceedButton; + float scroll_up; + float hiding_state; + int scroll; + PopUpState state; +} puzzlePreviewData; + +void confirmSelemetion(Scene *self) { + if (self == NULL) return; + puzzlePreviewData *data = ((Scene *)self)->data; + if (data == NULL) return; + TraceLog(LOG_INFO, "Loading a puzzle %s", data->puzzle->Name); + data->state = POPUP_HIDING; +} + + +void closePreviewWindow(Scene *self) { + TraceLog(LOG_INFO, "Closing a preview window"); + if (self == NULL) return; + puzzlePreviewData *data = ((Scene *)self)->data; + if (data == NULL) return; + data->state = POPUP_HIDING_ALT; +} + +bool updatePuzzlePreview(void *self) { + puzzlePreviewData *data = ((Scene *)self)->data; + switch (data->state) { + case POPUP_REVEALING: + data->scroll_up += SCROLL_SPEED * GetFrameTime(); + if (data->scroll_up >= 1) { + data->state = POPUP_ACTIVE; + data->scroll_up = 1; + } + return true; + + case POPUP_HIDING_ALT: + data->scroll_up -= SCROLL_SPEED * GetFrameTime(); + if (data->scroll_up <= 0) { + if (data->puzzle != NULL) FreePuzzle(data->puzzle); + DeleteSceneFromStack(); + } + return true; + + case POPUP_HIDING: + data->hiding_state += BLACKOUT_SPEED * GetFrameTime(); + if (data->hiding_state >= 2) { + DeleteSceneFromStack(); + AddScene(CreatePuzzleScene(data->puzzle)); + } + return true; + + default: break; + } + if (data->backButton != NULL) UpdateButton(data->backButton); + if (data->proceedButton != NULL) UpdateButton(data->proceedButton); + return true; +} + +static Rectangle getBodyRect(puzzlePreviewData *data) { + float screen_h = GetScreenHeight(); + float screen_w = GetScreenWidth(); + return (Rectangle) { + .x = PADDING, + .y = PADDING + (screen_h * (1 - data->scroll_up)), + .width = screen_w - PADDING * 2, + .height = screen_h - PADDING * 2, + }; +} + +bool drawPuzzlePreview(void *self) { + puzzlePreviewData *data = ((Scene *)self)->data; + DrawRectangle(0, 0, + GetScreenWidth(), GetScreenHeight(), + (Color) {0, 0, 0, MAX_TINT * data->scroll_up }); + + Rectangle body = getBodyRect(data); + Rectangle TextArea = { + .x = body.x, + .y = body.y, + .width = body.width, + .height = body.height * BODY_BUTTON_RATIO, + }; + + DrawRecBordered(TextArea, COLORSCHEME_WHITE, COLORSCHEME_ORANGE, BORDER); + if (data->puzzle != NULL) { + DrawTextInRec(TextArea, data->puzzle->Description, + GetMainFont(), TEXT_FONT_SIZE, COLORSCHEME_BROWN, + 3, &data->scroll); + } + + float btn_space_height = body.height * (1 - BODY_BUTTON_RATIO); + float btn_padding = body.height * BUTTON_PADDING_RATIO; + float btn_height = btn_space_height - 2 * btn_padding; + float btn_width = btn_height * 2; + + if (data->backButton != NULL) { + DrawButton(data->backButton, &(Rectangle) { + .x = PADDING, + .y = TextArea.y + TextArea.height + btn_padding, + .height = btn_height, + .width = btn_height * 2, + }); + } + + if (data->proceedButton != NULL) { + DrawButton(data->proceedButton, &(Rectangle) { + .x = body.x + body.width - btn_width, + .y = TextArea.y + TextArea.height + btn_padding, + .height = btn_height, + .width = btn_height * 2, + }); + } + + if (data->state == POPUP_HIDING) { + DrawRectangle(0, 0, + GetScreenWidth(), GetScreenHeight(), + (Color) {0, 0, 0, 255 * (data->hiding_state >= 1 ? 1 : data->hiding_state) }); + } + + return true; +} + +/// DOES NOT FREE THE PUZZLE! This should be handled separatly +void deinitPuzzlePreview(void *self) { + TraceLog(LOG_INFO, "Deleting a puzzle preview"); + if (self == NULL) return; + puzzlePreviewData *data = ((Scene *)self)->data; + if (data != NULL) { + if (data->backButton != NULL) free(data->backButton); + if (data->proceedButton != NULL) free(data->proceedButton); + } + free(self); + TraceLog(LOG_INFO, "Deleting a puzzle preview - success"); +} + +Scene *CreatePuzzlePreview(Puzzle *puzzle) { + if (puzzle == NULL) return NULL; + TraceLog(LOG_INFO, "Creating a puzzle preview for a puzzle %s", + puzzle->Name); + Scene *outp = malloc(sizeof(Scene)); + outp->Update = updatePuzzlePreview; + outp->Draw = drawPuzzlePreview; + outp->Deint = deinitPuzzlePreview; + outp->IsTransparent = true; + + puzzlePreviewData *data = malloc(sizeof(puzzlePreviewData)); + if (data == NULL) { + free(outp); + return NULL; + } + + data->puzzle = puzzle; + data->state = POPUP_REVEALING; + data->scroll_up = 0; + data->scroll = 0; + + Button *backButton = malloc(sizeof(Button)); + if (backButton != NULL) { + backButton->parent = outp; + backButton->OnClick = closePreviewWindow; + backButton->atlas = GetButtonsAtlas(); + backButton->textrueLocation = BACK_BUTTON_WIDE_LOCATION; + } + data->backButton = backButton; + + Button *proceedButton = malloc(sizeof(Button)); + if (proceedButton != NULL) { + proceedButton->parent = outp; + proceedButton->OnClick = confirmSelemetion; + proceedButton->atlas = GetButtonsAtlas(); + proceedButton->textrueLocation = PROCEED_BUTTON_WIDE_LOCATION; + } + data->proceedButton = proceedButton; + + outp->data = data; + + return outp; +} diff --git a/src/scenes/puzzleScene.c b/src/scenes/puzzleScene.c index 1671cf8..7f06672 100644 --- a/src/scenes/puzzleScene.c +++ b/src/scenes/puzzleScene.c @@ -15,6 +15,8 @@ typedef struct { size_t distraction_timer; // Miliseconds elapsed float time_acc; + float blackout_state; + PopUpState state; } puzzleSceneData; // Time in seconds @@ -97,6 +99,12 @@ bool drawPuzzleScene(void *self) { }; DrawControls(self, controls_rect); + if (data->state == POPUP_REVEALING) { + DrawRectangle(0, 0, + GetScreenWidth(), GetScreenHeight(), + (Color) {0, 0, 0, 255 * (data->blackout_state >= 1 ? 1 : data->blackout_state) }); + } + return true; } @@ -120,6 +128,14 @@ void createDistraction() { bool updatePuzzleScene(void *self) { puzzleSceneData *data = ((Scene *)self)->data; + if (data->state == POPUP_REVEALING) { + data->blackout_state -= BLACKOUT_SPEED * GetFrameTime(); + if (data->blackout_state <= 0) { + data->blackout_state = 0; + data->state = POPUP_ACTIVE; + } + return true; + } Rectangle body = GetBodyRect(); Rectangle pane1, pane2; @@ -192,6 +208,9 @@ Scene *CreatePuzzleScene(Puzzle *puzzle) { data->distraction_timer = BASE_TIME_LEFT; data->time_acc = 0; + data->state = POPUP_REVEALING; + data->blackout_state = 1; + if (puzzle->InitialCode != NULL) { data->EditorInfo = CreateTextAreaFromText(EditorDisplayParams, puzzle->InitialCode); } else { diff --git a/src/scenes/puzzleSelectionScene.c b/src/scenes/puzzleSelectionScene.c new file mode 100644 index 0000000..8529e35 --- /dev/null +++ b/src/scenes/puzzleSelectionScene.c @@ -0,0 +1,29 @@ +#include <raylib.h> +#include <stdlib.h> +#include "scenes.h" +#include "../resources/resources.h" + +bool updateMainMenu(void *self) { + return true; +} + +bool drawMainMenu(void *self) { + DrawBackground(); + DrawText("Main menu", 0, 0, 100, BLACK); + return true; +} + +void deinitMainMenu(void *self) { + TraceLog(LOG_INFO, "Deleting a main menu"); + free((Scene *)self); +} + +Scene *CreateMainMenu() { + TraceLog(LOG_INFO, "Creating a main menu"); + Scene *outp = malloc(sizeof(Scene)); + outp->Update = updateMainMenu; + outp->Draw = drawMainMenu; + outp->Deint = deinitMainMenu; + outp->IsTransparent = false; + return outp; +} diff --git a/src/scenes/resultView.c b/src/scenes/resultView.c index e51898e..0017d5a 100644 --- a/src/scenes/resultView.c +++ b/src/scenes/resultView.c @@ -7,7 +7,6 @@ #include "../ui_elements/UI.h" #include "../resources/resources.h" -static const int SCROLL_SPEED = 10; static const uint8_t MAX_TINT = 96; typedef struct { @@ -62,7 +61,7 @@ bool drawResultView(void *self) { DrawRecBordered(body, WHITE, data->value->result == RESULT_OK ? COLORSCHEME_GREEN : COLORSCHEME_ORANGE, BORDER); DrawTextInRec(body, data->value->stdout_sb, - GetMainFont(), 20, COLORSCHEME_BROWN, 3, &data->scroll); + GetMainFont(), TEXT_FONT_SIZE, COLORSCHEME_BROWN, 3, &data->scroll); return true; } diff --git a/src/scenes/scenes.h b/src/scenes/scenes.h index f71c2ee..d705feb 100644 --- a/src/scenes/scenes.h +++ b/src/scenes/scenes.h @@ -6,6 +6,16 @@ #define SCENE_STACK_SIZE 16 +typedef enum { + POPUP_REVEALING, + POPUP_REVEALING_ALT, + POPUP_ACTIVE, + POPUP_HIDING, + POPUP_HIDING_ALT, +} PopUpState; +static const int SCROLL_SPEED = 8; +static const int BLACKOUT_SPEED = 3; + /// This structure represents a scene that is stored in a stack. /// The main appeal of this data type is dynamic creation of different /// scenes that don't depend on global state @@ -34,5 +44,6 @@ Scene *CreateDistractionScene(DistractionPuzzle *puzzle, void (*addTime)(Scene * Scene *CreateResultView(SubmitionResult *result); Scene *CreatePuzzleCollectionScene(CollectionElement *el); +Scene *CreatePuzzlePreview(Puzzle *puzzle); #endif // SCENES_H diff --git a/src/ui_elements/UI.h b/src/ui_elements/UI.h index 3665de8..e48804e 100644 --- a/src/ui_elements/UI.h +++ b/src/ui_elements/UI.h @@ -13,6 +13,7 @@ static const float TAB_WIDTH = 4; static const int PADDING = 10; static const int HEADER_FONT_SIZE = 50; +static const int TEXT_FONT_SIZE = 20; static const int EDITOR_PADDING = 3; static const int BORDER = 2; static const int FOOTER_HEIGHT = 30; |
