最近看了一个shell写的游戏:俄罗斯方块(下方有下载),受其启发重写了之前的一个小游戏:贪吃蛇。
之前写的那个需要用到临时文件, 每个动作都需要多次读写,效率不行,看了别人的思路之后,很快就
重写一个。
以下变量定义了三部分内容:信号、边框属性和游戏本身PID,并对游戏等级做定义注释。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#signal
upper=20
down=21
left=22
right=23
stop=24
stopI=25
pause=26
start=27
speedup=28
slowdown=29
quit=30
height=4
width=10
HEIGHT=20
WIDTH=30
upper_boundary=$((height+1))
down_boundary=$((height+HEIGHT+2))
left_boundary=$((width+1))
right_boundary=$((width+WIDTH+2))
MYPID=$$
#About the level and the score.
#time(s) 0.9 0.8 0.7 0.6 0.5 0.4 0.3 0.2 0.1 0.0
#level 1 2 3 4 5 6 7 8 9 10
display_random_point函数用来在特定区域得到并显示一随机块。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#get one random point in the border.
display_random_point(){
local i succ=0
while :; do
while :; do
point1=$((RANDOM%down_boundary))
[[ $point1 -gt $upper_boundary ]] && [[ $point1 -lt $down_boundary ]] && break
done
while :; do
point2=$((RANDOM%right_boundary))
[[ $point2 -gt $left_boundary ]] && [[ $point1 -lt $right_boundary ]] && break
done
#for sure, not in the body points.
for((i=0; i<${#snake_body[@]}; i++)); do
[[ "$point1 $point2" == "${snake_body} ${snake_body[i+1]}" ]] && { succ=1; break; }
done
[[ $succ -eq 0 ]] && break
done
random_point=($point1 $point2)
echo -ne "[${point1};${point2}H[44m [0m"
}
exit_game 退出游戏
1
2
3
4
5
6
7
exit_game(){
kill -$stopI $MYPID
tput cnorm
echo -e "[$(((height+HEIGHT+2)/2));$(((width+WIDTH)/2))H[33mSnake Dead !![0m"
echo -e "[$((height+HEIGHT+3));$((width+WIDTH+3))H [0m"
exit
}
display_element 后台运行函数, 用来捕捉信号、显示游戏边框等信息以及移动蛇身
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
display_element(){
#隐藏鼠标
tput civis #Hide cursor
#捕捉信号
trap 'DIRECTION=upper' $upper
trap 'DIRECTION=down' $down
trap 'DIRECTION=left' $left
trap 'DIRECTION=right' $right
trap 'STOP=1' $stop
trap 'IFPAUSE=1' $pause
trap 'IFPAUSE=0' $start
trap '((level++))' $speedup
trap '((level--))' $slowdown
trap 'exit_game' $quit
#定义部分局部变量
score=0
level=5
STOP=0
DIRECTION=right
old_direction=$DIRECTION
snake_body=( $((height+2)) $((width+2)) )
#画边框
local i
for((i=height+1; i<=height+HEIGHT+2; i++))
do
echo -ne "[${i};$((width+1))H[42m [0m"
echo -ne "[${i};$((width+WIDTH+2))H[42m [0m"
done
for((i=width+1; i<=width+WIDTH+2; i++))
do
echo -ne "[$((height+1));${i}H[42m [0m"
echo -ne "[$((height+HEIGHT+2));${i}H[42m [0m"
done
#显示成绩、等级和运行状态
echo -ne "[${snake_body[0]};${snake_body[1]}H[41m [0m"
echo -ne "[$((height+2));$((width+WIDTH+3))H[1;34m Score: [1;39m$score[0m"
echo -ne "[$((height+4));$((width+WIDTH+3))H[1;34m Level: [1;35m$level[0m"
echo -ne "[$((height+6));$((width+WIDTH+3))H[1;34m State: [1;5;32mrunning[0m"
echo -ne "[${height};$((width+7))H[35m[ Snake ] by LingYi[0m"
display_random_point
#后台循环, 移动蛇身
while [[ $STOP -ne 1 ]]
do
#不允许相反方向移动
case $old_direction in
'upper') [[ $DIRECTION == 'down' ]] && DIRECTION=upper ;;
'down' ) [[ $DIRECTION == 'upper' ]] && DIRECTION=down ;;
'left' ) [[ $DIRECTION == 'right' ]] && DIRECTION=left ;;
'right') [[ $DIRECTION == 'left' ]] && DIRECTION=right ;;
esac
#得到新蛇头
new_head[0]=${snake_body[$((${#snake_body[@]}-2))]}
new_head[1]=${snake_body[$((${#snake_body[@]}-1))]}
case $DIRECTION in
'upper') ((new_head[0]-=1)) ;;
'down' ) ((new_head[0]+=1)) ;;
'left' ) ((new_head[1]-=1)) ;;
'right') ((new_head[1]+=1)) ;;
esac
#判断边框碰撞
case $DIRECTION in
'upper') [[ ${new_head[0]} -eq $upper_boundary ]] && exit_game ;;
'down' ) [[ ${new_head[0]} -eq $down_boundary ]] && exit_game ;;
'left' ) [[ ${new_head[1]} -eq $left_boundary ]] && exit_game ;;
'right') [[ ${new_head[1]} -eq $right_boundary ]] && exit_game ;;
esac
#判断蛇身碰撞
local i
for((i=0; i<${#snake_body[@]}; i++)); do
[[ "${new_head[@]}" == "${snake_body} ${snake_body[i+1]}" ]] && exit_game
done
#暂停、继续
while [[ $IFPAUSE -eq 1 ]]; do
echo -ne "[$((height+6));$((width+WIDTH+3))H[1;34m State: [1;5;31mpause [0m"
done
echo -ne "[$((height+6));$((width+WIDTH+3))H[1;34m State: [1;32mrunning[0m"
#加速、减速
if [[ $old_level != $level ]]; then
echo -ne "[$((height+4));$((width+WIDTH+3))H[1;34m Level: [1;35m$level[0m"
fi
old_level=$level
#吃到随机块,显示成绩和级别信息
if [[ ${new_head[@]} == ${random_point[@]} ]]; then
snake_body=( ${snake_body[@]} ${new_head[@]} )
display_random_point
let score++
[[ $((score%20)) -eq 0 ]] && let level++
echo -ne "[$((height+2));$((width+WIDTH+3))H[1;34m Score: [1;39m$score[0m"
echo -ne "[$((height+4));$((width+WIDTH+3))H[1;34m Level: [1;35m$level[0m"
else
echo -ne "[${snake_body[0]};${snake_body[1]}H [0m"
snake_body=( $(echo ${snake_body[@]} | cut -d ' ' -f 3-) ${new_head[@]})
fi
echo -ne "[${new_head[0]};${new_head[1]}H[41m [0m"
old_direction=$DIRECTION
sleep 0.$((10-level))
done
}
以下是运行主体代码, 主要是运行后台函数、捕捉按键和发送信号。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
clear
display_element &
back_pid=$!
trap 'EXIT=1' $stopI
trap 'kill -$stop $back_pid; stty echo; exit_game' 2
ESC=`echo -e ''`
while :; do
read -s -n 1 key
key=`echo $key | tr 'a-z' 'A-Z'`
[[ $key == '' ]] && sig=$pause # 空格:暂停
[[ $key == 'C' ]] && sig=$start # C键:继续
[[ $key == 'U' ]] && sig=$speedup # U键:加速
[[ $key == 'O' ]] && sig=$slowdown # O键:减速
[[ $key == 'Q' ]] && sig=$quit #Q键:退出
#改变移动方向
[[ $key == 'W' ]] || [[ $key == 'I' ]] && sig=$upper
[[ $key == 'S' ]] || [[ $key == 'K' ]] && sig=$down
[[ $key == 'D' ]] || [[ $key == 'L' ]] && sig=$right
[[ $key == 'A' ]] || [[ $key == 'J' ]] && sig=$left
[[ $key == $ESC ]] && {
for (( i=0; i<=1; i++ )); do read -s -n 1 KEY[$i]; done
[[ ${KEY[0]} == $ESC ]] && sig=$stop
[[ ${KEY[0]} == '[' ]] && {
[[ ${KEY[1]} == 'A' ]] && sig=$upper
[[ ${KEY[1]} == 'B' ]] && sig=$down
[[ ${KEY[1]} == 'C' ]] && sig=$right
[[ ${KEY[1]} == 'D' ]] && sig=$left
}
}
#发送信号
[[ $EXIT -ne 1 ]] && kill -$sig $back_pid || break
done
演示:
下载:
game_snake.rar
(1.94 KB, 下载次数: 2)
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com