
AIに対戦させてみる
前回は、2体のAIに協力リフティングをさせてみました。
今回は、対戦させてみます。
アドバイザーは、Gemini2.0です。
今日のハイライト

対戦用のプロジェクトを作る
協力プレイバージョンも残しておきたいので、協力プレイ用のプロジェクト(KickGame)をコピペし(KickBattle)に名前を変えてスタートします。
コピペのやり方は以下の記事を参考にしてください。
対戦の準備
キャラの色分け
同じ色だと分かりにくいので、Lを青にしてRの赤と差別化します。

Lキャラへの青キャラの組み込みは「AIリフティング」を参照してください。
LRの色替え実行
色替えしても仲良く新記録更新です。

真ん中に壁を置く
敵味方の陣地を分けるため、中央に壁を置きます。
・WallをStage_Tossにドラッグ&ドロップしてWall3を作る
・Wall3のインスペクターのTransformで、XのScaleを0.5、Yを0.3に変更
・Positionを(320,225)に変更

・pole.pngをファイルシステムに追加
・poleを画面中央にドラッグ&ドロップ
・Wall3と大きさが同じになるようにPoleの大きさを調整

・Wall3をBackground2とRoofの間に移動して隠す

対戦用の「スパイク」を作る
対戦用に敵陣へボールを打ちこむ「スパイク」を作ります。
「スパイク」のアニメーションを組み込む
Kickと同様にspikeのアニメーションを組み込みます。
組み込み方は、「AIリフティング」を参照してください。
ボールが敵陣側に来たらスパイク!
初期設定
・スパイク時のx方向の強さを設定
・x方向の手振れによる補正力にmini、maxを追加し敵陣側を大きく設定
AI_Toss_Lの初期設定
# スパイク関連
var x_force_range_mini = 40 # x方向の手振れmini
var x_force_range_max = 60 # x方向の手ブレにmax
var spike_force_mini = 100 # スパイクのパワーmini
var spike_force_max = 150 # スパイクのパワーmax
var spike_toss_mini = -500 # スパイクの上方向の力mini
var spike_toss_max = -800 # スパイクの上方向の力max
var spike_point = 5
AI_Toss_Rの初期設定
# スパイク関連
var x_force_range_mini = -60 # x方向の手振れmini
var x_force_range_max = -40 # x方向の手ブレにmax
var spike_force_mini = -100 # スパイクのパワーmini
var spike_force_max = -150 # スパイクのパワーmax
var spike_toss_mini = -500 # スパイクの上方向の力mini
var spike_toss_max = -800 # スパイクの上方向の力max
var spike_point = -5
ボールを攻撃
・スクリプトのfunc _processのボールを攻撃を修正
・ボールが自分の敵陣側に来たらスパイク(Lは右側、Rは左側)
・打点を前に取った方が前に飛ぶため、spike_pointで打点を補正
・spikeアニメーションを再生し、ボールに力を加える
・スパイクできなければ、スパイクできる位置にトスする
AI_Toss_L用のスクリプト
# ボールを攻撃
if global_position.distance_to(ball_position) < attack_distance and predicted_y > global_position.y:
# ボールが自分の右側に来たらスパイク
if global_position.x + spike_point < ball_position.x: # L専用の修正
var x_force = randi_range(spike_force_mini, spike_force_max)
var y_force = randi_range(spike_toss_mini, spike_toss_max)
$AnimatedSprite2D.play("spike")
kick_in = true
print("R Spike! ", str(x_force), str(y_force)) # デバッグ用
ball.apply_impulse(Vector2(x_force, y_force)) # ボールに上方向の力を加える
else:
# スパイクできる位置にトスする
var x_force = randi_range(x_force_range_mini, x_force_range_max)
var y_force = randi_range(toss_force_mini, toss_force_max)
print("R Toss ", str(x_force), str(y_force)) # デバッグ用
# y方向の力が大きければ、kickする
if y_force < -600:
$AnimatedSprite2D.play("kick")
kick_in = true
ball.apply_impulse(Vector2(x_force, y_force)) # ボールに上方向の力を加える
AI_Toss_R用のスクリプト差分(この行だけ変更)
# ボールが自分の左側に来たらスパイク
if global_position.x + spike_point > ball_position.x: # R専用の修正
スパイクで対戦!
F5で実行すると、対戦するようになりました。

次は対戦用の得点システムを作ろう!
色々パラメータを持てば、キャラ差をつけれるので、それも試してみようかなと。
誰かのエンタメになれば幸いです。