awkでRPGゲーム
ゲームでプログラミングとなると、大抵はjavascriptで作ることが多いと思います。
キーボード操作やマウス操作が絡んできますからね。
awkでも、リアルタイムでキーボード操作ができれば、ゲームを作ることができます。
キーボード操作そのものはシェルスクリプトになります。
簡単なRPGゲーム(?)を作成してみました。
いきなり、ドラクエの最後のボスとの直接対決からスタートします。
wキーが上に移動、sキーが下に移動します。
ぜひ、最後の魔王を倒して、世界に平和をもたらしてください。
#! /usr/bin/gawk -f # rpg.awk function getch( cmd,k){ cmd="bash -c 'read -r -s -n 1 ke;echo $ke'" cmd | getline k; close(cmd) fflush() return k } function cls(){ printf("\033[H\033[J") } #[6-1]ゲームを初期化する関数を宣言する function Init(){ #[6-1-1]プレイヤーのステータスを初期化する characters[CHARACTER_PLAYER]["hp"] = monsters[MONSTER_PLAYER]["hp"]; characters[CHARACTER_PLAYER]["maxHp"] = monsters[MONSTER_PLAYER]["maxHp"]; characters[CHARACTER_PLAYER]["mp"] = monsters[MONSTER_PLAYER]["mp"]; characters[CHARACTER_PLAYER]["maxMp"] = monsters[MONSTER_PLAYER]["maxMp"]; characters[CHARACTER_PLAYER]["attack"] = monsters[MONSTER_PLAYER]["attack"]; characters[CHARACTER_PLAYER]["name"] = monsters[MONSTER_PLAYER]["name"]; } #[6-2]戦闘シーンの画面を描画する関数を宣言する function DrawBattleScreen(){ #[6-2-1]画面をクリアする cls(); # [6-2-2]プレイヤーの名前を表示する printf("%s\n",characters[CHARACTER_PLAYER]["name"]); # [6-2-3]プレイヤーのステータスを表示する printf("HP:%d/%d MP:%d/%d\n", characters[CHARACTER_PLAYER]["hp"], characters[CHARACTER_PLAYER]["maxHp"], characters[CHARACTER_PLAYER]["mp"], characters[CHARACTER_PLAYER]["maxMp"]); #[6-2-4]1行空ける printf("\n"); #[6-2-5]モンスターのアスキーアートを描画する printf("%s",characters[CHARACTER_MONSTER]["aa"]); #[6-2-6]モンスターのHPを表示する printf("(HP:%d/%d)\n", characters[CHARACTER_MONSTER]["hp"], characters[CHARACTER_MONSTER]["maxHp"]); #[6-2-7]1行空ける printf("\n"); } #[6-3]コマンドを選択する関数を宣言する function SelectCommand(){ #[6-3-1]プレイヤーのコマンドを初期化する characters[CHARACTER_PLAYER][character_command] = 0; #character_command = 0; #[6-3-2]コマンドが決定するまでループする while(1){ #[6-3-3]戦闘画面を描画する関数を呼び出す DrawBattleScreen(); #[6-3-4]コマンドの一覧を表示する for(i = 0; i < COMMAND_MAX; i++){ #[6-3-5]選択中のコマンドなら if(i == characters[CHARACTER_PLAYER][character_command]){ #[6-3-6]カーソルを描画する printf(">"); }else{ #[6-3-7]選択中のコマンドでなければ printf(" "); } #[6-3-9]コマンドの名前を表示する printf("%s\n",commandNames[i]); } #[6-3-10]入力されたキーによって分岐する switch(getch()){ case "w": #[6-3-11]wキーが押されたら #[6-3-12]上のコマンドに切り替える characters[CHARACTER_PLAYER][character_command]--; #character_command--; break; case "s": #[6-3-13]sキーが押されたら #[6-3-14]下のコマンドに切り替える characters[CHARACTER_PLAYER][character_command]++ #character_command++; break; default:#[6-3-15]上記以外のキーが押されたら return; #[6-3-16]関数を抜ける } #[6-3-17]カーソルを上下にループさせる characters[CHARACTER_PLAYER][character_command] = (COMMAND_MAX + characters[CHARACTER_PLAYER][character_command]) % COMMAND_MAX; } } #[6-4]戦闘シーンの関数を宣言する function Battle(_monster){ #[6-4-1]モンスターのステータスを初期化する characters[CHARACTER_MONSTER]["hp"] = monsters[_monster]["hp"]; characters[CHARACTER_MONSTER]["maxHp"] = monsters[_monster]["maxHp"]; characters[CHARACTER_MONSTER]["mp"] = monsters[_monster]["mp"]; characters[CHARACTER_MONSTER]["maxMp"] = monsters[_monster]["maxMp"]; characters[CHARACTER_MONSTER]["name"] = monsters[_monster]["name"]; characters[CHARACTER_MONSTER]["attack"] = monsters[_monster]["attack"]; characters[CHARACTER_MONSTER]["aa"] = monsters[_monster]["aa"]; #[6-4-2]プレイヤーの攻撃対象をモンスターに設定する characters[CHARACTER_PLAYER]["target"] = CHARACTER_MONSTER; #[6-4-3]モンスターの攻撃対象をプレイヤーに設定する characters[CHARACTER_MONSTER]["target"] = CHARACTER_PLAYER; #[6-4-3]モンスターの攻撃対象をプレイヤーに設定する #[6-4-4]戦闘シーンの画面を描画する関数を呼び出す DrawBattleScreen(); #[6-4-5]戦闘シーンの最初のメッセージを表示する printf("%sがあらわれた!\n",characters[CHARACTER_MONSTER]["name"]); #[6-4-6]キーボード入力を待つ getch(); #[6-4-7]戦闘シーンが終了するまでループする while(1){ #[6-4-8]コマンドを選択する関数を呼び出す SelectCommand(); #[6-4-9]各キャラクターを反復する for(i = 0; i < CHARACTER_MAX; i++){ #[6-4-10]戦闘シーンの画面を描写する関数を呼び出す DrawBattleScreen(); switch(characters[i][character_command]){ case 0: #[6-4-12]戦う printf("%sのこうげき!\n",characters[i]["name"]); getch(); #[6-4-15]敵に与えるダメージを計算する damage = 1 + int(rand() * 1000) % characters[i]["attack"]; #[6-4-16]敵にダメージを与える characters[characters[i]["target"]]["hp"] -= damage; #[6-4-17]敵のHPが負の値になったかどうかを判定する if(characters[characters[i]["target"]]["hp"] < 0){ #[6-4-18]敵のHPを0にする characters[characters[i]["target"]]["hp"] = 0; } #[6-4-19]戦闘シーンの画面を再描画する関数を呼び出す DrawBattleScreen(); #[6-4-20:敵にダメージを与えたメッセージを表示する printf("%sに%dのダメージ!\n",\ characters[characters[i]["target"]]["name"],\ damage); #[6-4-21]キーボード入力を待つ getch(); break; case 1: #[6-4-22]回復 #[6-4-23]MPが足りるかどうかを判定する if(characters[i]["mp"] < SPELL_COST){ #[6-4-24]MPが足りないメッセージを表示する printf("MPがたりない!\n"); #[6-4-25]キーボード入力を待つ getch(); #[6-4-26]呪文を唱える処理を抜ける break; } #[6-4-27]MPを消費させる characters[i]["mp"] -= SPELL_COST; #[6-4-28]画面を再描画する DrawBattleScreen(); #[6-4-29]回復するメッセージを表示する printf("%sは回復することにした!\n",characters[i]["name"]); #[6-4-30]キーボード入力を待つ getch(); #[6-4-31]HPを回復させる characters[i]["hp"] = characters[i]["maxHp"]; #[6-4-32]戦闘シーンの画面を再描画する DrawBattleScreen(); #[6-4-33]HPが回復したメッセージを表示する printf("%sのきずがかいふくした!\n",characters[i]["name"]); #[6-4-34]キーボード入力を待つ getch(); break; case 2: #[6-4-35]逃げる #[6-4-36]逃げ出したメッセージを表示する printf("%sはにげだした!\n",characters[i]["name"]); #[6-4-37]キーボード入力を待つ getch(); #[6-4-38]戦闘処理を抜ける return; break; } #[6-4-39]攻撃対象を倒したかどうかを判定する if(characters[characters[i]["target"]]["hp"] <= 0){ #[6-4-40]攻撃対象によって処理を分岐させる switch(characters[i]["target"]){ #[6-4-41]プレイヤーなら case 0: #[6-4-42]プレイヤーが死んだメッセージを表示する printf("あなたはしにました"); break; #[6-4-43]モンスターなら case 1: #[6-4-44]モンスターのアスキーアートを何も表示しないよう書き換える characters[characters[i]["target"]]["aa"] = ""; #[6-4-45]戦闘シーンの画面を再描画する関数を呼び出す DrawBattleScreen(); #[6-4-46]モンスターを倒したメッセージを表示する printf("%sをたおした!\n",\ characters[characters[i]["target"]]["name"]); break; } #[6-4-47]キーボード入力を待つ getch(); #[6-4-48]戦闘シーンの関数を抜ける return; } } } } #[6-6]プログラムの実行開始点を宣言 BEGIN{ # [5]変数を定義 MONSTER_PLAYER = 0; #[3-1-1]プレイヤー MONSTER_SLIME = 1; #[3-1-2]スライム MONSTER_BOSS = 2; #[3-1-3]魔王 MONSTER_MAX = 3; #[3-1-4]モンスターの種類の数 monsters[MONSTER_PLAYER]["hp"] = 100; monsters[MONSTER_PLAYER]["maxHp"] = 100; monsters[MONSTER_PLAYER]["mp"] = 15; monsters[MONSTER_PLAYER]["maxMp"] = 15; monsters[MONSTER_PLAYER]["attack"] = 30; monsters[MONSTER_PLAYER]["name"] = "ゆうしゃ"; monsters[MONSTER_SLIME]["hp"] = 3; monsters[MONSTER_SLIME]["maxHp"] = 3; monsters[MONSTER_SLIME]["mp"] = 0; monsters[MONSTER_SLIME]["maxMp"] = 0; monsters[MONSTER_SLIME]["attack"] = 2; monsters[MONSTER_SLIME]["name"] = "スライム"; monsters[MONSTER_SLIME]["aa"] = "/・Д・\\n"\ "~~~~~~";#アスキーアート monsters[MONSTER_BOSS]["hp"] = 255; monsters[MONSTER_BOSS]["maxHp"] = 255; monsters[MONSTER_BOSS]["mp"] = 0; monsters[MONSTER_BOSS]["maxMp"] = 0; monsters[MONSTER_BOSS]["attack"] = 50; monsters[MONSTER_BOSS]["name"] = "まおう"; monsters[MONSTER_BOSS]["aa"] = " A@A\n"\ "~(▼皿▼)~"; CHARACTER_PLAYER = 0; #[3-2-1]プレイヤー CHARACTER_MONSTER = 1; #[3-2-2]モンスター CHARACTER_MAX = 2; #[3-2-3]キャラクターの種類 character_command = 0; COMMAND_MAX = 3; #コマンドの種類の数 # [5-3]コマンドの名前を宣言する commandNames[0] = "たたかう"; #[5-3-1] commandNames[1] = "かいふく"; #[5-3-2] commandNames[2] = "にげる"; #[5-3-3] SPELL_COST = 3; #呪文の消費MPを定義する #[6-6-1]乱数をシャッフルする srand(); # [6-6-2]ゲームを初期化する関数を呼び出す Init(); # [6-6-3]戦闘シーンの関数を呼び出す Battle(MONSTER_BOSS); # [6-6-4]キーボード入力を待つ getch(); }
私自身、awkでここまで大掛かりなプログラミングをしたのは初めてで、かなり苦労しました。
しかし、awkでもここまで出来ることが分かったのではないでしょうか?
utthi_fumi is game programmer!