#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 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; }