您的位置:首页 > 其它

脚本游戏之四: 坦克大战源码注释(待续。。。)

2016-04-15 18:54 603 查看
要点:
1、echo的高级用法,主要包括:颜色、位置定位输出等
2、trap 信号捕捉, kill 发送信号
3、捕捉用户输入,控制后台进程
参考:坦克大战 文章结尾的几段代码

总体:
多个进程后台并行运行, 前端一个段接受用户输入的代码,根据用户输入通过发送信号控制后台进程。
几乎每一个组件都是一个后台运行的函数。




#!/bin/bash
# BY: LingYi
# DATE: 2016.02.23

#place temporary files
tmpdir='/tmp'

#u:up d:down l:left r:right
boundary_u=2
boundary_d=26
boundary_l=3
boundary_r=80

boundary_color=45
smallboundary_color=34
#

#about time (second)
#about color (x0:black x1:red  x2:green x3:Orange x4:blue x5:pink x6:light blue) x=[3|4]

#about tank
#if enemy_tank_color is empty, it will be random value of enemy_tank_color_type.
enemy_tank_color_type=( 41 43 43 45 44 46 )
enemy_tank_color=''

#level: 0    1  ..  8   9   10   11   ..  18  19 (20)
#time : 1.0 0.9 .. 0.2 0.1 0.09 0.08  .. 0.01 0
game_level=9

my_tank_color=42

#about bullet
enemy_bullet_color=41
enemy_bullet_speed=0.02

my_bullet_color=41
my_bullet_speed=0

#after tank dead, next will appear
next_tank_interval_time=0.5

#about death symbol
symbol_keep_time=1

#game PID
MYPID=$$

#
#SIGNAL: [20-31] [35-36]
#stop enemy tank signal: 20 (PID: $run_enemytank_pid)
#enemy tank be hitted: 22 (PID: $run_enemytank_pid)
#enemy tank pause: 23 (PID: $run_enemytank_pid)
#enemy tank continue after pause: 24 (PID: $run_enemytank_pid)
#enemy tank level/speed up: 28 (PID: $run_enemytank_pid)
#enemy tank level/slow down: 29 (PID: $run_enemytank_pid)
#stealth mode: 35 (PID: $run_enemytank_pid)
#cancel stealth mode: 36 (PID: $run_enemytank_pid)

#game over: 21 (PID: $MYPID)
#mytank pause: 25 (PID: $MYPID)
#mytank continue: 26 (PID: $MYPID)

#for "LingYi" components: 27 (PID: run_print_mywords_pid)
#for "infor" components: 30 (PID: run_print_infors_pid)
#for "Dtime" components: 31 (PID: run_print_dtime_pid)

#components [ true|false ]
print_mode=true
print_infor=true
print_LingYi=true
print_dtime=true
print_roll=true

expressions=('o(-"-)o' '^*(- -)*^' '($ _ $)' '(^O^)' 'Y(^_^)Y')
string1="you are so smart !"
string2="you are really talented !"
string3="Come on, boy !"
string4="I believe you will win !"
string5="Keep up the good work !"
strings=("$string1" "$string2" "$string3" "$string4" "$string5")
gameover_string="Stupid guy ~~ ha-ha !!!"
#

infor1="The game is running !"
infor2='Press "C" to continue !'
infor3='Press "P" to pause game !'
infor4='Press "U" to level up !'
infor5='Press "L" to slow down ! '
infor6='Press "Q" to end the game !'
infor7='Press "F" to kill one tank !'
infor8='Press "G" to open/close Stealth Mode !'
infor9='Press "V" to open/close God Mode '
infor10='press "N" to kill all tanks !'
infor11='if pressed "N", press M to close it !'
infor12='Press Space or Enter key to shoot !'
infors=("$infor1" "$infor2" "$infor3" "$infor4" "$infor5" "$infor6" "$infor7"\
${infors[@]} "$infor7" "$infor9" "$infor10" "$infor11" "$infor12")

roll_words="Tank Game  LingYi 2016.03.01 Y(^_^)Y"
# Positions of Enemytanks:
# =============================
# | 0           4           2 |
# |      9(random)            |
# | 7           8           5 |
# |                           |
# | 1           6           3 |
# =============================
#Define random positions, if allow using.
#value [ yes|no ]
random_9_position="yes"
random_8_position="no"
random_7_position="yes"
random_6_position="yes"
random_5_position="yes"
random_4_position="yes"
random_3_position="yes"
random_2_position="yes"
random_1_position="yes"
random_0_position="yes"

#get random direction.
GetRandDirect()
{
case $[RANDOM%4] in
0) echo u;;
1) echo d;;
2) echo l;;
3) echo r;;
esac;
}

#display and record in the file.
#HandleTank {-d|-c} "x;y" {u|d|l|r} enemy/my
HandleTank()
{
local hp=($(echo "$2" | awk -F';' '{print $1,$2}'))
local body body_col
body[0]="$2"
case $3 in
'u')
body[1]="$((hp[0]+1));$((hp[1]-1))"
body[2]="$((hp[0]+1));$((hp[1]+1))"
body[3]="$((hp[0]+2));$((hp[1]-1))"
body[4]="$((hp[0]+2));$((hp[1]+1))"
;;
'd')
body[1]="$((hp[0]-1));$((hp[1]+1))"
body[2]="$((hp[0]-1));$((hp[1]-1))"
body[3]="$((hp[0]-2));$((hp[1]+1))"
body[4]="$((hp[0]-2));$((hp[1]-1))"
;;
'l')
body[1]="$((hp[0]+1));$((hp[1]+1))"
body[2]="$((hp[0]-1));$((hp[1]+1))"
body[3]="$((hp[0]+1));$((hp[1]+2))"
body[4]="$((hp[0]-1));$((hp[1]+2))"
;;
'r')
body[1]="$((hp[0]-1));$((hp[1]-1))"
body[2]="$((hp[0]+1));$((hp[1]-1))"
body[3]="$((hp[0]-1));$((hp[1]-2))"
body[4]="$((hp[0]+1));$((hp[1]-2))"
;;
esac
if [[ $1 == '-c' ]]; then
local i
for((i=0; i<5; i++)); do
echo -ne "\033[${body[i]}H \033[0m"
done
return
fi
case $4 in
"enemy")
body_col=$seted_enemy_tank_color
body_symbol=(' ' ' ' ' ' ' ' ' ')
echo "${body[@]}" >${tmpdir}/enemybody ;;
"my" )
body_col=$my_tank_color
body_symbol=('*' '*' '*' '*' '*')
echo "${body[@]}" >${tmpdir}/mybody    ;;
*    )  : ;;
esac
for((i=0; i<5; i++)); do
echo -ne "\033[${body[i]}H\033[${body_col}m${body_symbol[i]}\033[0m"
done
}
DisplayRandTank()
{
local positions='0123456789'
[[ ${random_9_position} == "no" ]] && positions=$(echo $positions | sed "s/9//")
[[ ${random_8_position} == "no" ]] && positions=$(echo $positions | sed "s/8//")
[[ ${random_7_position} == "no" ]] && positions=$(echo $positions | sed "s/7//")
[[ ${random_6_position} == "no" ]] && positions=$(echo $positions | sed "s/6//")
[[ ${random_5_position} == "no" ]] && positions=$(echo $positions | sed "s/5//")
[[ ${random_4_position} == "no" ]] && positions=$(echo $positions | sed "s/4//")
[[ ${random_3_position} == "no" ]] && positions=$(echo $positions | sed "s/3//")
[[ ${random_2_position} == "no" ]] && positions=$(echo $positions | sed "s/2//")
[[ ${random_1_position} == "no" ]] && positions=$(echo $positions | sed "s/1//")
[[ ${random_0_position} == "no" ]] && positions=$(echo $positions | sed "s/0//")
local rand_direct=$(GetRandDirect)
local rand_pos
while :
do
rand_pos=$[RANDOM%10]
echo $positions | grep -q $rand_pos && break
done

#set enemy tank body color
if [[ -z $enemy_tank_color ]]; then
seted_enemy_tank_color=${enemy_tank_color_type[$(( RANDOM % ${#enemy_tank_color_type[@]} ))]}
else
seted_enemy_tank_color=$enemy_tank_color
fi

PositionNine(){
local hand_1 hand_2
while :
do
head_1=$((RANDOM%boundary_d))
[[ $head_1 -ge $(( boundary_u+3)) ]] && [[ $head_1 -le $(( boundary_d-3 )) ]] && break
done
while :
do
head_2=$((RANDOM%boundary_r))
[[ $head_2 -ge $(( boundary_l+3)) ]] && [[ $head_2 -le $(( boundary_r-3 )) ]] && break
done
hp="${head_1};${head_2}"
}
case $rand_direct in
'u')
case $rand_pos in
0) hp="$(( boundary_u+1 ));$(( boundary_l+2 ))" ;;
1) hp="$(( boundary_d-3 ));$(( boundary_l+2 ))" ;;
2) hp="$(( boundary_u+1 ));$(( boundary_r-2 ))" ;;
3) hp="$(( boundary_d-3 ));$(( boundary_r-2 ))" ;;
4) hp="$(( boundary_u+1 ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
5) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( boundary_r-2 ))" ;;
6) hp="$(( boundary_d-3 ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
7) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( boundary_l+2 ))" ;;
8) hp="$(( (boundary_d-boundary_u)/2+boundary_u));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
9) PositionNine ;;
esac ;;
'd')
case $rand_pos in
0) hp="$(( boundary_u+3 ));$(( boundary_l+2 ))" ;;
1) hp="$(( boundary_d-1 ));$(( boundary_l+2 ))" ;;
2) hp="$(( boundary_u+3 ));$(( boundary_r-2 ))" ;;
3) hp="$(( boundary_d-1 ));$(( boundary_r-2 ))" ;;
4) hp="$(( boundary_u+3 ));$(( (boundary_r-boundary_l)/2+boundary_l  ))" ;;
5) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( boundary_r-2 ))" ;;
6) hp="$(( boundary_d-1 ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
7) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( boundary_l+2 ))" ;;
8) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
9) PositionNine ;;
esac ;;
'l')
case $rand_pos in
0) hp="$(( boundary_u+2 ));$(( boundary_l+1 ))" ;;
1) hp="$(( boundary_d-2 ));$(( boundary_l+1 ))" ;;
2) hp="$(( boundary_u+2 ));$(( boundary_r-3 ))" ;;
3) hp="$(( boundary_d-2 ));$(( boundary_r-3 ))" ;;
4) hp="$(( boundary_u+2 ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
5) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( boundary_r-3 ))" ;;
6) hp="$(( boundary_d-2 ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
7) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( boundary_l+1 ))" ;;
8) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
9) PositionNine ;;
esac ;;
'r')
case $rand_pos in
0) hp="$(( boundary_u+2 ));$(( boundary_l+3 ))" ;;
1) hp="$(( boundary_d-2 ));$(( boundary_l+3 ))" ;;
2) hp="$(( boundary_u+2 ));$(( boundary_r-1 ))" ;;
3) hp="$(( boundary_d-2 ));$(( boundary_r-1 ))" ;;
4) hp="$(( boundary_u+2 ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
5) hp="$(( (boundary_d-boundary_u)/2 ));$(( boundary_r-1 ))" ;;
6) hp="$(( boundary_d-2 ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
7) hp="$(( (boundary_d-boundary_u)/2+boundary_u ));$(( boundary_l+3 ))" ;;
8) hp="$(( (boundary_d-boundary_u)/2+boundary_ ));$(( (boundary_r-boundary_l)/2+boundary_l ))" ;;
9) PositionNine ;;
esac ;;
esac

enemytank_direct=$rand_direct
first_moving=true

#clean up the small boundary
local n m
for n in 1 2 3 4 5
do
for m in 4 5 6 7 8 9 10
do
echo -ne "\033[$((boundary_u+n));$((boundary_r+m))H*\033[0m"
done
done
#display a tank model in small boundary
case $enemytank_direct in
'u') small_boundary_tank_head="$((boundary_u+2));$((boundary_r+7))" ;;
'd') small_boundary_tank_head="$((boundary_u+4));$((boundary_r+7))" ;;
'l') small_boundary_tank_head="$((boundary_u+3));$((boundary_r+6))" ;;
'r') small_boundary_tank_head="$((boundary_u+3));$((boundary_r+8))" ;;
esac
HandleTank -d "$small_boundary_tank_head" $enemytank_direct enemy

HandleTank -d "$hp" $enemytank_direct enemy

}

#get a new position from new, old direction and an old position.
#GetNewPos $newdirect $olddirect $headpoint(x y)
GetNewPos(){
local new_head=($3 $4)

case $1 in
'u')
case $2 in
'u') [[ new_head[0] -gt $((boundary_u+1)) ]] && (( new_head[0]-=1 ));;
'd') (( new_head[0]-=2 ));;
'l') (( new_head[0]-=1 )); (( new_head[1]+=1 ));;
'r') (( new_head[0]-=1 )); (( new_head[1]-=1 ));;
esac
;;
'd')
case $2 in
'u') (( new_head[0]+=2 ));;
'd') [[ new_head[0] -lt $((boundary_d-1)) ]] && (( new_head[0]+=1 ));;
'l') (( new_head[0]+=1 )); (( new_head[1]+=1 ));;
'r') (( new_head[0]+=1 )); (( new_head[1]-=1 ));;
esac
;;
'l')
case $2 in
'u') (( new_head[0]+=1 )); (( new_head[1]-=1 ));;
'd') (( new_head[0]-=1 )); (( new_head[1]-=1 ));;
'l') [[ new_head[1] -gt $((boundary_l+1)) ]] && (( new_head[1]-=1 ));;
'r') (( new_head[1]-=2 ));;
esac
;;
'r')
case $2 in
'u') (( new_head[0]+=1 )); (( new_head[1]+=1 ));;
'd') (( new_head[0]-=1 )); (( new_head[1]+=1 ));;
'l') (( new_head[1]+=2 ));;
'r') [[ new_head[1] -lt $((boundary_r-1)) ]] && (( new_head[1]+=1 ));;
esac
;;
esac
echo "${new_head[@]}"
}

#it run in background
MoveEnemyTank(){

local upgrade_count=10
local bullet_interval=10   #default value
local bullet_interval_range=20
local StopEnemyTank=false
local BeHitted=false
local PauseEnemyTank=false
local game_score=0
local old_game_score=0
local ignore_other_tank=false
local kill_myself=false
local kill_myself_always=false
local god_mode=false
local kill_once_by_god=false

trap 'StopEnemyTank=true' 20
trap 'BeHitted=true' 22
trap 'PauseEnemyTank=true' 23
trap 'PauseEnemyTank=false; print_running' 24
trap '[[ $game_level -lt 19 ]] && (( game_level+=1)); print_level' 28
trap '[[ $game_level -gt 0  ]] && (( game_level-=1)); print_level' 29
trap 'ignore_other_tank=true' 35
trap 'ignore_other_tank=false' 36
trap 'kill_myself=true' 37
trap 'kill_myself_always=true' 38
trap 'kill_myself_always=false' 39
trap 'god_mode=true' 40
trap 'god_mode=false' 41
trap 'kill_once_by_god=true' 42

GetTimeFromLevel(){
[[ $game_level -ge 1  ]] && [[ $game_level -le 9 ]] && echo "0.$((10-game_level))"
[[ $game_level -ge 10 ]] && echo "0.0$((19-game_level))"
[[ $game_level -eq 0  ]] && echo "1"
}

print_running(){
echo -ne "\033[$((boundary_u+12));$((boundary_r+3))\
H\033[41m\033[33mState\033[0m  \033[1;34mrunning\033[0m"
}
print_level(){
echo -ne "\033[$((boundary_u+10));$((boundary_r+3))\
H\033[42m\033[31mLevel\033[0m  \033[1;34m$game_level \033[0m"
}
while ! $StopEnemyTank
do

echo -ne "\033[$((boundary_u+8));$((boundary_r+3))\
H\033[43m\033[31mScore\033[0m  \033[1;34m$game_score\033[0m"
[[ $old_game_score -ne $game_score ]] && [[ $((game_score%upgrade_count)) -eq 0 ]] && {
[[ game_level -lt 19 ]] && (( game_level+=1 )) && old_game_score=$game_score
}
print_level

current_direct=$enemytank_direct
if $first_moving; then
while :
do
future_direct=$( GetRandDirect )
[[ $future_direct != $current_direct ]] && { first_moving=false; break; }
done

else
future_direct=$( GetRandDirect )
fi
enemytank_direct=$future_direct
if [[ $current_direct != $future_direct ]]; then
current_tank_head=( `awk '{print $1}' ${tmpdir}/enemybody | tr ';' ' '` )
tank_head=( `GetNewPos $future_direct $current_direct ${current_tank_head[@]}` )
HandleTank -c "${current_tank_head[0]};${current_tank_head[1]}" $current_direct enemy
HandleTank -d "${tank_head[0]};${tank_head[1]}" $future_direct enemy
fi

#$ignore_other_tank || $god_mode && true_false_value=true || true_false_value=false
#Bullet $enemytank_direct ${tank_head[@]} enemy $true_false_value &

#get the random distance
case $future_direct in
'u') allow_distance=$(( tank_head[0]-boundary_u-1 )) ;;
'd') allow_distance=$(( boundary_d-tank_head[0]-1 )) ;;
'l') allow_distance=$(( tank_head[1]-boundary_l-1 )) ;;
'r') allow_distance=$(( boundary_r-tank_head[1]-1 )) ;;
esac
[[ allow_distance -eq 0 ]] && continue
rand_distance=$(( RANDOM % allow_distance + 1 ))

for ((j=1; j<=$rand_distance; j++))
do
$StopEnemyTank && break

if [[ $bullet_interval -eq 0 ]]; then
$ignore_other_tank || $god_mode && true_false_value=true || true_false_value=false
Bullet $enemytank_direct ${tank_head[@]} enemy $true_false_value &
bullet_interval=$(( RANDOM % bullet_interval_range + 1 ))
fi

#pause and continue
while $PauseEnemyTank
do
echo -ne "\033[$((boundary_u+12));$((boundary_r+3))\
H\033[41m\033[33mState\033[0m  \033[1;34mPause  \033[0m"
done

# if be hitted, make another one
$kill_myself && BeHitted=true
$kill_once_by_god && BeHitted=true
$kill_myself_always && BeHitted=true
if $BeHitted; then
DisplayDeathSymbol $future_direct ${tank_head[@]} enemy &
sleep $next_tank_interval_time
DisplayRandTank

#old_game_socre is for upgrade count.
old_game_score=$game_score
(( game_score+=1 ))

(( bullet_interval-=1 ))

BeHitted=false
$kill_myself && kill_myself=false
$kill_once_by_god && BeHitted=false
break
fi

old_tank_head=(${tank_head[@]})
case $future_direct in
'u') (( tank_head[0]-=1 )) ;;
'd') (( tank_head[0]+=1 )) ;;
'l') (( tank_head[1]-=1 )) ;;
'r') (( tank_head[1]+=1 )) ;;
esac
HandleTank -c "${old_tank_head[0]};${old_tank_head[1]}" $future_direct enemy
HandleTank -d "${tank_head[0]};${tank_head[1]}" $future_direct enemy

#judge if collision
if $(CollisJudge); then
$god_mode && {
DisplayDeathSymbol $future_direct ${tank_head[@]} enemy &
sleep $next_tank_interval_time
DisplayRandTank
old_game_score=$game_score
(( game_score+=1 ))
(( bullet_interval-=1 ))
break
}
! ${ignore_other_tank} && {
DisplayDeathSymbol $future_direct ${tank_head[@]} enemy &
kill -21 $MYPID
StopEnemyTank=true
}
fi
(( bullet_interval-=1 ))
sleep $(GetTimeFromLevel)
done
done
}

MoveMyTank()
{
old_mytank_direct=$mytank_direct
old_mytank_head=(${mytank_head[@]})
mytank_direct=$1
mytank_head=( `GetNewPos $1 $old_mytank_direct ${old_mytank_head[@]}` )
HandleTank -c "${old_mytank_head[0]};${old_mytank_head[1]}" $old_mytank_direct my
HandleTank -d "${mytank_head[0]};${mytank_head[1]}" $mytank_direct my

#collision judgement
if $(CollisJudge); then
if $if_god_mode; then
kill -42 $$run_enemytank_pid &>/dev/null
HandleTank -d "${mytank_head[0]};${mytank_head[1]}" $mytank_direct my
else
kill -20 $run_enemytank_pid &>/dev/null
kill -21 $MYPID
fi
fi
}

#Bullet $direct $headpoint(x y) { my | enemy [true|false] }
Bullet()
{
#tank head point / bullet distance [thp/bdis]
local thp=($2 $3) bdis n
local myfile=${tmpdir}/mybody
local enemyfile=${tmpdir}/enemybody

case $4 in
"my")
bullet_color=$my_bullet_color
bullet_symbol='@'
bullet_speed=$my_bullet_speed ;;
"enemy")
bullet_color=$enemy_bullet_color
bullet_symbol=' '
bullet_speed=$enemy_bullet_speed ;;
esac

case $1 in
'u') bdis=$(( thp[0]-boundary_u-2 )); (( thp[0]-=1 )) ;;
'd') bdis=$(( boundary_d-thp[0]-2 )); (( thp[0]+=1 )) ;;
'l') bdis=$(( thp[1]-boundary_l-2 )); (( thp[1]-=1 )) ;;
'r') bdis=$(( boundary_r-thp[1]-2 )); (( thp[1]+=1 ));;
esac

for((n=1; n<=bdis; n++))
do
case $1 in
'u') (( thp[0]-=1 )) ;;
'd') (( thp[0]+=1 )) ;;
'l') (( thp[1]-=1 )) ;;
'r') (( thp[1]+=1 )) ;;
esac

#if the files not exist, means game over.
#[[ ! -f $myfile ]] || [[ ! -f $enemyfile ]] && break

case $4 in
"my")
if echo " $(cat $enemyfile) " | grep -q " ${thp[0]};${thp[1]} "; then
kill -22 `cat ${tmpdir}/run_enemytank_pid` &>/dev/null
break
fi ;;
"enemy")
if ! $5 && echo " $(cat $myfile) " | grep -q " ${thp[0]};${thp[1]} "; then
kill -21 $MYPID
break
fi ;;
esac
echo -ne "\033[${thp[0]};${thp[1]}H\033[${bullet_color}m${bullet_symbol}\033[0m"
sleep $bullet_speed
echo -ne "\033[${thp[0]};${thp[1]}H \033[0m"
done
}

#Collision judgment
CollisJudge()
{
local k ifcoll=false
enemy_points=$(cat ${tmpdir}/enemybody)
my_points=( `cat ${tmpdir}/mybody` )
for((k=0; k<=4; k++))
do
echo " ${enemy_points} " | grep -q " ${my_points[k]} " && { ifcoll=true; break; }
done
echo $ifcoll
}

#DisplayDeathSymbol $direct $tank_head_point(x y) my/enemy [notclean]
#it should be run in background !!
#SYMBOL MODEL
#   1
#  234
# 56789  # [ dead!]
#  012   # 10 11 12
#   3    # 13
#so, we just need to make sure 1,5,9,13 four point.

DisplayDeathSymbol()
{
local center_point mnt_tank_head=($2 $3)
local logfile char
local points="2 3 4 6 7 8 10 11 12"
case $4 in
"my")
symbol_color=$my_tank_color
symbol_symbol='#';;
"enemy")
symbol_color=$seted_enemy_tank_color
symbol_symbol=' ';;
esac
#get the center point of the sysbol
case $1 in
'u')
center_point[0]=$(( mnt_tank_head[0]+1 ))
center_point[1]=${mnt_tank_head[1]} ;;
'd')
center_point[0]=$(( mnt_tank_head[0]-1 ))
center_point[1]=${mnt_tank_head[1]} ;;
'l')
center_point[0]=${mnt_tank_head[0]}
center_point[1]=$(( mnt_tank_head[1]+1 )) ;;
'r')
center_point[0]=${mnt_tank_head[0]}
center_point[1]=$(( mnt_tank_head[1]-1 )) ;;
esac

#get the thirteen point
point_2="$[center_point[0]-1];$[center_point[1]-1]"
point_3="$[center_point[0]-1];${center_point[1]}"
point_4="$[center_point[0]-1];$[center_point[1]+1]"
point_6="${center_point[0]};$[center_point[1]-1]"
point_7="${center_point[0]};${center_point[1]}"
point_8="${center_point[0]};$[center_point[1]+1]"
point_10="$[center_point[0]+1];$[center_point[1]-1]"
point_11="$[center_point[0]+1];${center_point[1]}"
point_12="$[center_point[0]+1];$[center_point[1]+1]"
if [[ $((center_point[0]-boundary_u)) -ge 3 ]]; then
point_1="$[center_point[0]-2];${center_point[1]}"
points="${points} 1"
fi
if [[ $((center_point[1]-boundary_l)) -ge 3 ]]; then
point_5="${center_point[0]};$[center_point[1]-2]"
points="${points} 5"
fi
if [[ $((boundary_r-center_point[1])) -ge 3 ]]; then
point_9="${center_point[0]};$[center_point[1]+2]"
points="${points} 9"
fi
if [[ $((boundary_d-center_point[0])) -ge 3 ]]; then
point_13="$[center_point[0]+2];${center_point[1]}"
points="${points} 13"
fi
for pn in $points
do
case $pn in
5) char='d' ;;
6) char='e' ;;
7) char='a' ;;
8) char='d' ;;
9) char='!' ;;
*) char=" " ;;
esac
eval echo -ne "\\\033\[\${point_${pn}}H\\\033\[${symbol_color}m\\\033\[31m${char}\\\033\[0m"
done

sleep $symbol_keep_time

#clean up the symbol
if [[ -z $5 ]]; then
for pn in $points
do
eval echo -ne "\\\033\[\${point_${pn}}H \\\033\[0m"
done
fi
}

game_over()
{
StopKeyboardInput=true
kill -20 $run_enemytank_pid &>/dev/null
$print_LingYi && kill -27 $run_print_mywords_pid &>/dev/null
$print_infor  && kill -30 $run_print_infors_pid &>/dev/null
$print_dtime  && kill -31 $run_print_dtime_pid &>/dev/null
$print_mode   && kill -20 $run_print_mode_pid &>/dev/null
$print_roll   && kill -10 $run_print_roll_words_pid &>/dev/null
echo -ne "\033[$((boundary_u+12));$((boundary_r+3))H\033[41m\033[33mState\033[0m  \033[1;34mGame Over !!\033[0m"
local line_posi=$(( (boundary_d-boundary_u)/2+boundary_u-2 ))
local col_posi=$(( (boundary_r-boundary_l)/2+boundary_l-18 ))
DisplayDeathSymbol $mytank_direct ${mytank_head[@]} my notclean
echo -e "\033[$((line_posi + 0 ));${col_posi}H\033[1;31m-----------------------------------\033[0m"
echo -e "\033[$((line_posi + 1 ));${col_posi}H\033[1;31m|                                 |\033[0m"
echo -e "\033[$((line_posi + 2 ));${col_posi}H\033[1;31m|      Shit , You Are Dead !      |\033[0m"
echo -e "\033[$((line_posi + 3 ));${col_posi}H\033[1;31m|                                 |\033[0m"
echo -e "\033[$((line_posi + 4 ));${col_posi}H\033[1;31m-----------------------------------\033[0m"
tput cnorm
echo -ne "\033[$((boundary_d+1));$((boundary_r+1))H\n\033[0m"
#read -s -t 1 -n 100
}

print_mywords()
{
[[ -z $strings ]] || [[ -z $expressions ]] && return
StopSaying=false
trap 'StopSaying=true' 27
local oldwords space_sum="" i mywords="example"
local myexpress="" oldexpress

echo -ne "\033[$((boundary_u+20));$((boundary_r+3))H\033[45m\033[1;39mLingYi\033[0m:"
while ! $StopSaying
do
space_sum=" "

#print the words and expression.
mywords="${strings[$((RANDOM%${#strings[@]}))]}"
myexpress="${expressions[$((RANDOM%${#expressions[@]}))]}"
c1=3$((RANDOM%6+1))
c2=3$((RANDOM%6+1))
echo -ne "\033[$((boundary_u+21));$((boundary_r+3))H\033[1;${c1}m${mywords} \033[${c2}m${myexpress}\033[0m"
sleep $((RANDOM%2))

#clean up the words and expression
for((i=1; i<=$((${#mywords}+${#myexpress})); i++))
do
space_sum="${space_sum} "
done
echo -ne "\033[$((boundary_u+21));$((boundary_r+3))H${space_sum}\033[0m"
done
c3=3$((RANDOM%6+1))
echo -ne "\033[$((boundary_u+21));$((boundary_r+3))H\033[${c3}m${gameover_string}\033[0m"
}

print_infors()
{
[[ -z $infors ]] && return
StopPrinting=false
trap 'StopPrinting=true' 30
local space_sum infor i

echo -ne "\033[$((boundary_u+17));$((boundary_r+3))H\033[46m\033[1;39mInfor\033[0m: "
while ! $StopPrinting
do
space_sum=""
infor="${infors[$((RANDOM%${#infors[@]}))]}"
echo -ne "\033[$((boundary_u+18));$((boundary_r+3))H${infor}\033[0m"
sleep $((RANDOM%2))

for((i=1; i<=${#infor}; i++))
do
space_sum="${space_sum} "
done
echo -ne "\033[$((boundary_u+18));$((boundary_r+3))H${space_sum}\033[0m"
done
echo -ne "\033[$((boundary_u+18));$((boundary_r+3))HGame is over, bye !\033[0m"
}

print_dtime()
{
StopDate=false
trap 'StopDate=true' 31
echo -ne "\033[$((boundary_u+23));$((boundary_r+3))H\033[42m\033[1;33mDtime\033[0m"
while ! $StopDate
do
echo -ne "\033[$((boundary_u+24));$((boundary_r+3))H$(date +'%Y.%m.%d %H:%M:%S')\033[0m"
sleep 1
done
}

print_mode()
{
StopMode=false

StealthModeState="off"
SMc=31
GodModeState="off"
GMc=31
KillAlwaysModeState="off"
KMc=31
trap 'StealthModeState="on "; SMc=32' 21
trap 'StealthModeState="off"; SMc=31' 22
trap 'GodModeState="on "; GMc=32' 23
trap 'GodModeState="off"; GMc=31' 24
trap 'KillAlwaysModeState="on "; KMc=32' 25
trap 'KillAlwaysModeState="off"; KMc=31' 26
trap 'StopMode=true' 20

echo -ne "\033[$((boundary_u+14));$((boundary_r+3))H\033[43m\033[1;33mMode \033[0m"
while ! $StopMode
do
STRING1="Stealth: $StealthModeState God: $GodModeState Kills: $KillAlwaysModeState"
echo -ne "\033[$((boundary_u+15));$((boundary_r+3))\
H\033[1;34mStealth: \033[${SMc}m$StealthModeState\033[0m"
echo -ne "\033[$((boundary_u+15));$((boundary_r+17))\
H\033[1;34mGod: \033[${GMc}m$GodModeState\033[0m"
echo -ne "\033[$((boundary_u+15));$((boundary_r+26))\
H\033[1;34mKills: \033[${KMc}m$KillAlwaysModeState\033[0m"
sleep 1
done
}

print_roll_words()
{
local stop_roll=false
local strings=$roll_words
local line=$boundary_u
local col_s=$((boundary_l+1))
local col_e=$((boundary_r-1))
local sleep_time=0.1
local i
local rull_pids=()

trap 'stop_roll=true' 10

print_char()
{	local j old_j=$col_e
local stop_print=false
trap 'stop_print=true' 10
for((j=$col_e; j>=col_s; j--))
do	$stop_print && break
[[ $i -eq $((${#strings}-1)) ]] && echo -ne "\033[${line};${old_j}H\033[${boundary_color}m \033[0m"
echo -ne "\033[${line};${j}H\033[${boundary_color}m\033[1;37m${strings:i:1}\033[0m"
old_j=$j
sleep $sleep_time
done
}
while :
do
for((i=0; i<${#strings}; i++))
do
$stop_roll && break
print_char &
roll_pids=(${roll_pids[@]} $!)
sleep $sleep_time
done
echo -ne "\033[${line};${col_s}H\033[${boundary_color}m \033[0m"
$stop_roll && {
for((i=0; i<${#roll_pids[@]}; i++))
do
kill -10 ${roll_pids[i]} &>/dev/null
done
break
}
for((t=1; t<=12; t++))
do
$stop_roll && break || sleep 0.5
done

done
for((i=boundary_l; i<=boundary_r; i++))
do
echo -ne "\033[${boundary_u};${i}H\033[${boundary_color}m \033[0m"
done
}

#StealthMode true/false
StealthMode()
{
[[ -n $if_god_mode ]] && $if_god_mode && return
if_opened=${if_opened:-false}
stealth_opened_times=${stealth_opened_times:-0}
! $if_opened && [[ $stealth_opened_times -eq 0 ]]&& {
kill -35 $run_enemytank_pid &>/dev/null
kill -21 $run_print_mode_pid &>/dev/null
if_opened=true
let stealth_opened_times++
old_my_tank_color1=$my_tank_color
my_tank_color=$boundary_color
HandleTank -d "${mytank_head[0]};${mytank_head[1]}" $mytank_direct my
return
}
$if_opened && [[ $stealth_opened_times -ne 0 ]] && {
kill -36 $run_enemytank_pid &>/dev/null
kill -22 $run_print_mode_pid &>/dev/null
if_opened=false
let stealth_opened_times--
my_tank_color=$old_my_tank_color1
HandleTank -d "${mytank_head[0]};${mytank_head[1]}" $mytank_direct my
}
}

GodMode()
{
if_god_mode=${if_god_mode:-false}
god_opened_times=${god_opened_times:-0}
! $if_god_mode && [[ $god_opened_times -eq 0 ]] && {
kill -40 $run_enemytank_pid &>/dev/null
kill -23 $run_print_mode_pid &>/dev/null
if_god_mode=true
let god_opened_times++
old_my_tank_color2=$my_tank_color
my_tank_color=41
HandleTank -d "${mytank_head[0]};${mytank_head[1]}" $mytank_direct my
return
}
$if_god_mode && [[ $god_opened_times -ne 0 ]] && {
kill -41 $run_enemytank_pid &>/dev/null
kill -24 $run_print_mode_pid &>/dev/null
if_god_mode=false
let god_opened_times--
my_tank_color=$old_my_tank_color2
HandleTank -d "${mytank_head[0]};${mytank_head[1]}" $mytank_direct my
}
}

#-------------------------------------
#|         executable code           |
#-------------------------------------

DisFrame()
{
stop=false
trap "stop=true" 10
while ! $stop
do
for ((i=1; i<=cols;    i++)); do
echo -ne "\033[1;${i}H\033[4$((RANDOM%6+1))m \033[0m"
done
for ((i=2; i<=lines;   i++)); do
echo -ne "\033[${i};${cols}H\033[4$((RANDOM%6+1))m \033[0m"
done
for ((i=cols-1; i>=1 ; i--)); do
echo -ne "\033[${lines};${i}H\033[4$((RANDOM%6+1))m \033[0m"
done
for ((i=lines-1; i>=2; i--)); do
echo -ne "\033[${i};1H\033[4$((RANDOM%6+1))m \033[0m"
done
for ((i=2; i<=cols-1;  i++)); do
echo -ne "\033[2;${i}H\033[4$((RANDOM%6+1))m \033[0m"
done
for ((i=2; i<=lines-1; i++)); do
echo -ne "\033[${i};$[cols-1]H\033[4$((RANDOM%6+1))m \033[0m"
done
for ((i=cols-2; i>=2;  i--)); do
echo -ne "\033[$[lines-1];${i}H\033[4$((RANDOM%6+1))m \033[0m"
done
for ((i=lines-2; i>=2; i--)); do
echo -ne "\033[${i};2H\033[4$((RANDOM%6+1))m \033[0m"
done
sleep 0.1
done
}

# $0 char sleep_time start_line end_line start_col  upper/low  upper/low  left/right
PrintChar2(){
aa='echo -ne "\033[${i};${5}H\033[1;${6}m$1\033[0m"; sleep $2'
bb='[[ $i -ne $4 ]] && echo -ne "\033[${i};${5}H\033[1;${6}m \033[0m"'
if [[ ${8} == "left" ]]; then
[[ ${7} == "upper" ]] && for((i=$3; i<=$4; i++)); do eval "$aa; $bb"; done
[[ ${7} == "low"   ]] && for((i=$3; i>=$4; i--)); do eval "$aa; $bb"; done
fi
}

cols=`tput cols`
lines=`tput lines`
clear

DisFrame &
DisFramePid=$!

#DisSymbol $[lines/2-6] $[cols/2-34] 32
a='&&&&&    &     &    &&  &   &      &        &        &     &     &&&&&&'
b='  &     & &    &   & &  & &       & & &    & &      & &   &      &     '
c='  &    &&&&&   &  &  &  &&       &  &&&   &&&&&    &   & &   &&  &&&&&&'
d='  &   &     &  & &   &  & &       &   &  &     &  &     &     &  &     '
e='  &  &       & &&    &  &   &       & & &       &&             & &&&&&&'
abcde=(a b c d e)
for((i=0; i<5; i++)); do
eval echo -ne "\"\033[$(($[lines/2-6]+$i));$[cols/2-34]H\033[1;5;32m\$${abcde[i]}\033[0m\""
sleep 0.1
done

echo -ne "\033[$[lines/2];$[cols/2-3]H\(==)/"

i=1
col=$[cols/2-17]
while [[ $i -le 35 ]]; do
echo -ne "\033[$[lines/2+1];${col}H\033[45m \e[0m"
echo -ne "\033[$[lines/2+3];${col}H\033[45m \e[0m"
sleep 0
(( i+=1 ))
(( col+=1 ))
done

strings="Made by LingYi"
col=$[cols/2-6]
for ((a=0;a<=${#strings}-1;a++)); do
for((i=$[cols-2]; i>=$col; i--)); do
echo -ne "\033[$[lines/2+2];${i}H\033[1;33m${strings:a:1}\033[0m"
[[ $i -ne $col ]] && echo -ne "\033[$[lines/2+2];${i}H\033[1;$33m \033[0m"
done
let col++
done

strings='Are You Ready ? [Y/N]'
col=$[cols/2-10]
for ((a=0;a<=${#strings}-1;a++)); do
[[ $[RANDOM%2] -eq 0 ]] && {
PrintChar2 "${strings:a:1}" 0 $[lines/2+4] $[lines/2+5] $col  31 upper left
} || PrintChar2 "${strings:a:1}" 0 $[lines-2] $[lines/2+5] $col  31 low left
let col++
done

while :; do
echo "ynq" | grep -q ${ch:-H} && {
kill -10 ${DisFramePid} &>/dev/null
break
}
echo -ne "\033[$[lines/2+5];$[cols/2-10]H\033[1;31mAre You Ready ? [Y/N]"
read -s -n 1 ch
ch=$(echo ${ch} | tr 'A-Z' 'a-z')
done

#======

[[ -z $ch ]] || [[ $ch == 'y' ]] && : || { clear; exit; }

check_invironment(){

local n=0 m=0 q=0 i j k long
if [[ $((boundary_d-boundary_u)) -lt 24 ]]; then
echo windows [ lines ] too small !
exit
fi
for((i=0; i<${#expressions[@]}; i++))
do
[[ ${#expressions[i]} -gt n ]] && n=${#expressions[i]}
done
for((j=0; j<${#strings[@]}; j++))
do
[[ ${#strings[j]} -gt m ]] && m=${#strings[j]}
done
for((k=0; k<${#infors[@]}; k++))
do
[[ ${#infors[k]} -gt q ]] && q=${#infors[k]}
done
[[ $((n+m)) -gt q ]] && long=$((n+m)) || long=$q
[[ ${#gameover_string} -gt $long ]] && long=${#gameover_string}
if [[ $((`tput cols`-boundary_r)) -le $((long+2)) ]]; then
echo windows [ cols ] too small !
exit
fi
}

check_invironment

StopKeyboardInput=false
PauseMyTank=false

trap '' 2
trap 'game_over' 21

#pause and continue
trap 'PauseMyTank=true; kill -23 $run_enemytank_pid &>/dev/null' 25
trap 'PauseMyTank=false; kill -24 $run_enemytank_pid &>/dev/null' 26

sleep 0.5
clear
tput civis

#draw boundary
for((i=boundary_l-1; i<=boundary_r+1; i++))
do
echo -ne "\033[${boundary_u};${i}H\033[${boundary_color}m "
echo -ne "\033[${boundary_d};${i}H\033[${boundary_color}m "
done
for((i=boundary_u+1; i<boundary_d; i++))
do
echo -ne "\033[${i};$((boundary_l-1))H\033[${boundary_color}m "
echo -ne "\033[${i};${boundary_l}H\033[${boundary_color}m "
echo -ne "\033[${i};${boundary_r}H\033[${boundary_color}m "
echo -ne "\033[${i};$((boundary_r+1))H\033[${boundary_color}m "
done
echo -ne "\033[0m"
echo -ne "\033[$((boundary_u+0));$((boundary_r+3))H\033[1;${smallboundary_color}m---------"
echo -ne "\033[$((boundary_u+6));$((boundary_r+3))H\033[1;${smallboundary_color}m---------"
echo -ne "\033[$((boundary_u+1));$((boundary_r+3))H\033[1;${smallboundary_color}m|       |"
echo -ne "\033[$((boundary_u+2));$((boundary_r+3))H\033[1;${smallboundary_color}m|       |"
echo -ne "\033[$((boundary_u+3));$((boundary_r+3))H\033[1;${smallboundary_color}m|       |"
echo -ne "\033[$((boundary_u+4));$((boundary_r+3))H\033[1;${smallboundary_color}m|       |"
echo -ne "\033[$((boundary_u+5));$((boundary_r+3))H\033[1;${smallboundary_color}m|       |"
echo -ne "\033[0m"
echo -ne "\033[$((boundary_u+12));$((boundary_r+3))H\033[41m\033[33mState\033[0m  \033[1;34mrunning\033[0m"

$print_LingYi && {
print_mywords &
run_print_mywords_pid=$!
}

$print_infor && {
print_infors &
run_print_infors_pid=$!
}

$print_dtime && {
print_dtime &
run_print_dtime_pid=$!
}

$print_mode && {
print_mode &
run_print_mode_pid=$!
}

$print_roll && {
print_roll_words &
run_print_roll_words_pid=$!
}

#display enemy tank
DisplayRandTank

#display mytank
mytank_direct='u'
mytank_head=($[(boundary_d-boundary_u)/2+boundary_u] $[(boundary_r-boundary_l)/2+boundary_l])
HandleTank -d "${mytank_head[0]};${mytank_head[1]}" $mytank_direct my

#make enemy tank move
MoveEnemyTank &
run_enemytank_pid=$!
#MoveEnemyTank cann't get the value of $run_enemytank_pid, so record it in file.
echo $run_enemytank_pid >${tmpdir}/run_enemytank_pid

#accept keyboard input
ESC=`echo -e '\033'`
stty -echo
while ! $StopKeyboardInput
do
while $PauseMyTank
do
read -s -n 1 kk
[[ $kk == 'c' ]] || [[ $kk == 'C' ]] && kill -26 $MYPID
done
read -s -n 1 key

# this judging is necessary, to stop this loop.
$StopKeyboardInput && break

key=`echo $key | tr 'a-z' 'A-Z'`

[[ $key == 'W' ]] && MoveMyTank u
[[ $key == 'S' ]] && MoveMyTank d
[[ $key == 'D' ]] && MoveMyTank r
[[ $key == 'A' ]] && MoveMyTank l

[[ $key == 'U' ]] && kill -28  $run_enemytank_pid
[[ $key == 'L' ]] && kill -29  $run_enemytank_pid
[[ $key == 'F' ]] && kill -37 $run_enemytank_pid
[[ $key == 'N' ]] && kill -38 $run_enemytank_pid && $print_mode && kill -25 $run_print_mode_pid
[[ $key == 'M' ]] && kill -39 $run_enemytank_pid && $print_mode && kill -26 $run_print_mode_pid

[[ $key == 'G' ]] && StealthMode
[[ $key == 'V' ]] && GodMode

[[ $key == 'P' ]] && kill -25 $MYPID
[[ $key == 'Q' ]] && kill -21 $MYPID

[[ -z $key ]] && Bullet  $mytank_direct ${mytank_head[@]} my &

[[ $key == $ESC ]] && {
for (( i=0; i<=1; i++ )); do read -s -n 1  KEY[$i]; done
[[ ${KEY[0]} == '['   ]] && {
[[ ${KEY[1]} == 'A' ]] &&  MoveMyTank u
[[ ${KEY[1]} == 'B' ]] &&  MoveMyTank d
[[ ${KEY[1]} == 'C' ]] &&  MoveMyTank r
[[ ${KEY[1]} == 'D' ]] &&  MoveMyTank l
}
}
done

stty echo
echo -e "\033[$((boundary_d+2));1H\033[0m"


本文出自 “逆行者” 博客,请务必保留此出处http://lingyi.blog.51cto.com/2837715/1764285
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: