Snake [ALFA] em Shell Script
Fala pessoal do VOL!
Como treinamento de lógica avançada de programação estou tentando recriar jogos clássicos sem olhar nenhum código fonte (ou seja, fazer na raça mesmo :P).
Com isso decidi que meu primeiro jogo seria nada mais nada menos do que aquele que todos jogavam nos seus "Tijorolas": Snake!
Sim, aquela cobra simpática que vai aumentando conforme come a ração. :P
Estou há aproximadamente 3 meses mexendo no GNU/Linux e aprendendo Shell Script desde então. Nunca havia visto nenhum dos dois antes. :o
Enfim, segue abaixo o meu código, lembrando que ainda está na VERSÃO ALFA, portanto, existem mil e um bugs que ainda precisam ser encontrados e resolvidos.
Obs.: para movimentar-se utilize as teclas WASD (para quem não conhece: W - cima; A - esquerda; S - baixo; D - direita).
Espero que gostem e me deem um feedback, Cya. :D
Como treinamento de lógica avançada de programação estou tentando recriar jogos clássicos sem olhar nenhum código fonte (ou seja, fazer na raça mesmo :P).
Com isso decidi que meu primeiro jogo seria nada mais nada menos do que aquele que todos jogavam nos seus "Tijorolas": Snake!
Sim, aquela cobra simpática que vai aumentando conforme come a ração. :P
Estou há aproximadamente 3 meses mexendo no GNU/Linux e aprendendo Shell Script desde então. Nunca havia visto nenhum dos dois antes. :o
Enfim, segue abaixo o meu código, lembrando que ainda está na VERSÃO ALFA, portanto, existem mil e um bugs que ainda precisam ser encontrados e resolvidos.
Obs.: para movimentar-se utilize as teclas WASD (para quem não conhece: W - cima; A - esquerda; S - baixo; D - direita).
Espero que gostem e me deem um feedback, Cya. :D
Descrição
Fala pessoal do VOL!
Como treinamento de lógica avançada de programação estou tentando recriar jogos clássicos sem olhar nenhum código fonte (ou seja, fazer na raça mesmo :P).
Com isso decidi que meu primeiro jogo seria nada mais nada menos do que aquele que todos jogavam nos seus "Tijorolas": Snake!
Sim, aquela cobra simpática que vai aumentando conforme come a ração. :P
Estou há aproximadamente 3 meses mexendo no GNU/Linux e aprendendo Shell Script desde então. Nunca havia visto nenhum dos dois antes. :o
Enfim, segue abaixo o meu código, lembrando que ainda está na VERSÃO ALFA, portanto, existem mil e um bugs que ainda precisam ser encontrados e resolvidos.
Obs.: para movimentar-se utilize as teclas WASD (para quem não conhece: W - cima; A - esquerda; S - baixo; D - direita).
Espero que gostem e me deem um feedback, Cya. :D
Como treinamento de lógica avançada de programação estou tentando recriar jogos clássicos sem olhar nenhum código fonte (ou seja, fazer na raça mesmo :P).
Com isso decidi que meu primeiro jogo seria nada mais nada menos do que aquele que todos jogavam nos seus "Tijorolas": Snake!
Sim, aquela cobra simpática que vai aumentando conforme come a ração. :P
Estou há aproximadamente 3 meses mexendo no GNU/Linux e aprendendo Shell Script desde então. Nunca havia visto nenhum dos dois antes. :o
Enfim, segue abaixo o meu código, lembrando que ainda está na VERSÃO ALFA, portanto, existem mil e um bugs que ainda precisam ser encontrados e resolvidos.
Obs.: para movimentar-se utilize as teclas WASD (para quem não conhece: W - cima; A - esquerda; S - baixo; D - direita).
Espero que gostem e me deem um feedback, Cya. :D
Versões atualizadas deste script
#!/bin/bash
#=====================================================================================#
#
# Programa: snake.bsh
#
# Autor: Cavalca Filho, Marcelo (15/09/2013)
#
# Objetivo: Jogo snake em shell :D
#
#=====================================================================================#
#
# Versão: 1.0 - 19/09/2013
# > Utiliza um vetor para exibir a cobra e reinicia o mapa inteiro a
# cada movimento.
#
# 1.1 - 21/09/2013
# > Ideia para criação de uma nova lógica pois a versão 1.0 trava mais
# conforme a cobra vai aumentando.
# Agora a cobra se move sozinha com o tempo, não necessitando o
# "readkey" para cada próximo movimento.
#
# 1.2 - 22/09/2013
# > Lógica melhorada para a posição da "nova comida" pois antes gerava
# comida nas bordas ou dentro da cobra, bugando o jogo.
#
# 1.3 - 25/09/2013
# > Versão alfa completa!
# Agora o jogo não gera "lag" devido ao aumento da cobra pois com a
# nova lógica a cobra não é uma matriz e sim o próprio terreno, por
# assim dizer.
# Pode parecer simples mas a lógica para a movimentação da cobra
# conforme ela faz curvas é um pouco complexa. Leia o apêndice abaixo
#
#=====================================================================================#
#=============================== CURVAS: COMO LIDAR ==================================#
#
# O grande problema no início foi que a cobra era uma matriz e o terreno
# era outra. Isso gerava um pequeno "lag" conforme a cobra aumentava. Foi pensada
# então em uma lógica que fizesse com que a cobra fosse parte do terreno.
# O maior empecilho para isso foi quando ela se curvava: Para onde o "rabo" dela
# vai quando ela vira? E se ela fizer mais de uma curva?
# Então foi pensada na seguinte lógica: Existe uma matriz que guarda as curvas
# feitas. Existe também um vetor que vai indicar qual o próximo movimento da
# cabeça e qual o próximo movimento do rabo. Uma posição de CURVA armazena a
# quantidade de curvas que ela ainda tem de realizar. Conforme ela vai fazendo
# as curvas esse valor é decrementado e o vetor é renovado para que ele saiba
# para onde ir na próxima curva.
#
# ex.: a cobra vira:
# baixo - direita - cima - direita - baixo
# [4] - [1] - [3] - [1] - [4]
#
# CURVA[0,0]= 5 (total)
# CURVA[0,1]= 4 (valor de "baixo")
#
# O rabo encontrou a posição onde ele deve ir para baixo logo a matriz será
# atualizada para:
#
# CURVA[0,0]= 4
# CURVA[0,1]= 1 (valor de "direita")
#
# Portanto, na próxima curva que ela chegar ela saberá que tem de ir para a
# direita, e depois "cima", e por aí vai :)
#
#
# tl;dr: Tem uma matriz que guarda o movimento da próxima curva. Ao chegar lá
# essa matriz é atualizada para os valores das outras curvas.
#
#=====================================================================================#
#================================= GERAR TERRENO =====================================#
clear
# Declaração das matrizes do campo
declare -A CAMPO
declare -A CURVA
# Aqui voce pode alterar a altura e a largura conforme desejar
# ___________
#| |
HEIGHT=15 # ALTURA
WIDTH=30 # LARGURA
#|___________|
# Verdadeira geração do terreno. Ele irá colocar o campo na tela e inserir os caracteres
# para uma boa visualização do mesmo.
let m=${HEIGHT}+1
let n=${WIDTH}+1
let i=$n
while [ $i -ge 0 ]; do
let j=$m
while [ $j -ge 0 ]; do
if [ $i -eq 0 ] || [ $j -eq 0 ] || [ $i -eq $n ] || [ $j -eq $m ]; then
if [ $i -eq 0 ] && [ $j -eq 0 ]; then
tput cup $j $i
echo -ne "#"
elif [ $i -eq $n ] && [ $j -eq 0 ]; then
tput cup $j $i
echo -ne "#"
elif [ $i -eq $n ] && [ $j -eq $m ]; then
tput cup $j $i
echo -ne "#"
elif [ $i -eq 0 ] && [ $j -eq $m ]; then
tput cup $j $i
echo -ne "#"
elif [ $i -eq 0 ] || [ $i -eq $n ]; then
tput cup $j $i
echo -ne "‖"
else
tput cup $j $i
echo -ne "="
fi
CAMPO[$i,$j]=1
# echo -ne "█"
else
CAMPO[$i,$j]=0
fi
let j=$j-1
done
let i=$i-1
done
#=====================================================================================#
#=============================== INICIALIZAR VARIAVEIS ===============================#
DIFIC=0.05 # Dificuldade ou velocidade de atualização do movimento
# [!] De preferência não alterar as variáveis abaixo, a menos que saiba o que esteja
# fazendo
# _____________________________________________________________________________________
#| |
y[0]=1
x[0]=2
x[1]=1
y[1]=1
CURVA[0,0]=0
m=$((RANDOM%${WIDTH}+1)) # Gerando...
n=$((RANDOM%${HEIGHT}+1)) # ...a primeira...
CAMPO[$m,$n]=2 # ...bolinha dentro da caixa.
LASTMOV[0]=1 # A cobra andará para a direita primeiramente.
LASTMOV[1]=1
PONT=0
INPUT="d" # Inicialização da entrada.
WHATDO="d" # Qual movimento será o primeiro.
REVDO="a" # Reverso do primeiro movimento para evitar cobra louca.
LOSTGAME=false # Detecção de game perdido.
tput civis
tput cup $n $m
echo -ne "*"
tput cup ${y[0]} ${x[0]}
echo -ne "ᕙ"
tput cup ${y[1]} ${x[1]}
echo -ne "∎"
let n=$HEIGHT+4 # Exibição dos controles.
tput cup $n 1
#|_______________________________________________________________________________________|
#=====================================================================================#
read -s -n 1 INPUT
while :; do
let n=$HEIGHT+2
tput cup $n 3
stty echo
echo " X[0]=${x[0]} Y[0]=${y[0]} "
echo " PONTUACAO = $PONT "
stty -echo
read -s -t ${DIFIC} -n 1 INPUT
if [ $INPUT = "d" ] 2>&- || [ $INPUT = "a" ] 2>&- || [ $INPUT = "s" ] 2>&- || [ $INPUT = "w" ] 2>&- ; then
if [ $INPUT != $WHATDO ] && [ $INPUT != $REVDO ]; then
WHATDO=$INPUT
fi
fi
if [ ${CAMPO[${x[1]},${y[1]}]} -eq 3 ]; then
CAMPO[${x[1]},${y[1]}]=1
LASTMOV[1]=${CURVA[0,1]}
let CURVA[0,0]=${CURVA[0,0]}-1
CURVA[1,0]=1
while [ ${CURVA[1,0]} -le ${CURVA[0,0]} ]; do
let CURVA[1,1]=${CURVA[1,0]}+1
CURVA[0,${CURVA[1,0]}]=${CURVA[0,${CURVA[1,1]}]}
CURVA[0,${CURVA[1,1]}]=0
let CURVA[1,0]=${CURVA[1,0]}+1
done
fi
if [ $WHATDO = "d" ]; then
let m=${x[0]}+1
let n=${y[0]}
REVDO="a"
if [ ${LASTMOV[0]} -ne 1 ]; then
CAMPO[${x[0]},${y[0]}]=3
let CURVA[0,0]=${CURVA[0,0]}+1
CURVA[0,${CURVA[0,0]}]=1
fi
case ${CAMPO[$m,$n]} in
0 ) CAMPO[${x[1]},${y[1]}]=0
tput cup ${y[1]} ${x[1]}
stty echo
echo -ne " "
case ${LASTMOV[1]} in
1) let x[1]=${x[1]}+1;;
2) let x[1]=${x[1]}-1;;
3) let y[1]=${y[1]}-1;;
4) let y[1]=${y[1]}+1;;
esac
tput cup ${y[0]} ${x[0]}
echo -ne "∎"
x[0]=$m
CAMPO[${x[0]},${y[0]}]=1
tput cup ${y[0]} ${x[0]}
echo -ne "ᕙ"
stty -echo ;;
1 ) LOSTGAME=true
break ;;
2 ) let PONT=$PONT+1
stty echo
tput cup ${y[0]} ${x[0]}
echo -ne "∎"
x[0]=$m
CAMPO[${x[0]},${y[0]}]=1
tput cup ${y[0]} ${x[0]}
echo -ne "ᕙ"
NOYOUCANT=true
while [ $NOYOUCANT = true ]; do
m=$((RANDOM%${WIDTH}+1))
n=$((RANDOM%${HEIGHT}+1))
if [ ${CAMPO[$m,$n]} -eq 0 ]; then
tput cup $n $m
NOYOUCANT=false
fi
done
CAMPO[$m,$n]=2
echo -ne "*"
stty -echo ;;
3 ) LOSTGAME=true
break ;;
esac
LASTMOV[0]=1
fi
if [ $WHATDO = "a" ]; then
let m=${x[0]}-1
let n=${y[0]}
REVDO="d"
if [ ${LASTMOV[0]} -ne 2 ]; then
CAMPO[${x[0]},${y[0]}]=3
let CURVA[0,0]=${CURVA[0,0]}+1
CURVA[0,${CURVA[0,0]}]=2
fi
case ${CAMPO[$m,$n]} in
0 ) CAMPO[${x[1]},${y[1]}]=0
tput cup ${y[1]} ${x[1]}
stty echo
echo -ne " "
case ${LASTMOV[1]} in
1) let x[1]=${x[1]}+1;;
2) let x[1]=${x[1]}-1;;
3) let y[1]=${y[1]}-1;;
4) let y[1]=${y[1]}+1;;
esac
tput cup ${y[0]} ${x[0]}
echo -ne "∎"
x[0]=$m
CAMPO[${x[0]},${y[0]}]=1
tput cup ${y[0]} ${x[0]}
echo -ne "ᕗ"
stty -echo ;;
1 ) LOSTGAME=true
break ;;
2 ) let PONT=$PONT+1
stty echo
tput cup ${y[0]} ${x[0]}
echo -ne "∎"
x[0]=$m
CAMPO[${x[0]},${y[0]}]=1
tput cup ${y[0]} ${x[0]}
echo -ne "ᕗ"
NOYOUCANT=true
while [ $NOYOUCANT = true ]; do
m=$((RANDOM%${WIDTH}+1))
n=$((RANDOM%${HEIGHT}+1))
if [ ${CAMPO[$m,$n]} -eq 0 ]; then
tput cup $n $m
NOYOUCANT=false
fi
done
CAMPO[$m,$n]=2
echo -ne "*"
stty -echo ;;
esac
LASTMOV[0]=2
fi
if [ $WHATDO = "w" ]; then
let m=${x[0]}
let n=${y[0]}-1
REVDO="s"
if [ ${LASTMOV[0]} -ne 3 ]; then
CAMPO[${x[0]},${y[0]}]=3
let CURVA[0,0]=${CURVA[0,0]}+1
CURVA[0,${CURVA[0,0]}]=3
fi
case ${CAMPO[$m,$n]} in
0 ) CAMPO[${x[1]},${y[1]}]=0
tput cup ${y[1]} ${x[1]}
stty echo
echo -ne " "
case ${LASTMOV[1]} in
1) let x[1]=${x[1]}+1;;
2) let x[1]=${x[1]}-1;;
3) let y[1]=${y[1]}-1;;
4) let y[1]=${y[1]}+1;;
esac
tput cup ${y[0]} ${x[0]}
echo -ne "∎"
y[0]=$n
CAMPO[${x[0]},${y[0]}]=1
tput cup ${y[0]} ${x[0]}
echo -ne "ᕓ"
stty -echo ;;
1 ) LOSTGAME=true
break ;;
2 ) let PONT=$PONT+1
stty echo
tput cup ${y[0]} ${x[0]}
echo -ne "∎"
y[0]=$n
CAMPO[${x[0]},${y[0]}]=1
tput cup ${y[0]} ${x[0]}
echo -ne "ᕓ"
NOYOUCANT=true
while [ $NOYOUCANT = true ]; do
m=$((RANDOM%${WIDTH}+1))
n=$((RANDOM%${HEIGHT}+1))
if [ ${CAMPO[$m,$n]} -eq 0 ]; then
tput cup $n $m
NOYOUCANT=false
fi
done
CAMPO[$m,$n]=2
echo -ne "*"
stty -echo ;;
esac
LASTMOV[0]=3
fi
if [ $WHATDO = "s" ]; then
let m=${x[0]}
let n=${y[0]}+1
REVDO="w"
if [ ${LASTMOV[0]} -ne 4 ]; then
CAMPO[${x[0]},${y[0]}]=3
let CURVA[0,0]=${CURVA[0,0]}+1
CURVA[0,${CURVA[0,0]}]=4
fi
case ${CAMPO[$m,$n]} in
0 ) CAMPO[${x[1]},${y[1]}]=0
tput cup ${y[1]} ${x[1]}
stty echo
echo -ne " "
case ${LASTMOV[1]} in
1) let x[1]=${x[1]}+1;;
2) let x[1]=${x[1]}-1;;
3) let y[1]=${y[1]}-1;;
4) let y[1]=${y[1]}+1;;
esac
tput cup ${y[0]} ${x[0]}
echo -ne "∎"
y[0]=$n
CAMPO[${x[0]},${y[0]}]=1
tput cup ${y[0]} ${x[0]}
echo -ne "ᕕ"
stty -echo ;;
1 ) LOSTGAME=true
break ;;
2 ) let PONT=$PONT+1
stty echo
tput cup ${y[0]} ${x[0]}
echo -ne "∎"
y[0]=$n
CAMPO[${x[0]},${y[0]}]=1
tput cup ${y[0]} ${x[0]}
echo -ne "ᕕ"
NOYOUCANT=true
while [ $NOYOUCANT = true ]; do
m=$((RANDOM%${WIDTH}+1))
n=$((RANDOM%${HEIGHT}+1))
if [ ${CAMPO[$m,$n]} -eq 0 ]; then
tput cup $n $m
NOYOUCANT=false
fi
done
CAMPO[$m,$n]=2
echo -ne "*"
stty -echo ;;
esac
LASTMOV[0]=4
fi
if [ $INPUT = "q" ] 2>/dev/null; then
clear
tput cnorm
exit 0
fi
done
if [ $LOSTGAME ]; then
clear
echo "Voce perdeu! Conseguiu um total de $PONT pontos!"
echo
fi
tput cnorm
exit