ぬーぶのメモ帳

フリーゲームエンジン「Godot」でプログラム経験のない素人の備忘録 最近は色々な動作を考えて試すのが好き。

【Godot】練習に簡易RPGに挑戦したら大変だった3 

その1 : 【Godot】練習に簡易RPGに挑戦したら大変だった1 - ぬーぶのメモ帳
その2 : 【Godot】練習に簡易RPGに挑戦したら大変だった2 - ぬーぶのメモ帳
戦闘システムの作成



フィールド関連のUIとシステムが完成して戦闘システムに移ります。
今回は簡素にこちらが先手の1対1のバトルを考えています。

戦闘ターンの大まかな部分はこちらのチュートリアルを参考にしました。
しかし戦闘システム自体のチュートリアルではないのでダメージ計算などは自力で作ります。

www.youtube.com


コマンドも簡素に3種類

  • 攻撃 : ダメージ計算も(攻撃力 ー 防御力)の単純な方法
  • 防御 : 現在の防御力の1.5倍にして、敵ターン終了後に戻す
  • 逃げる: 敵のHPを満タンに戻す


まず作るのはテキストを進めるためのコード、ここはチュートリアルからの流用。
戦闘中の文章は全てyield()と言うコマンドで一時停止して、マウスクリックで飛ばしたシグナルに反応して続きを表示させます。

# 左クリックするとメッセージウィンドウが消えシグナルを飛ばす
func _input(event: InputEvent) -> void:
	if Input.is_mouse_button_pressed(BUTTON_LEFT):
		$message.hide()
		emit_signal("textbox_close")
# 敵出現
	display_text(str(enemy[0]["name"]) + " が 現れた!!")
	yield(self, "textbox_close")
# ここのyieldで命令が一時停止する、textbox_close の信号を受け取ると続きのスクリプトが実行される
	display_text("コマンド?")
	switch = true

画像だとこう

  • yieldGodot 4.0にバージョンが上がると廃止されて別のコマンドになります

次にターンの流れを大まかに考えてみる。

ルール作りはカードゲームやボードゲームのような感覚があって楽しい

こちらが行動すると敵が行動する流れに、コマンドにはGodotのボタンのシグナル接続を利用してそれぞれ関数を作ってみます。

この場合attackボタンを押すと接続した関数が実行されるようになる



工程の少ない逃走から作成、しかし逃走したあと敵のHPが回復しない…

原因は敵のグローバル変数の値を直接使用したからだと考えました。
今回は最大HPもグローバル変数に追加し逃げた際「HP(int値) = 最大HP(int値)」と設定して回復させる事に、
本来の解決策としては敵のステータスをあらかじめ格納する変数を作りそれを使う事だと思います。


またショップ画面、戦闘画面が開いたままキャラクターが移動すると困るのでフィールドは停止させます。
方法は「get_tree().paused = true」が実行された際全ての動作が中断する、なので逃走する際はそれも解除する。

ただ全て動作が止まるとショップと戦闘画面も停止するためそれを防ぐのがインスペクター欄の下にあるPause Modeになります。

これをProcessに設定したノードはPause中でも動作する



次に攻撃、防御に使うダメージ関数を作成、攻撃から防御を引くだけの非常に単純なものです。

# 関数の名前は任意でOK今回は combat
func combat(atk, def) -> int:
	var dmg
	if atk <= def:
		dmg = 0
	else:
		dmg = atk - def
	return dmg
  • 例 : combat(味方の攻撃力, 敵の防御力) 上のatkとdefは全て関数()に入力したものに代入され、dmgの値を返す。

別の関数でこれを呼び出す時も同じ事をして敵味方の攻撃と防御に使う。

func _on_attack_pressed() -> void:
# 関数()内に変数を設定した場合 設定した数だけ 変数を入れないとエラーになる。
	enemy[0].hp = enemy[0].hp  - combat(p_atk ,enemy[0].def)
	display_text(str(combat(p_atk, enemy[0].def)) + " ダメージ!!")
	yield(self, "textbox_close")
	set_hp()

攻撃関数内にダメージ関数を呼び出し敵のHPと差し引く、差し引いた結果はHP更新の関数を更に呼び出す。
防御関数は単に防御を増加させ敵にターンを渡す、敵がダメージ計算を行いどちらか倒れるまでこれを繰り返す事になる。

完成品

1~3を通した映像はこちら

今回一番上手くいった事はアイテム欄の読み込み。

改善する点は綺麗にシグナルの導線を作る事が出来なかった点です。
戦闘システムもHP処理やその他をダメージ計算に上手く組み込めず、防御等はターンエンド処理を作った方が良かったなと思ったり。
今回は目に見える所よりコード内を綺麗に構築できなった事が気になりました。

それでも今回配列、特に辞書を使う勉強になり大変ではあったけど挑戦して良かったと感じます。