見出し画像

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関数の中の「重力処理」の下に以下のスクリプトを追加

左上が原点で、地面のY座標は340になるのでボールのY座標が250以内だったらジャンプ
	# ボールとの高低差が十分ならジャンプ
	if ball_position.y < 250 and is_on_floor():
		velocity.y = jump_speed

跳べるのね。AI…あなた…

F5で実行。余裕で飛び跳ねてリフティングしますね。。。


演出させてもらいやす、AIさん!

派手さを足すために、サマーソルトキックなど入れます。

これをicon_kick_red.pngにして使ってください

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

※詳しくは、RigidBody2Dをキックを参照
※defaultがidleに変わっているかも確認してください。キャラ消えちゃうので。

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

※詳しくは、RigidBody2Dでリフティングを参照
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

背景もつけちゃいます!

Gemini2.0に描いてもらいました。よろしければ使ってください。

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

曲芸リフティング

F5で実行。どうでしょう?

次は、AIに対戦させてみるかな?

誰かのお役に立てていれば幸いです。


使用ツール

アドバイザー

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

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