見出し画像

ジャンケン NPC同士を戦わせる

これまで、何体かNPCを作りましたが、結局、どういう思考パターンがジャンケンで一番強いのか検証したいと思います。
まずは、NPC同士で戦えるようにします。

今日のハイライト


プレイヤーとCPU ➡ 1Pと2Pに変更

シーンの構造を変更

これまで、プレイヤーはキー入力、CPUは思考パターンによる乱数で1~3までの数字を出力してきましたが、NPC同士で戦わせる場合は、両方が、それぞれの思考パターンによる乱数を出力します。

プレイヤーとCPUという分け方にはならなくなるため、1Pと2Pにし、分かれていた処理を、同じスクリプトの「Characterシーン」で処理を行うようにしました。

Characterシーンのスクリプト

初期設定
・1Pと2P両方で使うCPUキャラクターのパスを設定
・1Pと2Pの表示のパスを設定
・必要な変数の定義

extends Node

# 初期設定

# 親ノード
@onready var main = get_node("../")

# charのパス
@onready var chr0 = $Human # プレイヤー
@onready var chr1 = $CPU_Boy
@onready var chr2 = $CPU_Gu
@onready var chr3 = $CPU_Choki
@onready var chr4 = $CPU_Pa
@onready var chr5 = $CPU_History
@onready var chr6 = $CPU_MindHack
@onready var chr7 = $CPU_Fortune

# 1p,2pのパス
@onready var name1 = $"HUD/1PName"
@onready var name2 = $"HUD/2PName"  
@onready var hand1 = $"HUD/1PHand"
@onready var hand2 = $"HUD/2PHand"

var p1 = "" # 1Pキャラのパスを入れる変数
var p2 = "" # 2Pキャラのパスを入れる変数
var selected_1p = false # 1Pが選択したか?フラグ
var selected_2p = false # 2Pが選択したか?フラグ

キャラを設定
・1P、2Pのキャラを設定し、絵と名前を表示する

# キャラ選択
func _ready() -> void:
	# 1Pと2Pのキャラ選択
	p1 = chr1
	p2 = chr2

	# chr0だったら1Pはプレイヤー、それ以外はCPU
	if p1 == chr0: 
		Global.ai_on = false
	else:
		Global.ai_on = true
	
	# 1pと2pのキャラ表示
	p1.show()
	p1.position = Vector2(90,150)
	p2.show()
	p2.position = Vector2(550,150)
	name1.text = "1P:" + p1.chr_name
	name2.text = "2P:" + p2.chr_name

プレイヤーのキー入力
・キー入力を数字に変換し、1P入力フラグを立てて、2Pの手の選択へ

# プレイヤーの手をキー入力で取得
func _process(delta: float) -> void:
	if not Global.game_set and not Global.ai_on:
		if Input.is_action_just_pressed("gu"):
			Global.player_hand = 1 # グーは1
		elif Input.is_action_just_pressed("choki"):
			Global.player_hand = 2 # チョキは2
		elif Input.is_action_just_pressed("pa"):
			Global.player_hand = 3 # パーは3
		else:
			return # どのキーも押されていない場合は何もしない
		Global.input_janken_key = true
		selected_1p = true
		select_2p_hand()

1PがNPCの場合の手を選択
・Mainシーンからの指示で、1PのCPUへ手をリクエストし2Pの手の選択へ

# 1PがNPCの場合の手をリクエスト
func select_1p_hand():
	if not selected_1p and Global.ai_on == true: # ai_onの時はCPUへリクエスト
		Global.whose_request = 1 # 1Pからのリクエストであると設定
		p1.choose_number() # 1Pに設定されたCPUに1Pの手をリクエスト
		selected_1p = true # 1Pの手を選択済みにする
		select_2p_hand() # 2Pの手の選択へ

2Pの手を選択
・2PのCPUへリクエスト

# 2Pの手をリクエスト
func select_2p_hand():
	if not selected_2p:
		Global.whose_request = 2
		p2.choose_number()	
		selected_2p = true

CPUから手を受け取る
・リクエストを出していたCPUから手を受け取る
・1Pと2Pの手の表示を指示し、MainシーンのJudgeへ手を返す

# CPUから手を受け取る
func hand_count():
	print("hand count")	
	update_hand() # 1Pと2Pの手を表示
	main.judge() # メインで勝敗判断
	selected_2p = true	# 選択済みフラグをON

プレイヤーとCPUの手を表示
・手を表示する前に一瞬消すことで、同じ手を出しても分かるように変更
・1Pと2Pの手を表示

# プレイヤーとCPUの手を表示
func update_hand():
	var text_direct = {1: "✊", 2: "✌", 3: "✋"} # 数字とCPUの手を定義

	hand1.hide()
	hand2.hide()
	await get_tree().create_timer(0.05).timeout

	# 1Pの手を表示
	hand1.show()
	hand1.text = text_direct[Global.player_hand] # YourHandラベルに表示

	# 2Pの手を表示
	hand2.show()
	hand2.text = text_direct[Global.cpu_hand] # CPUHandラベルに表示

Mainシーンの変更

ジャンケンコールの修正
・janken_call関数の最後にプレイヤーの手をAIに任せる処理を追加

		#プレイヤーの手をAIに任せる
		if Global.ai_on == true:
			character.select_1p_hand()

Globalシーンへ変数を追加

var ai_on = false # 手をAIに任せるかどうかのフラグ 
var whose_request = 0 # 1P,2Pどちらのリクエストかのフラグ

新キャラを追加

完全にランダムの手を出すNPC

普通の子供。塾帰りのナオト。Image Createrで作成

NPC同士のジャンケン対決

グーを出しがちな鉄拳グーに対して、完全な乱数で対抗するナオト。
ナオトが先行しますが途中でグーが逆転、しかし、最後はナオトが再逆転で勝利しました。


次はキャラクターセレクト画面を作ります

ジャンケンは簡単だしプログラムの練習に丁度良いですね。
誰かのお役に立てれば幸いです。


使用ツール

アドバイザー

画像生成

いいなと思ったら応援しよう!

この記事が参加している募集