Answer the question
In order to leave comments, you need to log in
Animation in bash?
Good afternoon! How can I improve the script that draws a bat that moves in different directions. The problem is that the cursor is constantly flickering, before changing the tub it is at the beginning of the terminal, and after drawing the picture it is at the end, respectively. Is there any way to make it smoother? Most likely it's clear. Any suggestions?
And the second question: now the number of lines that fit in one terminal screen is not calculated for me. The `tput rows` function returns an invalid value.
PS the task was given at the university
#!/bin/bash
let y=0
let x=0
let max_x=$(tput cols)
let max_y=24
let wall=0
draw_top() {
local line1=' ###### ## | ## ##### '
local line2='.##############################'
local line3=' ######################## '
local line4=' ################### '
local line5=' ####### '
local line6=' #### '
local line7=' # '
# Сдвиг сверху
for ((i = 0; i < $1; i++)) ; do
echo " "
done
# Сдвиг слева
for index in {1..7}; do
for ((j = 0; j < $2; j++)) ; do
echo -n " "
done
var="line$index"
echo "${!var}"
done
}
draw_bottom() {
local line1=' # '
local line2=' ##### '
local line3=' ################## '
local line4=' ######################## '
local line5='###############################'
local line6=' ######## ## | ## ####### '
local line7=' ### ### '
# Сдвиг сверху
for ((i = 0; i < $1; i++)) ; do
echo " "
done
# Сдвиг слева
for index in {1..7}; do
for ((j = 0; j < $2; j++)) ; do
echo -n " "
done
var="line$index"
echo "${!var}"
done
}
draw_right() {
local line1=' # '
local line2=' ## '
local line3=' #### '
local line4=' #######'
local line5=' ######## '
local line6=' ####### '
local line7=' ###### '
local line8=' ########## '
local line9='###########- '
local line10=' ########## '
local line11=' ###### '
local line12=' ####### '
local line13=' ########'
local line14=' ##### '
local line15=' ### '
local line16=' # '
# Сдвиг сверху
for ((i = 0; i < $1; i++)) ; do
echo " "
done
# Сдвиг слева
for index in {1..16}; do
for ((j = 0; j < $2; j++)) ; do
echo -n " "
done
var="line$index"
echo "${!var}"
done
}
draw_left() {
local line1=' # '
local line2=' ## '
local line3=' #### '
local line4=' ######## '
local line5='######## '
local line6=' ####### '
local line7=' ####### '
local line8='########## '
local line9=' -##########'
local line10='########## '
local line11=' ######## '
local line12=' ######## '
local line13='########## '
local line14=' ####### '
local line15=' #### '
local line16=' ## '
# Сдвиг сверху
for ((i = 0; i < $1; i++)) ; do
echo " "
done
# Сдвиг слева
for index in {1..16}; do
for ((j = 0; j < $2; j++)) ; do
echo -n " "
done
var="line$index"
echo "${!var}"
done
}
move_right() {
if ((x < max_x - 15))
then
((x++))
else
wall=1
fi
clear
draw_right $y $x
}
move_bottom() {
if ((y < max_y - 8))
then
((y++))
else
wall=1
fi
clear
draw_bottom $y $x
}
move_left() {
if (( x > 0 ))
then
((x--))
else
wall=1
fi
clear
draw_left $y $x
}
move_top() {
if (( y > 0 ))
then
((y--))
else
wall=1
fi
clear
draw_top $y $x
}
random_choice() {
RANGE=$1
number=$RANDOM
let "number %= $RANGE"
echo "$number"
}
move() {
if [ "$1" == 0 ]
then
move_right
fi
if [ "$1" == 1 ]
then
move_left
fi
if [ "$1" == 2 ]
then
move_top
fi
if [ "$1" == 3 ]
then
move_bottom
fi
}
calculate_coords() {
let vertical=$1
# Вертикально -> Горизонтально
if (( vertical > 0))
then
x=$((x-8))
y=$((y+5))
if (( x < 0 ))
then
x=0
fi
if (( x + 31 > max_x))
then
x=$((max_x-31))
fi
if (( y + 8 > max_y))
then
y=$((max_y-8))
fi
# Горизонтально -> Вертикально
else
x=$((x+8))
y=$((y-5))
if (( y < 0 ))
then
y=0
fi
if ((x + 13 > max_x))
then
x=$((max_x - 13))
fi
if ((y + 17 > max_y))
then
y=$((max_y - 17))
fi
fi
}
start() {
current=0
direction=0
prevent_direction=0
while true; do
# Calculate dicrection
if ((current == 20 || wall == 1))
then
wall=0
current=0
prevent_direction=$direction
direction=$(random_choice 4)
if (( direction < 2 && prevent_direction > 1 ))
then
calculate_coords 0
fi
if (( direction > 1 && prevent_direction < 2 ))
then
calculate_coords 1
fi
fi
# Move
move $direction
current=$((current+1))
sleep .2
done
}
start
Answer the question
In order to leave comments, you need to log in
instead of clear try using "tput cup $y 0" and only make clear on a direction change.
It is also possible to shorten the calculations by calculating the move to the left only when moving left and right.
And use indexes instead of converting the variable name.
And somehow everything is not neat with you. The mouse is crooked, you would paint it more evenly, something like this:
#!/bin/bash
let y=0
let x=0
let max_x=120 #$(tput cols)
let max_y=24
let wall=0
let space=""
draw_top() {
local line[0]=' ### ###'
local line[1]=' ##### ## | ## #####'
local line[2]='########################### '
local line[3]=' ####################### '
local line[4]=' ################# '
local line[5]=' ####### '
local line[6]=' ##### '
local line[7]=' # '
local line[8]=' '
for index in {0..8}; do
echo "$space${line[$index]}"
done
}
draw_bottom() {
local line[0]=' '
local line[1]=' # '
local line[2]=' ##### '
local line[3]=' ####### '
local line[4]=' ################# '
local line[5]=' ####################### '
local line[6]='###########################'
local line[7]=' ##### ## | ## #####'
local line[8]=' ### ###'
for index in {0..8}; do
echo "$space${line[$index]}"
done
}
draw_right() {
local line[0]=' # '
local line[1]=' ## '
local line[2]=' #### '
local line[3]=' #######'
local line[4]=' ######## '
local line[5]=' ####### '
local line[6]=' ###### '
local line[7]=' ########## '
local line[8]='###########- '
local line[9]=' ########## '
local line[10]=' ###### '
local line[11]=' ####### '
local line[12]=' #######'
local line[13]=' #### '
local line[14]=' ## '
local line[15]=' # '
# Вычисляем сдвиг слева
space=""
for ((j = 0; j < $2; j++)) ; do
space="$space "
done
for index in {0..15}; do
echo "$space${line[$index]}"
done
}
draw_left() {
local line[0]=' # '
local line[1]=' ## '
local line[2]=' #### '
local line[3]='####### '
local line[4]=' ######## '
local line[5]=' ####### '
local line[6]=' ###### '
local line[7]=' ########## '
local line[8]=' -########### '
local line[9]=' ########## '
local line[10]=' ###### '
local line[11]=' ####### '
local line[12]='####### '
local line[13]=' #### '
local line[14]=' ## '
local line[15]=' # '
# Вычисляем сдвиг слева
space=""
for ((j = 0; j < $2; j++)) ; do
space="$space "
done
for index in {0..15}; do
echo "$space${line[$index]}"
done
}
move_right() {
if ((x < max_x - 15))
then
((x++))
else
wall=1
fi
tput cup $y 0
draw_right $y $x
}
move_bottom() {
if ((y < max_y - 8))
then
((y++))
else
wall=1
fi
tput cup $y 0
draw_bottom $y $x
}
move_left() {
if (( x > 0 ))
then
((x--))
else
wall=1
fi
tput cup $y 0
draw_left $y $x
}
move_top() {
if (( y > 0 ))
then
((y--))
else
wall=1
fi
tput cup $y 0
draw_top $y $x
}
random_choice() {
RANGE=$1
number=$RANDOM
let "number %= $RANGE"
echo "$number"
}
move() {
if [ "$1" == 0 ]
then
move_right
fi
if [ "$1" == 1 ]
then
move_left
fi
if [ "$1" == 2 ]
then
move_top
fi
if [ "$1" == 3 ]
then
move_bottom
fi
}
calculate_coords() {
let vertical=$1
# Вертикально -> Горизонтально
if (( vertical > 0))
then
x=$((x-8))
y=$((y+5))
if (( x < 0 ))
then
x=0
fi
if (( x + 31 > max_x))
then
x=$((max_x-31))
fi
if (( y + 8 > max_y))
then
y=$((max_y-8))
fi
# Горизонтально -> Вертикально
else
x=$((x+8))
y=$((y-5))
if (( y < 0 ))
then
y=0
fi
if ((x + 13 > max_x))
then
x=$((max_x - 13))
fi
if ((y + 17 > max_y))
then
y=$((max_y - 17))
fi
fi
}
start() {
current=0
direction=0
prevent_direction=0
clear
while true; do
# Calculate dicrection
if ((current == 20 || wall == 1))
then
wall=0
current=0
prevent_direction=$direction
direction=$(random_choice 4)
if (( direction < 2 && prevent_direction > 1 ))
then
calculate_coords 0
fi
if (( direction > 1 && prevent_direction < 2 ))
then
calculate_coords 1
fi
clear
fi
# Move
move $direction
current=$((current+1))
/bin/sleep .05
done
}
start
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question