A Bash Creativity Showcase by wuseman
Unleash the creativity of your terminal with a unique collection of custom screensavers crafted by Wuseman. This guide features a variety of screensavers, from simple doodles to complex dynamic matrix effects, all designed to transform your command line interface into a canvas of digital art
Dive into the world of Bash scripting with these innovative screensaver examples, and discover how you can bring life, movement, and color to your terminal
One-liner: random colors + random emojis (and less flicker)
trap 'printf "\033[0m\033[?25h\033[2J\033[H\n"; exit' INT TERM; printf '\033[?25l'; while :; do cols=$(tput cols); lines=$(tput lines); printf '\033[2J\033[H'; for ((i=0;i<cols*lines/14;i++)); do x=$((RANDOM%(cols-2)+1)); y=$((RANDOM%lines+1)); r=$((RANDOM%256)); g=$((RANDOM%256)); b=$((RANDOM%256)); em=( "✨" "💫" "⭐" "🌟" "⚡" "🔥" "🌈" "🍄" "👾" "🪐" "🌙" "☄️" "🧿" "🌀" "🔮" "💎" "🦄" "🎲" "🎯" "🧊" "🧠" "🕳️" "🧬" "🧪" "🛰️" ); ch=${em[RANDOM%${#em[@]}]}; printf '\033[%d;%dH\033[38;2;%d;%d;%dm%s\033[0m' "$y" "$x" "$r" "$g" "$b" "$ch"; done; sleep 0.05; done
ASCII Rain
while true; do printf "\033[2J"; for ((i=0;i<($(tput cols)*$(tput lines)/10);i++)); do x=$((RANDOM%$(tput cols))); y=$((RANDOM%$(tput lines))); printf "\033[${y};${x}H|"; done; sleep 0.05; done
Random Numeric Noise Screensaver (Terminal Static Effect)
while true; do printf "\033[2J"; digits=("0" "1" "2" "3" "4" "5" "6" "7" "8" "9"); num_digits=$(($(tput cols)*$(tput lines)/10)); for ((i=0;i<num_digits;i++)); do x=$((RANDOM%$(tput cols))); y=$((RANDOM%$(tput lines))); digit=${digits[$((RANDOM%${#digits[@]}))]} ; printf "\033[${y};${x}H${digit}"; done; sleep 0.05; done
Random Snowfall Screensaver (Unicode Flakes Terminal Storm)
while :; do printf "\033[2J"; a=("❄" "❅" "❆"); n=$(($(tput cols)*$(tput lines)/20)); for ((i=0;i<n;i++)); do x=$((RANDOM%$(tput cols))); y=$((RANDOM%$(tput lines))); printf "\033[${y};${x}H${a[$((RANDOM%${#a[@]}))]}"; done; sleep 0.1; done
Random Blinking Starburst Effect (ANSI Color Sparkles)
while true; do printf "\033[2J"; c=("31" "32" "33" "34" "35" "36" "37"); n=15; for ((i=0;i<n;i++)); do x=$((RANDOM%$(tput cols))); y=$((RANDOM%$(tput lines))); for r in {1..5}; do color=${c[$((RANDOM%${#c[@]}))]} ; printf "\033[${y};${x}H\033[${color}m*\033[0m"; sleep 0.05; printf "\033[${y};${x}H "; sleep 0.05; done; done; done
One-Liner Shrinking Spiral Spinner with Color Cycling and Bouncing Ball Finale
#!/usr/bin/env bash
set -euo pipefail
cleanup() {
printf '\033[0m\033[?25h\033[2J\033[H'
}
trap cleanup INT TERM EXIT
# Hide cursor + clear
printf '\033[?25l\033[2J\033[H'
spinner=(◐ ◓ ◑ ◒ ⣾ ⣽ ⣻ ⢿ ⡿ ⣟ ⣯ ⣷)
colors=(31 32 33 34 35 36 37)
n=${#spinner[@]}
m=${#colors[@]}
# Spiral bounds
sx=0; sy=0
ex=$(( $(tput cols) - 1 ))
ey=$(( $(tput lines) - 1 ))
# Spiral cursor + direction
x=$sx; y=$sy
dx=1; dy=0
# Indices + laps
si=0; ci=0; laps=0
# Bouncing ball state (center)
bx=$((ex/2)); by=$((ey/2))
bdx=-1; bdy=-1
draw_at() { # color row col char (row/col are 0-based)
local co="$1" row="$2" col="$3" ch="$4"
printf '\033[%sm\033[%d;%dH%s\033[0m' "$co" "$((row+1))" "$((col+1))" "$ch"
}
next_spiral_dir() {
if (( x > ex )); then
x=$ex; y=$((y+1)); dx=0; dy=1
elif (( y > ey )); then
y=$ey; x=$((x-1)); dx=-1; dy=0
elif (( x < sx )); then
x=$sx; y=$((y-1)); dx=0; dy=-1
elif (( y < sy )); then
y=$sy; x=$((x+1)); dx=1; dy=0
fi
}
shrink_bounds() {
((sx++, sy++, ex--, ey--))
x=$sx; y=$sy
dx=1; dy=0
}
bounce_ball() {
while :; do
local co="${colors[ci]}"
draw_at "$co" "$by" "$bx" "●"
bx=$((bx + bdx))
by=$((by + bdy))
(( bx <= sx || bx >= ex )) && bdx=$((-bdx))
(( by <= sy || by >= ey )) && bdy=$((-bdy))
sleep 0.01
ci=$(( (ci+1) % m ))
done
}
while :; do
ch="${spinner[si]}"; si=$(( (si+1) % n ))
co="${colors[ci]}"; ci=$(( (ci+1) % m ))
draw_at "$co" "$y" "$x" "$ch"
x=$((x + dx))
y=$((y + dy))
next_spiral_dir
if (( x == sx && y == sy )); then
laps=$((laps + 1))
if (( laps == 5 )); then
bounce_ball
else
shrink_bounds
fi
fi
sleep 0.01
done
Doodle Screensaver
HEIGHT=$(tput lines)
WIDTH=$(tput cols)
while true; do
printf "\033[2J" # Clear the screen
for ((i = 0; i < $((HEIGHT - 1)); i++)); do
for ((j = 0; j < $((WIDTH - 1)); j++)); do
if ((RANDOM % 10 == 0)); then
printf "\033[%d;%dH" $i $j
printf "█"
fi
done
done
sleep 0.1
done
Matrix Screensaver (run once and stop)
tput setaf 2 setab 0 civis clear
xxd -p -c1 -l $(( $(tput cols)*$(tput lines) )) /dev/urandom \
| awk -v w=$(tput cols) '{printf "%d",strtonum("0x"$1)%2; if(++n%w==0)print""}'
tput cnorm
Matrix Screensaver (forever - random colors)
xxd -p -c1 /dev/urandom \
| awk -v cols="${COLUMNS:-$(tput cols)}" '
BEGIN {
split("32 36 92 96 37", C)
for (i=0;i<cols;i++) col[i]=C[int(rand()*length(C))+1]
}
{
b=strtonum("0x"$1)
cpos = n % cols
if (b % 8) printf " "
else printf "\033[%sm%c\033[0m", col[cpos], 48+(b%10)
if (++n%cols==0) print ""
}'
Matrix Screensaver (random color)
#!/bin/bash
# Get the terminal size
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
# Generate random binary digits
generate_binary() {
if ((RANDOM % 2 == 0)); then
echo -n "0"
else
echo -n "1"
fi
}
generate_color() {
RED=$((RANDOM % 256))
GREEN=$((RANDOM % 256))
BLUE=$((RANDOM % 256))
echo -ne "\033[38;2;${RED};${GREEN};${BLUE}m"
}
create_matrix_screensaver() {
while true; do
color=$(generate_color)
for ((row = 0; row < HEIGHT; row++)); do
for ((col = 0; col < WIDTH; col++)); do
binary=$(generate_binary)
echo -ne "$color$binary"
done
echo ""
done
sleep 0.1 # Adjust the sleep duration to control the speed
tput cup 0 0 # Move the cursor to the top-left corner of the screen
done
}
tput clear
tput civis
for ((i = 0; i < 10; i++)); do
create_matrix_screensaver
tput clear
done
tput cvvis
Full-Screen Colorized Block Matrix Screensaver
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
create_colorized_matrix_screensaver() {
while true; do
for ((row = 0; row < HEIGHT; row++)); do
for ((col = 0; col < WIDTH; col++)); do
color=$((RANDOM % 8 + 30))
echo -ne "\033[0;"$color"m\u2588"
done
echo ""
done
sleep 0.1 # Adjust the sleep duration to control the speed
tput cup 0 0 # Move the cursor to the top-left corner of the screen
done
}
tput clear
tput civis
create_colorized_matrix_screensaver
Falling Characters Matrix Screensaver
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
characters=("@" "#" "$" "%" "&" "*")
create_falling_characters_matrix_screensaver() {
while true; do
for ((col = 0; col < WIDTH; col++)); do
for ((row = 0; row < HEIGHT; row++)); do
character=${characters[$((RANDOM % ${#characters[@]}))]}
echo -ne "\033[$((row+1));$((col+1))H$character"
sleep 0.01
done
done
tput cup 0 0
sleep 0.5
tput clear
done
}
tput civis
create_falling_characters_matrix_screensaver
Expanding Square Rectangle Terminal Animation in Bash
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
create_expanding_matrix_screensaver() {
for ((radius = 0; radius < WIDTH || radius < HEIGHT; radius++)); do
for ((row = 0; row < HEIGHT; row++)); do
for ((col = 0; col < WIDTH; col++)); do
if ((col >= WIDTH/2 - radius && col <= WIDTH/2 + radius && row >= HEIGHT/2 - radius && row <= HEIGHT/2 + radius)); then
echo -ne "\u2588"
else
echo -ne " "
fi
done
echo ""
done
sleep 0.1
tput cup 0 0
done
}
tput clear
tput civis
create_expanding_matrix_screensaver
Random Block Matrix Screensaver
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
create_random_block_matrix_screensaver() {
while true; do
for ((row = 0; row < HEIGHT; row++)); do
for ((col = 0; col < WIDTH; col++)); do
if ((RANDOM % 2 == 0)); then
echo -ne "\u2588"
else
echo -ne " "
fi
done
echo ""
done
sleep 0.1
tput cup 0 0
done
}
tput clear
tput civis
create_random_block_matrix_screensaver
Create a visually twisted effect by alternating the direction of the "staples" effect vertically.
while :; do for ((i=0;i<$(tput cols);i++));do clear;for ((j=0;j<$(tput lines);j++));do printf \
"\e[48;5;$((RANDOM%256))m%*s\e[0m\n" $(((j+i)%2?$(tput cols)-i:i)) "";done;sleep 0.05;done;done
Wobbly line
while :; do
printf "\e[32m%*s\e[0m" $(tput cols) $(shuf -e {0..1} -n $(($(tput lines) * $(tput cols))));
sleep 0.1;
done
while true; do
printf "\e[32m%*s\e[0m" $(tput cols) $(shuf -e {0..1} -n $(tput cols))
sleep 0.1;
done
Color filler vertically
while :; do
for ((i = 0; i < $(tput cols); i++)); do clear;
for ((j = 0; j < $(tput lines); j++)); do
printf "\e[48;5;$((RANDOM % 256))m%*s\e[0m\n" $i "";
done;
sleep 0.05;
done;
done
Binary screensaver
#!/bin/bash
rows=$(tput lines)
cols=$(tput cols)
while true; do
clear
for ((i = 0; i < rows; i++)); do
tput cup $i $((RANDOM % cols))
printf "%01d" $((RANDOM % 2))
done
sleep 0.05
done
Retro screensaver
color_codes=("31" "32" "33" "34" "35" "36")
while true; do
clear
for ((i = 0; i < $(tput lines); i++)); do
tput cup $i $((RANDOM % $(tput cols)))
color=${color_codes[$((RANDOM % ${#color_codes[@]}))]}
printf "\033[${color}m#\033[0m"
done
sleep 0.1
done
Starfield screensaver
#!/bin/bash
rows=$(tput lines)
cols=$(tput cols)
while true; do
clear
for ((i = 0; i < rows; i++)); do
tput cup $i $((RANDOM % cols))
printf "*"
done
sleep 0.05
done
Digital clock screensaver
#!/bin/bash
rows=$(tput lines)
cols=$(tput cols)
while true; do
clear
tput cup $((rows / 2)) $((cols / 2 - 8))
printf "%(%H:%M:%S)T"
sleep 1
done
Snake Screensaver
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
snake_x=$((WIDTH / 2))
snake_y=$((HEIGHT / 2))
dx=1
dy=0
create_snake_matrix_screensaver() {
while true; do
tput cup $snake_y $snake_x
echo -ne "\u2588" # Print the snake character
snake_x=$((snake_x + dx))
snake_y=$((snake_y + dy))
if ((snake_x <= 0 || snake_x >= WIDTH - 1 || snake_y <= 0 || snake_y >= HEIGHT - 1)); then
snake_x=$((WIDTH / 2))
snake_y=$((HEIGHT / 2))
fi
sleep 0.1
tput clear
done
}
tput civis
create_snake_matrix_screensaver
Snake Screensaver v2
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
snake_x=0
snake_y=$((HEIGHT - 1))
dx=1
create_snake_screensaver() {
while true; do
tput clear
tput cup $snake_y $snake_x
echo -ne "---->"
snake_x=$((snake_x + dx))
# Check for wall collisions
if ((snake_x >= WIDTH - 5)); then
snake_x=0
fi
sleep 0.1
done
}
tput civis
create_snake_screensaver
Fish Screensaver
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
fish_x=$((WIDTH / 2))
fish_y=$((HEIGHT / 2))
dx=1
dy=1
fish_layouts=("><(((°>" "<°)))><" "><(((°>")
num_layouts=${#fish_layouts[@]}
create_fish_screensaver() {
while true; do
# Clear the screen
tput clear
layout_index=$((fish_x % num_layouts))
fish_layout=${fish_layouts[$layout_index]}
tput cup $fish_y $fish_x
echo -e "$fish_layout"
fish_x=$((fish_x + dx))
fish_y=$((fish_y + dy))
if ((fish_x >= WIDTH - 8)); then
dx=-1
elif ((fish_x <= 0)); then
dx=1
fi
if ((fish_y >= HEIGHT - 1)); then
dy=-1
elif ((fish_y <= 0)); then
dy=1
fi
sleep 0.1
done
}
tput civis
create_fish_screensaver
Shark hunting and eating fish
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
fish_x=$((WIDTH / 2))
fish_y=$((HEIGHT / 2))
dx=1
dy=0
shark_x=$((WIDTH / 2 - 10))
shark_y=$((HEIGHT / 2))
shark_dx=1
shark_dy=0
create_fish_screensaver() {
while true; do
tput clear
tput cup $fish_y $fish_x
echo -e "><(((°>"
tput cup $shark_y $shark_x
echo -e "▄▄▄▄▄▄▄▄▄▄▄▄▄▄"
fish_x=$((fish_x + dx))
fish_y=$((fish_y + dy))
if ((fish_x > shark_x)); then
shark_dx=1
elif ((fish_x < shark_x)); then
shark_dx=-1
else
shark_dx=0
fi
if ((fish_y > shark_y)); then
shark_dy=1
elif ((fish_y < shark_y)); then
shark_dy=-1
else
shark_dy=0
fi
shark_x=$((shark_x + shark_dx))
shark_y=$((shark_y + shark_dy))
sleep 0.1
done
}
tput civis
create_fish_screensaver
Shark hunting fish 2, multiple fishes
#!/bin/bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
fish_count=5
declare -a fish_x
declare -a fish_y
declare -a fish_dx
declare -a fish_dy
for ((i = 0; i < fish_count; i++)); do
fish_x[$i]=$((RANDOM % (WIDTH - 9) + 1))
fish_y[$i]=$((RANDOM % (HEIGHT - 1) + 1))
fish_dx[$i]=$((RANDOM % 2 * 2 - 1))
fish_dy[$i]=$((RANDOM % 2 * 2 - 1))
done
shark_x=$((WIDTH / 2 - 20))
shark_y=$((HEIGHT / 2))
shark_dx=1
shark_dy=0
create_fish_screensaver() {
while true; do
# Clear the screen
tput clear
# Print the fish
for ((i = 0; i < fish_count; i++)); do
tput cup ${fish_y[$i]} ${fish_x[$i]}
echo -e "><(((°>"
done
tput cup $shark_y $shark_x
echo -e "▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄"
tput cup $((shark_y + 1)) $shark_x
echo -e "▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀"
for ((i = 0; i < fish_count; i++)); do
fish_x[$i]=$((fish_x[$i] + fish_dx[$i]))
fish_y[$i]=$((fish_y[$i] + fish_dy[$i]))
if ((fish_x[$i] >= WIDTH - 9)) || ((fish_x[$i] <= 0)); then
fish_dx[$i]=$((fish_dx[$i] * -1))
fi
if ((fish_y[$i] >= HEIGHT - 1)) || ((fish_y[$i] <= 0)); then
fish_dy[$i]=$((fish_dy[$i] * -1))
fi
done
shark_x=$((shark_x + shark_dx))
shark_y=$((shark_y + shark_dy))
if ((shark_x >= WIDTH - 10)) || ((shark_x <= 0)); then
shark_dx=$((shark_dx * -1))
fi
if ((shark_y >= HEIGHT - 2)) || ((shark_y <= 0)); then
shark_dy=$((shark_dy * -1))
fi
sleep 0.1
done
}
tput civis
create_fish_screensaver
Fishes swim around the boat
#!/bin/bash
# Get the terminal size
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
# Initialize the fish positions and directions
fish_count=5
declare -a fish_x
declare -a fish_y
declare -a fish_dx
declare -a fish_dy
for ((i = 0; i < fish_count; i++)); do
fish_x[$i]=$((RANDOM % (WIDTH - 9) + 1))
fish_y[$i]=$((RANDOM % (HEIGHT - 1) + 1))
fish_dx[$i]=$((RANDOM % 2 * 2 - 1))
fish_dy[$i]=$((RANDOM % 2 * 2 - 1))
done
# Initialize the boat position and direction
boat_x=$((WIDTH / 2 - 15))
boat_y=$((HEIGHT / 2))
boat_dx=1
boat_dy=0
create_fish_screensaver() {
while true; do
# Clear the screen
tput clear
# Print the fish
for ((i = 0; i < fish_count; i++)); do
tput cup ${fish_y[$i]} ${fish_x[$i]}
echo -e "><(((°>"
done
# Print the boat
tput cup $boat_y $boat_x
echo " ____"
tput cup $((boat_y + 1)) $boat_x
echo " ---|"
tput cup $((boat_y + 2)) $boat_x
echo " \/ /| \/"
tput cup $((boat_y + 3)) $boat_x
echo " / |\\"
tput cup $((boat_y + 4)) $boat_x
echo " / | \\ \/"
tput cup $((boat_y + 5)) $boat_x
echo " / || \\"
tput cup $((boat_y + 6)) $boat_x
echo " / | | \\"
tput cup $((boat_y + 7)) $boat_x
echo " / | | \\"
tput cup $((boat_y + 8)) $boat_x
echo " / | | \\"
tput cup $((boat_y + 9)) $boat_x
echo " / || \\"
tput cup $((boat_y + 10)) $boat_x
echo " / / \\"
tput cup $((boat_y + 11)) $boat_x
echo " /________/ \\"
tput cup $((boat_y + 12)) $boat_x
echo " ________/__________--/"
tput cup $((boat_y + 13)) $boat_x
echo " ~~~ \___________________/"
tput cup $((boat_y + 14)) $boat_x
echo " ~~~~~~~~~~ ~~~~~~~~"
tput cup $((boat_y + 15)) $boat_x
echo "~~~~~~~~~~~~~ ~~~~~~~~~"
tput cup $((boat_y + 16)) $boat_x
echo " ~~~~~~~~~"
for ((i = 0; i < fish_count; i++)); do
fish_x[$i]=$((fish_x[$i] + fish_dx[$i]))
fish_y[$i]=$((fish_y[$i] + fish_dy[$i]))
if ((fish_x[$i] >= WIDTH - 9)) || ((fish_x[$i] <= 0)); then
fish_dx[$i]=$((fish_dx[$i] * -1))
fi
if ((fish_y[$i] >= HEIGHT - 1)) || ((fish_y[$i] <= 0)); then
fish_dy[$i]=$((fish_dy[$i] * -1))
fi
done
boat_x=$((boat_x + boat_dx))
boat_y=$((boat_y + boat_dy))
if ((boat_x >= WIDTH - 34)) || ((boat_x <= 0)); then
boat_dx=$((boat_dx * -1))
fi
if ((boat_y >= HEIGHT - 17)) || ((boat_y <= 0)); then
boat_dy=$((boat_dy * -1))
fi
sleep 0.1
done
}
tput civis
create_fish_screensaver
Boat + Airplane
# Get the terminal size
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
# Initialize the fish positions and directions
fish_count=5
declare -a fish_x
declare -a fish_y
declare -a fish_dx
declare -a fish_dy
for ((i = 0; i < fish_count; i++)); do
fish_x[$i]=$((RANDOM % (WIDTH - 9) + 1))
fish_y[$i]=$((RANDOM % (HEIGHT - 1) + 1))
fish_dx[$i]=$((RANDOM % 2 * 2 - 1))
fish_dy[$i]=$((RANDOM % 2 * 2 - 1))
done
# Initialize the boat position and direction
boat_x=$((WIDTH / 2 - 15))
boat_y=$((HEIGHT / 2))
boat_dx=1
boat_dy=0
# Initialize the airplane position and direction
airplane_x=0
airplane_y=$((HEIGHT / 4))
airplane_dx=1
airplane_dy=0
# Create the fish screensaver
create_fish_screensaver() {
while true; do
# Clear the screen
tput clear
# Print the fish
for ((i = 0; i < fish_count; i++)); do
tput cup ${fish_y[$i]} ${fish_x[$i]}
echo -e "><(((°>"
done
# Print the boat
tput cup $boat_y $boat_x
echo " ____"
tput cup $((boat_y + 1)) $boat_x
echo " ---|"
tput cup $((boat_y + 2)) $boat_x
echo " \/ /| \/"
tput cup $((boat_y + 3)) $boat_x
echo " / |\\"
tput cup $((boat_y + 4)) $boat_x
echo " / | \\ \/"
tput cup $((boat_y + 5)) $boat_x
echo " / || \\"
tput cup $((boat_y + 6)) $boat_x
echo " / | | \\"
tput cup $((boat_y + 7)) $boat_x
echo " / | | \\"
tput cup $((boat_y + 8)) $boat_x
echo " / | | \\"
tput cup $((boat_y + 9)) $boat_x
echo " / || \\"
tput cup $((boat_y + 10)) $boat_x
echo " / / \\"
tput cup $((boat_y + 11)) $boat_x
echo " /________/ \\"
tput cup $((boat_y + 12)) $boat_x
echo " ________/__________--/"
tput cup $((boat_y + 13)) $boat_x
echo " ~~~ \___________________/"
tput cup $((boat_y + 14)) $boat_x
echo " ~~~~~~~~~~ ~~~~~~~~"
tput cup $((boat_y + 15)) $boat_x
echo "~~~~~~~~~~~~~ ~~~~~~~~~"
tput cup $((boat_y + 16)) $boat_x
echo " ~~~~~~~~~"
# Print the airplane
tput cup $airplane_y $airplane_x
echo " ______"
tput cup $((airplane_y + 1)) $airplane_x
echo " _\\ _~-\___"
tput cup $((airplane_y + 2)) $airplane_x
echo " = = ==(__WUSEMAN__D"
tput cup $((airplane_y + 3)) $airplane_x
echo " \\_____\___________________,-~~~~~~~\`-.._"
tput cup $((airplane_y + 4)) $airplane_x
echo " / o O o o o o O O o o o o o o O o |\_"
tput cup $((airplane_y + 5)) $airplane_x
echo " \`~-.__ ___..----.. )"
tput cup $((airplane_y + 6)) $airplane_x
echo " \`---~~\\___________/------------\`\`\`\`"
tput cup $((airplane_y + 7)) $airplane_x
echo " = ===(_________D"
# Move the fish
for ((i = 0; i < fish_count; i++)); do
fish_x[$i]=$((fish_x[$i] + fish_dx[$i]))
fish_y[$i]=$((fish_y[$i] + fish_dy[$i]))
if ((fish_x[$i] >= WIDTH - 9)) || ((fish_x[$i] <= 0)); then
fish_dx[$i]=$((fish_dx[$i] * -1))
fi
if ((fish_y[$i] >= HEIGHT - 1)) || ((fish_y[$i] <= 0)); then
fish_dy[$i]=$((fish_dy[$i] * -1))
fi
done
# Move the boat
boat_x=$((boat_x + boat_dx))
boat_y=$((boat_y + boat_dy))
if ((boat_x >= WIDTH - 34)) || ((boat_x <= 0)); then
boat_dx=$((boat_dx * -1))
fi
if ((boat_y >= HEIGHT - 17)) || ((boat_y <= 0)); then
boat_dy=$((boat_dy * -1))
fi
# Move the airplane
airplane_x=$((airplane_x + airplane_dx))
airplane_y=$((airplane_y + airplane_dy))
if ((airplane_x >= WIDTH - 23)) || ((airplane_x <= 0)); then
airplane_dx=$((airplane_dx * -1))
fi
if ((airplane_y >= HEIGHT / 2 - 7)) || ((airplane_y <= 0)); then
airplane_dy=$((airplane_dy * -1))
fi
sleep 0.1 # Adjust the sleep duration to control the speed
done
}
# Hide the cursor
tput civis
# Create the fish screensaver
create_fish_screensaver
Bouncing dvd logo screensaving using tput and bash
set -u
cleanup(){ tput cnorm; tput sgr0; clear; }
trap cleanup EXIT INT TERM
tput civis
clear
logo="DVD"
dx=1; dy=1
x=0; y=0
while :; do
W=$(tput cols)
H=$(tput lines)
# erase previous
tput cup "$y" "$x"; printf "%*s" "${#logo}" ""
x=$((x + dx))
y=$((y + dy))
(( x <= 0 )) && dx=1
(( y <= 0 )) && dy=1
(( x >= W - ${#logo} )) && dx=-1
(( y >= H - 1 )) && dy=-1
tput cup "$y" "$x"
tput setaf $((RANDOM % 7 + 1))
printf "%s" "$logo"
tput sgr0
sleep 0.03
done
ANSI color spiral screensaver in bash
#!/usr/bin/env bash
WIDTH=$(tput cols)
HEIGHT=$(tput lines)
characters=('@' '#' '$' '%' '&' '*')
cleanup(){ tput cnorm; tput sgr0; clear; }
trap cleanup INT TERM EXIT
tput civis
tput clear
while :; do
top=0; left=0; bottom=$((HEIGHT-1)); right=$((WIDTH-1))
while (( top <= bottom && left <= right )); do
# top row: left -> right
for ((c=left; c<=right; c++)); do
ch=${characters[RANDOM % ${#characters[@]}]}
color=$((RANDOM % 256))
printf '\033[%d;%dH\033[38;5;%dm%s\033[0m' \
$((top+1)) $((c+1)) "$color" "$ch"
sleep 0.001
done
((top++))
# right col: top -> bottom
for ((r=top; r<=bottom; r++)); do
ch=${characters[RANDOM % ${#characters[@]}]}
color=$((RANDOM % 256))
printf '\033[%d;%dH\033[38;5;%dm%s\033[0m' \
$((r+1)) $((right+1)) "$color" "$ch"
sleep 0.001
done
((right--))
# bottom row: right -> left
if (( top <= bottom )); then
for ((c=right; c>=left; c--)); do
ch=${characters[RANDOM % ${#characters[@]}]}
color=$((RANDOM % 256))
printf '\033[%d;%dH\033[38;5;%dm%s\033[0m' \
$((bottom+1)) $((c+1)) "$color" "$ch"
sleep 0.001
done
((bottom--))
fi
# left col: bottom -> top
if (( left <= right )); then
for ((r=bottom; r>=top; r--)); do
ch=${characters[RANDOM % ${#characters[@]}]}
color=$((RANDOM % 256))
printf '\033[%d;%dH\033[38;5;%dm%s\033[0m' \
$((r+1)) $((left+1)) "$color" "$ch"
sleep 0.001
done
((left++))
fi
done
# start over (optional)
sleep 0.2
tput cup 0 0
done
Animated Terminal Aquarium with Submarine, Fish, UFO, and Particle Effects
cleanup() { tput cnorm; tput sgr0; clear; }
trap cleanup EXIT INT TERM
tput civis
tput sgr0
clear
# ---------- helpers ----------
rand_color() {
# bright-ish ANSI colors
local colors=(31 32 33 34 35 36 91 92 93 94 95 96 97)
printf "\033[%sm" "${colors[RANDOM % ${#colors[@]}]}"
}
draw_art() {
# draw multi-line art at (y,x)
local y="$1" x="$2"; shift 2
local i=0
for line in "$@"; do
tput cup $((y+i)) "$x"
printf "%s" "$line"
((i++))
done
}
clamp() { # clamp val min max
local v="$1" lo="$2" hi="$3"
(( v < lo )) && v="$lo"
(( v > hi )) && v="$hi"
printf "%s" "$v"
}
# ---------- terminal size ----------
W=$(tput cols)
H=$(tput lines)
# ---------- entities ----------
fish_count=9
declare -a fx fy fdx
# fish glyphs (right/left)
fish_r=("><(((°>" "><>" ">))'>" ">°)))>" ">===>")
fish_l=("<°)))><" "<><" "<'((<" "<)))°<" "<===<")
for ((i=0; i<fish_count; i++)); do
fx[$i]=$((RANDOM % (W-12) + 1))
fy[$i]=$((RANDOM % (H-6) + 3))
fdx[$i]=$(( (RANDOM % 2) ? 1 : -1 ))
done
# submarine
sub_x=$((W/3))
sub_y=$((H*2/3))
sub_dx=1
sub_w=24
sub_h=4
# ufo
ufo_x=$((W/2))
ufo_y=$((H/6))
ufo_dx=-1
ufo_w=19
ufo_h=3
beam_on=1
# bubbles (particle system)
bubble_max=40
declare -a bx by bdy bch bactive
for ((i=0;i<bubble_max;i++)); do bactive[$i]=0; done
spawn_bubble() {
for ((i=0;i<bubble_max;i++)); do
if (( bactive[$i] == 0 )); then
bactive[$i]=1
bx[$i]="$1"
by[$i]="$2"
bdy[$i]=$(( (RANDOM % 2) + 1 ))
local chars=( "o" "°" "." "•" )
bch[$i]="${chars[RANDOM % ${#chars[@]}]}"
return
fi
done
}
# lightning timer
flash=0
flash_t=$((RANDOM % 120 + 80))
# ---------- art ----------
# keep lines same widths (avoid terminal jitter)
sub_lines=(
" |\\"
" _______|_\\______"
"| __ __ __ _\\__"
"\\__(_)__(_)__(_)____/"
)
ufo_lines=(
" _.-^-._"
" .-' ___ '-."
"(_.-' '-._)"
)
# waves: animate by phase (two patterns)
wave1="~ ~~ ~~~~ ~~ ~ ~~~ ~~~~ ~~ ~ "
wave2=" ~~ ~~~~ ~~ ~ ~~ ~~~~ ~~ ~ ~~"
# ---------- main loop ----------
while :; do
# refresh size for resize
W=$(tput cols); H=$(tput lines)
# background ocean + sky split
sky_h=$((H/3))
sea_top=$((sky_h))
sea_h=$((H - sea_top))
# lightning flash logic
((flash_t--))
if (( flash_t <= 0 )); then
flash=1
flash_t=$((RANDOM % 160 + 120))
else
flash=0
fi
# clear frame
tput cup 0 0
if (( flash )); then
printf "\033[47m\033[30m" # white bg, black fg
else
printf "\033[0m"
fi
tput clear
# draw stars in sky
for ((s=0; s< (W/10); s++)); do
tput cup $((RANDOM % (sky_h>1?sky_h:1))) $((RANDOM % W))
printf "%s" "*"
done
# waves (two moving lines)
phase=$((RANDOM % 2))
tput sgr0
tput setaf 36
tput cup "$sea_top" 0
printf "%.*s" "$W" "$wave1$wave2$wave1$wave2"
tput cup $((sea_top+1)) 0
printf "%.*s" "$W" "$wave2$wave1$wave2$wave1"
tput sgr0
# submarine (colored)
sub_y=$(clamp "$sub_y" $((sea_top+2)) $((H-sub_h-2)))
sub_x=$(clamp "$sub_x" 1 $((W-sub_w-2)))
tput sgr0
tput setaf 33
draw_art "$sub_y" "$sub_x" "${sub_lines[@]}"
tput sgr0
# bubbles near sub (spawn a few each frame)
if (( RANDOM % 2 == 0 )); then
spawn_bubble $((sub_x + 8 + (RANDOM%6))) $((sub_y + 0))
fi
if (( RANDOM % 4 == 0 )); then
spawn_bubble $((sub_x + 14 + (RANDOM%6))) $((sub_y + 1))
fi
# fish school
for ((i=0; i<fish_count; i++)); do
# pick fish glyph based on direction
idx=$((RANDOM % ${#fish_r[@]}))
if (( fdx[$i] > 0 )); then
glyph="${fish_r[$idx]}"
else
glyph="${fish_l[$idx]}"
fi
# keep fish in sea
(( fy[$i] < sea_top+2 )) && fy[$i]=$((sea_top+2))
(( fy[$i] > H-2 )) && fy[$i]=$((H-2))
(( fx[$i] < 0 )) && fx[$i]=0
(( fx[$i] > W-10 )) && fx[$i]=$((W-10))
tput cup "${fy[$i]}" "${fx[$i]}"
rand_color
printf "%s\033[0m" "$glyph"
# move fish
fx[$i]=$((fx[$i] + fdx[$i] * ( (RANDOM%2) + 1 )))
# little vertical drift
(( RANDOM % 6 == 0 )) && fy[$i]=$((fy[$i] + (RANDOM%3 - 1)))
# bounce edges
if (( fx[$i] >= W-10 )); then fdx[$i]=-1; fi
if (( fx[$i] <= 0 )); then fdx[$i]=1; fi
done
# UFO in sky with beam
ufo_x=$((ufo_x + ufo_dx))
if (( ufo_x <= 0 )); then ufo_dx=1; fi
if (( ufo_x >= W-ufo_w )); then ufo_dx=-1; fi
ufo_y=$(clamp "$ufo_y" 1 $((sky_h-3)))
# toggle beam sometimes
(( RANDOM % 25 == 0 )) && beam_on=$((1-beam_on))
tput sgr0
tput setaf 35
draw_art "$ufo_y" "$ufo_x" "${ufo_lines[@]}"
tput sgr0
if (( beam_on )); then
tput setaf 96
# beam down into sea top
for ((yy=ufo_y+3; yy<sea_top; yy++)); do
tput cup "$yy" $((ufo_x + 8))
printf "|"
done
tput sgr0
fi
# animate bubbles
for ((i=0;i<bubble_max;i++)); do
(( bactive[$i] == 0 )) && continue
# draw bubble
if (( by[$i] > 1 )); then
tput cup "${by[$i]}" "${bx[$i]}"
tput setaf 97
printf "%s" "${bch[$i]}"
tput sgr0
fi
# move bubble up with slight horizontal drift
by[$i]=$((by[$i] - bdy[$i]))
(( RANDOM % 5 == 0 )) && bx[$i]=$((bx[$i] + (RANDOM%3 - 1)))
# deactivate if out of screen or into sky
if (( by[$i] <= sea_top+1 || bx[$i] < 0 || bx[$i] >= W )); then
bactive[$i]=0
fi
done
# move submarine
sub_x=$((sub_x + sub_dx))
if (( sub_x <= 1 )); then sub_dx=1; fi
if (( sub_x >= W-sub_w-2 )); then sub_dx=-1; fi
# subtle bobbing
(( RANDOM % 10 == 0 )) && sub_y=$((sub_y + (RANDOM%3 - 1)))
# footer hint (optional)
tput cup $((H-1)) 0
tput sgr0
printf "AQUARIUM RAID | Ctrl+C to exit "
sleep 0.06
done
Colorful Bouncing “W” Screensaver with Bounce Counter in Bash
ROWS=$(tput lines)
COLS=$(tput cols)
tput civis
trap "tput cnorm; exit" SIGINT
symbols=("@" "#" "%" "&" "*" "+" "-" "=" "!" "?" "/" "\\" "|" "(" ")" "[" "]" "{" "}" "<" ">" "^" "~" "," "." ":" ";" " ")
function random_color() {
local color_code="\e["
local colors=("31m" "32m" "33m" "34m" "35m" "36m" "91m" "92m" "93m" "94m" "95m" "96m")
echo -n "${color_code}${colors[$((RANDOM % ${#colors[@]}))]}"
}
function get_w_char() {
local col=$1
local middle_col=$((COLS / 2))
local symbol=${symbols[$((RANDOM % ${#symbols[@]}))]}
local color_code=${color_codes[$color_index]}
if [ $col -eq 0 ] || [ $col -eq $((COLS - 1)) ]; then
echo -ne "\e[0m${symbol}"
elif [ $col -lt $middle_col ] && [ $col -gt 0 ]; then
local distance=$((middle_col - col))
if [ $((distance % 2)) -eq 0 ]; then
echo -ne "${color_code}${symbol}"
else
echo -ne "${color_code}${symbol}"
fi
elif [ $col -eq $middle_col ]; then
echo -ne "${color_code}${symbol}"
else
local distance=$((col - middle_col))
if [ $((distance % 2)) -eq 0 ]; then
echo -ne "${color_code}${symbol}"
else
echo -ne "${color_code}${symbol}"
fi
fi
}
function display_bounce_counter() {
local counter=$1
local message="Bounces: $counter"
local message_length=${#message}
local center_row=$((ROWS / 2))
local center_col=$((COLS / 2 - message_length / 2))
tput cup $center_row $center_col
echo -n "$message"
}
function clear_screen() {
tput reset
}
function move_cursor() {
local row=$1
local col=$2
tput cup $row $col
}
function screensaver() {
local x=0
local y=0
local direction_x=1
local direction_y=1
local bounce_counter=0
local stop_x=$((COLS / 2))
local stop_y=$((ROWS / 2))
local color_codes=()
local color_index=0
local sleep_duration=0.03
local direction_change_timer=0
local max_direction_change_time=20
while true; do
color_codes+=($(random_color))
move_cursor $y $x
echo -n "$(get_w_char $x)"
sleep $sleep_duration
x=$((x + direction_x))
y=$((y + direction_y))
if [ $x -eq $stop_x ] && [ $y -eq $stop_y ]; then
sleep 0.2
direction_x=$((direction_x * -1))
direction_y=$((direction_y * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
((direction_change_timer++))
if [ $direction_change_timer -ge $max_direction_change_time ]; then
direction_x=$((RANDOM % 3 - 1))
direction_y=$((RANDOM % 3 - 1))
direction_change_timer=0
fi
fi
if [ $x -ge $((COLS - 1)) ] || [ $x -le 0 ]; then
direction_x=$((direction_x * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
fi
if [ $y -ge $((ROWS - 1)) ] || [ $y -le 0 ]; then
direction_y=$((direction_y * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
fi
if [ $color_index -ge ${#color_codes[@]} ]; then
color_index=0
fi
done
}
screensaver
Expanding Rainbow Circle Effect Inside a Unicode Box (Bash + tput)
columns=$(tput cols)
lines=$(tput lines)
clear_screen() {
tput clear
}
draw_box() {
local top_left_corner="┌"
local top_right_corner="┐"
local bottom_left_corner="└"
local bottom_right_corner="┘"
local horizontal_line="─"
local vertical_line="│"
local start_x=3
local start_y=3
local end_x=$((columns - 1))
local end_y=$((lines - 1))
tput cup $start_y $start_x
echo -n "$top_left_corner"
tput cup $start_y $end_x
echo -n "$top_right_corner"
tput cup $end_y $start_x
echo -n "$bottom_left_corner"
tput cup $end_y $end_x
echo -n "$bottom_right_corner"
for ((i = $((start_x + 1)); i < end_x; i++)); do
tput cup $start_y $i
echo -n "$horizontal_line"
tput cup $end_y $i
echo -n "$horizontal_line"
done
for ((i = $((start_y + 1)); i < end_y; i++)); do
tput cup $i $start_x
echo -n "$vertical_line"
tput cup $i $end_x
echo -n "$vertical_line"
done
}
generate_effect() {
local colors=("31" "32" "33" "34" "35" "36" "37")
local num_colors=${#colors[@]}
local cx=$((columns / 2))
local cy=$((lines / 2))
local r=1
local symbol="●"
local color_index=0
while true; do
local color=${colors[$color_index]}
color_index=$(((color_index + 1) % num_colors))
local x=0
local y=$r
local d=$((5 - 4 * r))
while ((x <= y)); do
tput cup $((cy - y)) $((cx + x))
printf "\033[${color}m${symbol}\033[0m"
tput cup $((cy - x)) $((cx + y))
printf "\033[${color}m${symbol}\033[0m"
tput cup $((cy - x)) $((cx - y))
printf "\033[${color}m${symbol}\033[0m"
tput cup $((cy - y)) $((cx - x))
printf "\033[${color}m${symbol}\033[0m"
tput cup $((cy + y)) $((cx - x))
printf "\033[${color}m${symbol}\033[0m"
tput cup $((cy + x)) $((cx - y))
printf "\033[${color}m${symbol}\033[0m"
tput cup $((cy + x)) $((cx + y))
printf "\033[${color}m${symbol}\033[0m"
tput cup $((cy + y)) $((cx + x))
printf "\033[${color}m${symbol}\033[0m"
if ((d >= 0)); then
d=$((d + 8 * (x - y) + 12))
y=$((y - 1))
else
d=$((d + 8 * x + 8))
fi
x=$((x + 1))
done
sleep 0.1
r=$((r + 1))
if ((cx - r <= 0 || cx + r >= columns || cy - r <= 0 || cy + r >= lines)); then
break
fi
done
}
while true; do
clear_screen
draw_box
generate_effect
done
Rainbow Spiral Rectangle Walker Animation (Bash ANSI Cursor Drawing)
clear_screen() {
printf "\033[2J"
}
generate_effect() {
local colors=("31" "32" "33" "34" "35" "36" "37")
local num_colors=${#colors[@]}
local x=$(tput cols)/2
local y=$(tput lines)/2
local dx=1 dy=0 step=1 color_index=0 symbol="●"
while :; do
local color=${colors[color_index]}
color_index=$(( (color_index + 1) % num_colors ))
printf "\033[${color}m\033[${y};${x}H${symbol}\033[0m"
x=$((x + dx))
y=$((y + dy))
if ((x <= 0 || x >= $(tput cols) || y <= 0 || y >= $(tput lines))); then
break
fi
sleep 0.01
((step_count++))
if ((step_count == step)); then
step_count=0
case "$dx $dy" in
"1 0") dx=0; dy=1 ;;
"0 1") dx=-1; dy=0; ((step++)) ;;
"-1 0") dx=0; dy=-1 ;;
"0 -1") dx=1; dy=0; ((step++)) ;;
esac
fi
done
}
while :; do
clear_screen
generate_effect
done
Rainbow Spinner Border Animation That Collapses Inward, Then Switches to a Bouncing Ball
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to generate a spinner effect with changing colors
generate_effect() {
local spinner=("◐" "◓" "◑" "◒" "⣾" "⣽" "⣻" "⢿" "⡿" "⣟" "⣯" "⣷") # Characters for the spinner
local colors=("31" "32" "33" "34" "35" "36" "37") # ANSI escape codes for text colors
local num_spinner=${#spinner[@]} # Number of characters in the spinner
local num_colors=${#colors[@]} # Number of colors
local start_x=0
local start_y=0
local end_x=$((columns - 1))
local end_y=$((lines - 1))
local x=$start_x
local y=$start_y
local dx=1
local dy=0
local spinner_index=0
local color_index=0
local corner_count=0
local ball_x=$((columns / 2))
local ball_y=$((lines / 2))
local ball_dx=-1
local ball_dy=-1
while true
do
# Get the current character from the spinner
local char=${spinner[$spinner_index]}
spinner_index=$(( (spinner_index + 1) % num_spinner ))
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Print the colored character at the current position
printf "\033[${color}m\033[${y};${x}H${char}\033[0m"
# Update position
x=$((x + dx))
y=$((y + dy))
# Check for reaching the end of each side and adjust direction accordingly
if ((x > end_x))
then
x=$end_x
y=$((y + 1))
dx=0
dy=1
elif ((y > end_y))
then
x=$((x - 1))
y=$end_y
dx=-1
dy=0
elif ((x < start_x))
then
x=$start_x
y=$((y - 1))
dx=0
dy=-1
elif ((y < start_y))
then
x=$((x + 1))
y=$start_y
dx=1
dy=0
fi
# Check for completing the full circle
if ((x == start_x && y == start_y))
then
corner_count=$((corner_count + 1))
if ((corner_count == 5))
then
while true
do
# Print the colored ball at the current position
printf "\033[${color}m\033[${ball_y};${ball_x}H●\033[0m"
# Update ball position
ball_x=$((ball_x + ball_dx))
ball_y=$((ball_y + ball_dy))
# Check for bouncing off the walls
if ((ball_x <= start_x || ball_x >= end_x))
then
ball_dx=$((ball_dx * -1))
fi
if ((ball_y <= start_y || ball_y >= end_y))
then
ball_dy=$((ball_dy * -1))
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
else
start_x=$((start_x + 1))
start_y=$((start_y + 1))
end_x=$((end_x - 1))
end_y=$((end_y - 1))
x=$((start_x))
y=$((start_y))
fi
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
}
# Main loop
while true
do
clear_screen
generate_effect
done
Multi-Effect Terminal Animation Suite (Spinner + Bouncing Ball + Pulsating Heart)
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to generate a rotating spinner effect with changing colors
generate_spinner_effect() {
local spinner=("◐" "◓" "◑" "◒") # Characters for the spinner
local colors=("31" "32" "33" "34" "35" "36" "37") # ANSI escape codes for text colors
local num_spinner=${#spinner[@]} # Number of characters in the spinner
local num_colors=${#colors[@]} # Number of colors
local x=$((columns / 2))
local y=$((lines / 2))
local spinner_index=0
local color_index=0
while true
do
# Get the current character from the spinner
local char=${spinner[$spinner_index]}
spinner_index=$(( (spinner_index + 1) % num_spinner ))
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Print the colored character at the current position
printf "\033[${color}m\033[${y};${x}H${char}\033[0m"
sleep 0.1 # Adjust the sleep duration to control the speed of the effect
done
}
# Function to generate a bouncing ball effect with a changing color
generate_bouncing_ball_effect() {
local ball=("●") # Character for the ball
local colors=("31" "32" "33" "34" "35" "36" "37") # ANSI escape codes for text colors
local num_colors=${#colors[@]} # Number of colors
local x=$((columns / 2))
local y=$((lines / 2))
local dx=1
local dy=1
local color_index=0
while true
do
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Print the colored ball at the current position
printf "\033[${color}m\033[${y};${x}H${ball}\033[0m"
# Update position
x=$((x + dx))
y=$((y + dy))
# Reverse direction if the ball reaches the edge of the screen
if ((x <= 0 || x >= columns))
then
dx=$((dx * -1))
fi
if ((y <= 0 || y >= lines))
then
dy=$((dy * -1))
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
}
# Function to generate a pulsating heart effect with changing colors
generate_pulsating_heart_effect() {
local heart=("❤") # Character for the heart
local colors=("31" "32" "33" "34" "35" "36" "37") # ANSI escape codes for text colors
local num_colors=${#colors[@]} # Number of colors
local x=$((columns / 2))
local y=$((lines / 2))
local scale=10
local color_index=0
while true
do
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Scale the heart based on the current scale value
local scaled_heart=""
for ((i = 0; i < scale; i++))
do
scaled_heart+=" $heart"
done
# Print the colored and scaled heart at the current position
printf "\033[${color}m\033[${y};${x}H${scaled_heart}\033[0m"
# Update the scale to create the pulsating effect
scale=$(( (scale + 1) % 20 + 1 ))
sleep 0.1 # Adjust the sleep duration to control the speed of the effect
done
}
# Main loop
while true
do
clear_screen
generate_spinner_effect &
spinner_pid=$!
generate_bouncing_ball_effect &
ball_pid=$!
generate_pulsating_heart_effect &
heart_pid=$!
# Wait for user input to stop the animations
read -n 1 -r
# Terminate the background processes
kill $spinner_pid $ball_pid $heart_pid
done
Framed Matrix Rain Hex Wall (Green Digits Inside a Terminal Border)
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Wall dimensions
wall_start_x=10
wall_start_y=5
wall_end_x=$((columns - 10))
wall_end_y=$((lines - 5))
# Array of characters for matrix rain
characters=("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F")
# Initialize an array to store the column position of each raindrop
declare -a drops
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to draw the wall
draw_wall() {
local x
local y
# Draw the top level of the wall
for ((x = wall_start_x; x <= wall_end_x; x++))
do
printf "\033[${wall_start_y};${x}H="
done
# Draw the bottom level of the wall
for ((x = wall_start_x; x <= wall_end_x; x++))
do
printf "\033[${wall_end_y};${x}H="
done
# Draw the left side of the wall
for ((y = wall_start_y + 1; y < wall_end_y; y++))
do
printf "\033[${y};${wall_start_x}H|"
done
# Draw the right side of the wall
for ((y = wall_start_y + 1; y < wall_end_y; y++))
do
printf "\033[${y};${wall_end_x}H|"
done
}
# Function to generate the matrix rain effect inside the wall
generate_effect() {
local num_drops=$(( (wall_end_x - wall_start_x) / 2 )) # Number of raindrops to generate
# Initialize the position of each raindrop randomly inside the wall
for ((i = 0; i < num_drops; i++))
do
drops[$i]=$(( (RANDOM % (wall_end_y - wall_start_y - 2)) + wall_start_y + 1 ))
done
while true
do
# Update the position of each raindrop and print it
for ((i = 0; i < num_drops; i++))
do
local x=$((i * 2 + wall_start_x + 1)) # Each raindrop occupies two columns inside the wall
# Print the raindrop in green color
printf "\033[32m\033[${drops[$i]};${x}H${characters[$((RANDOM % 16))]}"
# Update the position of the raindrop
drops[$i]=$((drops[$i] + 1))
# Reset the raindrop to the top if it reaches the bottom of the wall
if ((drops[$i] >= wall_end_y))
then
drops[$i]=$((wall_start_y + 1))
fi
done
sleep 0.05 # Adjust the sleep duration to control the speed of the effect
done
}
# Main loop
while true
do
clear_screen
draw_wall
generate_effect
done
Colored Shooting Stars Screensaver (Randomized ANSI Sparkle Trails)
# Clear the screen
clear
# Get the terminal size
rows=$(tput lines)
cols=$(tput cols)
# Define the shooting star characters and colors
SHOOTING_STAR_CHARACTERS=("✦" "✧" "✶" "✴" "✹" "✷")
SHOOTING_STAR_COLORS=("196" "202" "208" "214" "220" "226")
# Define the maximum number of shooting stars
MAX_SHOOTING_STARS=10
# Array to store the shooting stars
shooting_stars=()
# Function to generate a random number within a range
generate_random_number() {
min=$1
max=$2
echo $((RANDOM % (max - min + 1) + min))
}
# Function to generate a random shooting star
generate_random_shooting_star() {
row=$(generate_random_number 1 $rows)
col=$(generate_random_number 1 $cols)
speed=$(generate_random_number 5 10)
echo "$row:$col:$speed"
}
# Generate initial shooting stars
for ((i=0; i<MAX_SHOOTING_STARS; i++)); do
shooting_stars[$i]=$(generate_random_shooting_star)
done
# Function to update the shooting stars
update_shooting_stars() {
updated_stars=()
for star in "${shooting_stars[@]}"; do
IFS=':' read -ra star_info <<< "$star"
row="${star_info[0]}"
col="${star_info[1]}"
speed="${star_info[2]}"
tput cup "$row" "$col"
echo " "
new_row=$((row + speed))
new_col=$((col + (speed / 2)))
if ((new_row > rows)); then
updated_stars+=($(generate_random_shooting_star))
else
updated_stars+=("$new_row:$new_col:$speed")
fi
done
shooting_stars=("${updated_stars[@]}")
}
while true; do
update_shooting_stars
# Print the shooting stars
for star in "${shooting_stars[@]}"; do
IFS=':' read -ra star_info <<< "$star"
row="${star_info[0]}"
col="${star_info[1]}"
color="${SHOOTING_STAR_COLORS[$((RANDOM % ${#SHOOTING_STAR_COLORS[@]}))]}"
# Print the shooting star at its current position with the random color
tput setaf "$color"
tput cup "$row" "$col"
echo -ne "${SHOOTING_STAR_CHARACTERS[$((RANDOM % ${#SHOOTING_STAR_CHARACTERS[@]}))]}"
tput sgr0
done
# Delay between frames (adjust as needed for desired speed)
sleep 0.1
done
Simple Shooting Star Screensaver (Diagonal Starfall Animation)
#!/bin/bash
# Clear the screen
clear
# Get the terminal size
rows=$(tput lines)
cols=$(tput cols)
# Define the shooting star character
SHOOTING_STAR_CHARACTER="✦"
# Define the maximum number of shooting stars
MAX_SHOOTING_STARS=10
# Array to store the shooting stars
shooting_stars=()
# Function to generate a random number within a range
generate_random_number() {
min=$1
max=$2
echo $((RANDOM % (max - min + 1) + min))
}
# Function to generate a random shooting star
generate_random_shooting_star() {
row=$(generate_random_number 1 $rows)
col=$(generate_random_number 1 $cols)
speed=$(generate_random_number 5 10)
echo "$row:$col:$speed"
}
# Generate initial shooting stars
for ((i=0; i<MAX_SHOOTING_STARS; i++)); do
shooting_stars[$i]=$(generate_random_shooting_star)
done
# Function to update the shooting stars
update_shooting_stars() {
updated_stars=()
# Update each shooting star's position
for star in "${shooting_stars[@]}"; do
IFS=':' read -ra star_info <<< "$star"
row="${star_info[0]}"
col="${star_info[1]}"
speed="${star_info[2]}"
# Clear the previous shooting star position
tput cup "$row" "$col"
echo " "
# Calculate the new position for the shooting star
new_row=$((row + speed))
new_col=$((col + (speed / 2)))
# Check if the shooting star has reached the bottom of the screen
if ((new_row > rows)); then
# Regenerate a new shooting star
updated_stars+=($(generate_random_shooting_star))
else
# Add the updated shooting star position to the updated_stars array
updated_stars+=("$new_row:$new_col:$speed")
fi
done
# Update the shooting stars array with the new positions
shooting_stars=("${updated_stars[@]}")
}
# Main loop
while true; do
# Update the shooting stars
update_shooting_stars
# Print the shooting stars
for star in "${shooting_stars[@]}"; do
IFS=':' read -ra star_info <<< "$star"
row="${star_info[0]}"
col="${star_info[1]}"
# Print the shooting star at its current position
tput cup "$row" "$col"
echo -ne "$SHOOTING_STAR_CHARACTER"
done
# Delay between frames (adjust as needed for desired speed)
sleep 0.1
done
Random Starfield Drift Screensaver (Twinkling Unicode Stars)
#!/bin/bash
# Clear the screen
clear
# Get the terminal size
rows=$(tput lines)
cols=$(tput cols)
# Define the star characters
STAR_CHARACTERS=("✦" "✧" "★" "☆" "✶" "✷" "✸" "✹" "✺" "✻" "✼" "❉" "❋" "❂")
# Define the maximum number of stars
MAX_STARS=50
# Function to generate a random number within a range
generate_random_number() {
min=$1
max=$2
echo $((RANDOM % (max - min + 1) + min))
}
# Function to generate a random star
generate_random_star() {
row=$(generate_random_number 1 $rows)
col=$(generate_random_number 1 $cols)
character=${STAR_CHARACTERS[$((RANDOM % ${#STAR_CHARACTERS[@]}))]}
echo "$row:$col:$character"
}
# Array to store the stars
stars=()
# Generate initial stars
for ((i=0; i<MAX_STARS; i++)); do
stars[$i]=$(generate_random_star)
done
# Function to update the stars
update_stars() {
updated_stars=()
# Update each star's position
for star in "${stars[@]}"; do
IFS=':' read -ra star_info <<< "$star"
row="${star_info[0]}"
col="${star_info[1]}"
character="${star_info[2]}"
# Clear the previous star position
tput cup "$row" "$col"
echo " "
# Generate new position for the star
new_row=$((row + $(generate_random_number -1 1)))
new_col=$((col + $(generate_random_number -1 1)))
# Wrap the star around if it goes beyond the terminal boundaries
if ((new_row > rows)); then
new_row=1
elif ((new_row < 1)); then
new_row=$rows
fi
if ((new_col > cols)); then
new_col=1
elif ((new_col < 1)); then
new_col=$cols
fi
# Add the updated star position to the updated_stars array
updated_stars+=("$new_row:$new_col:$character")
done
# Update the stars array with the new positions
stars=("${updated_stars[@]}")
}
# Main loop
while true; do
# Update the stars
update_stars
# Print the stars
for star in "${stars[@]}"; do
IFS=':' read -ra star_info <<< "$star"
row="${star_info[0]}"
col="${star_info[1]}"
character="${star_info[2]}"
# Print the star at its current position
tput cup "$row" "$col"
echo -ne "$character"
done
# Delay between frames (adjust as needed for desired speed)
sleep 0.1
done
Centered Multi-Style Spinner Animation (Unicode Frame Cycler)
#!/bin/bash
# Clear the screen
clear
# Get the terminal size
rows=$(tput lines)
cols=$(tput cols)
# Calculate the center coordinates of the terminal
center_row=$((rows / 2))
center_col=$((cols / 2))
# Define the animation frames
frames=(
"⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
"◐◓◑◒"
"▖▘▝▗"
"◢◣◤◥"
)
# Calculate the total number of frames
num_frames=${#frames[@]}
# Set the initial frame index
frame_index=0
# Main loop
while true; do
# Get the current frame
current_frame="${frames[$frame_index]}"
start_row=$((center_row - 1))
start_col=$((center_col - (${#current_frame} / 2)))
tput clear
tput cup "$start_row" "$start_col"
printf "%s" "$current_frame"
frame_index=$(( (frame_index + 1) % num_frames ))
sleep 0.1
done
Colorized Waterfall Rain Screensaver (Vertical Unicode Drops)
# Define the characters to be used as water drops
CHARS=("▒" "░" "▓" "█")
# Define the colors for the drops
COLORS=("33" "34" "35" "36" "37")
# Clear the screen
clear
# Get the terminal size
rows=$(tput lines)
cols=$(tput cols)
# Array to store the current position and color of each drop
drops=()
# Initialize the drops at random positions and colors
for ((i=0; i<cols; i++)); do
drops[$i]="$(($RANDOM % rows)):${COLORS[$(($RANDOM % ${#COLORS[@]}))]}"
done
# Function to update the drops
update_drops() {
for ((i=0; i<cols; i++)); do
# Split the drop position and color
IFS=':' read -ra drop_info <<< "${drops[$i]}"
drop_pos="${drop_info[0]}"
drop_color="${drop_info[1]}"
# Print the drop at the current position and color
tput setaf "$drop_color"
tput cup "$drop_pos" "$i"
printf "${CHARS[$((RANDOM % ${#CHARS[@]}))]}"
tput sgr0
# Move the drop down by one row
drop_pos=$(( (drop_pos + 1) % rows ))
# Update the drop position and color in the array
drops[$i]="$drop_pos:${COLORS[$(($RANDOM % ${#COLORS[@]}))]}"
done
}
# Main loop
while true; do
# Update the drops
update_drops
# Delay between frames (adjust as needed for desired speed)
sleep 0.05
done
Blue Waterfall Rain Screensaver (Minimal Terminal Drop Effect)
CHARS=("▒" "░" "▓" "█")
clear
rows=$(tput lines)
cols=$(tput cols)
drops=()
# Initialize the drops at random positions
for ((i=0; i<cols; i++)); do
drops[$i]=$((RANDOM % rows))
done
# Function to update the drops
update_drops() {
for ((i=0; i<cols; i++)); do
# Print the drop at the current position with blue color
tput setaf 4 # Set text color to blue
tput cup ${drops[$i]} $i
printf "${CHARS[$((RANDOM % ${#CHARS[@]}))]}"
tput sgr0 # Reset text color
# Move the drop down by one row
drops[$i]=$(( (drops[$i]+1) % rows ))
done
}
# Main loop
while true; do
# Update the drops
update_drops
# Delay between frames (adjust as needed for desired speed)
sleep 0.1
done
White and Grey Waterfall Rain Screensaver (Minimal Terminal Drop Effect)
# Define the characters to be used as water drops
CHARS=("▒" "░" "▓" "█")
# Clear the screen
clear
# Get the terminal size
rows=$(tput lines)
cols=$(tput cols)
# Array to store the current position of each drop
drops=()
# Initialize the drops at random positions
for ((i=0; i<cols; i++)); do
drops[$i]=$((RANDOM % rows))
done
# Function to update the drops
update_drops() {
for ((i=0; i<cols; i++)); do
# Print the drop at the current position
tput cup ${drops[$i]} $i
printf "${CHARS[$((RANDOM % ${#CHARS[@]}))]}"
# Move the drop down by one row
drops[$i]=$(( (drops[$i]+1) % rows ))
done
}
# Main loop
while true; do
# Update the drops
update_drops
# Delay between frames (adjust as needed for desired speed)
sleep 0.1
done
Accelerating Corner-Bounce Screensaver with Random Symbols and Color Cycling
# Set the number of rows and columns for the terminal
ROWS=$(tput lines)
COLS=$(tput cols)
# Hide the cursor
tput civis
# Trap the SIGINT (Ctrl+C) signal to exit gracefully
trap "tput cnorm; exit" SIGINT
# Array of symbols to use in the screensaver
symbols=("@" "#" "%" "&" "*" "+" "-" "=" "!" "?" "/" "\\" "|" "(" ")" "[" "]" "{" "}" "<" ">" "^" "~" "," "." ":" ";" " ")
# Function to generate a random color code (ANSI color escape code)
function random_color() {
local color_code="\e["
local colors=("31m" "32m" "33m" "34m" "35m" "36m" "91m" "92m" "93m" "94m" "95m" "96m")
echo -n "${color_code}${colors[$((RANDOM % ${#colors[@]}))]}"
}
# Function to generate the character for the "W" pattern with random symbol and color
function get_w_char() {
local col=$1
local middle_col=$((COLS / 2))
local symbol=${symbols[$((RANDOM % ${#symbols[@]}))]} # Get random symbol
local color_code=${color_codes[$color_index]}
if [ $col -eq 0 ] || [ $col -eq $((COLS - 1)) ]; then
echo -ne "\e[0m${symbol}" # Reset color after each character
elif [ $col -lt $middle_col ] && [ $col -gt 0 ]; then
local distance=$((middle_col - col))
if [ $((distance % 2)) -eq 0 ]; then
echo -ne "${color_code}${symbol}"
else
echo -ne "${color_code}${symbol}"
fi
elif [ $col -eq $middle_col ]; then
echo -ne "${color_code}${symbol}"
else
local distance=$((col - middle_col))
if [ $((distance % 2)) -eq 0 ]; then
echo -ne "${color_code}${symbol}"
else
echo -ne "${color_code}${symbol}"
fi
fi
}
# Function to display the bounce counter in the middle center of the screen
function display_bounce_counter() {
local counter=$1
local message="Bounces: $counter"
local message_length=${#message}
local center_row=$((ROWS / 2))
local center_col=$((COLS / 2 - message_length / 2))
tput cup $center_row $center_col
echo -n "$message"
}
# Function to clear the screen
function clear_screen() {
tput reset
}
# Function to move the cursor to a specific position
function move_cursor() {
local row=$1
local col=$2
tput cup $row $col
}
# Function to generate the screensaver animation
function screensaver() {
local x=0 # Start from the leftmost column
local y=0 # Start from the top row
local direction_x=1
local direction_y=1
local bounce_counter=0
# Set the stop positions
local stop_x=$((COLS / 2))
local stop_y=$((ROWS / 2))
local color_codes=()
local color_index=0
local sleep_duration=0.03
local direction_change_timer=0
local max_direction_change_time=20 # Change direction after 20 bounces (adjust as needed)
while true; do
color_codes+=($(random_color))
move_cursor $y $x
echo -n "$(get_w_char $x)"
sleep $sleep_duration
# Move the position
x=$((x + direction_x))
y=$((y + direction_y))
# Check if the screensaver reached the center
if [ $x -eq $stop_x ] && [ $y -eq $stop_y ]; then
# Pause the animation for a moment
sleep 0.2
direction_x=$((direction_x * -1)) # Reverse direction
direction_y=$((direction_y * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
# Check if it's time to change direction randomly
((direction_change_timer++))
if [ $direction_change_timer -ge $max_direction_change_time ]; then
direction_x=$((RANDOM % 3 - 1)) # Randomly set direction between -1, 0, 1
direction_y=$((RANDOM % 3 - 1))
direction_change_timer=0
fi
fi
# Check if the screensaver moved beyond the screen boundaries
if [ $x -ge $((COLS - 1)) ] || [ $x -le 0 ]; then
direction_x=$((direction_x * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
fi
if [ $y -ge $((ROWS - 1)) ] || [ $y -le 0 ]; then
direction_y=$((direction_y * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
fi
if [ $color_index -ge ${#color_codes[@]} ]; then
color_index=0
fi
done
}
# Start the screensaver
screensaver
Psychedelic Lava Lamp Screensaver (Random ANSI Colors + Unicode Glyph Field)
# Clear the screen
clear
# Get the terminal size
rows=$(tput lines)
cols=$(tput cols)
# Define the lava lamp colors
LAVA_COLORS=("196" "202" "208" "214" "220" "226" "160" "165" "170" "175")
# Define the lava lamp speed
LAVA_SPEED=0.05
# Define the lava lamp symbols
LAVA_SYMBOLS=("☀" "☼" "⚡" "☄" "✨" "✿" "❀" "❂" "❄" "❅" "❆" "❇" "❈" "❉" "❊" "❋" "❌" "❍" "❎" "❏" "❐" "❑" "❒" "❖" "❘" "❙" "❚" "❛" "❜" "❝" "❞" "❡" "❢" "❣" "❤" "❥" "❦" "❧" "❨" "❩" "❪" "❫" "❬" "❭" "❮" "❯" "❰" "❱" "❲" "❳" "❴" "❵" "❶" "❷" "❸" "❹" "❺" "❻" "❼" "❽" "❾" "❿" "➀" "➁" "➂" "➃" "➄" "➅" "➆" "➇" "➈" "➉" "➊" "➋" "➌" "➍" "➎" "➏" "➐" "➑" "➒" "➓")
# Function to generate a random number within a range
generate_random_number() {
min=$1
max=$2
echo $((RANDOM % (max - min + 1) + min))
}
# Function to generate a random color escape sequence
generate_color_sequence() {
color_code="\e[${1}m"
echo -e $color_code
}
# Function to move the lava lamps
move_lava_lamps() {
while true; do
# Clear the screen
clear
for ((i = 1; i <= $rows; i++)); do
for ((j = 1; j <= $cols; j++)); do
# Generate a random color for the lava lamp
color_index=$(generate_random_number 0 $((${#LAVA_COLORS[@]} - 1)))
color="${LAVA_COLORS[$color_index]}"
# Calculate the symbol index based on the current row and column
symbol_index=$((j % ${#LAVA_SYMBOLS[@]}))
# Get the symbol at the calculated index
symbol="${LAVA_SYMBOLS[$symbol_index]}"
# Move the cursor to the current coordinates
echo -e "\e[${i};${j}H"
# Set the color and print the symbol
echo -e "$(generate_color_sequence ${color})${symbol}"
done
done
# Sleep for a short duration to control the speed
sleep ${LAVA_SPEED}
done
}
# Hide the cursor
tput civis
# Enable keyboard interrupts
trap "tput cnorm; exit" INT
# Start the lava lamp screensaver
move_lava_lamps
Particle Explosion
# Clear the screen
clear
# Get the terminal size
rows=$(tput lines)
cols=$(tput cols)
# Define the particle ASCII characters
PARTICLE_CHARACTERS=("•" "◦" "∘" "·" "⁕" "∙" "⋆" "⚫" "⚪" "●" "○")
# Define the particle colors
PARTICLE_COLORS=("196" "202" "208" "214" "220" "226" "160" "165" "170" "175")
# Define the number of explosions
NUM_EXPLOSIONS=5
# Define the number of particles per explosion
NUM_PARTICLES=100
# Define the explosion speed
EXPLOSION_SPEED=0.01
# Array to store the particle positions and velocities
explosion_positions=()
explosion_velocities=()
# Function to generate a random number within a range
generate_random_number() {
local min=$1
local max=$2
echo $((RANDOM % (max - min + 1) + min))
}
# Function to initialize the explosion positions and velocities
initialize_explosion_positions() {
for ((i=0; i<NUM_EXPLOSIONS; i++)); do
local position_row=$((rows / 2))
local position_col=$((cols / 2))
local velocity_row=$(generate_random_number -10 10)
local velocity_col=$(generate_random_number -20 20)
explosion_positions[$i]="$position_row:$position_col"
explosion_velocities[$i]="$velocity_row:$velocity_col"
done
}
# Function to update the explosion positions
update_explosion_positions() {
for ((i=0; i<NUM_EXPLOSIONS; i++)); do
local position="${explosion_positions[$i]}"
local velocity="${explosion_velocities[$i]}"
IFS=':' read -ra position_parts <<< "$position"
IFS=':' read -ra velocity_parts <<< "$velocity"
local position_row="${position_parts[0]}"
local position_col="${position_parts[1]}"
local velocity_row="${velocity_parts[0]}"
local velocity_col="${velocity_parts[1]}"
position_row=$((position_row + velocity_row))
position_col=$((position_col + velocity_col))
if ((position_row < 1 || position_row >= rows || position_col < 1 || position_col >= cols)); then
position_row=$((rows / 2))
position_col=$((cols / 2))
velocity_row=$(generate_random_number -10 10)
velocity_col=$(generate_random_number -20 20)
fi
explosion_positions[$i]="$position_row:$position_col"
explosion_velocities[$i]="$velocity_row:$velocity_col"
done
}
# Function to render the particles on the screen
render_particles() {
for ((i=0; i<NUM_EXPLOSIONS; i++)); do
local position="${explosion_positions[$i]}"
IFS=':' read -ra position_parts <<< "$position"
local position_row="${position_parts[0]}"
local position_col="${position_parts[1]}"
for ((j=0; j<NUM_PARTICLES; j++)); do
local character=${PARTICLE_CHARACTERS[$((RANDOM % ${#PARTICLE_CHARACTERS[@]}))]}
local color=${PARTICLE_COLORS[$((RANDOM % ${#PARTICLE_COLORS[@]}))]}
tput setaf "$color"
tput cup "$position_row" "$position_col"
echo -ne "$character"
done
done
}
# Main loop
while true; do
# Update the explosion positions
update_explosion_positions
# Render the particles on the screen
render_particles
# Delay between frames
sleep $EXPLOSION_SPEED
done
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to generate the spinning circle effect
generate_effect() {
local circle=("◐" "◓" "◑" "◒") # Characters for the spinning circle
local colors=("31" "32" "33" "34" "35" "36" "37") # ANSI escape codes for text colors
local num_circle=${#circle[@]} # Number of characters in the spinning circle
local num_colors=${#colors[@]} # Number of colors
local x=$((columns / 2))
local y=$((lines / 2))
local dx=0
local dy=0
local circle_index=0
local color_index=0
local step=0
while true
do
# Get the current character from the spinning circle
local char=${circle[$circle_index]}
circle_index=$(( (circle_index + 1) % num_circle ))
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Print the colored character at the current position
printf "\033[${color}m\033[${y};${x}H${char}\033[0m"
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
case $step in
0)
dx=0
dy=1
((y++))
if ((y == (lines - 1)))
then
((step++))
fi
;;
1)
dx=1
dy=-1
((x++))
((y--))
if ((x == (columns - 1)))
then
((step++))
fi
;;
2)
dx=0
dy=-1
((y--))
if ((y == 0))
then
((step++))
fi
;;
3)
dx=1
dy=1
((x++))
((y++))
if ((x == (columns / 2)))
then
((step++))
fi
;;
4)
dx=-1
dy=-1
((x--))
((y--))
if ((x == 0))
then
((step++))
fi
;;
5)
dx=0
dy=0
if ((y == (lines / 2)))
then
break
fi
;;
esac
done
}
# Main loop
while true
do
clear_screen
generate_effect
done
Color-Cycling Spinner Path Animation (Spinning Circle Traversing the Screen)
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to generate the matrix rain effect
generate_effect() {
local matrix=("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F") # Characters for matrix rain
local colors=("32" "33" "34" "35" "36") # ANSI escape codes for text colors
local num_matrix=${#matrix[@]} # Number of characters in the matrix rain
local num_colors=${#colors[@]} # Number of colors
local start_x=10
local start_y=5
local end_x=$((columns - 11))
local end_y=$((lines - 6))
local x=$start_x
local y=$start_y
local dx=1
local dy=0
local matrix_index=0
local color_index=0
while true
do
# Get the current character from the matrix rain
local char=${matrix[$matrix_index]}
matrix_index=$(( (matrix_index + 1) % num_matrix ))
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Print the colored character at the current position
printf "\033[${color}m\033[${y};${x}H${char}\033[0m"
# Update position
x=$((x + dx))
y=$((y + dy))
# Check for reaching the end of each side and adjust direction accordingly
if ((x > end_x))
then
x=$end_x
y=$((y + 1))
dx=0
dy=1
elif ((y > end_y))
then
x=$((x - 1))
y=$end_y
dx=-1
dy=0
elif ((x < start_x))
then
x=$start_x
y=$((y - 1))
dx=0
dy=-1
elif ((y < start_y))
then
x=$((x + 1))
y=$start_y
dx=1
dy=0
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
}
# Function to draw the wall
draw_wall() {
local x
local y
local wall_start_x=10
local wall_start_y=5
local wall_end_x=$((columns - 11))
local wall_end_y=$((lines - 6))
# Draw the top level of the wall
for ((x = wall_start_x; x <= wall_end_x; x++))
do
printf "\033[32m\033[${wall_start_y};${x}H█"
done
# Draw the bottom level of the wall
for ((x = wall_start_x; x <= wall_end_x; x++))
do
printf "\033[32m\033[${wall_end_y};${x}H█"
done
# Draw the left side of the wall
for ((y = wall_start_y + 1; y < wall_end_y; y++))
do
printf "\033[32m\033[${y};${wall_start_x}H█"
done
# Draw the right side of the wall
for ((y = wall_start_y + 1; y < wall_end_y; y++))
do
printf "\033[32m\033[${y};${wall_end_x}H█"
done
# Update wall dimensions for the next level
wall_start_x=$((wall_start_x + 1))
wall_start_y=$((wall_start_y + 1))
wall_end_x=$((wall_end_x - 1))
wall_end_y=$((wall_end_y - 1))
}
# Main loop
while true
do
clear_screen
draw_wall
generate_effect
draw_wall
done
Psychedelic Lava Lamp Screensaver (Random ANSI Colors + Unicode Glyph Field)
#!/bin/bash
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to generate the spinning circle effect
generate_effect() {
local circle=("◐" "◓" "◑" "◒") # Characters for the spinning circle
local colors=("31" "32" "33" "34" "35" "36" "37") # ANSI escape codes for text colors
local num_circle=${#circle[@]} # Number of characters in the spinning circle
local num_colors=${#colors[@]} # Number of colors
local x=$((columns / 2))
local y=$((lines / 2))
local dx=0
local dy=0
local circle_index=0
local color_index=0
local step=0
while true
do
# Get the current character from the spinning circle
local char=${circle[$circle_index]}
circle_index=$(( (circle_index + 1) % num_circle ))
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Print the colored character at the current position
printf "\033[${color}m\033[${y};${x}H${char}\033[0m"
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
case $step in
0)
dx=0
dy=1
((y++))
if ((y == (lines - 1)))
then
((step++))
fi
;;
1)
dx=1
dy=-1
((x++))
((y--))
if ((x == (columns - 1)))
then
((step++))
fi
;;
2)
dx=0
dy=-1
((y--))
if ((y == 0))
then
((step++))
fi
;;
3)
dx=1
dy=1
((x++))
((y++))
if ((x == (columns / 2)))
then
((step++))
fi
;;
4)
dx=-1
dy=-1
((x--))
((y--))
if ((x == 0))
then
((step++))
fi
;;
5)
dx=0
dy=0
if ((y == (lines / 2)))
then
break
fi
;;
esac
done
}
# Main loop
while true
do
clear_screen
generate_effect
done
Shrinking Spiral Spinner Border That Transitions into a Bouncing Ball
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to generate a spinner effect with changing colors
generate_effect() {
local spinner=("◐" "◓" "◑" "◒" "⣾" "⣽" "⣻" "⢿" "⡿" "⣟" "⣯" "⣷") # Characters for the spinner
local colors=("31" "32" "33" "34" "35" "36" "37") # ANSI escape codes for text colors
local num_spinner=${#spinner[@]} # Number of characters in the spinner
local num_colors=${#colors[@]} # Number of colors
local start_x=0
local start_y=0
local end_x=$((columns - 1))
local end_y=$((lines - 1))
local x=$start_x
local y=$start_y
local dx=1
local dy=0
local spinner_index=0
local color_index=0
local corner_count=0
local ball_x=$((columns / 2))
local ball_y=$((lines / 2))
local ball_dx=-1
local ball_dy=-1
while true
do
# Get the current character from the spinner
local char=${spinner[$spinner_index]}
spinner_index=$(( (spinner_index + 1) % num_spinner ))
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Print the colored character at the current position
printf "\033[${color}m\033[${y};${x}H${char}\033[0m"
# Update position
x=$((x + dx))
y=$((y + dy))
# Check for reaching the end of each side and adjust direction accordingly
if ((x > end_x))
then
x=$end_x
y=$((y + 1))
dx=0
dy=1
elif ((y > end_y))
then
x=$((x - 1))
y=$end_y
dx=-1
dy=0
elif ((x < start_x))
then
x=$start_x
y=$((y - 1))
dx=0
dy=-1
elif ((y < start_y))
then
x=$((x + 1))
y=$start_y
dx=1
dy=0
fi
# Check for completing the full circle
if ((x == start_x && y == start_y))
then
corner_count=$((corner_count + 1))
if ((corner_count == 5))
then
while true
do
# Print the colored ball at the current position
printf "\033[${color}m\033[${ball_y};${ball_x}H●\033[0m"
# Update ball position
ball_x=$((ball_x + ball_dx))
ball_y=$((ball_y + ball_dy))
# Check for bouncing off the walls
if ((ball_x <= start_x || ball_x >= end_x))
then
ball_dx=$((ball_dx * -1))
fi
if ((ball_y <= start_y || ball_y >= end_y))
then
ball_dy=$((ball_dy * -1))
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
else
start_x=$((start_x + 1))
start_y=$((start_y + 1))
end_x=$((end_x - 1))
end_y=$((end_y - 1))
x=$((start_x))
y=$((start_y))
fi
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
}
# Main loop
while true
do
clear_screen
generate_effect
done
Rainbow Spinner Perimeter Loop (Center Start, Edge Trace, Return to Center)
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to generate the spinning circle effect
generate_effect() {
local circle=("◐" "◓" "◑" "◒") # Characters for the spinning circle
local colors=("31" "32" "33" "34" "35" "36" "37") # ANSI escape codes for text colors
local num_circle=${#circle[@]} # Number of characters in the spinning circle
local num_colors=${#colors[@]} # Number of colors
local x=$((columns / 2))
local y=$((lines / 2))
local dx=0
local dy=0
local circle_index=0
local color_index=0
local step=0
while true
do
# Get the current character from the spinning circle
local char=${circle[$circle_index]}
circle_index=$(( (circle_index + 1) % num_circle ))
# Get the current color
local color=${colors[$color_index]}
color_index=$(( (color_index + 1) % num_colors ))
# Print the colored character at the current position
printf "\033[${color}m\033[${y};${x}H${char}\033[0m"
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
case $step in
0)
dx=1
dy=0
((x++))
if ((x == (columns - 1)))
then
((step++))
fi
;;
1)
dx=0
dy=1
((y++))
if ((y == (lines - 1)))
then
((step++))
fi
;;
2)
dx=-1
dy=0
((x--))
if ((x == 0))
then
((step++))
fi
;;
3)
dx=0
dy=-1
((y--))
if ((y == 0))
then
((step++))
fi
;;
4)
dx=0
dy=0
if ((x == (columns / 2) && y == (lines / 2)))
then
break
fi
;;
esac
done
}
# Main loop
while true
do
clear_screen
generate_effect
done
Emoji Confetti Screensaver (Alternate Screen, Smiley Set)
emojis=("🙂" "😀" "😁" "😆" "😅" "😂" "🤣" "😊" "😍" "🥰")
cleanup() {
tput cnorm 2>/dev/null
tput sgr0 2>/dev/null
tput rmcup 2>/dev/null # leave alternate screen
}
trap cleanup INT TERM EXIT
tput smcup 2>/dev/null # enter alternate screen (no scrollback junk)
tput civis 2>/dev/null
tput clear 2>/dev/null
while :; do
cols=$(tput cols)
lines=$(tput lines)
for _ in {1..50}; do
# emojis are often double-width -> avoid last column
x=$((RANDOM % (cols>1 ? cols-1 : 1)))
y=$((RANDOM % lines))
emoji=${emojis[RANDOM % ${#emojis[@]}]}
tput cup "$y" "$x"
printf '\e[1m%s\e[0m' "$emoji"
sleep 0.05
done
sleep 0.2
tput clear
tput cup 0 0
done
Random Emoji Scatter Screensaver (ANSI Clear, Mixed Symbols)
emojis=("😎" "🤖" "👾" "🎉" "✨" "🔥" "💥" "🌈" "⚡" "🌀" "🚀" "🛸" "🌟" "💫" "👽")
cleanup() {
tput cnorm
tput sgr0
printf '\033[2J\033[H'
}
trap cleanup INT TERM EXIT
tput civis
while true; do
cols=$(tput cols)
lines=$(tput lines)
# clear FIRST
printf '\033[2J\033[H'
for _ in {1..50}; do
x=$((RANDOM % (cols > 1 ? cols-1 : 1))) # avoid last column (emoji width)
y=$((RANDOM % lines))
emoji=${emojis[RANDOM % ${#emojis[@]}]}
tput cup "$y" "$x"
printf '\e[1m%s\e[0m' "$emoji"
done
sleep 0.5
done
Colorful Heart Emoji Confetti Screensaver
emojis=("❤️" "🧡" "💛" "💚" "💙" "💜" "🤎" "🖤" "🤍" "💖" "💗" "💘" "💝" "💞" "💟")
cleanup() {
tput cnorm
tput sgr0
printf '\033[2J\033[H'
}
trap cleanup INT TERM EXIT
tput civis
while true; do
cols=$(tput cols)
lines=$(tput lines)
# clear FIRST
printf '\033[2J\033[H'
for _ in {1..50}; do
x=$((RANDOM % (cols > 1 ? cols-1 : 1))) # avoid last column (emoji width)
y=$((RANDOM % lines))
emoji=${emojis[RANDOM % ${#emojis[@]}]}
tput cup "$y" "$x"
printf '\e[1m%s\e[0m' "$emoji"
done
sleep 0.5
done
Randomized Emoji Confetti Screensaver
emojis=(
"✨" "🌟" "💫" "⭐" "⚡" "🔥" "💥" "🌈" "🌀" "❄️"
"☄️" "🌙" "🌕" "🌑" "🪐" "🌍" "🌎" "🌏" "🛸" "🚀"
"🎆" "🎇" "🎉" "🎊" "🎈" "🧨" "💎" "🔮" "🪄" "🧿"
"👾" "🤖" "👽" "🧠" "👁️" "🫀" "🫁" "🦾" "🦿" "🧬"
)
cleanup() {
tput cnorm
tput sgr0
printf '\033[2J\033[H'
}
trap cleanup INT TERM EXIT
tput civis
while true; do
cols=$(tput cols)
lines=$(tput lines)
# clear FIRST
printf '\033[2J\033[H'
for _ in {1..50}; do
x=$((RANDOM % (cols > 1 ? cols-1 : 1))) # avoid last column (emoji width)
y=$((RANDOM % lines))
emoji=${emojis[RANDOM % ${#emojis[@]}]}
tput cup "$y" "$x"
printf '\e[1m%s\e[0m' "$emoji"
done
sleep 0.5
done
Snowfall Colorized
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to display the winter scene with colored snowflakes
display_winterscene() {
local x y
local colors=("96" "97" "94" "95" "92" "93") # Add more colors if desired
local snowflakes=("❄" "❅" "❆")
local num_snowflakes=$((columns * lines / 20)) # Adjust the density of snowflakes
for ((i = 0; i < num_snowflakes; i++)); do
x=$((RANDOM % columns))
y=$((RANDOM % lines))
color=${colors[$((RANDOM % ${#colors[@]}))]}
snowflake=${snowflakes[$((RANDOM % ${#snowflakes[@]}))]}
printf "\033[${y};${x}H\033[${color}m${snowflake}\033[0m"
done
}
# Main loop
while true; do
clear_screen
display_winterscene
sleep 0.1 # Adjust the sleep duration to control the animation speed
done
Random Emoji Confetti Screensaver (Alternate Screen, Bold Unicode Scatter)
emojis=("🙂" "😀" "😁" "😆" "😅" "😂" "🤣" "😊" "😍" "🥰")
cleanup() {
tput cnorm 2>/dev/null
tput sgr0 2>/dev/null
tput rmcup 2>/dev/null # leave alternate screen
}
trap cleanup INT TERM EXIT
tput smcup 2>/dev/null # enter alternate screen (no scrollback junk)
tput civis 2>/dev/null
tput clear 2>/dev/null
while :; do
cols=$(tput cols)
lines=$(tput lines)
for _ in {1..50}; do
# emojis are often double-width -> avoid last column
x=$((RANDOM % (cols>1 ? cols-1 : 1)))
y=$((RANDOM % lines))
emoji=${emojis[RANDOM % ${#emojis[@]}]}
tput cup "$y" "$x"
printf '\e[1m%s\e[0m' "$emoji"
sleep 0.05
done
sleep 0.2
tput clear
tput cup 0 0
done
Blinking Starry Night Screensaver (Randomized Twinkling Sky Effect)
# Set terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Function to clear the screen
clear_screen() {
printf "\033[2J"
}
# Function to display the starry night sky
display_starry_night() {
local x y
local num_stars=$((columns * lines / 10)) # Adjust the density of stars
for ((i = 0; i < num_stars; i++)); do
x=$((RANDOM % columns))
y=$((RANDOM % lines))
color=$((RANDOM % 7 + 90)) # Random ANSI escape code for color
printf "\033[${y};${x}H\033[${color}m*\033[0m"
done
}
# Function to randomly blink stars
blink_stars() {
local x y
local num_blinks=$((columns * lines / 20)) # Adjust the density of blinking stars
for ((i = 0; i < num_blinks; i++)); do
x=$((RANDOM % columns))
y=$((RANDOM % lines))
color=$((RANDOM % 7 + 90)) # Random ANSI escape code for color
printf "\033[${y};${x}H\033[${color}m \033[0m"
sleep 0.1 # Adjust the blink duration
printf "\033[${y};${x}H\033[${color}m*\033[0m"
sleep 0.1 # Adjust the blink duration
done
}
# Main loop
while true; do
clear_screen
display_starry_night
blink_stars
sleep 0.5 # Adjust the sleep duration to control the animation speed
done
Random-Symbol “W” Bouncer with Color Cycling and Bounce Counter
# Set the number of rows and columns for the terminal
ROWS=$(tput lines)
COLS=$(tput cols)
# Hide the cursor
tput civis
# Trap the SIGINT (Ctrl+C) signal to exit gracefully
trap "tput cnorm; exit" SIGINT
# Array of symbols to use in the screensaver
symbols=("@" "#" "%" "&" "*" "+" "-" "=" "!" "?" "/" "\\" "|" "(" ")" "[" "]" "{" "}" "<" ">" "^" "~" "," "." ":" ";" " ")
# Function to generate a random color code (ANSI color escape code)
function random_color() {
local color_code="\e["
local colors=("31m" "32m" "33m" "34m" "35m" "36m" "91m" "92m" "93m" "94m" "95m" "96m")
echo -n "${color_code}${colors[$((RANDOM % ${#colors[@]}))]}"
}
# Function to generate the character for the "W" pattern with random symbol and color
function get_w_char() {
local col=$1
local middle_col=$((COLS / 2))
local symbol=${symbols[$((RANDOM % ${#symbols[@]}))]} # Get random symbol
local color_code=${color_codes[$color_index]}
if [ $col -eq 0 ] || [ $col -eq $((COLS - 1)) ]; then
echo -ne "\e[0m${symbol}" # Reset color after each character
elif [ $col -lt $middle_col ] && [ $col -gt 0 ]; then
local distance=$((middle_col - col))
if [ $((distance % 2)) -eq 0 ]; then
echo -ne "${color_code}${symbol}"
else
echo -ne "${color_code}${symbol}"
fi
elif [ $col -eq $middle_col ]; then
echo -ne "${color_code}${symbol}"
else
local distance=$((col - middle_col))
if [ $((distance % 2)) -eq 0 ]; then
echo -ne "${color_code}${symbol}"
else
echo -ne "${color_code}${symbol}"
fi
fi
}
# Function to display the bounce counter in the middle center of the screen
function display_bounce_counter() {
local counter=$1
local message="Bounces: $counter"
local message_length=${#message}
local center_row=$((ROWS / 2))
local center_col=$((COLS / 2 - message_length / 2))
tput cup $center_row $center_col
echo -n "$message"
}
# Function to clear the screen
function clear_screen() {
tput reset
}
# Function to move the cursor to a specific position
function move_cursor() {
local row=$1
local col=$2
tput cup $row $col
}
# Function to generate the screensaver animation
function screensaver() {
local x=0 # Start from the leftmost column
local y=0 # Start from the top row
local direction_x=1
local direction_y=1
local bounce_counter=0
# Set the stop positions
local stop_x=$((COLS / 2))
local stop_y=$((ROWS / 2))
local color_codes=()
local color_index=0
local sleep_duration=0.03
local direction_change_timer=0
local max_direction_change_time=20 # Change direction after 20 bounces (adjust as needed)
while true; do
color_codes+=($(random_color))
move_cursor $y $x
echo -n "$(get_w_char $x)"
sleep $sleep_duration
# Move the position
x=$((x + direction_x))
y=$((y + direction_y))
# Check if the screensaver reached the center
if [ $x -eq $stop_x ] && [ $y -eq $stop_y ]; then
# Pause the animation for a moment
sleep 0.2
direction_x=$((direction_x * -1)) # Reverse direction
direction_y=$((direction_y * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
# Check if it's time to change direction randomly
((direction_change_timer++))
if [ $direction_change_timer -ge $max_direction_change_time ]; then
direction_x=$((RANDOM % 3 - 1)) # Randomly set direction between -1, 0, 1
direction_y=$((RANDOM % 3 - 1))
direction_change_timer=0
fi
fi
# Check if the screensaver moved beyond the screen boundaries
if [ $x -ge $((COLS - 1)) ] || [ $x -le 0 ]; then
direction_x=$((direction_x * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
fi
if [ $y -ge $((ROWS - 1)) ] || [ $y -le 0 ]; then
direction_y=$((direction_y * -1))
color_index=$((color_index + 1))
sleep_duration=$(awk -v sleep_duration="$sleep_duration" 'BEGIN {print sleep_duration * 0.8}')
((bounce_counter++))
display_bounce_counter $bounce_counter
fi
if [ $color_index -ge ${#color_codes[@]} ]; then
color_index=0
fi
done
}
# Start the screensaver
screensaver
Accelerating Random-Symbol “W” Screensaver with Color Cycling
#!/usr/bin/env bash
# Set the number of rows and columns for the terminal
ROWS=$(tput lines)
COLS=$(tput cols)
# Use alternate screen so the terminal content (your pasted script) is hidden
tput smcup
# Hide cursor + clear screen before starting
tput civis
tput clear
tput cup 0 0
# Trap signals to exit gracefully and restore terminal
cleanup() {
tput cnorm
printf '\e[0m'
tput rmcup
exit
}
trap cleanup INT TERM
# Array of symbols to use in the screensaver
symbols=("@" "#" "%" "&" "*" "+" "-" "=" "!" "?" "/" "\\" "|" "(" ")" "[" "]" "{" "}" "<" ">" "^" "~" "," "." ":" ";" " ")
# Function to generate a random color code (ANSI color escape code)
random_color() {
local colors=("31m" "32m" "33m" "34m" "35m" "36m" "91m" "92m" "93m" "94m" "95m" "96m")
printf '\e[%s' "${colors[RANDOM % ${#colors[@]}]}"
}
# Function to move the cursor to a specific position
move_cursor() {
tput cup "$1" "$2"
}
# Function to generate the character for the "W" pattern with random symbol and color
# NOTE: We pass color_code in so we don't depend on a local array from another scope.
get_w_char() {
local col=$1
local color_code=$2
local middle_col=$((COLS / 2))
local symbol=${symbols[RANDOM % ${#symbols[@]}]}
if [ "$col" -eq 0 ] || [ "$col" -eq $((COLS - 1)) ]; then
printf '\e[0m%s' "$symbol"
elif [ "$col" -le "$middle_col" ]; then
printf '%b%s' "$color_code" "$symbol"
else
printf '%b%s' "$color_code" "$symbol"
fi
}
screensaver() {
local x=0 y=0
local direction_x=1 direction_y=1
local stop_x=$((COLS / 2))
local stop_y=$((ROWS / 2))
local color_code
local sleep_duration=0.03
# Make sure we start drawing from a clean frame
tput clear
tput cup 0 0
while true; do
color_code="$(random_color)"
move_cursor "$y" "$x"
get_w_char "$x" "$color_code"
sleep "$sleep_duration"
x=$((x + direction_x))
y=$((y + direction_y))
if [ "$x" -eq "$stop_x" ] && [ "$y" -eq "$stop_y" ]; then
sleep 0.2
direction_x=$((direction_x * -1))
direction_y=$((direction_y * -1))
sleep_duration=$(awk -v s="$sleep_duration" 'BEGIN {print s * 0.8}')
fi
if [ "$x" -ge $((COLS - 1)) ] || [ "$x" -le 0 ]; then
direction_x=$((direction_x * -1))
sleep_duration=$(awk -v s="$sleep_duration" 'BEGIN {print s * 0.8}')
fi
if [ "$y" -ge $((ROWS - 1)) ] || [ "$y" -le 0 ]; then
direction_y=$((direction_y * -1))
sleep_duration=$(awk -v s="$sleep_duration" 'BEGIN {print s * 0.8}')
fi
done
}
screensaver
African Flag Spiral Border Animation with Color Cycling and Bouncing Ball Finale
# Define the array of African flags
flags=(
"🇦🇴" "🇧🇯" "🇧🇼" "🇧🇫" "🇧🇮" "🇨🇻" "🇨🇲" "🇨🇫" "🇹🇩" "🇰🇲"
"🇨🇬" "🇨🇩" "🇨🇮" "🇩🇯" "🇪🇬" "🇬🇶" "🇪🇷" "🇸🇿" "🇪🇹" "🇬🇦"
"🇬🇲" "🇬🇭" "🇬🇳" "🇬🇼" "🇰🇪" "🇱🇸" "🇱🇷" "🇱🇾" "🇲🇬" "🇲🇼"
"🇲🇱" "🇲🇷" "🇲🇺" "🇲🇦" "🇲🇿" "🇳🇦" "🇳🇪" "🇳🇬" "🇷🇼" "🇸🇹"
"🇸🇳" "🇸🇨" "🇸🇱" "🇸🇴" "🇿🇦" "🇸🇸" "🇸🇩" "🇹🇿" "🇹🇬" "🇹🇳"
"🇺🇬" "🇿🇲" "🇿🇼"
)
# Define colors (ANSI color codes)
colors=("36" "32" "33" "34" "35" "36" "37")
# Get terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Initialize variables for movement
start_x=0
start_y=0
end_x=$((columns - 1))
end_y=$((lines - 1))
x=$start_x
y=$start_y
dx=1
dy=0
spinner_index=0
color_index=0
corner_count=0
ball_x=$((columns / 2))
ball_y=$((lines / 2))
ball_dx=-1
ball_dy=-1
# Function to clear the screen
clear_screen() {
printf "\033c"
}
# Function to generate the spiraling effect with flags
generate_effect() {
local num_flags=${#flags[@]} # Number of flags
local num_colors=${#colors[@]} # Number of colors
while true; do
# Get the current flag
local flag=${flags[$spinner_index]}
spinner_index=$(((spinner_index + 1) % num_flags))
# Get the current color
local color=${colors[$color_index]}
color_index=$(((color_index + 1) % num_colors))
# Print the colored flag at the current position
printf "\033[${color}m\033[${y};${x}H${flag}\033[0m"
# Update position
x=$((x + dx))
y=$((y + dy))
# Check for reaching the end of each side and adjust direction accordingly
if ((x > end_x)); then
x=$end_x
y=$((y + 1))
dx=0
dy=1
elif ((y > end_y)); then
x=$((x - 1))
y=$end_y
dx=-1
dy=0
elif ((x < start_x)); then
x=$start_x
y=$((y - 1))
dx=0
dy=-1
elif ((y < start_y)); then
x=$((x + 1))
y=$start_y
dx=1
dy=0
fi
# Check for completing the full circle
if ((x == start_x && y == start_y)); then
corner_count=$((corner_count + 1))
if ((corner_count == 5)); then
# Switch to bouncing ball effect after 5 complete circles
while true; do
# Print the colored ball at the current position
printf "\033[${color}m\033[${ball_y};${ball_x}H●\033[0m"
# Update ball position
ball_x=$((ball_x + ball_dx))
ball_y=$((ball_y + ball_dy))
# Check for bouncing off the walls
if ((ball_x <= start_x || ball_x >= end_x)); then
ball_dx=$((ball_dx * -1))
fi
if ((ball_y <= start_y || ball_y >= end_y)); then
ball_dy=$((ball_dy * -1))
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
else
# Reduce the bounding box for the next circle
start_x=$((start_x + 1))
start_y=$((start_y + 1))
end_x=$((end_x - 1))
end_y=$((end_y - 1))
x=$((start_x))
y=$((start_y))
fi
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
}
# Main loop
while true; do
clear_screen
generate_effect
done
Euorpes Flag Spiral Border Animation with Color Cycling and Bouncing Ball Finale
# Define the array of African flags
flags=(
"🇦🇱" "🇦🇩" "🇦🇹" "🇧🇪" "🇧🇦" "🇧🇬" "🇭🇷" "🇨🇾" "🇨🇿" "🇩🇰"
"🇪🇪" "🇫🇮" "🇫🇷" "🇩🇪" "🇬🇷" "🇭🇺" "🇮🇸" "🇮🇪" "🇮🇹" "🇱🇻"
"🇱🇮" "🇱🇹" "🇱🇺" "🇲🇹" "🇲🇩" "🇲🇨" "🇲🇪" "🇳🇱" "🇲🇰" "🇳🇴"
"🇵🇱" "🇵🇹" "🇷🇴" "🇷🇸" "🇸🇲" "🇸🇰" "🇸🇮" "🇪🇸" "🇸🇪" "🇨🇭"
"🇺🇦" "🇬🇧" "🇻🇦"
)
# Define colors (ANSI color codes)
colors=("36" "32" "33" "34" "35" "36" "37")
# Get terminal dimensions
columns=$(tput cols)
lines=$(tput lines)
# Initialize variables for movement
start_x=0
start_y=0
end_x=$((columns - 1))
end_y=$((lines - 1))
x=$start_x
y=$start_y
dx=1
dy=0
spinner_index=0
color_index=0
corner_count=0
ball_x=$((columns / 2))
ball_y=$((lines / 2))
ball_dx=-1
ball_dy=-1
# Function to clear the screen
clear_screen() {
printf "\033c"
}
# Function to generate the spiraling effect with flags
generate_effect() {
local num_flags=${#flags[@]} # Number of flags
local num_colors=${#colors[@]} # Number of colors
while true; do
# Get the current flag
local flag=${flags[$spinner_index]}
spinner_index=$(((spinner_index + 1) % num_flags))
# Get the current color
local color=${colors[$color_index]}
color_index=$(((color_index + 1) % num_colors))
# Print the colored flag at the current position
printf "\033[${color}m\033[${y};${x}H${flag}\033[0m"
# Update position
x=$((x + dx))
y=$((y + dy))
# Check for reaching the end of each side and adjust direction accordingly
if ((x > end_x)); then
x=$end_x
y=$((y + 1))
dx=0
dy=1
elif ((y > end_y)); then
x=$((x - 1))
y=$end_y
dx=-1
dy=0
elif ((x < start_x)); then
x=$start_x
y=$((y - 1))
dx=0
dy=-1
elif ((y < start_y)); then
x=$((x + 1))
y=$start_y
dx=1
dy=0
fi
# Check for completing the full circle
if ((x == start_x && y == start_y)); then
corner_count=$((corner_count + 1))
if ((corner_count == 5)); then
# Switch to bouncing ball effect after 5 complete circles
while true; do
# Print the colored ball at the current position
printf "\033[${color}m\033[${ball_y};${ball_x}H●\033[0m"
# Update ball position
ball_x=$((ball_x + ball_dx))
ball_y=$((ball_y + ball_dy))
# Check for bouncing off the walls
if ((ball_x <= start_x || ball_x >= end_x)); then
ball_dx=$((ball_dx * -1))
fi
if ((ball_y <= start_y || ball_y >= end_y)); then
ball_dy=$((ball_dy * -1))
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
else
# Reduce the bounding box for the next circle
start_x=$((start_x + 1))
start_y=$((start_y + 1))
end_x=$((end_x - 1))
end_y=$((end_y - 1))
x=$((start_x))
y=$((start_y))
fi
fi
sleep 0.01 # Adjust the sleep duration to control the speed of the effect
done
}
# Main loop
while true; do
clear_screen
generate_effect
done