-
Notifications
You must be signed in to change notification settings - Fork 3
/
snake
executable file
·87 lines (68 loc) · 2.27 KB
/
snake
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
#!/bin/bash
stty -echo
trap 'end 130' EXIT INT; trap init_term WINCH
skip(){ if (( ${n:=1} > ${1:-1} )); then :; else ((n++)); false; fi; }
init_term(){
IFS='[;' read -sp $'\e[999;999H\e[6n' -d R -rs _ LINES COLS
((ROWS=LINES-1)); ((snakeX=COLS/2)); ((snakeY=ROWS/2)); CENTER="$snakeY;$snakeX"
printf '\e[?1049h\e[2J\e[?25l\e[?7l'
rand_block
}
end(){ stty echo; printf '\e[?1049l\e[?25h\e[?7h'; exit "${1:-0}"; }
game_over(){
local i
until (( i > $1 )); do
for _ in 1 7; do
printf '\e[%sH\e[3D\e[3%dmGAME OVER\e[m' "$CENTER" "$_"
sleep .1
done; ((++i))
done; end "$2"
}
read_keys(){
local i
case $1 in
20) i=.7;; 19) i=.6;; 18) i=.5;; 17) i=.4;; 16) i=.3;; 15) i=.2;; 14) i=.1;;
13) i=.09;; 12) i=.08;; 11) i=.075;; 10) i=.07;; 9) i=.065;; 8) i=.06;; 7) i=.055;;
6) i=.05;; 5) i=.045;; 4) i=.04;; 3) i=.035;; 2) i=.03;; 1) i=.025;;
esac
while read -rsn1 -t "$i"; do
[[ $REPLY == $'\e' ]]&& read -rsn2 -t "$i"; KEY="${REPLY^^}"
done
}
status_bar(){
printf '\e[999H\e[2K\e[1;32mSNAKE\e[m x:%d y:%d len:%d spe:%d' "$1" "$2" "$3" "$4"
}
rand_block(){
((blockX=SRANDOM%COLS+1)); ((blockY=SRANDOM%ROWS+1)); block="$blockY;$blockX"
printf '\e[%sH\e[41m \e[m' "$block"
}
snake_direction(){
case ${KEY:-$1} in
Q) game_over 2;;
H|A|\[D) (( dirX == 1 ))||{ dirX=-1 dirY=0; };;
J|S|\[B) (( dirY == -1 ))||{ dirX=0 dirY=1; };;
K|W|\[A) (( dirY == 1 ))||{ dirX=0 dirY=-1; };;
L|D|\[C) (( dirX == -1 ))||{ dirX=1 dirY=0; };;
esac; ((snakeX+=dirX)); ((snakeY+=dirY))
}
draw_snake(){ snake+=("$2;$1"); printf '\e[%sH\e[42m \e[m' "${snake[-1]}"; }
erase_snake(){ printf '\e[%sH \e[m' "${snake[0]}"; snake=("${snake[@]:1}"); }
consume_block(){ [[ $1 == "$block" ]]&&{ ((delay--)); ((len++)); rand_block; }; }
self_collision(){ [[ $1 == "${snake[-1]}" ]]&& game_over 4 1; }
wall_collision(){ (( $1 < 1|| $1 > COLS|| $2 < 1|| $2 > ROWS ))&& game_over 4 1; }
len=3 delay=20
init_term
for((;;)){
status_bar "$snakeX" "$snakeY" "$len" "$delay"
read_keys "$delay"
snake_direction L; draw_snake "$snakeX" "$snakeY"
wall_collision "$snakeX" "$snakeY"
skip "$len"&&{
erase_snake
((snakeBodyCount=${#snake[@]}-1))
for _ in "${snake[@]::$snakeBodyCount}"; do
consume_block "$_"
self_collision "$_"
done
}
}