こんにちは。
「Pythonでつくる ゲーム開発 入門講座」の
Chapter11,12(本格RPGを作ろう!全編・後編)を基にRPGを作っていきます。
前回は戦闘に関する修正で、味方全員が物理攻撃を出来るようにしました。
今回から呪文を使えるように修正していきます。
今回は回復など自身や仲間に使う呪文を使えるように修正します。
目次
呪文の対象
呪文を使う対象を選択できるようにします。
例:回復呪文の場合は誰を回復するか。
仲間がいない時は選択する必要が
なかったのですが、
仲間を追加したので、
対象を誰にするのか
選択できるようにします。
対象を選択している時、
以下箇所の名前を点滅させます。

この例ではハロ3を
選択しているので
決定キーを押下すれば
ハロ3に呪文をかけます。
※回復呪文の時は
ハロ3を回復
対象の選択は
左右(←→)キーを使います。
対象を選択
それでは、呪文を使う対象を
選択できるようにします。
変更前
def spell_target_select(bg, key, player): # 呪文の対象を選択
global idx, spell_target_i
ent = False
if chara.get_spell_target(player[0].mas_spell[sel_spell_i]) <= 1: # 呪文の対象が味方
if key[K_SPACE] or key[K_RETURN]: # 決定
ent = True
変更後
def spell_target_select(key, player): # 呪文の対象を選択 player[btl_player]:呪文選択中のプレイヤー
global idx, spell_target_i
ent = False
if chara.get_spell_target(player[btl_player].mas_spell[sel_spell_i]) == 0:
if key[K_LEFT] and spell_target_i > 0: # ←キー
spell_target_i -= 1
elif key[K_RIGHT] and spell_target_i < len(player)-1: # →キー
spell_target_i += 1
elif key[K_SPACE] or key[K_RETURN]: # 決定
player[btl_player].target = player[spell_target_i] # 対象をセット
ent = True
elif chara.get_spell_target(player[btl_player].mas_spell[sel_spell_i]) == 1:
if key[K_SPACE] or key[K_RETURN]: # 決定
ent = True
elif chara.get_spell_target(player[btl_player].mas_spell[sel_spell_i]) == 2: # 呪文の対象がモンスター単体
(省略)
elif chara.get_spell_target(player[btl_player].mas_spell[sel_spell_i]) == 3: # 呪文の対象がモンスターグループ
(省略)
elif chara.get_spell_target(player[btl_player].mas_spell[sel_spell_i]) == 4: # 呪文の対象がモンスター全体
(省略)
※spell_target_select関数の引数について
「bg」は不要だったので消しています。
呼び出す側も消します。
前々回、コマンド選択中のキャラの
インデックスをbtl_playerにしたので
player[0]をplayer[btl_player]にしています。
※攻撃呪文についても
ついでに変更しています。
if chara.get_spell_target(player[0].mas_spell[sel_spell_i]) <= 1: # 呪文の対象が味方
if key[K_SPACE] or key[K_RETURN]: # 決定
ent = True
変更前は仲間がいないので、
対象が単体でも複数でも
動作は同じだったので、
0と1を同じ処理にしていました。
※対象の選択不要
※get_spell_targetの戻り値
呪文の対象が
0→味方単体
1→味方全員
2→敵単体
3→敵グループ
4→敵全体
です。
if chara.get_spell_target(player[btl_player].mas_spell[sel_spell_i]) == 0:
if key[K_LEFT] and spell_target_i > 0: # ←キー
spell_target_i -= 1
elif key[K_RIGHT] and spell_target_i < len(player)-1: # →キー
spell_target_i += 1
仲間を追加したので、
対象が味方単体の呪文は
左右(←→)キーで
対象を移動します。
※左右キーを押下すると
点滅する名前を変更する
※spell_target_iは
呪文対象のインデックスです。
elif key[K_SPACE] or key[K_RETURN]: # 決定
player[btl_player].target = player[spell_target_i] # 対象をセット
対象を決めたら
対象オブジェクトを
targetに格納します。
※targetは前回追加した
インスタンス変数です。
elif chara.get_spell_target(player[btl_player].mas_spell[sel_spell_i]) == 1:
if key[K_SPACE] or key[K_RETURN]: # 決定
ent = True
対象が味方全員の時は
選択不要になります。
対象を点滅
冒頭に記載したように
誰を選択中なのか
分かるように名前を点滅させます。
変更前
def draw_battle(bg, fnt, obj, player): # 戦闘画面の描画 obj:戦闘で行動中のオブジェクト
(省略)
for i, p in enumerate(player):
x_i_t.append(x_i + x_b*i + 10) # テキストのx座標の開始位置
# 名前の表示(回復呪文の対象を選択中の時は点滅)
if idx == 25 and chara.get_spell_target(p.mas_spell[sel_spell_i]) == 0: # 呪文の対象の選択中,呪文の対象が味方なら
draw_text(bg, "{}".format(p.name), x_i_t[i], y_i_t, fnt, BLINK[tmr%6])
else: # 呪文の対象の選択中でなければ
draw_text(bg, "{}".format(p.name), x_i_t[i], y_i_t, fnt, col)
変更後
def draw_battle(bg, fnt, obj, player): # 戦闘画面の描画 obj:戦闘で行動中のオブジェクト
(省略)
for i, p in enumerate(player):
x_i_t.append(x_i + x_b*i + 10) # テキストのx座標の開始位置
# 名前の表示(回復呪文の対象を選択中の時は点滅)
if idx == 25 and ((chara.get_spell_target(p.mas_spell[sel_spell_i]) == 0 and i == spell_target_i) or chara.get_spell_target(p.mas_spell[sel_spell_i]) == 1): # 呪文の対象の選択中,呪文の対象が味方なら、対象が単体の時は対象のみ、対象が全員の時は全員
draw_text(bg, "{}".format(p.name), x_i_t[i], y_i_t, fnt, BLINK[tmr%6])
else: # 呪文の対象の選択中でなければ
draw_text(bg, "{}".format(p.name), x_i_t[i], y_i_t, fnt, col)
点滅の条件を追加しています。
if idx == 25 and ((chara.get_spell_target(p.mas_spell[sel_spell_i]) == 0 and i == spell_target_i) or chara.get_spell_target(p.mas_spell[sel_spell_i]) == 1):
・対象が単体 かつ 選択中 の場合、
・対象が味方全員 の場合、
は名前を点滅するようにしています。
※味方全員の場合は全員の名前が点滅
対象を確定
呪文の対象を確定したら
行動(act)に26(呪文を使う)を
格納します。
def main(screen, clock, font, fontS, player, area):
(省略)
elif idx == 25: # 呪文の対象を決める
draw_battle(screen, fontS, turn_obj, player)
if spell_target_select(key, player) == True:
player[btl_player].act = 26 # get_battle_turnの戻り値idxを26
player[btl_player].act = 26 # get_battle_turnの戻り値idxを26
呪文を選択したキャラの
行動(act)についても
player[0]から
player[btl_player]に
変更します。
if spell_target_select(key, player) == True:
spell_target_select関数の
引数「bg」を削除したので
呼び出す側も「screen」を
削除しています。
呪文発動
使った呪文が
正常に動作するように
修正します。
まず、player[0]を
修正します。
ここではplayer[btl_player]ではなく
turn_objに変更しています。
player[btl_player]→コマンド選択中のキャラ
turn_obj→ターン内で行動中のキャラ(モンスター含む)
def main(screen, clock, font, fontS, player, area):
(省略)
elif idx == 26: # 呪文発動
draw_battle(screen, fontS, turn_obj, player)
spell_point = 0 # プレイヤーが与えるダメージ、受けるダメージ 呪文用
if tmr == 1:
spell_blink = chara.get_spell_blink(turn_obj.mas_spell[tmp_sel_spell_i]) # 呪文演出(いろ)
spell_blink = spell_blink.split(",")
set_message(turn_obj.name + " は " + turn_obj.mas_spell[sel_spell_i] + " となえた!")
if 2 <= tmr and tmr <= 4:
print(spell_blink)
print(tmr)
print(spell_blink[tmr%3])
pygame.draw.rect(screen, spell_blink[tmr%3], [0, 0, screen.get_width(), screen.get_height()])
if tmr == 8:
if turn_obj.check_mp(turn_obj.mas_spell[sel_spell_i]): # mpが足りていたら
spell_target_no = chara.get_spell_target(turn_obj.mas_spell[sel_spell_i]) # 呪文の対象(0:味方単体,1:味方全員,2:敵単体,3:敵グループ,4:敵全体)
if spell_target_no == 0: # 呪文の対象が味方単体
spell_point, spell_message = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], turn_obj.target, spell_target_no)
if spell_point != -1: # 回復系、-1は補助系
turn_obj.target.hp += spell_point
if turn_obj.target.hp > turn_obj.target.maxhp:
turn_obj.target.hp = turn_obj.target.maxhp
set_message(spell_message)
spell_blink = chara.get_spell_blink(turn_obj.mas_spell[tmp_sel_spell_i]) # 呪文演出(いろ)
player[0]→turn_obj
に修正しています。
if spell_target_no == 0: # 呪文の対象が味方単体
spell_point, spell_message = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], turn_obj.target, spell_target_no)
if spell_point != -1: # 回復系、-1は補助系
turn_obj.target.hp += spell_point
if turn_obj.target.hp > turn_obj.target.maxhp:
turn_obj.target.hp = turn_obj.target.maxhp
player[0]→turn_obj.target
に修正しています。
ここは呪文を使う側ではなく、
使われる側(呪文の対象)です。
次に、味方全員に使う呪文の
処理を追加します。
def main(screen, clock, font, fontS, player, area):
(省略)
elif idx == 26: # 呪文発動
(省略)
if spell_target_no == 0: # 呪文の対象が味方単体
(省略)
elif spell_target_no == 1: # 呪文の対象が味方全体
for i, p in enumerate(player):
spell_point, spell_message = turn_obj.use_spell(turn_obj.mas_spell[sel_spell_i], p, spell_target_no)
set_message(spell_message)
if spell_point != -1: # 回復系、-1は補助系
p.hp += spell_point
if p.hp > p.maxhp:
p.hp = p.maxhp
draw_battle(screen, fontS, turn_obj, player)
pygame.display.update() # 少し時間をとめる
pygame.time.delay(delay_speed)
仲間がいない時は
使うことがないので
「pass」にしていました。
1人ずつuse_spellメソッドを
呼び出して、呪文をかけます。
※回復呪文の場合は回復する
pygame.display.update() # 少し時間をとめる
pygame.time.delay(delay_speed)
メッセージ表示の為に
少し時間を止めています。
他の箇所でも使っていますが
この方法で時間を止めるのは
何となく辞めたほうが良い気がするので、
変更しようと思っています。
※そのうち・・
とりあえず、回復など自身や仲間に使う呪文は
使えるようになりましたが、
複数人が回復呪文を使った場合、
使う呪文は最後のキャラが選択した呪文を
全員使うことになります。
例
1人目:スカラ
2人目:ホイミ
3人目:ベホイミ
4人目:ベホマラー
を選択した場合、
全員ベホマラーを使ってしまいます。
これは前回の攻撃対象と
似たような原因と思います。
選択した呪文が何かを格納する際に
全員同じ変数を使っている為
上書きされてしまっていると思います。
この辺りは次回修正しようと思います。
といういことで、
呪文に関する修正について
今回は以上にします・・
その他
バグというわけではないですが
経験値の取得について、少し変更します。
変更前
def main(screen, clock, font, fontS, player, area):
(省略)
if tmr == 11:
tmp_exp = do_attack(turn_obj.target, dmg, turn_obj)
if dmg != 0 and tmp_exp == 0 and turn_obj.target.flag_sleep: # 攻撃を受けた かつ 生きている かつ 眠っている
if random.randint(0, 99) < 55:
turn_obj.target.invalid_sleep()
set_message(turn_obj.target.name + " はめをさました!")
btl_exp += tmp_exp
check_monster()
変更後
def main(screen, clock, font, fontS, player, area):
(省略)
if tmr == 11:
btl_exp += do_attack(turn_obj.target, dmg, turn_obj) # 倒していない時は0が返る
if dmg != 0 and turn_obj.target.hp != 0 and turn_obj.target.flag_sleep: # 攻撃を受けた かつ 生きている かつ 眠っている
if random.randint(0, 99) < 100:
turn_obj.target.invalid_sleep()
set_message(turn_obj.target.name + " はめをさました!")
check_monster()
眠っている対象に攻撃をした場合
条件を満たせば、
一定確率で目を覚ますようにしています。
その条件は
攻撃を受けた、生きている、眠っている
の3つです。
※ミス(ダメージ0)は対象外
この条件の中の生きているかどうかを
確認する為に
変更前はdo_attack関数の
戻り値(経験値)を使っていました。
※経験値が0の場合は
まだ生きている、
経験値が0でない場合、
対象を倒した
この条件を単純に攻撃対象のHPが
0かそうでないかに変更しました。
というだけです・・
そして、今回は以上です!(`・ω・´)
最後に
今回は戦闘における呪文について
回復など自身や仲間に使う呪文を
使えるように修正しました。
次回も呪文を修正したいと思います。
【ご注意】
プログラムやデータなどは著作権法により保護されています。
著作者の許諾を得ずに、プログラムおよびデータそのものまたは改変したものを
配布したり販売したりすることはできません。
また、これらを利用して発生した損害などに関して、著作者は一切責任を負いません。