Let it snow

#!/usr/bin/env bash

# Terminalgröße einmal ermitteln
cols=$(stty size | awk '{print $2}')
lines=$(stty size | awk '{print $1}')

# Cursor aus, Screen leeren
printf "\e[?25l\e[2J"

declare -a x y speed
flake="❄"

cleanup() {
    printf "\e[?25h\e[0m\e[2J"
    exit
}
trap cleanup INT TERM

while true; do
    # neue Flocken (begrenzt)
    for ((i=0; i<cols/14; i++)); do
        x+=($((RANDOM % cols + 1)))
        y+=(1)
        speed+=($((RANDOM % 2 + 1)))
    done

    # alte Positionen löschen
    for ((i=0; i<${#x[@]}; i++)); do
        (( y[i] > 1 && y[i] < lines )) && \
            printf "\e[%d;%dH " "${y[i]}" "${x[i]}"
    done

    # neue Positionen zeichnen
    for ((i=0; i<${#x[@]}; i++)); do
        ((y[i] += speed[i]))

        if (( y[i] < lines )); then
            printf "\e[%d;%dH%s" "${y[i]}" "${x[i]}" "$flake"
        else
            unset x[i] y[i] speed[i]
        fi
    done

    # Arrays verdichten
    x=("${x[@]}")
    y=("${y[@]}")
    speed=("${speed[@]}")

    sleep 0.03
done