diff options
| author | physick <mynameisgennadiy@vk.com> | 2026-08-31 21:17:22 +0500 |
|---|---|---|
| committer | physick <mynameisgennadiy@vk.com> | 2026-08-31 21:17:22 +0500 |
| commit | 9b545255d4496903455c5dd49042c87e1a1f7af4 (patch) | |
| tree | fc3355947341636c5e3e01c1997c77a358fbe653 | |
| parent | e4b96cc66d8c4269661745ce187cb58c852542d3 (diff) | |
scroll in the puzzle selection scene
| -rw-r--r-- | README.md | 16 | ||||
| -rwxr-xr-x | assets/textures/buttons_atlas.png | bin | 1496 -> 1960 bytes | |||
| -rw-r--r-- | puzzles/1.2.b.pz | 0 | ||||
| -rw-r--r-- | puzzles/1.a.pz | 0 | ||||
| -rw-r--r-- | puzzles/3.c.pz | 0 | ||||
| -rw-r--r-- | puzzles/4.d.pz | 0 | ||||
| -rw-r--r-- | puzzles/le verylongtestnamethatistoowideforascreen/layered puzzle.pz | 0 | ||||
| -rw-r--r-- | src/main.c | 3 | ||||
| -rw-r--r-- | src/puzzles/collection.c | 21 | ||||
| -rw-r--r-- | src/resources/TextruesAtlas.h | 14 | ||||
| -rw-r--r-- | src/scenes/collectionScene.c | 88 | ||||
| -rw-r--r-- | src/scenes/scenes.h | 3 |
12 files changed, 130 insertions, 15 deletions
@@ -28,3 +28,19 @@ The colorscheme is applied at the runtime. Follow the following colorscheme in t - #FF7F00 - accent light - #0000FF - accent dark - #000000 - dark + +## Puzzle location +The puzzles are stored in so called collections. The collection is basically +a directory that contains other directories and .pz (puzzle) files. +The collection can have an icon that will be displayed on the bottom of each of its elements. +They are intended to be semi-transparent. +To use it put `icon.png` in the root of the directory. + +The naming of the file is as follows: +`<order>.<name>.pz` +The order is optional but is advised to sort the puzzles in the game. Order field +can contain dots, only last or second to last parts will be used as a name. +Only the name part will be applied. + +It is not recommended to nest the puzzles deeper than 3 layers because it might cause +some funky glithes in the scene stack logic. diff --git a/assets/textures/buttons_atlas.png b/assets/textures/buttons_atlas.png Binary files differindex ce4a4f1..a50a500 100755 --- a/assets/textures/buttons_atlas.png +++ b/assets/textures/buttons_atlas.png diff --git a/puzzles/1.2.b.pz b/puzzles/1.2.b.pz new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/puzzles/1.2.b.pz diff --git a/puzzles/1.a.pz b/puzzles/1.a.pz new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/puzzles/1.a.pz diff --git a/puzzles/3.c.pz b/puzzles/3.c.pz new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/puzzles/3.c.pz diff --git a/puzzles/4.d.pz b/puzzles/4.d.pz new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/puzzles/4.d.pz diff --git a/puzzles/le verylongtestnamethatistoowideforascreen/layered puzzle.pz b/puzzles/le verylongtestnamethatistoowideforascreen/layered puzzle.pz new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/puzzles/le verylongtestnamethatistoowideforascreen/layered puzzle.pz @@ -1,3 +1,4 @@ +#include <stdbool.h> #include <stdio.h> #include <raylib.h> #include "scenes/scenes.h" @@ -31,7 +32,7 @@ int main(void) { return 1; } - if (!AddScene(CreatePuzzleCollectionScene(&el))) { + if (!AddScene(CreatePuzzleCollectionScene(&el, true))) { printf("Failed to create a collection scene\n"); return 1; } diff --git a/src/puzzles/collection.c b/src/puzzles/collection.c index ca2743c..a88bae4 100644 --- a/src/puzzles/collection.c +++ b/src/puzzles/collection.c @@ -13,6 +13,14 @@ static const char *IMAGE_NAME = "icon.png"; static const float NAME_IN_CARD_RATIO = 0.2f; +int compare_elements(const void *a, const void *b) { + const CollectionElement *elA = (const CollectionElement *)a; + const CollectionElement *elB = (const CollectionElement *)b; + + // Sort alphabetically by name + return strcmp(elA->path, elB->path); +} + CollectionElementType getTypeFromPath(char *fullPath) { struct stat st; if (stat(fullPath, &st) != 0) return COLLECTION_ELEMENT_UNKNOWN; @@ -65,16 +73,20 @@ char *getName(char *name) { char buf[1024]; strncpy(buf, name, sizeof(buf)); size_t len = strlen(name); + size_t span_start = 0; + size_t span_end = 0; // Cutting a file extention for (size_t i = 0; i < len; ++i) { if (buf[i] == '.') { - buf[i] = 0x0; - break; + if (span_end != 0) span_start = span_end + 1; + span_end = i; } } + if (span_end != 0) + buf[span_end] = 0x0; - return strdup(buf); + return strdup(buf + span_start); } size_t getElementCount(DIR *dir, CollectionElement *el) { @@ -136,6 +148,9 @@ void initCollectionFromDir(CollectionElement *el, void (*callback)(CollectionEle idx += 1; } + if (idx > 1) { + qsort(el->children, idx, sizeof(CollectionElement), compare_elements); + } closedir(dir); } diff --git a/src/resources/TextruesAtlas.h b/src/resources/TextruesAtlas.h index 97eb889..a9202c2 100644 --- a/src/resources/TextruesAtlas.h +++ b/src/resources/TextruesAtlas.h @@ -50,4 +50,18 @@ static const Rectangle PROCEED_BUTTON_WIDE_LOCATION = { .height = 32, }; +static const Rectangle LEFT_ARROW_ICON_LOCATION = { + .x = 0, + .y = 32, + .width = 32, + .height = 96, +}; + +static const Rectangle RIGHT_ARROW_ICON_LOCATION = { + .x = 32, + .y = 32, + .width = 32, + .height = 96, +}; + #endif // TEXTURES_ATLAS_H diff --git a/src/scenes/collectionScene.c b/src/scenes/collectionScene.c index cda6fd1..1f1173e 100644 --- a/src/scenes/collectionScene.c +++ b/src/scenes/collectionScene.c @@ -1,6 +1,8 @@ #include <dirent.h> #include <raylib.h> +#include <stdbool.h> #include <stddef.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -10,19 +12,31 @@ #include "../utils/arena.h" #include "../resources/TextruesAtlas.h" +static const float MENU_SCROLL_SENC = 75.0f; static const size_t ARENA_SIZE = 1024 * 64; +static const int SCENE_PADDING = 30; +static const int FOOTER_PADDING = 60; +static const float ARROWS_HEIGHT = 0.4f; +static const uint8_t ARROWS_ALPHA = 128; +/// Height / width +static const float ELEMENT_WIDTH_RATIO = 0.45f; typedef struct { CollectionElement *collection; + CollectionElement *selected; Button *backButton; size_t count; + float blackout_state; + PopUpState state; + float scroll; } CollectionSceneData; CollectionSceneData *getData(void *self) { return ((Scene *)self)->data; } -void backButton_onClick(Scene *self) { +static void backButton_onClick(Scene *self) { + // CollectionSceneData *data = getData(self); DeleteSceneFromStack(); } @@ -34,7 +48,7 @@ void collectionElement_onSelect(CollectionElement *caller) { AddScene(CreatePuzzlePreview(ReadPuzzleFromFile(caller->path))); break; case COLLECTION_ELEMENT_COLLECTION: - AddScene(CreatePuzzleCollectionScene(caller)); + AddScene(CreatePuzzleCollectionScene(caller, false)); break; default: TraceLog(LOG_WARNING, "Invalid CollectionElement type for %s", caller->path); @@ -43,9 +57,9 @@ void collectionElement_onSelect(CollectionElement *caller) { } void DrawCollectionName(char *name) { - Vector2 width = MeasureTextEx(*GetMainFont(), name, 50, 1); + Vector2 width = MeasureTextEx(*GetMainFont(), name, HEADER_FONT_SIZE, 1); int screen_width = GetScreenWidth(); - Vector2 pos = { .y = 20, .x = (screen_width - width.x) / 2, }; + Vector2 pos = { .y = SCENE_PADDING , .x = (screen_width - width.x) / 2, }; DrawTextEx(*GetMainFont(), name, pos, HEADER_FONT_SIZE, 1, COLORSCHEME_BROWN); } @@ -63,10 +77,21 @@ char *getCollectionName(char *path) { bool updateCollectionScene(void *self) { CollectionSceneData *data = getData(self); - if (data->collection != NULL) + if (data->state == POPUP_REVEALING) { + data->blackout_state -= BLACKOUT_SPEED * GetFrameTime(); + if (data->blackout_state <= 0) { + data->blackout_state = 0; + data->state = POPUP_ACTIVE; + TraceLog(LOG_INFO, "Done revealing"); + } + return true; + } + + if (data->collection != NULL) { for (size_t i = 0; i < data->collection->childCount; ++i) { UpdateCollectionElement(&data->collection->children[i]); } + } if (data->backButton != NULL) UpdateButton(data->backButton); return true; @@ -85,14 +110,53 @@ bool drawCollectionScene(void *self) { .height = 36, // TODO: make it match the page view scale }); + float element_height = GetScreenHeight() - SCENE_PADDING * 2 - HEADER_FONT_SIZE - FOOTER_PADDING; + float element_width = element_height * ELEMENT_WIDTH_RATIO; for (size_t i = 0; i < data->collection->childCount; ++i) { DrawCollectionElement(&data->collection->children[i], data->collection, (Rectangle) { - .x = 10 + 210 * i, - .y = 80, - .width = 200, - .height = 450, + .x = SCENE_PADDING + (element_width + PADDING) * i - data->scroll, + .y = SCENE_PADDING + HEADER_FONT_SIZE, + .width = element_width, + .height = element_height, }); } + + data->scroll -= GetMouseWheelMove() * MENU_SCROLL_SENC; + if (data->scroll < 0) data->scroll = 0; + float max_scroll = (element_width + PADDING) * data->collection->childCount + SCENE_PADDING * 2 - GetScreenWidth(); + if (max_scroll < 0) max_scroll = 0; + if (data->scroll > max_scroll) data->scroll = max_scroll; + + float arrows_height_px = GetScreenHeight() * ARROWS_HEIGHT; + Color arrows_color = { .r = 255, .g = 255, .b = 255, .a = ARROWS_ALPHA, }; + + + if (data->scroll != 0) + DrawTexturePro(*GetButtonsAtlas(), + LEFT_ARROW_ICON_LOCATION, + (Rectangle) { + .x = 0, + .y = (GetScreenHeight() - arrows_height_px) / 2, + .width = SCENE_PADDING, + .height = arrows_height_px + }, (Vector2) {0}, 0, arrows_color); + + if (data->scroll != max_scroll) + DrawTexturePro(*GetButtonsAtlas(), + RIGHT_ARROW_ICON_LOCATION, + (Rectangle) { + .x = GetScreenWidth() - SCENE_PADDING, + .y = (GetScreenHeight() - arrows_height_px) / 2, + .width = SCENE_PADDING, + .height = arrows_height_px + }, (Vector2) {0}, 0, arrows_color); + + if (data->state != POPUP_ACTIVE) { + DrawRectangle(0, 0, + GetScreenWidth(), GetScreenHeight(), + (Color) {0, 0, 0, 255 * (data->blackout_state >= 1 ? 1 : data->blackout_state) }); + } + return true; } @@ -107,7 +171,7 @@ void deinitCollectionScene(void *self) { free((Scene *)self); } -Scene *CreatePuzzleCollectionScene(CollectionElement *el) { +Scene *CreatePuzzleCollectionScene(CollectionElement *el, bool smooothEntry) { TraceLog(LOG_INFO, "Creating a collection scene"); Scene *outp = malloc(sizeof(Scene)); if (outp == NULL) return NULL; @@ -124,6 +188,10 @@ Scene *CreatePuzzleCollectionScene(CollectionElement *el) { if (!el->IsInitialized) InitializeCollection(el, collectionElement_onSelect); data->collection = el; + data->selected = NULL; + data->state = smooothEntry? POPUP_REVEALING : POPUP_ACTIVE; + data->blackout_state = 1.0f; + data->scroll = 0.0f; Button *backButton = malloc(sizeof(Button)); if (backButton != NULL) { diff --git a/src/scenes/scenes.h b/src/scenes/scenes.h index d705feb..f4ba579 100644 --- a/src/scenes/scenes.h +++ b/src/scenes/scenes.h @@ -40,10 +40,11 @@ bool UpdateScene(); Scene *CreateMainMenu(); Scene *CreatePuzzleScene(Puzzle *puzzle); +/// Expects a callback to add time (second argument = amount of seconds) to the scene. Scene *CreateDistractionScene(DistractionPuzzle *puzzle, void (*addTime)(Scene *, size_t)); Scene *CreateResultView(SubmitionResult *result); -Scene *CreatePuzzleCollectionScene(CollectionElement *el); +Scene *CreatePuzzleCollectionScene(CollectionElement *el, bool smooothEntry); Scene *CreatePuzzlePreview(Puzzle *puzzle); #endif // SCENES_H |
