ユーザー入力を受信しながらコマンドを実行する方法はありますか?

ユーザー入力を受信しながらコマンドを実行する方法はありますか?

私はスクリプトに初めて触れており、どのように作業するかについての高度な質問があります。

私は現在、次の2つの主な機能を備えたSpace Invadersに似たシンプルなゲームをデザインしたいと思います。

  1. 毎秒画面上部の弾丸が落ちます。
  2. ユーザーは画面の下部で船を動かして弾丸を避けることができます。

問題は、入力を受けている間に弾丸を下に移動する方法が見つからないことです。

メインループのほとんどのコードは次のとおりです。

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

ユーザー入力に関係なく、画面を毎秒更新したいと思います。タイムアウトを入力するのに時間がかかるため、プログラムは中断に更新されます。読み出しタイムアウト値が低い場合は問題ありませんが、下げると「間違ったタイムアウト仕様」というエラーが発生します。

この問題を解決する方法はありますか?それとも完全に異なるプログラム構成がありますか?

答え1

マルチスレッドが必要です。見るGNUパラレル

答え2

解決策が見つかりました。デフォルトでは、バックグラウンドで更新ループを実行し、フォアグラウンドでメインループを実行します。トラップ/キルコマンドを使用して互いに通信できます。

完全な例を提供するために、.shファイルをgithubにアップロードしました。

どのように動作するかについての修正された概要は次のとおりです。

注:エスケープするにはctrl-cを使用する必要があります。

#!/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

上記のサンプルスクリプトを実際のサンプルバージョンとして使用してください。しかし、すでに持っています!プログラムアーキテクチャに対するいくつかの修正です。

関連情報