diff options
| author | Syndamia <kamen@syndamia.com> | 2026-03-31 21:07:19 +0300 |
|---|---|---|
| committer | Syndamia <kamen@syndamia.com> | 2026-03-31 21:07:19 +0300 |
| commit | 69743511c4bc59ad9ff84fa223f7a7c2625522f2 (patch) | |
| tree | c69f278b32c526c7918df62fc70c0152486af166 /renders/anim_sort.c | |
| parent | 9b4a190499144090cf6eac49bf5a5ccdcf07099d (diff) | |
| download | ppm_graphics-69743511c4bc59ad9ff84fa223f7a7c2625522f2.tar ppm_graphics-69743511c4bc59ad9ff84fa223f7a7c2625522f2.tar.gz ppm_graphics-69743511c4bc59ad9ff84fa223f7a7c2625522f2.zip | |
Diffstat (limited to 'renders/anim_sort.c')
| -rw-r--r-- | renders/anim_sort.c | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/renders/anim_sort.c b/renders/anim_sort.c new file mode 100644 index 0000000..f8e1a71 --- /dev/null +++ b/renders/anim_sort.c @@ -0,0 +1,202 @@ +#include "../AnimationRender/AnimationRender.h" +#include "../AnimationRender/F_Draw.h" +#include "../AnimationRender/F_FrameRange.h" +#include "../AnimationRender/F_Interpolate.h" +#include "../AnimationRender/FrameCallback.h" +#include "../FrameRender/P_Circle.h" +#include "../FrameRender/P_Square.h" +#include "../FrameRender/P_TransformCenter.h" +#include "../FrameRender/PixelCallback.h" +#include <stdlib.h> + +struct FrameCallbackArray { + FrameCallback** arr; + u32 count; + u32 allocated; + + const u32* elements; + const TransformCenter* positions; + const PixelCallback** callbacksPositions; +}; + +void +FrameCallbackArray_push(struct FrameCallbackArray* fca, u32 from, u32 to, u32 start, u32 end) { + // resize + if (fca->count + 5 >= fca->allocated) { + fca->allocated = fca->allocated == 0 ? 8 : fca->allocated << 1; + FrameCallback** arrLarger = calloc(sizeof(FrameCallback*), fca->allocated); + + for (unsigned i = 0; i < fca->count; ++i) + arrLarger[i] = fca->arr[i]; + free(fca->arr); + fca->arr = arrLarger; + } + + fca->arr[fca->count++] = NULL; + fca->arr[fca->count++] = FrameRange_setup((FrameRange){ + .startFrame = start, .endFrame = end, + }); + fca->arr[fca->count++] = Interpolate_setup((Interpolate){ + .startValue = fca->positions + from, .endValue = fca->positions + to, + .value = fca->callbacksPositions[fca->elements[from]]->callback_self, + .interpolate = (f_interpolate)Interpolate_TransformCenter, + }); +} + +struct SwapCallbackArgs { + struct FrameCallbackArray* fca; + u32* frames; + u32 duration; + u32 rest; +}; + +void +swap_callback(struct SwapCallbackArgs* sca, u32 from, u32 to) { + FrameCallbackArray_push(sca->fca, + from, to, *sca->frames, *sca->frames + sca->duration); + FrameCallbackArray_push(sca->fca, + to, from, *sca->frames, *sca->frames + sca->duration); + *sca->frames += sca->duration + sca->rest; +} + +void +swap_u32(struct SwapCallbackArgs* sca, u32* a, u32 i, u32 j) { + swap_callback(sca, i, j); + u32 temp = a[i]; + a[i] = a[j]; + a[j] = temp; +} + +void +bubble_sort(u32* a, u32 length, struct SwapCallbackArgs* sca) { + for (u32 i = 0; i < length - 1; ++i) { + for (u32 j = 0; j < length - 1 - i; ++j) { + // Sorts in ascending order + if (a[j] > a[j+1]) + swap_u32(sca, a, j, j+1); + } + } +} + +void +insertion_sort(u32* a, u32 length, struct SwapCallbackArgs* sca) { + for (u32 i = 1; i < length; ++i) { + u32 j = i; + // Sorts in descending order + while (j > 0 && a[j-1] < a[j]) { + swap_u32(sca, a, j, j-1); + --j; + } + } +} + +void +selection_sort(u32* a, u32 length, struct SwapCallbackArgs* sca) { + for (u32 i = 0; i < length - 1; ++i) { + int minind = i; + for (int j = i + 1; j < length; ++j) { + // Sorts in ascending order + if (a[j] < a[minind]) + minind = j; + } + + if (minind != i) + swap_u32(sca, a, i, minind); + } +} + +int +main() { + /* Sesttings */ + + // Animation settings + u32 width = 960; + u32 height = 320; + const u32 FPS = 60; + + // Elements settings + u32 elements[] = { 5, 4, 3, 2, 1, 0 }; + #define ELEMENTS_COUNT (sizeof(elements) / sizeof(*elements)) + u32 elementSpacing = 40; + + /* Implementation */ + + // Spaced out elements + u32 minRadius = (width / ELEMENTS_COUNT) / 4 - elementSpacing / 2; + u32 maxRadius = (width / ELEMENTS_COUNT) / 2 - elementSpacing / 2; + + TransformCenter positions[ELEMENTS_COUNT]; + for (unsigned i = 0; i < ELEMENTS_COUNT; ++i) { + positions[i].centerX = i * width / ELEMENTS_COUNT + maxRadius + elementSpacing / 2; + positions[i].centerY = height / 2; + } + + PixelCallback* callbacksPositions[ELEMENTS_COUNT]; + PixelCallback* callbacksElements[1 + ELEMENTS_COUNT * 3] = { + /* Background */ + Square_setup((Square){ + .size = width, .color = 0xFFF0F0F0, + }), + }; + for (unsigned i = 0; i < ELEMENTS_COUNT; ++i) { + double p = elements[i] / (ELEMENTS_COUNT - 1.0); + + callbacksElements[1+i*3] = NULL; + callbacksElements[1+i*3+1] = callbacksPositions[elements[i]] = TransformCenter_setup(positions[i]); + callbacksElements[1+i*3+2] = Circle_setup((Circle){ + .radius = minRadius * (1-p) + maxRadius * p, + .color = 0xFF000000 + 0xFFFF * p, + }); + } + u32 callbacksElementsSize = 1 + ELEMENTS_COUNT * 3; + + // Elements movement + u32 frames = FPS; + + struct FrameCallbackArray fca = { + .arr = NULL, + .elements = elements, + .positions = positions, + .callbacksPositions = (const PixelCallback**)callbacksPositions, + }; + struct SwapCallbackArgs sca = { + .fca = &fca, + .frames = &frames, + .duration = FPS * 1, + .rest = FPS * 0.5, + }; + + // Sort + + bubble_sort(elements, ELEMENTS_COUNT, &sca); + insertion_sort(elements, ELEMENTS_COUNT, &sca); + selection_sort(elements, ELEMENTS_COUNT, &sca); + + frames += FPS; + + // Render + + fca.arr[fca.count++] = NULL; + fca.arr[fca.count++] = Draw_setup((Draw){ + .callbacks = (const PixelCallback**)callbacksElements, .sizeCallbacks = callbacksElementsSize, + }); + + FrameCallback** callbacksMove = fca.arr; + u32 callbacksMoveSize = fca.count; + RenderAnimation(width, height, frames, (const FrameCallback**)callbacksMove, callbacksMoveSize); + + // Free + for (u32 i = 0; i < callbacksElementsSize; ++i) { + if (callbacksElements[i] == NULL) continue; + free(callbacksElements[i]->callback_self); + free(callbacksElements[i]); + } + for (u32 i = 0; i < callbacksMoveSize; ++i) { + if (callbacksMove[i] == NULL) continue; + free(callbacksMove[i]->callback_self); + free(callbacksMove[i]); + } + free(callbacksMove); + + return 0; +} |
