bashスクリプトを学び、Quadronixを書きます

ハブには既にbashゲームに関する多くの記事があります;これらはChessXonixSokobanSea Battle 、さらには擬似3Dグラフィックスを備えシューターです。 しかし、これらすべてのゲームでは、制御はキーボードを介して行われます。 さらに進んで、bashでゲームを作成し、マウスで制御します。 同時に、端末のサイズ変更に対してゲームを耐性にする方法を見つけます。 それでは、Quadronixゲームを作成しましょう。





Quadronixのゲームを初めて見たのは、数年前に兄と一緒に電話をしていたときで、すぐにそれが好きでした。 しかし、私の弟はほとんど電話をくれなかったので、私はためらうことなく、Javaアプレットの形でゲームのクローンを実現しました。

そして今、 プロセッサ3Dゲームの エミュレータが既にbashで何をしているのかを見て、bashでのXonixの実装はすでに20世紀であり、先に進む必要があることに気付きました。 そして、Quadronixをbashに実装することは、脳にとって良いトレーニングになると思いました。

ゲームのルールは簡単です。 4つの頂点がすべて同じ色である長方形を見つける必要があります。 そのような長方形を削除するには、対角線上にある頂点をクリックする必要があります。 この場合、長方形に追加されるポイントの数は、その面積に比例します。 そして、破壊された長方形の代わりに、ランダムな色の新しい正方形が表示されます。 ゲームはしばらくプレイされます。プレイするためには、より面白く、ポイントが多いほど時間が短くなります。 また、プレーヤーが長方形の選択と間違えられた場合、ペナルティが残りの時間から差し引かれます。 最後に、誤ってマークされた頂点の選択を解除するには、もう一度クリックします。

マウスがなければ、このようなゲームをプレイするのは面白くないことは明らかです。 まあ、私たちはマウスを実現しています。 man console_codesを読むと、エスケープシーケンスESC [ ? 9 h ESC [ ? 9 hマウストラッキングモードを有効にし、
エスケープシーケンスはESC [ ? 9 l ESC [ ? 9 lはこのモードをオフにします。
追跡モードがオンのとき、マウスの状態が変化すると、マウスの状態を記述する制御シーケンスがコンソール入力ストリームに書き込まれます。 ESC [ M bxy形式ESC [ M bxybには押されたボタンと修飾キーに関する情報ESC [ M bxyxyにはマウスの座標に関する情報ESC [ M bxyます。 シンボルbは、私たちにとって興味深いものではありません。 また、マウスの座標を取得するには、 xy両方から32を引く必要があります。

しかし、bashで最も簡単なタスクは、文字コードを取得することではありません。 私の意見では、最も単純なコマンドは、実験を通じて得られた次のものです。
 LC_ALL=C printf -v code '%d' "'$data" 

ここでは、ドル記号の前の単一のペアになっていない引用符に注意する必要があります。 次の文字ではなく、そのコードが表示されることを意味します。 また、 LC_ALL=C場合、127を超えるコードを持つ文字は、マルチバイト文字の一部としてではなく、それ自体で解釈される必要があります。

そこで、次のスクリプトを作成します。
 #!/bin/bash declare -i mouseX declare -i mouseY declare -i mouseButton declare -r ESC_CODE=$'\e' declare -r EXIT_CODE='x' printMouseInfo() { echo button=$mouseButton column=$mouseX row=$mouseY } readMouse() { local mouseButtonData local mouseXData local mouseYData read -r -s -n 1 -t 1 mouseButtonData read -r -s -n 1 -t 1 mouseXData read -r -s -n 1 -t 1 mouseYData local -i mouseButtonCode local -i mouseXCode local -i mouseYCode LC_ALL=C printf -v mouseButtonCode '%d' "'$mouseButtonData" LC_ALL=C printf -v mouseXCode '%d' "'$mouseXData" LC_ALL=C printf -v mouseYCode '%d' "'$mouseYData" ((mouseButton = mouseButtonCode)) ((mouseX = mouseXCode - 32)) ((mouseY = mouseYCode - 32)) } declare key echo -ne "\e[?9h" while true; do key="" read -r -s -t 1 -n 1 key case "$key" in $EXIT_CODE) break;; $ESC_CODE) read -r -s -t 1 -n 1 key if [[ "$key" == '[' ]]; then read -r -s -t 1 -n 1 key if [[ "$key" == "M" ]]; then readMouse printMouseInfo fi fi;; esac done echo -ne "\e[?9l" 


これが正しい方法であると言うわけではありませんが、動作します:
 $ ./mouse.sh button=0 column=46 row=17 button=0 column=61 row=19 button=0 column=64 row=15 button=0 column=59 row=11 button=0 column=43 row=9 button=0 column=36 row=10 button=0 column=42 row=17 button=0 column=63 row=23 button=0 column=75 row=22 button=0 column=91 row=19 $ 

エスケープシーケンスESC [ ? 1000 h ESC [ ? 1000 h 、マウスボタンのクリックとリリースに関する情報を取得できます。

次に、信号を使用してユーザーアクションからスクリプトの脆弱性を減らす方法を見てみましょう。

最初に行うことは、スクリプトの実行中にCtrl + Cを押した場合にresetコマンドを呼び出すことです。 これは開発中に非常に便利です。ゲームで色を使用し、ユーザー入力を抑制します。スクリプトが中断された場合、ランダムにresetを入力するまで、ターミナルは完全に機能しない状態になります。

信号を受信したときにコードを実行するには、 trapコマンドを使用します。
 trap   

trap -l入力すると、 パラメーターの可能な値を見つけることができます。 パラメーターが存在しない場合、デフォルトのアクションが設定されます。 パラメーターとしてEXITを指定すると、スクリプトの終了時に指定されたコマンドが実行されます。これが必要なことです。 私たちは書きます:

 function initApplication() { stty -echo echo -ne $HIDE_CURSOR_CODE trap finishApplication EXIT ... } function finishApplication() { trap EXIT reset } initApplication runApplication finishApplication 


シグナルハンドラが必要な2番目のケースは、ウィンドウのサイズ変更です。 たとえば、ウィンドウを開いた場合、またはその逆の場合、美しいグラフィックはすべてクロールされますが、実際にはクロールされません。 端末ウィンドウのサイズが変更されたことを確認するには、 SIGWINCHシグナルを使用できます。
 function repaint() { LINES=`tput lines` COLUMNS=`tput cols` mapXPosition=$(((COLUMNS - CELL_WIDTH * MAP_WIDTH) / 2 + 1)) mapYPosition=$(((LINES - CELL_HEIGHT * MAP_HEIGHT) / 2 + 1)) timerXPosition=$((MAP_WIDTH * CELL_WIDTH + mapXPosition + 6)) timerYPosition=$((mapYPosition)) echo -ne "\e[0m" clear drawMap drawHeader drawFooter ((isInvalidated = 0)) } function initApplication() { ... trap "((isInvalidated = 1))" SIGWINCH } function runGame() { local key ... while true; do if ((isInvalidated)); then repaint fi ... key="" ... case "$key" in $NEW_GAME_CODE) continue 2;; $EXIT_CODE) break 2;; $ESC_CODE) ... esac ... done } 


DEBUGとして指定すると、指定したコマンドは各スクリプトコマンドの後に実行されることに注意してください。デバッグに役立つ場合があります。

さて、スクリプトコードへのリンク: quadronix.sh

最後に、 man bashman console_codes 、ABSは無限に読むことができ、そのたびにbashでのプログラミングの新しい側面を発見できると言います。

Source: https://habr.com/ru/post/J131921/


All Articles