diff options
Diffstat (limited to 'bin/fire')
| -rwxr-xr-x | bin/fire | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/bin/fire b/bin/fire new file mode 100755 index 0000000..b9c6c98 --- /dev/null +++ b/bin/fire @@ -0,0 +1,173 @@ +#!/bin/bash + +### +# ASCII fire + +# TODO: +# Better gradient for cooling flame. + +r=$'\e[31m' +y=$'\e[33m' +br=$'\e[1;31m' +by=$'\e[1;33m' +c=$'\e[0m' +bs=$'\e[1;30m' +#w=$'\e[37m' + +flame_gradient=( +# "$w#$c" + "$by@$c" + "$by#$c" + "$y#$c" + "$y@$c" + "$br@$c" + "$br#$c" + "$r#$c" +# "$bs($c" +# "$bs($c" +# "$bs)$c" +# "$bs.$c" + " " +) +# TODO: Use 256 color palette. + +declare -ia cells=() + +## +# init + +tput clear +n_rows=$(tput lines) +n_cols=$(tput cols) + +printf 'rows: %d\ncols: %d\n' "$n_rows" "$n_cols" + +#for cell in $(seq 0 $(((n_rows * n_cols) - 1))) +for ((cell=0;cell<n_rows*n_cols;++cell)) +do cells[cell]=0 +done + +### +# It is best if the bottom row is row #0. +# Even if the terminal is resized, +# there will always be a row #0. +# Of course this means the rows will be drawn in reverse order. +new_base_row(){ + # TODO: If the terminal is resized, re-evaluate the number of columns. +# for cell in $(seq 0 $((n_cols-1))) + declare -i delta=32 # ±16 + for ((cell=0;cell<n_cols;++cell)) + do cells[cell]=$(((cells[cell]+RANDOM%delta-(delta/2)+256)%256)) + done + # TODO: Adjust delta to size of terminal? Not sure how. +} + +# end init +## + +num_to_cell(){ + # Cells have a value between 0 and 255, inclusive. + # Arrays are 0-indexed. + echo -n "${flame_gradient[(255-$1)*${#flame_gradient[@]}/256]}" + # printf makes no apparent difference. +} + +## +# Compute the values of the indicated row +# from the values of the row below. +# Indicated row should not be the bottom row. +# TODO: Does a lot of repeatedly computing the same numbers; could be avoided. +burn_row(){ + declare -i row_number=$1 + declare -i cell + for ((cell=row_number*n_cols;cell<(row_number+1)*n_cols;++cell)) + do + cell_l=${cells[$cell-$n_cols-1]} + cell_b=${cells[$cell-$n_cols]} + cell_r=${cells[$cell-$n_cols+1]} + # The flames cool between rows. + cells[cell]=$(((cell_l+cell_b+cell_r)/3-(256/n_rows))) + [[ ${cells[cell]} -lt 0 ]] && cells[cell]=0 + done +} +# By burning iteratively, the entire array can be processed at once. +# It is only a matter of direction. + +burn(){ + declare -i cell cell_l cell_b cell_r + for ((cell=${#cells[@]}-1;cell>=n_cols;--cell)) + do + cell_l=${cells[$cell-$n_cols-1]} + cell_b=${cells[$cell-$n_cols]} # cell_l from previous iteration. + cell_r=${cells[$cell-$n_cols+1]} # cell_b from previous iteration. + # The flames cool between rows. + cells[cell]=$(((cell_l+cell_b+cell_r)/3-(256/n_rows))) + [[ ${cells[cell]} -lt 0 ]] && cells[cell]=0 + done +} + +print_all(){ +# Wrong order. This burns downwards. + declare -i cell + for cell in "${cells[@]}" + do + num_to_cell $cell + done +} + +print_rows(){ + declare -i row + for ((row=n_rows-1;row>=0;--row)) + do + # Print rows top to bottom: + tput cup $((n_rows-row)) 0 + print_row $row + # Print rows bottom to top: + # tput cup $row 0 + # print_row $((n_rows-1-row)) + done + # TODO: + # It should be more efficient to print all at once. +} + +print_row(){ + declare -i row=$1 + declare -i cell + for ((cell=row*n_cols;cell<(row+1)*n_cols;++cell)) + do + num_to_cell "${cells[cell]}" + done +} + +test_fire() { + # Saturate base row. + for ((cell=0;cell<n_cols;++cell)) + do cells[cell]=255 + done + # Print buffer. + tput cup 0 0 + print_rows + # Burn. + for ((counter=0;counter<n_rows;++counter)) + do + burn + print_rows + done +} + +## +# main + +#test_fire +#exit + +new_base_row +while : +do + burn + print_rows + new_base_row + tput cup 0 0 +# sleep 0.2 +# sleep 1 +done |
