Existe uma maneira de executar comandos durante a entrada do usuário?

3

Sou relativamente novo em scripts e tenho uma pergunta de alto nível sobre como fazer algo.

Eu quero criar um jogo simples semelhante aos invasores do espaço, com esses dois principais recursos por enquanto:

  1. Os marcadores aparecem no topo da tela a cada segundo.
  2. O usuário pode mover o navio doméstico pela linha inferior da tela e desviar das balas.

A questão é que não consigo encontrar uma maneira de mover as balas constantemente enquanto ainda recebo informações.

Maior parte do código do loop principal:

while true #gets user input and updates screen.
do
    read -r -sn1 -t 1 USERIN
    case $USERIN in
        D) moveleft ;;
        C) moveright ;;
    esac 
    updatescreen #(my code makes sure that at least a second has passed since the last "updatescreen" execution before running this)
done

Eu quero que a tela seja atualizada a cada segundo, independentemente da entrada do usuário. No momento, o programa é instável quando é atualizado porque, às vezes, ele precisa aguardar mais tempo para a entrada expirar. Seria bom ter um tempo limite de leitura mais baixo, mas se eu diminuí-lo, recebo um erro: "especificação de tempo limite inválido".

Existe alguma maneira de contornar isso ou talvez uma organização de programa totalmente diferente?

    
por Sman865 22.10.2014 / 20:45

2 respostas

1

Eu encontrei uma solução. Basicamente, você executa o loop de atualização em segundo plano e tem o loop principal em primeiro plano. Eles podem se comunicar uns com os outros usando comandos trap / kill.

Enviei um arquivo .sh para o github para dar um exemplo completo.

Aqui está um resumo modificado de como isso funciona:

Nota: você tem que usar ctrl-c para escapar.

#!/bin/bash

update()
{
    trap "move_left;" $LEFT
    trap "move_right;" $RIGHT

    while true; do
         #output whatever needed
    done
}

read_in()
{
    trap "return;" SIGINT SIGQUIT

    while true; do
        read -s -n 1 key
        case key in
            C) kill -$RIGHT $game_pid ;;
            D) kill -$LEFT $game_pid ;;
        esac
    done
}

move_left()
{
    #update position variable
}

move_right()
{
    #update position variable
}

update &
game_pid=$!
read_in

kill -9 $game_pid

Use o script de exemplo vinculado acima para uma versão de exemplo de trabalho, mas você o tem! Apenas fiz uma pequena reformulação da arquitetura do programa.

    
por 30.10.2014 / 19:41
2

Você precisa de multi-threading. Dê uma olhada no Paralelo GNU

    
por 22.10.2014 / 22:01