
AIは曲芸リフティングができるのか?
前回、AIがボールの位置情報だけで無限リフティングしちゃいました。
今回は、もう少し派手な動きのリフティングをさせてみます。
今回もアドバイザーはGemini4.3です。
今日のハイライト

人間っぽい動きを再現
前回のAIは正確にボールのx軸を捉え、無限にリフティングしました。
これでは地味で面白くないので、人間の手振れを数値に手を加えて再現してみます。

AI_Tossのスクリプトに「手ブレ」を導入
# 初期設定
・前回作ったスクリプトの初期設定に定数を追加
・var toss_forceは使わないので、#でコメントアウト
・x方向とy方向に手ブレによる補正値を設定
# var toss_force = -450.0 # 今回は使わないのでコメントアウト
var x_force_range = 80 # x方向の手ブレによる補正力
var toss_force_mini = -400.0 # y方向の手売れ力の最低値
var toss_force_max = -700.0 # y方向の手振れ力の最高値
#_ready関数を定義
・乱数を定義
・待機アニメーションを定義
func _ready() -> void:
randomize() # 乱数
$AnimatedSprite2D.play("idle")
# ボールを攻撃
・前回作ったスクリプトの「func _proces」s内の「#ボールを攻撃」を修正
・x_force(x方向の力)とy_force(y方向の力)をランダムに選ぶ
# ボールを攻撃
if global_position.distance_to(ball_position) < attack_distance and predicted_y > global_position.y:
#ball.apply_impulse(Vector2(0, toss_force)) # 今回は使わないのでコメントアウトか削除
# 手振れ補正された力を加える
var x_force = randi_range(-x_force_range, x_force_range) # x方向の手振れ力を補正
var y_force = randi_range(toss_force_mini, toss_force_max) # y方向の手振れ力を補正
print(str(x_force), str(y_force)) # デバッグ用
ball.apply_impulse(Vector2(x_force, toss_force)) # ボールに上方向の力を加える
手ブレでランダムな力で弾く
F5で実行。
上下左右にランダムな力で揺さぶってみましたが、AIには楽勝のようです。
x軸追跡しかしてないのにスゲーなあAI。

跳んでみろや!AI!
AIが余裕ぶっこいているので、ジャンプさせちゃいます。
ジャンプ用のスクリプト
#初期設定
・初期設定の一番下にjump_speedとkick_inを追加
var jump_speed = -400.0
var kick_in = false
#func _processにジャンプを追加
・func_process関数の中の「重力処理」の下に以下のスクリプトを追加
# ボールとの高低差が十分ならジャンプ
if ball_position.y < 250 and is_on_floor():
velocity.y = jump_speed
跳べるのね。AI…あなた…
F5で実行。余裕で飛び跳ねてリフティングしますね。。。

演出させてもらいやす、AIさん!
派手さを足すために、サマーソルトキックなど入れます。

サマーソルトのアニメーションの取り込み
・AI_Tossの子ノードのAnimatedSprite2Dを選択
・アニメーションに「kick」を追加
・「kick」のフレームを選択で「icon_kick_rd.png」を選択
・今回は真ん中の3フレームだけ選んで追加
・ループを解除して、FPSを10に変更

他のアクションも取り込み
・idle, move, jumpなどの画像も設定しておく



キックアニメーションをスクリプトに追加
・func _processの「ボールを攻撃」の中の「print」の下に以下を追加
# y方向の力が大きければ、kickする
if y_force < -550:
$AnimatedSprite2D.play("kick")
kick_in = true
キックアニメーションの終了処理
・AI_TossのAnimatedSprite2Dを選択
・ノードのシグナルの「animation_finished」をAI_Tossのスクリプトに接続
・アニメーションをidleに戻すスクリプトを追加

func _on_animated_sprite_2d_animation_finished() -> void:
$AnimatedSprite2D.play("idle")
kick_in = false
移動アクションも追加
・func _processの「ボールを追跡」を以下に修正
# ボールを追跡
else:
velocity.x = direction.x * speed
if not kick_in and is_on_floor():
$AnimatedSprite2D.play("move")
$AnimatedSprite2D.flip_h = velocity.x < 0
背景もつけちゃいます!

背景のつけ方
・Stage_Tossに背景のファイルをドラッグ&ドロップ
・子ノードは下に置くほど表示優先が高いので、BallやAI_Tossより上になるように配置して位置を調整

曲芸リフティング
F5で実行。どうでしょう?

次は、AIに対戦させてみるかな?
誰かのお役に立てていれば幸いです。