diff --git a/assets/mask.png b/assets/mask.png new file mode 100644 index 0000000..e500e1c Binary files /dev/null and b/assets/mask.png differ diff --git a/assets/mask2.png b/assets/mask2.png new file mode 100644 index 0000000..00e8b11 Binary files /dev/null and b/assets/mask2.png differ diff --git a/mask.py b/mask.py new file mode 100644 index 0000000..644fc50 --- /dev/null +++ b/mask.py @@ -0,0 +1,45 @@ +from PIL import Image + +# Wymiary (bez zmian) +SZEROKOSC = 1280 +WYSOKOSC_PLYNNA = 1080 +WYSOKOSC_CZARNA = 720 +WYSOKOSC_GRADIENTU = WYSOKOSC_PLYNNA - WYSOKOSC_CZARNA # 360 + +# Stopień nieliniowości (im wyższy, tym wolniejszy spadek na początku) +# 1.0 = Liniowy, 2.0 = Quadratic (Wolniejszy start, szybszy koniec), 3.0 = Cubic +WSPOLCZYNNIK_EASING = 2.5 + +# 1. Utwórz przezroczysty obraz +img = Image.new('RGBA', (SZEROKOSC, WYSOKOSC_PLYNNA), (0, 0, 0, 0)) +pixels = img.load() + +# 2. Ustaw w pełni czarny obszar (bez zmian) +for x in range(SZEROKOSC): + for y in range(WYSOKOSC_CZARNA): + pixels[x, y] = (0, 0, 0, 255) + +# 3. Zmodyfikowany gradient nieliniowy (Ease-In, czyli spowolnienie na początku) +for y in range(WYSOKOSC_CZARNA, WYSOKOSC_PLYNNA): + + # 1. Oblicz współrzędną w zakresie 0.0 do 1.0 (liniowo) + y_gradient = y - WYSOKOSC_CZARNA + wspolczynnik_liniowy = y_gradient / WYSOKOSC_GRADIENTU # 0.0 na 720px, 1.0 na 1080px + + # 2. Zastosuj funkcję nieliniową (np. Power/Expo Ease-In) + # Ta funkcja powoduje, że 'współczynnik_nieliniowy' rośnie wolniej na początku. + wspolczynnik_nieliniowy = wspolczynnik_liniowy ** WSPOLCZYNNIK_EASING + + # 3. Konwersja na krycie (alpha) + # Ponieważ chcemy, by krycie MALAŁO od 255 do 0: + # Używamy 1.0 - wspolczynnik_nieliniowy (czyli od 1.0 do 0.0) + krycie_skalarne = 1.0 - wspolczynnik_nieliniowy + alpha = int(255 * krycie_skalarne) + + # Zastosuj krycie + for x in range(SZEROKOSC): + # Użyj maks. 0, aby uniknąć ujemnych wartości na wszelki wypadek + pixels[x, y] = (0, 0, 0, max(0, alpha)) + +# Zapisz obraz +img.save('mask.png') \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index aa33416..80764f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -63,14 +63,25 @@ int main() { uint32_t dialogue_id = compositor_insert(compositor, text_getfb(dialogue_text), WIDTH - 140, 160, 60, HEIGHT - 130, 4); - uint32_t* black = (uint32_t*)malloc(WIDTH * HEIGHT * sizeof(uint32_t)); - for (int i = 0; i < WIDTH * HEIGHT; i++) { - black[i] = 0xFF000000; - } - uint32_t black_id = compositor_insert(compositor, black, - WIDTH, HEIGHT, 0, 0, 5); - compositor_set_alpha(compositor, black_id, 0.0f); + uint32_t* mask = image_load_resized("assets/mask.png", 1280, 1080); + // okay so this requires some math + // inserting at 0,0 (top-left anchor) means it will cover the whole screen + // we need to insert it above the screen, so -1080 + uint32_t mask_id = compositor_insert(compositor, mask, 1280, 1080, 0, -1080, 5); + compositor_set_visible(compositor, mask_id, false); + + uint32_t* mask2 = image_load_resized("assets/mask2.png", 1280, 1080); + // here, we put it in the center, as this is the slide out + uint32_t mask2_id = compositor_insert(compositor, mask2, 1280, 1080, 0, 0, 5); + compositor_set_visible(compositor, mask2_id, false); + + uint32_t* black = (uint32_t*)malloc(WIDTH * HEIGHT * sizeof(uint32_t)); + for (int i = 0; i < WIDTH * HEIGHT; i++) { + black[i] = 0xFF000000; + } + uint32_t black_id = compositor_insert(compositor, black, WIDTH, HEIGHT, 0, 0, 6); compositor_set_visible(compositor, black_id, false); + compositor_set_alpha(compositor, black_id, 0.0f); compositor_animate_move(compositor, maksw_happy_id, 60, POS_Y, 1.0f, EASE_OUT_CUBIC); compositor_animate_scale(compositor, maksw_happy_id, 1.05f, 0.3f, EASE_IN_OUT_CUBIC, true); @@ -133,12 +144,14 @@ int main() { static unsigned int lines = 0; static bool dialog_finished = false; + static bool transitioning = false; // HACK if (mouse_clicked || key_pressed) { if (text_is_animating(dialogue_text)) { text_show_all_current(dialogue_text); } else { + // do i like this approach? mixed feelings if (lines == 0) { // line 2 compositor_animation_complete_all(compositor); @@ -153,22 +166,20 @@ int main() { else if (lines == 1) { // line 3 compositor_animation_complete_all(compositor); - compositor_animate_scale(compositor, wikor_id, 1.0f, 0.2f, EASE_IN_OUT_CUBIC); - compositor_set_visible(compositor, maksw_happy_id, false); - compositor_set_visible(compositor, maksw_neutral_id, true); - compositor_animate_scale(compositor, maksw_neutral_id, 1.05f, 0.3f, EASE_IN_OUT_CUBIC); - text_clear(dialogue_text); - text_clear(name_text); - text_push(name_text, "maksw", 0.0f, true); - text_push(dialogue_text, "why so.. serious?", 30.0f, true); + + compositor_set_visible(compositor, mask_id, true); + compositor_animate_move(compositor, mask_id, 0, 0, 0.5f, EASE_OUT_CUBIC, false); + + transitioning = true; lines++; } else if (lines == 2) { - // fade out - compositor_animation_complete_all(compositor); - compositor_animate_scale(compositor, maksw_neutral_id, 1.0f, 0.2f, EASE_IN_OUT_CUBIC); - compositor_set_visible(compositor, black_id, true); - compositor_animate_fade(compositor, black_id, 1.0f, 1.5f, EASE_IN_OUT_CUBIC); + // (line 4), fade out + compositor_animation_complete_all(compositor); + + compositor_set_visible(compositor, black_id, true); + compositor_animate_fade(compositor, black_id, 1.0f, 1.0f, EASE_IN_OUT_CUBIC, false); + dialog_finished = true; lines++; } @@ -180,12 +191,31 @@ int main() { compositor_tick(compositor, delta_time_sec); + if (transitioning) { + if (compositor_is_element_animating(compositor, mask_id) == false) { + compositor_set_visible(compositor, maksw_happy_id, false); + compositor_set_visible(compositor, maksw_neutral_id, true); + compositor_animate_scale(compositor, maksw_neutral_id, 1.05f, 0.5f, EASE_IN_OUT_CUBIC); + text_clear(dialogue_text); + text_clear(name_text); + text_push(name_text, "maksw", 0.0f, true); + text_push(dialogue_text, "why so.. serious?", 30.0f, true); + + compositor_set_visible(compositor, mask_id, false); + compositor_set_visible(compositor, mask2_id, true); + compositor_animate_move(compositor, mask2_id, 0, HEIGHT, 0.5f, EASE_IN_CUBIC, false); + + transitioning = false; + } + } + if (dialog_finished) { compositor_mark_content_dirty(compositor, black_id); if (compositor_is_element_animating(compositor, black_id) == false) { running = false; } } + if (text_nextframe(name_text, delta_time_sec)) compositor_mark_content_dirty(compositor, name_id); if (text_nextframe(dialogue_text, delta_time_sec)) @@ -200,6 +230,9 @@ int main() { if (wikor) image_free(wikor); if (black) free(black); + if (mask) image_free(mask); + if (mask2) image_free(mask2); + if (bg) image_free(bg); if (textbox) image_free(textbox);