If you want to write an action game in bash, you need the ability to check for user input without actually waiting for it. While bash doesn’t let you poll the keyboard in a great way, it does let you wait for input for a miniscule amount of time with read -t 0.0001
.
Here’s a snippet that demonstrates this by bouncing some text back and forth, and letting the user control position and color. It also sets (and unsets) the necessary terminal settings for this to look good:
#!/usr/bin/env bash # Reset terminal on exit trap 'tput cnorm; tput sgr0; clear' EXIT # invisible cursor, no echo tput civis stty -echo text="j/k to move, space to color" max_x=$(($(tput cols) - ${#text})) dir=1 x=1 y=$(($(tput lines)/2)) color=3 while sleep 0.05 # GNU specific! do # move and change direction when hitting walls (( x == 0 || x == max_x )) && \ ((dir *= -1)) (( x += dir )) # read all the characters that have been buffered up while IFS= read -rs -t 0.0001 -n 1 key do [[ $key == j ]] && (( y++ )) [[ $key == k ]] && (( y-- )) [[ $key == " " ]] && color=$((color%7+1)) done # batch up all terminal output for smoother action framebuffer=$( clear tput cup "$y" "$x" tput setaf "$color" printf "%s" "$text" ) # dump to screen printf "%s" "$framebuffer" done