rain (2550B)
1 #!/bin/bash 2 RAINS=("|" "│" "┃" "┆" "┇" "┊" "┋" "╽" "╿") 3 COLORS=("\e[37m" "\e[37;1m") 4 # More from 256 color mode 5 for i in {244..255}; do 6 COLORS=("${COLORS[@]}" "\e[38;5;${i}m") 7 done 8 NRAINS=${#RAINS[@]} 9 NCOLORS=${#COLORS[@]} 10 NUM_RAIN_METADATA=5 11 12 13 sigwinch() { 14 TERM_WIDTH=$(tput cols) 15 TERM_HEIGHT=$(tput lines) 16 STEP_DURATION=0.025 17 ((MAX_RAINS = TERM_WIDTH * TERM_HEIGHT / 4)) 18 ((MAX_RAIN_LENGTH = TERM_HEIGHT < 10 ? 1 : TERM_HEIGHT / 10)) 19 # In percentage 20 ((NEW_RAIN_ODD = TERM_HEIGHT > 50 ? 100 : TERM_HEIGHT * 2)) 21 ((NEW_RAIN_ODD = NEW_RAIN_ODD * 75 / 100)) 22 ((FALLING_ODD = TERM_HEIGHT > 25 ? 100 : TERM_HEIGHT * 4)) 23 ((FALLING_ODD = FALLING_ODD * 90 / 100)) 24 } 25 26 do_exit() { 27 echo -ne "\e[${TERM_HEIGHT};1H\e[0K" 28 29 # Show cursor and echo stdin 30 echo -ne "\e[?25h" 31 stty echo 32 exit 0 33 } 34 35 do_render() { 36 # Clean screen first 37 for ((idx = 0; idx < num_rains * NUM_RAIN_METADATA; idx += NUM_RAIN_METADATA)); do 38 X=${rains[idx]} 39 Y=${rains[idx + 1]} 40 LENGTH=${rains[idx + 4]} 41 for ((y = Y; y < Y + LENGTH; y++)); do 42 (( y < 1 || y > TERM_HEIGHT )) && continue 43 echo -ne "\e[${y};${X}H " 44 done 45 done 46 47 for ((idx = 0; idx < num_rains * NUM_RAIN_METADATA; idx += NUM_RAIN_METADATA)); do 48 if ((100 * RANDOM / 32768 < FALLING_ODD)); then 49 # Falling 50 if ((++rains[idx + 1] > TERM_HEIGHT)); then 51 # Out of screen, bye sweet <3 52 rains=("${rains[@]:0:idx}" 53 "${rains[@]:idx+NUM_RAIN_METADATA:num_rains*NUM_RAIN_METADATA}") 54 ((num_rains--)) 55 continue 56 fi 57 fi 58 X=${rains[idx]} 59 Y=${rains[idx + 1]} 60 RAIN=${rains[idx + 2]} 61 COLOR=${rains[idx + 3]} 62 LENGTH=${rains[idx + 4]} 63 for ((y = Y; y < Y + LENGTH; y++)); do 64 (( y < 1 || y > TERM_HEIGHT )) && continue 65 echo -ne "\e[${y};${X}H${COLOR}${RAIN}" 66 done 67 done 68 } 69 70 trap do_exit TERM INT 71 trap sigwinch WINCH 72 # no echo stdin and hide the cursor 73 stty -echo 74 echo -ne "\e[?25l" 75 76 echo -ne "\e[2J" 77 rains=() 78 sigwinch 79 while :; do 80 read -n 1 -t $STEP_DURATION ch 81 case "$ch" in 82 q|Q) 83 do_exit 84 ;; 85 esac 86 87 if ((num_rains < MAX_RAINS)) && ((100 * RANDOM / 32768 < NEW_RAIN_ODD)); then 88 # Need new |, 1-based 89 RAIN="${RAINS[NRAINS * RANDOM / 32768]}" 90 COLOR="${COLORS[NCOLORS * RANDOM / 32768]}" 91 LENGTH=$((MAX_RAIN_LENGTH * RANDOM / 32768 + 1)) 92 X=$((TERM_WIDTH * RANDOM / 32768 + 1)) 93 Y=$((1 - LENGTH)) 94 rains=("${rains[@]}" "$X" "$Y" "$RAIN" "$COLOR" "$LENGTH") 95 ((num_rains++)) 96 fi 97 98 # let rain fall! 99 do_render 100 done