[Python]ターミナルで動くRPGゲームを作る。
1.ターミナルで動くRPG
ターミナルで動くRPGを作ります。ゲームはプレイヤーと敵キャラクターを登場させ互いのHPが無くなるまで攻撃し、最後にどちらが勝ったかを判定します。
2.敵キャラ情報の設定
3体の敵キャラの情報をリストと辞書を使って表現します。敵キャラの情報には名前、HP、攻撃力を設定します。攻撃力は固定にせず、決めた範囲内でランダムに設定します。そのためにrandomモジュールを使用するので事前にインポートしてください
from random import randint
ENEMEY_INFO = [
{
"name": "スライム",
"status":
{
"hp":10,
"atk": randint(1, 3)
}
},
{
"name": "キラーマシーン",
"status":
{
"hp":100,
"atk": randint(3, 15)
}
},
{
"name": "竜王",
"status":
{
"hp":500,
"atk": randint(15, 75)
}
}
]
3.プレイヤー情報の作成
プレイヤーの基本ステータスを設定する関数を作ります。HP、攻撃力は上記2のモンスター同様に定められた範囲内でランダムに設定します。
def set_player_param():
player_hp = randint(1, 100)
player_atk = randint(1, 50)
player_param = player_hp, player_atk
return player_param
一度タプルにそれぞれの値を格納して、プレイヤー情報を返します。
4.プレイヤー情報の表示
実際のゲームで自身の強さを見たい時があります。(例.「つよさをみる」)
そこで、作成したプレイヤーのステータスが確認できる関数を作ります。
def show_player_status(param):
hp, atk = param
print("** YOUR STATUS **")
print("HP: {0:>6}".format(hp))
print("ATK: {0:>5}".format(atk))
print("** **** ***** **")
(例.実行結果)
** YOUR STATUS **
HP: 97
ATK: 7
** **** ***** **
5.敵キャラ情報の作成
1の方で敵キャラの情報を設定しました。今度は設定した情報に基づいて敵キャラを作成します。設定した情報からランダムにキャラを選び、それぞれの名前、HP、攻撃力をタプルに格納して作成した敵キャラの情報を返す関数を作ります。
def set_enemy_param():
ene_index = randint(0, len(ENEMEY_INFO) - 1)
enemy_info = ENEMEY_INFO[ene_index]
ene_name = enemy_info["name"]
ene_hp = enemy_info["status"]["hp"]
ene_atk = enemy_info["status"]["atk"]
enemy_param = ene_name, ene_hp, ene_atk
return enemy_param
6.ダメージの計算
ダメージの計算を処理する関数を作成します。この関数は4つの引数を受け取ります。既存の攻撃力、攻撃力の範囲、攻撃する側の名前、攻撃される側の名前の4つになります。
まず、与える攻撃力について考えます。そのまま、設定した攻撃力を与えればいいのではと思いますが、敵キャラとプレイヤーは現実でもゲームでも毎回同じパフォーマンスを振るう事は難しいです。そこで、パフォーマンスを決める値を既存の攻撃力に追加して最終的な攻撃力を決めます。
最終的な攻撃力 = 既存の攻撃力 + パフォーマンスによる値の調整値
また、残りの攻撃する側、される側の引数は誰から誰への攻撃をしたかの出力を表示する為に渡します。これらを踏まえてコードは以下になります。
def calc_dmg(atk, range_atk, from_who, to_who):
total_atk = atk + randint(-1 * range_atk, range_atk)
if total_atk > 0:
print("{0}:{1}に{2}のダメージを与えた!".format(from_who, to_who, total_atk))
return total_atk
else:
print("ミス!ダメージを与えられなかった")
total_atk = 0
return total_atk
if文では最終的な攻撃力が0以下の場合ミス!と分岐させて表示します。
7.勝利の判定
勝利条件の判定はプレイヤーのHPと敵HP決めます。
def judge_who_win(player_hp, enemy_hp):
if player_hp < 0:
ply_win_flag = False
elif enemy_hp < 0:
ply_win_flag = True
return ply_win_flag
8.ゲーム進行
ゲームの進行処理は1から7で作ったモノを利用して進めていきます。
if __name__ == "__main__":
print("ようこそケーリュケイオンの世界へ")
start_flag = int(input("冒険を始めますか?:[1:始める/0:やめる]:"))
if start_flag != 1:
sys.exit()
else:
#ゲームスタート
pass
ゲームスタート処理で敵、プレイヤー情報を事前に呼び込みます。
else節以降に記述します。
while True:
#プレイヤー情報生成
player_info = set_player_param()
#プレイヤー情報取得
ply_hp = player_info[0]
ply_atk = player_info[1]
#敵情報生成
enemy_info = set_enemy_param()
#敵情報の取得
ene_name = enemy_info[0]
ene_hp = enemy_info[1]
ene_atk = enemy_info[2]
ここでユーザーに、選択肢を与え、それぞれの処理に分岐させます。
戦闘シーンは演出を持たせるために、sleepで表現しています。攻撃の順番は
プレイヤーが先行です。atk_indexに1を加えていきます。
それによって、以下の表の通りにatk_indexが2で割り切れた場合、Trueでプレイヤーが攻撃を、Falseで敵キャラが攻撃を切り替えています。
(T:True, F:False, P:プレイヤー,E:敵キャラ)
atk_index| 0 | 1 | 2 | 3 | 4 | .....
判定 |T | F | T | F | T | .....
攻撃者 |P | E | P | E | P | ....
select_mode = int(input("女神:「異世界から参りし者よ、何用じゃ?」[1:冒険に出かける/2:自分の状態を知る/0:休息を取る]:"))
if select_mode == 0: break
if select_mode == 2:
show_player_status(player_info)
else:
#攻撃の順番
atk_index = 0
for i in range(randint(1, 5)):
print(".")
sleep(1)
print("{0}があらわれた!".format(ene_name))
#戦闘開始
while ply_hp > 0 and ene_hp > 0:
if atk_index % 2 == 0:
total_atk = calc_dmg(ply_atk, 3, "冒険者", ene_name)
ene_hp -= total_atk
else:
total_atk = calc_dmg(ene_atk, 5, ene_name, "冒険者")
ply_hp -= total_atk
atk_index += 1
#1秒待って戦闘ログを出力
sleep(1)
player_win_flag = judge_who_win(ply_hp, ene_hp)
#ゲーム判定
if player_win_flag:
print("{0}を倒した!おめでとう!".format(ene_name))
else:
print("冒険者は倒れてしまった。返事がない..")
10.実行結果
11.コード最終形
from random import randint
from time import sleep
import sys
ENEMEY_INFO = [
{
"name": "スライム",
"status":
{
"hp":10,
"atk": randint(1, 3)
}
},
{
"name": "キラーマシーン",
"status":
{
"hp":100,
"atk": randint(3, 15)
}
},
{
"name": "竜王",
"status":
{
"hp":500,
"atk": randint(15, 75)
}
}
]
def set_enemy_param():
ene_index = randint(0, len(ENEMEY_INFO) - 1)
enemy_info = ENEMEY_INFO[ene_index]
ene_name = enemy_info["name"]
ene_hp = enemy_info["status"]["hp"]
ene_atk = enemy_info["status"]["atk"]
enemy_param = ene_name, ene_hp, ene_atk
return enemy_param
def set_player_param():
player_hp = randint(1, 100)
player_atk = randint(1, 50)
player_param = player_hp, player_atk
return player_param
def show_player_status(param):
hp, atk = param
print("** YOUR STATUS **")
print("HP: {0:>6}".format(hp))
print("ATK: {0:>5}".format(atk))
print("** **** ***** **")
def calc_dmg(atk, range_atk, from_who, to_who):
total_atk = atk + randint(-1 * range_atk, range_atk)
if total_atk > 0:
print("{0}:{1}に{2}のダメージを与えた!".format(from_who, to_who, total_atk))
return total_atk
else:
print("ミス!ダメージを与えられなかった")
total_atk = 0
return total_atk
def judge_who_win(player_hp, enemy_hp):
if player_hp < 0:
ply_win_flag = False
elif enemy_hp < 0:
ply_win_flag = True
return ply_win_flag
if __name__ == "__main__":
print("ようこそケーリュケイオンの世界へ")
start_flag = int(input("冒険を始めますか?:[1:始める/0:やめる]:"))
if start_flag != 1:
sys.exit()
else:
#ゲームスタート
while True:
#プレイヤー情報生成
player_info = set_player_param()
#プレイヤー情報取得
ply_hp = player_info[0]
ply_atk = player_info[1]
#敵情報生成
enemy_info = set_enemy_param()
#敵情報の取得
ene_name = enemy_info[0]
ene_hp = enemy_info[1]
ene_atk = enemy_info[2]
select_mode = int(input("女神:「異世界から参りし者よ、何用じゃ?」[1:冒険に出かける/2:自分の状態を知る/0:休息を取る]:"))
if select_mode == 0: break
if select_mode == 2:
show_player_status(player_info)
else:
#攻撃の順番
atk_index = 0
print("{0}があらわれた".format(ene_name))
while ply_hp > 0 and ene_hp > 0:
if atk_index % 2 == 0:
total_atk = calc_dmg(ply_atk, 3, "冒険者", ene_name)
ene_hp -= total_atk
else:
total_atk = calc_dmg(ene_atk, 5, ene_name, "冒険者")
ply_hp -= total_atk
atk_index += 1
sleep(1)
player_win_flag = judge_who_win(ply_hp, ene_hp)
if player_win_flag:
print("{0}を倒した!おめでとう!".format(ene_name))
else:
print("冒険者は倒れてしまった。返事がない..")