πŸ“œ ⬆️ ⬇️

Playfully BASH'im further

The first article I. BASH'im top

image

Inspired by the reviews on the first article, I continued developing piu-piu. Intro \ menu appeared in the game, character-by-character appearance of objects was implemented, the color scheme was changed. The palette is now determined by the time of year, however, due to the lack of colors, we had to limit ourselves to 3 options: winter - the beginning of spring, spring - summer and autumn. Changes can be estimated by downloading the game here . Next, a few letters how it all happened.

Gif with new gameplay
image

I started with the implementation of character-by-character output. What could be easier? Just cut the sprite element, but ...
')
image

The control codes (color) will be cut off, and instead of a color symbol you will get porridge. It is necessary to reassemble the element of the sprite character by inserting the necessary control codes before each character. Having scored a fair amount of time with slices, I finally developed a similar algorithm. Test script:

#!/bin/bash #      . ~/SCR/color #   sprite=( '/Β―Β―Β―Β―Β―\' '| 0 |' '\_____/' ) #    sprite_color=( "$RED" "$GRN" "$BLU" ) #        function bye () { stty echo printf "${CON}${DEF}" clear ls --color=auto exit } function get_dimensions { size=($(stty size)) endx=${size[1]} endy=${size[0]} } #  get_dimensions X=$endx Y=$[$endy/2] sn=${#sprite[@]} #    sl=${#sprite[0]} #  ,     trap bye INT; stty -echo; printf "${COF}"; clear #  while true; do sleep 0.1; get_dimensions for (( p=0; p<${sn}; p++ )); do #     end=$[1-(${X}-${endx})] if [ $X -gt 0 ]; then bgn=0 XY ${X} $(($Y + $p)) \ #  |   "${sprite_color[$p]}${sprite[$p]:${bgn}:${end}} ${DEF}" else bgn=$[1-$X] XY 1 $(($Y + $p)) \ "${sprite_color[$p]}${sprite[$p]:${bgn}:${end}} ${DEF}" fi done ((X--)); [ $X -lt -${sl} ] && X=$endx done 

It turned out like this:

image

But this algorithm allows you to "paint" only the entire line, it was not the ultimate dream and did not match the existing coloring of the sprites. I had to sit still. The color table has expanded, each character has its own color. Each element of the color array is converted into a separate array, the indices of which coincide with the indices of the element of the sprite. Then the color element and the sprite element are drawn in the right place at the right time.

 #!/bin/bash . ~/SCR/color #    sprite=( ' /Β―Β―Β―Β―Β―\ ' '-----|12345|-------- ' ' --|12345|--- ' ' ----|12345|---- ' ' \_____/ ' ) #   ,      C01=$UND$BLU; C02=$UND$BLD$BLU C03=$DEF$MGN sprite_color=( "$DEF $DEF $DEF $DEF $DEF $DEF $DEF" "$DEF $RED $GRN $C01 $C03 $YLW $DEF $RED $DEF $DEF $DEF $BLU $DEF" "$DEF $RED $GRN $C02 $C03 $YLW $DEF $DEF $GRN $DEF $DEF $DEF $DEF" "$DEF $RED $GRN $C01 $C03 $YLW $DEF $DEF $DEF $BLU $DEF $DEF $DEF" "$DEF $DEF $DEF $DEF $DEF $DEF $DEF" ) function bye () { stty echo printf "${CON}${DEF}" clear ls --color=auto exit } function get_dimensions { size=($(stty size)) endx=${size[1]} endy=${size[0]} } get_dimensions X=$endx Y=$[$endy/2] L=1 sn=${#sprite[@]} sl=${#sprite[1]} trap bye INT; stty -echo; printf "${COF}"; clear while true; do sleep 0.1; get_dimensions ((L++)); ((X--)); [ $X -lt -${sl} ] && { X=$endx; L=1; } for (( p=0; p<${sn}; p++ )); do color=(${sprite_color[p]}); YY=$[$Y+${p}] #       if [ $X -gt 1 ]; then for (( k=0; k<${L}; k++ )); do XY $[${k}+${X}] ${YY} \ "${color[$k]}${sprite[$p]:$k:1}" done else for (( k=1; k<${sl}; k++ )); do XY ${k} ${YY} \ "${color[$[$k-$X]]}${sprite[$p]:$[$k-$X]}" done fi done done 

Now all characters can be multi-colored:

image

Fine! I decided to test how it would be drawn on top of another sprite. Added static sprite to main loop:

 for (( p=0; p<${sn}; p++ )); do XY 3 $[${endy}/2+${p}] "${sprite[$p]}" done 

And checked:

image

Normally, but if the back β€œmask” turns out by itself, then the front part is drawn by a square, rubbing everything, again squatting.

 #!/bin/bash . ~/SCR/color #      sprite=( 5' /Β―Β―Β―Β―Β―\ ' 0' -----|12345|-------- ' 3' --|12345|--- ' 1' ----|12345|---- ' 5' \_____/ ' ) #     sprite_color=( "$DEF" "$DEF $DEF $DEF $DEF $DEF $DEF $DEF $MGN $YLW $grn $RED $MGN $DEF" "$DEF $DEF $DEF $DEF $DEF $DEF $DEF $BLU $GRN $cyn $ylw $blu $DEF" "$DEF $DEF $DEF $DEF $DEF $DEF $DEF $YLW $RED $BLU $grn $YLW $DEF" "$DEF" ) function bye { stty echo printf "${CON}${DEF}" clear ls --color=auto exit } function get_dimensions { size=($(stty size)) endx=${size[1]} endy=${size[0]} } get_dimensions X=$endx Y=$[$endy/2] L=1 sn=${#sprite[@]} sl=${#sprite[1]} trap bye INT; stty -echo; printf "${COF}"; clear while true; do sleep 0.1; get_dimensions #   for (( p=0; p<${sn}; p++ )); do XY 3 $[${endy}/2+${p}] "${sprite[$p]}" done #   ((L++)); ((X--)) [ $X -lt -${sl} ] && { X=$endx; L=1; } for (( p=0; p<${sn}; p++ )); do #   color=(${sprite_color[p]}) #  Y YY=$[$Y+${p}] #   stp=${sprite[$p]:0:1} #   spr=${sprite[$p]:1} if [ $X -gt 1 ]; then for (( k=0; k<${L}; k++ )); do if [ $k -ge $stp ]; then XY $[${k}+${X}] ${YY} \ "${DEF}${color[$k]}${spr:$k:1}" fi done else for (( k=1; k<${sl}; k++ )); do XY ${k} ${YY} \ "${color[$[$k-$X]]}${spr:$[$k-$X]}" done fi done done 

Beauty!

image

Small lyrical digression
The mechanics of character output is built on slices. Sections are generally very convenient. They can be used for all sorts of cool pieces when working with text.

Bash allows you to make cuts of both variables and arrays. Example, variable slice:

 a=1234567890 #  3   echo ${a:3} 4567890 #  3    echo ${a:3:3} 456 #       ,    echo ${a:(-4)} 123456 echo ${a:(-5):(-2)} 678 

And now the array slice:
 a=( 1 2 3 4 5 6 7 8 9 0 ) #  3   echo ${a[*]:3} 4 5 6 7 8 9 0 #  3    echo ${a[*]:3:3} #    echo ${a[@]:(-5)} 6 7 8 9 0 #   -  echo ${a[@]:(-5):(-1)} bash: (-1):   < 0 

I remember in the days of the Spectrum you could not be called a cool coder, if you did not make a cool scroller. And all the cool guys did them (we too). In all demos there were scrollers with endless gatings, mats, jokes, jokes. It was a good time. Let's try to scroll the scroller on BASH using sections of course:

 #!/bin/bash #      XY . ~/SCR/color # ,    text=${1:-'Hello Wo00000o0000000o000orld! '}; N=${#text} #    function bye { stty echo printf "${CON}${DEF}" clear ls --color=auto exit } function get_dimensions { size=($(stty size)) endx=${size[1]} endy=${size[0]} } #  get_dimensions trap bye INT stty -echo printf "${COF}" X=$[$endx+1] Y=$[$endy/2] L=0; clear #  while true; do sleep 0.05; get_dimensions [ $X -gt 1 ] \ && XY $X $Y "${text:0:$L}" \ || XY 1 $Y "${text:$[1-$X]:$L}" [ $X -lt -$N ] && { X=$endx; L=0; } || ((X--)) [ $L -lt $endx ] && ((L++)) done 

Hello World!

image

And if you screw a figlet here, it will turn out generally good:

 #!/bin/bash . ~/SCR/color text=${1:-'Hello Wo00000o0000000o000orld! '}; N=${#text} function bye { stty echo printf "${CON}${DEF}" clear ls --color=auto exit } function get_dimensions { size=($(stty size)) endx=${size[1]} endy=${size[0]} } get_dimensions trap bye INT stty -echo printf "${COF}" IFSOLD=$IFS IFS=$'\n' #   figlet_text=( $(figlet -w$[$N*10] "${text}") ) IFS=$IFSOLD NF=${#figlet_text[1]} NFL=${#figlet_text[*]} X=$[$endx+1] Y=$[$endy/2-$NFL/2] L=0; clear while true; do sleep 0.05; get_dimensions if [ $X -gt 1 ]; then #      for ((i=0; i<$NFL; i++)); do XY $X $[$Y+$i] "${figlet_text[$i]:0:$L}" done else for ((i=0; i<$NFL; i++)); do XY 1 $[$Y+$i] "${figlet_text[$i]:$[1-$X]:$L}" done fi [ $X -lt -$NF ] && { X=$endx; L=0; } || ((X--)) [ $L -lt $endx ] && ((L++)) done 

There is one subtlety. I redefine the delimiter character. The default delimiters are: space, tab, line break. All this is stored in the system variable IFS . I remember the old meaning:

 IFSOLD=$IFS 

Then I set the delimiter only the line break \ n :

 IFS=$'\n' 

I drop the text into the array figlet_text with the command:

 figlet_text=( $(figlet -w$[$N*10] "${text}") ) 

The -w switch sets the width of the string because by default, it writes text to the screen. This adds unnecessary transitions to the string, and the miracle does not occur. Well, I return the old value of the separator:

 IFS=$IFSOLD 

A scroller scroller!

image

So, sprites are cut, rather push this algorithm into the game! I tried and oh ... very much upset. The speed, to put it mildly, left much to be desired:

image

Multiple nested loops have a negative effect on speed (suddenly). But I tried without trees, clouds and other tinsel, mda.

But after so many squattings, I didn’t want to throw the idea out into the dustbin. Mosk started working. A solution was found. Use both methods! Juha! The appearance / disappearance of the characters and the flight on the screen "fast" method. The loop of objects now looks like this:

 NO=${#OBJ[@]} for (( i=0; i<$NO; i++ )); do OI=(${OBJ[$i]}) OX=${OI[0]} OY=${OI[1]} cuter=${OI[2]} type=${OI[3]} case $type in #    (\) #  1   "tree1" ) sprite=("${tree1[@]}") #    sprite_color=("${tree1_color[@]}") #   sprite_fast=("${tree12[@]}") #  -  # +---------+------+------+------+ # |  |||| # +---------+------+------+------+ mover $Q 4 4;; #  2 "tree2" ) sprite=("${tree2[@]}") sprite_color=("${tree2_color[@]}") sprite_fast=("${tree22[@]}") mover $W 6 6;; #  3 "tree3" ) sprite=("${tree3[@]}") sprite_color=("${tree3_color[@]}") sprite_fast=("${tree32[@]}") mover $E 9 10;; #  1 "cloud1") sprite=("${cloud1[@]}") sprite_color=("${cloud1_color[@]}") sprite_fast=("${cloud12[@]}") mover $Q 3 7;; #  2 "cloud2") sprite=("${cloud2[@]}") sprite_color=("${cloud2_color[@]}") sprite_fast=("${cloud22[@]}") mover $W 3 9;; #  3 "cloud3") sprite=("${cloud3[@]}") sprite_color=("${cloud3_color[@]}") sprite_fast=("${cloud32[@]}") mover $E 3 12;; #  "alien" ) sprite=("${alien[@]}") sprite_color=("${alien_color[@]}") sprite_fast=("${alien2[@]}") mover 0 3 5;; #      #   #   "bfire" ) sprite=("${bfire[@]}") #  -  # +---------+------+------+------+ # |  |||| # +---------+------+------+------+ mover 0 6 4;; #  -  "ammo" ) sprite=("${ammob[@]}") mover 0 3 4;; #  -  "life" ) sprite=("${lifep[@]}") mover 0 3 4;; #  -   "gunup" ) sprite=("${gunup[@]}") mover 0 3 4;; # ,  ,  1  "boom" ) er=${boomC} for part in "${boom[@]:$B:$boomC}"; do stp=${part:0:1} spr=${part:1} XY $[${OX} + $stp] ${OY} "${spr}"; ((OY++)) done [ ${E} = 0 ] && { ((B+=${boomC})) [ $B -gt ${boomN} ] && { B=0; erase_obj ${i}; }; };; esac; done 

But the mover function:

 function mover () { er=$2 # -   width=$3 #   #   [ ${1} = 0 ] && { ((OX--)) ((cuter++)) OBJ[$i]="$OX $OY $cuter $type" } #     case ${type} in 'alien'|'tree'[1-3]|'cloud'[1-3]) [ $OX -lt -$width ] && { remove_obj ${i} case ${type} in "alien") ((enumber--));; esac; return };; *) [ $OX -lt 1 ] && { erase_obj ${i} case ${type} in "alien") ((enumber--));; esac; return; };; esac #  for (( p=0; p<${er}; p++ )); do case ${type} in # \  'alien'|'tree'[1-3]|'cloud'[1-3]) color=(${sprite_color[$p]}) YY=$[$OY+${p}] stp=${sprite[$p]:0:1} spr=${sprite[$p]:1} # \ if [ $OX -gt 1 ]; then if [ $cuter -lt $width ]; then # ,   for (( k=0; k<${cuter}; k++ )); do if [ $k -ge $stp ]; then XY $[$k+$OX] $YY \ "${color[$k]}${spr:$k:1}" fi done else # ,     stp=${sprite_fast[$p]:0:1} spr=${sprite_fast[$p]:1} XY $[${OX} + $stp] $[$OY + $p] "${spr}" fi #  else #   for (( k=1; k<${width}; k++ )); do x=$[$k-$OX] XY $k $YY "${color[$x]}${spr:$x}" done fi;; #    *) XY ${OX} $[$OY + $p] "${sprite[$p]}";; esac #   case ${type} in "gunup" ) case "$[$OY + $p] $OX" in "$HY $HX") [ ${G} -lt 4 ] && ((G++)) erase_obj ${i} break;; esac;; "life" ) case "$[$OY + $p] $OX" in "$HY $HX") ((life++)) erase_obj ${i} break;; esac;; "ammo" ) case "$[$OY + $p] $OX" in "$HY $HX") ((ammo+=100)) erase_obj ${i} break;; esac;; "bfire" ) case "$OY $OX" in "$HY $HX") ((life--)) erase_obj ${i} break;; esac;; "alien" ) #    for (( t=0; t<${NP}; t++ )); do case "$[$OY + 1] $[$OX + $p]" in "${PIU[$t]}") #  ? if [ $[RANDOM % $rnd] -eq 0 ]; then OBJ+=("$OX $OY 0 ${bonuses[$[RANDOM % \ ${#bonuses[@]}]]}") ((frags++)) ((enumber--)) remove_obj ${i} remove_piu ${t} OBJ+=("${OX} ${OY} 0 boom") break fi;; esac done #    case "$[$OY + 1] $[$OX + $p]" in "$HY $HX") ((life--)) ((frags++)) ((enumber--)) remove_obj ${i} OBJ+=("${OX} ${OY} 0 boom") break;; esac;; esac done } 

I had to draw 2 sets of sprites for both methods of withdrawal. And limit the number of simultaneously departing objects. For others, I added timing to the appearance condition. And trees \ clouds reduced the likelihood of occurrence. Here are the sprites turned out, for example, a tree:

 # ""  tree3=( 3' _._ ' 2' / \ ' 1' _\ | / ' 0'/ \β•‘/__ ' 0'\_\/β•‘/ \ ' 3' \β•‘|/_/ ' 4' β•‘/ ' 4' β•‘ ' 4' β•‘ ') #         case $month in 0[1-4]|12) CLR=${cyn} ;; #  0[5-8] ) CLR=${BLD}${GRN};; #  09|1[0-1]) CLR=${DIM}${red};; #  esac CM1=${SKY}${BLK} tree3_color=( "${SKY} ${SKY} ${SKY} ${CLR} ${CLR} ${CLR} ${SKY}" "${SKY} ${SKY} ${CLR} ${SKY} ${SKY} ${SKY} ${CLR} ${SKY}" "${SKY} ${CLR} ${CLR} ${SKY} ${CM1} ${SKY} ${CLR} ${SKY}" "${CLR} ${SKY} ${SKY} ${CLR} ${CM1} ${CLR} ${CLR} ${CLR} ${SKY}" "${CLR} ${CLR} ${CM1} ${CLR} ${CM1} ${CLR} ${SKY} ${SKY} ${CLR} ${SKY}" "${SKY} ${SKY} ${SKY} ${CM1} ${CM1} ${CLR} ${CM1} ${CLR} ${CLR} ${SKY}" "${SKY} ${SKY} ${SKY} ${SKY} ${CM1} ${CM1} ${SKY}" "${SKY} ${SKY} ${SKY} ${SKY} ${CM1} ${SKY}" "${SKY} ${SKY} ${SKY} ${SKY} ${CM1} ${SKY}") # ""  tree32=( 3${CLR}'_._ '${SKY} 2${CLR}'/ \ '${SKY} 1${CLR}'_\ '${CM1}'|'${CLR}' / '${SKY} 0${CLR}'/ \\'${CM1}'β•‘'${CLR}'/__ '${SKY} 0${CLR}'\_'${CM1}'\\'${CLR}'/'${CM1}'β•‘'${CLR}'/ \ '${SKY} 3${BLK}'\β•‘'${CLR}'|'${CM1}'/'${CLR}'_/ '${SKY} 4${BLK}'β•‘/ '${SKY} 4${BLK}'β•‘ '${SKY} 4${BLK}'β•‘ '${SKY}) 

And here we smoothly move on to the next feature. The main color of trees, clouds and background varies with the seasons. The time of year is determined by the month. The month is determined by the date :
 month=$(date +'%m') 

At different times of the year the game will look different. Now, autumn:

image

And soon it will be so, winter - the beginning of spring:

image

And it will not be so soon. Spring Summer:

image

But cheaters can do this:

 month=07 

Yes, the bullet can increase to x5, and the boss has grown a bit.
But this intro \ menu appeared in the game:

image

But here, too, not everything was smooth in terms of speed. Large sprites, even one by one, were terribly slowed down in the character-by-character output mode. I had to do squats again, yes.
I decided to cut the sprites into pieces of 3 characters each and display them in the β€œfast” method:

 D=$DEF; C1=$BLU; C2=$RED; C3=$YLW; C4=$red C5=$BLD$YLW; C6=$BLD$GRN; C7=$blu; C8=$BLD$RED # β–‘ β–‘β–‘β–‘ β–‘β–‘ β–‘ β–‘β–‘ β–‘β–‘ β–‘β–‘ β–‘ # β–‘ β–‘ β–’β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–‘β–’β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–’β–ˆβ–ˆβ–‘ β–’β–ˆβ–ˆ # β–‘ β–‘β–‘β–’β–“β–ˆβ–ˆ β–’β–“β–ˆβ–ˆ β–“β–“β–“β–ˆβ–ˆβ–“ β–’β–“β–ˆβ–ˆ β–‘β–’β–“β–ˆβ–ˆβ–‘β–‘ β–‘ #β–‘ β–‘ β–‘β–‘β–’β–“β–ˆβ–ˆ β–’β–“β–ˆβ–ˆ β–’β–’β–’β–“β–ˆβ–ˆ β–‘β–’β–“β–ˆβ–ˆβ–‘ β–’β–“β–ˆβ–ˆβ–‘ # β–’β–“β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘ β–‘β–’β–“β–ˆβ–ˆ β–‘β–’β–“β–ˆβ–ˆ β–‘β–’β–“β–ˆβ–ˆβ–‘β–‘ β–‘ β–‘ # β–‘ β–’β–“β–ˆβ–ˆβ–“β–“β–“β–“ β–‘ β–’β–“β–ˆβ–ˆβ–‘ β–’β–“β–ˆβ–ˆβ–‘β–‘β–’β–“β–ˆβ–ˆ β–‘ # β–’β–“β–ˆβ–ˆβ–ˆβ–ˆβ–’β–’β–’β–‘ β–‘ β–“β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–’β–“β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–‘β–‘ β–‘ #β–‘ β–‘β–’β–“β–“β–“β–“ β–‘ β–‘β–‘β–’β–“β–“β–“β–“β–“β–“ β–‘ β–’β–“β–“β–“β–“β–“β–‘ # β–‘ β–’β–’ β–‘ β–‘ β–‘ β–‘β–’β–’β–’β–’β–’β–’ β–‘ β–‘β–‘β–’β–’β–’β–’β–‘ β–‘ piu=( "$C1 " "β–‘ " " β–‘β–‘" "β–‘ β–‘" "β–‘ " " " "β–‘ " "β–‘β–‘ " " " " β–‘" "β–‘ " "β–‘β–‘ " "β–‘$D " " " "$C1 β–‘ " " β–‘" " $C2β–’" "$C3β–ˆβ–ˆβ–ˆ" "β–ˆβ–ˆβ–ˆ" " $C1β–‘$C2β–’" "$C3β–ˆβ–ˆβ–ˆ" "β–ˆβ–ˆβ–ˆ" " $C2β–’$C3β–ˆ" "β–ˆ$C1β–‘ " " $C2β–’$C3β–ˆ" "β–ˆ$D " " " " " "$C1 " "β–‘ β–‘" "β–‘$C2β–’$C4β–“" "$C3β–ˆβ–ˆ " "$C2β–’$C4β–“$C3β–ˆ" "β–ˆ $C4β–“" "β–“β–“$C3β–ˆ" "β–ˆ$C4β–“ " "$C1β–’$C4β–“$C3β–ˆ" "β–ˆ $C1β–‘" "$C2β–’$C4β–“$C3β–ˆ" "β–ˆ$C1β–‘β–‘" " β–‘$D " " " "$C1β–‘ β–‘" " β–‘β–‘" "$C2β–’$C4β–“$C3β–ˆ" "β–ˆ $C2β–’" "$C4β–“$C3β–ˆβ–ˆ" " $C2β–’β–’" "β–’$C4β–“$C3β–ˆ" "β–ˆ $C2β–‘" "β–’$C4β–“$C3β–ˆ" "β–ˆ$C1β–‘ " "$C2β–’$C4β–“$C3β–ˆ" "β–ˆ$C1β–‘$D " " " " " "$C1 " " " "$C2β–’$C4β–“$C5β–ˆ" "β–ˆβ–ˆβ–ˆ" "β–ˆβ–ˆ$C1β–‘" " β–‘$C2β–’" "$C4β–“$C3β–ˆβ–ˆ" " $C1β–‘$C2β–’" "$C4β–“$C3β–ˆβ–ˆ" " $C1β–‘$C2β–’" "$C4β–“$C3β–ˆβ–ˆ" "$C1β–‘β–‘ " "β–‘ β–‘$D" " " "$C1 β–‘" " $C2β–’" "$C4β–“$C3β–ˆβ–ˆ" "$C4β–“β–“β–“" "β–“ " "$C1β–‘ $C2β–’" "$C4β–“$C3β–ˆβ–ˆ" "$C1β–‘ $C2β–’" "$C4β–“$C3β–ˆβ–ˆ" "$C1β–‘β–‘$C2β–’" "$C4β–“$C3β–ˆβ–ˆ" " $C1β–‘$D " " " " " "$C2 " "β–’$C4β–“$C3β–ˆ" "β–ˆβ–ˆβ–ˆ" "$C2β–’β–’β–’" "$C1β–‘ β–‘" " $C4β–“$C3β–ˆ" "β–ˆβ–ˆβ–ˆ" "β–ˆβ–ˆ " "$C1β–’$C4β–“$C3β–ˆ" "β–ˆβ–ˆβ–ˆ" "β–ˆβ–ˆ$C1β–‘" "β–‘ β–‘$D" " " " " "$C1β–‘ β–‘" "$C2β–’$C4β–“β–“" "β–“β–“ " "$C1β–‘ β–‘" "β–‘$C2β–’$C4β–“" "β–“β–“β–“" "β–“β–“ " "$C1β–‘ $C2β–’" "$C4β–“β–“β–“" "β–“β–“$C1β–‘$D" " " " " " " " " "$C1 β–‘ " "β–’β–’ " "β–‘ β–‘" " β–‘ " "β–‘β–’β–’" "β–’β–’β–’" "β–’ β–‘" " β–‘β–‘" "β–’β–’β–’" "β–’β–‘ " " β–‘ " " " " " "$D ") piuN=${#piu[*]}; piuC=14 # β–‘β–‘ β–’β–’β–ˆβ–ˆβ–ˆβ–‘ # β–‘β–‘β–‘ β–’β–ˆβ–ˆβ–ˆβ–ˆ β–’β–“β–ˆβ–ˆβ–ˆβ–‘ # β–‘ β–’β–ˆβ–ˆβ–ˆβ–ˆβ–’β–“β–“β–“β–“ β–‘β–‘β–’β–“β–“β–ˆβ–ˆβ–ˆ β–‘β–‘ β–‘ #β–‘ β–’β–“β–“β–“β–“ β–’β–ˆβ–ˆβ–ˆβ–ˆβ–‘β–’β–“β–ˆβ–ˆβ–ˆβ–‘β–‘ # β–’ β–’β–’ β–’β–“β–“β–“β–“β–’β–“β–ˆβ–ˆβ–ˆβ–‘ # β–‘β–‘β–‘ β–’β–’β–’ β–‘β–‘β–’β–’β–‘ arr=( " " " " " " " " " $C7β–‘β–‘" " $C3β–’β–’" "$C6β–ˆβ–ˆβ–ˆ" "$C7β–‘$D " "" "" " " " " " $C7β–‘" "β–‘β–‘ " "$C2β–’$C8β–ˆβ–ˆ" "β–ˆβ–ˆ " "$C7β–’$C3β–“$C6β–ˆ" "β–ˆβ–ˆ$C7β–‘$D" "" "" " " " $C7β–‘ " "β–’$C8β–ˆβ–ˆ" "β–ˆβ–ˆ$D$C2β–’" "$C3β–“β–“β–“" "β–“ $C7β–‘" "β–‘$C7β–’$C3β–“" "β–“$C6β–ˆβ–ˆ" "β–ˆ $C7β–‘" "β–‘ β–‘$D" " " "$C7β–‘ $C2β–’" "$C3β–“β–“β–“" "β–“ $C2β–’" "$C8β–ˆβ–ˆβ–ˆ" "β–ˆ$D$C7β–‘$C3β–’" "$C3β–“$C6β–ˆβ–ˆ" "β–ˆ$C7β–‘β–‘$D" " " "" " " " $C7β–’ " "β–’β–’ " " $C2β–’$C3β–“" "β–“β–“β–“" "$C7β–’$C3β–“$C6β–ˆ" "β–ˆβ–ˆ$C7β–‘$D" " " "" "" " " " " " $C7β–‘β–‘" "β–‘ β–’" "β–’β–’ " "β–‘β–‘β–’" "β–’β–‘$D " " " "" "") arrN=${#arr[*]}; arrC=10 

All this beauty is drawn with its left , right and intro functions:

 function left () { N=$1; C=$2 # move [ $OX -ge $end ] && { ((OX-=3)); [ $cuter -ne $C ] && ((cuter++)) for ((j=0; j<$N; j+=$C)); do line=("${sprite[@]:$j:$cuter}") YY=$[$OY+$j/$C]; spr= for part in "${line[@]}"; dospr+="${part}"; done XY $OX $YY "${spr}" done; OBJ[$i]="$OX $OY $cuter $end $type $pause" } || { remove_obj $i; ((Q++)); OBJ+=("${scenario[$Q]}"); } } function right () { N=$1; C=$2 # move [ $OX -le $end ] && { [ $cuter -ne $C ] && ((cuter++)) || ((OX+=3)) for ((j=0; j<$N; j+=$C)); do line=("${sprite[@]:$j:$C}") YY=$[$OY+$j/$C]; spr= for ((k=$[$C-$cuter]; k<$C; k++)); do spr+="${line[k]}"; done XY $OX $YY "${spr}" done; OBJ[$i]="$OX $OY $cuter $end $type $pause" } || { remove_obj $i; ((Q++)); OBJ+=("${scenario[$Q]}"); } } function intro { get_dimensions; Q=0 scenario=( #    #----------+-------+-----+------------+----+ #  X | Y||  X | | #----------+-------+-----+------------+----+ "$[$endx+1] 3 0 $[endx/2-34] piu" "$[$endx+1] 3 0 $[endx/2+2] piu" "-2 12 0 $[endx/2-16] arr" "0 0 0 0 end") OBJ=("${scenario[$Q]}") while true; do sleep 0.005; NO=${#OBJ[@]} for (( i=0; i<$NO; i++ )); do OI=(${OBJ[$i]}); OX=${OI[0]}; OY=${OI[1]} cuter=${OI[2]}; end=${OI[3]}; type=${OI[4]} case $type in #-----+-------------------+------+------+------+ # |  |.||| #-----+-------------------+------+------+------+ "arr") sprite=("${arr[@]}"); right $arrN $arrC;; "piu") sprite=("${piu[@]}"); left $piuN $piuC;; "end") return ;; esac done done } 

The sequence of the appearance of objects is specified in the scenario array. The menu item conf allows customization of the (small) airplane. You can change the color of the airplane and the symbol on the tail (and its color).

image

And a handful of minor improvements \ corrections in the course of writing two articles (to the word about the benefits of articles). Then I want to work on optimization, raise the FPS and try to implement a cooperative network, to be continued. That's all for now (I heard it somewhere).

Continued I. BASH'im together

Piu, piu, piu! :)

Source: https://habr.com/ru/post/337896/


All Articles