PR

AIとゲームつくる│ChatGPTのいいところ 

AIとゲームつくる
PR
PR

ChatGPTはどう使うといいか

前回 全部Claudeに依頼すればいいんじゃないか? みたいな話をしたけども

ChatGPTにはChatGPTで使える点もある 

一番は気軽に使える点
あと 難しすぎないクリエイティビティなタスクならClaudeよりも優秀かもしれない


武器システムの案を出してもらった

まず パワーアップのシステムから考えても良い?

シューティングの画面だけじゃなくて ステージ選択の画面を用意して 8面+ラスボスを用意して 8個の特殊技 をそれぞれの面で修得可能で どれかはどれかの特効(弱点)だったりするっていうシステムのを作ってみたいんだよね (ロックマン風) で 追尾弾 とか 機体の周りをぐるぐる回ってる球 とか そういうの8個提案してくんない?

いいね、それかなり面白そうだし、STGとロックマン系のボス特効システムの相性も良い。
じゃあ、8面それぞれの「特殊武器」候補を、見た目・効果・弱点関係までセットで提案するね。


特殊技案(8種)

  1. ホーミングミサイル(追尾弾)
    • 敵を自動追尾する中速弾。発射レート低め。
    • 弱点:動きの速い小型敵(追尾精度が追いつかない)。
    • 特効:回避行動が遅い大型ボス。
  2. サテライトオーブ
    • 自機の周囲を2〜4個の球体が回転し、接触ダメージ&弾防御。
    • 弱点:画面端から一気に突っ込んでくる敵。
    • 特効:弾幕系ボス(防御力として機能)。
  3. レーザービーム
    • 貫通力のある直線ビーム。溜め撃ち可。
    • 弱点:敵の位置取りがバラけるステージ。
    • 特効:敵が一直線に並ぶ配置。
  4. スプレッドショット(拡散弾)
    • 扇状に広がるショット。弾速やや遅め。
    • 弱点:単体の高耐久ボス。
    • 特効:小型敵の群れ。
  5. シールドフィールド
    • 一定時間、自機の周囲に防御バリアを展開(接触ダメージあり)。
    • 弱点:持続時間が短い。
    • 特効:突撃系の敵、弾幕密集地帯。
  6. タイムスロー
    • 敵と弾の速度を一時的にスロー化。
    • 弱点:効果時間が短く、リチャージに時間がかかる。
    • 特効:高機動のボスや高速弾幕。
  7. ワームレーザー(蛇行ビーム)
    • 蛇のように左右に揺れながら進むビーム。地形の裏に隠れた敵にも当てやすい。
    • 弱点:射程が短い。
    • 特効:地形に遮られやすい配置の敵。
  8. ナパームボム
    • 敵に命中or一定距離で爆発、爆風が広範囲にダメージ。
    • 弱点:弾速遅め。
    • 特効:地上配置や密集敵グループ。

相性(弱点)例

  • ホーミングミサイル ← タイムスローで回避精度を落とせる敵に有効
  • サテライトオーブ ← ナパームボムに弱い
  • レーザービーム ← スプレッドショット持ちの敵に強い
  • スプレッドショット ← サテライトオーブ持ちの敵に不利
  • シールドフィールド ← ワームレーザーで貫通される
  • タイムスロー ← 高火力単発系に弱い(レーザーなど)
  • ワームレーザー ← ホーミングミサイルに弱い(遠距離対応される)
  • ナパームボム ← シールドフィールドに弱い(爆風防御される)

もしこの案で行くなら、次の段階で

  • ステージごとのテーマ(宇宙港・氷惑星・要塞内部…など)
  • ボスの見た目と特殊技の割り当て
    を作れば、特効システムをゲーム内で自然に落とし込める構成にできるよ。

これ、ステージ構成まで作る?
それともまず武器の実装順序決めから入る?


武器に対応するステージ案を考えてもらった

よしやってこうやってこう
ボスの見た目と割り当てをやってみて

で これ考えると システム的には 
敵AIとステージよりも先に 弾の実装を先にした方がよくない?

そうそう、その順番の方が作業しやすいね。

理由を整理すると、

  • 弾の実装が先だと、各武器の挙動テストがすぐできる
  • それを基準に敵AIやステージギミックを作れる
  • 特殊武器の挙動を先に決めないと、ステージの難易度や敵配置のバランスも決められない

だから流れとしては

  1. 全8種の武器の弾・効果実装(自機用でOK、敵用は後で使い回し)
  2. 武器切替・取得UI
  3. ステージごとのテーマ設定
  4. ボスのビジュアル・攻撃パターン設定
  5. ステージ構築 & 敵AI実装

じゃあまずボスの見た目 & 割り当て案を出すね。

ステージ・ボス割り当て案(ロックマン風)

  1. ステージ1:アストロポート(宇宙港)
    • ボス:ホーミング・クラーケン(巨大な宇宙タコ)
    • 修得武器:ホーミングミサイル
  2. ステージ2:サテライト・オービタル(宇宙ステーション)
    • ボス:オービット・ガード(球体衛星+アーム付き)
    • 修得武器:サテライトオーブ
  3. ステージ3:レーザーキャニオン(巨大砲台要塞)
    • ボス:ビーム・デストロイヤー(巨大ビーム砲を背負った戦艦)
    • 修得武器:レーザービーム
  4. ステージ4:ジャンクアステロイド(廃棄衛星群)
    • ボス:スクラップ・レイダー(ジャンクを纏った大型ロボ)
    • 修得武器:スプレッドショット
  5. ステージ5:プラズマベース(高エネルギー研究施設)
    • ボス:プラズマ・フォートレス(バリア展開型要塞)
    • 修得武器:シールドフィールド
  6. ステージ6:タイム・リフト(時間歪曲宙域)
    • ボス:クロノ・ファントム(時を操る亡霊型兵器)
    • 修得武器:タイムスロー
  7. ステージ7:ネビュラケーブ(ガス星雲洞窟)
    • ボス:サーペント・ウェーブ(宇宙竜型ビーム生物)
    • 修得武器:ワームレーザー
  8. ステージ8:バーニングコロニー(炎のコロニー)
    • ボス:ナパーム・タイタン(火炎放射型重装甲機)
    • 修得武器:ナパームボム
  9. ラストステージ:マザー・ドレッドノート
    • 全武器を駆使して戦う総合戦ボス。

この割り当てで行くなら、次は
全武器の弾挙動仕様書実装順序
を作るのが最短ルートになる。

弾の挙動仕様、今ここで書いちゃう?


弾のスクリプトを出してもらう

全部やっちゃってよ

挙動仕様 ➝ スクリプトの記載

それから これって 画像で準備しないと難しい部分とかある?
コード的な記載だけで実装できそう?

じゃあ全部まとめてやるね。

まずは挙動仕様 → そのまま Godot 4 用 GDScript 実装例まで出す。
基本的に画像はなくても実装できる(Polygon2D や ColorRect で簡易表示可能)から、まずはコードでいけるよ。
後から差し替えればOK。

じゃあ全部まとめてやるね。

まずは挙動仕様 → そのまま Godot 4 用 GDScript 実装例まで出す。
基本的に画像はなくても実装できる(Polygon2D や ColorRect で簡易表示可能)から、まずはコードでいけるよ。
後から差し替えればOK。


全8種武器の挙動仕様 & 実装例


1. ホーミングミサイル(Homing Missile)

  • 発射数:1発ずつ
  • 弾速:中
  • 特徴:敵を自動追尾(近い敵を優先)
  • 寿命:2.5秒
  • 当たり判定:小
  • 見た目:三角形の弾頭(Polygon2D)

スクリプト例homing_missile.gd

extends Area2D

@export var speed: float = 200
@export var turn_speed: float = 5
var target: Node2D = null
var life_time: float = 2.5

func _ready():
	$CollisionShape2D.disabled = false
	look_for_target()

func _physics_process(delta):
	if target and target.is_inside_tree():
		var direction = (target.global_position - global_position).normalized()
		var angle_diff = direction.angle() - rotation
		rotation += clamp(angle_diff, -turn_speed * delta, turn_speed * delta)
	global_position += Vector2.RIGHT.rotated(rotation) * speed * delta

	life_time -= delta
	if life_time <= 0:
		queue_free()

func look_for_target():
	var enemies = get_tree().get_nodes_in_group("enemies")
	if enemies.size() > 0:
		target = enemies[0] # 一番近い敵にするなら距離計算

2. サテライトオーブ(Satellite Orb)

  • 発射数:自機の周囲を回転
  • 特徴:一定時間ごとに小型弾を発射
  • 寿命:ステージ終了まで(パワーアップ解除時消滅)
  • 見た目:円形

スクリプト例satellite_orb.gd

extends Node2D

@export var orbit_radius: float = 40
@export var orbit_speed: float = 2
@export var fire_interval: float = 0.8
var angle: float = 0
var player: Node2D
var timer: float = 0

func _ready():
	player = get_parent()

func _physics_process(delta):
	if not player: return
	angle += orbit_speed * delta
	global_position = player.global_position + Vector2(orbit_radius, 0).rotated(angle)

	timer += delta
	if timer >= fire_interval:
		timer = 0
		fire()

func fire():
	var bullet = preload("res://scenes/projectile/orb_bullet.tscn").instantiate()
	bullet.global_position = global_position
	get_tree().current_scene.add_child(bullet)

3. レーザービーム(Laser Beam)

  • 発射数:押している間継続照射
  • 特徴:貫通
  • 見た目:長方形のビーム

スクリプト例laser_beam.gd

extends Area2D

@export var length: float = 400
@export var width: float = 4
@export var damage_per_second: float = 100

func _ready():
	$CollisionShape2D.shape = RectangleShape2D.new()
	$CollisionShape2D.shape.extents = Vector2(length, width)

func _physics_process(delta):
	for body in get_overlapping_bodies():
		if body.is_in_group("enemies"):
			body.apply_damage(damage_per_second * delta)

4. スプレッドショット(Spread Shot)

  • 発射数:3〜5発
  • 特徴:扇状に広がる
  • 見た目:小型弾

スクリプト例spread_shot.gd

extends Node2D

@export var bullet_scene: PackedScene
@export var spread_angle: float = 30
@export var bullet_count: int = 5
@export var bullet_speed: float = 300

func fire():
	var angle_step = deg_to_rad(spread_angle) / (bullet_count - 1)
	var start_angle = -deg_to_rad(spread_angle) / 2
	for i in range(bullet_count):
		var bullet = bullet_scene.instantiate()
		bullet.rotation = rotation + start_angle + i * angle_step
		bullet.global_position = global_position
		bullet.speed = bullet_speed
		get_tree().current_scene.add_child(bullet)

5. シールドフィールド(Shield Field)

  • 発射数:常時展開
  • 特徴:弾を防ぐ、敵接触でダメージ
  • 見た目:透明な円

スクリプト例shield_field.gd

extends Area2D

@export var radius: float = 50

func _ready():
	var shape = CircleShape2D.new()
	shape.radius = radius
	$CollisionShape2D.shape = shape

func _on_body_entered(body):
	if body.is_in_group("enemy_bullets"):
		body.queue_free()

6. タイムスロー(Time Slow)

  • 効果:一定時間、敵と弾の速度半減
  • クールタイム:8秒
  • 見た目:エフェクトのみ

スクリプト例time_slow.gd

extends Node

@export var slow_factor: float = 0.5
@export var duration: float = 3

func activate():
	Engine.time_scale = slow_factor
	await get_tree().create_timer(duration).timeout
	Engine.time_scale = 1

7. ワームレーザー(Worm Laser)

  • 発射数:1本
  • 特徴:蛇のように曲がるレーザー
  • 見た目:Line2D

スクリプト例worm_laser.gd

extends Line2D

@export var speed: float = 200
@export var wave_amplitude: float = 20
@export var wave_frequency: float = 5
var elapsed: float = 0

func _physics_process(delta):
	elapsed += delta
	for i in range(points.size()):
		var x = i * 10
		var y = sin(elapsed * wave_frequency + i * 0.2) * wave_amplitude
		points[i] = Vector2(x, y)

8. ナパームボム(Napalm Bomb)

  • 発射数:1発
  • 特徴:着弾地点で爆発し、範囲ダメージ
  • 見た目:円形爆発

スクリプト例napalm_bomb.gd

extends Area2D

@export var speed: float = 150
@export var explosion_radius: float = 60

func _physics_process(delta):
	global_position += Vector2.RIGHT.rotated(rotation) * speed * delta

func explode():
	var bodies = get_overlapping_bodies()
	for body in bodies:
		if body.is_in_group("enemies"):
			body.apply_damage(50)
	queue_free()

これ全部、画像なくても Polygon2D や Line2D で簡易表示可能だから、すぐ動作確認できるよ。
後からスプライトを読み込んで差し替える形でOK。


この順番で行くと、まずはホーミングミサイルからテストしながら進めるのがオススメ。
理由は敵グループと当たり判定の基盤を作れるから、そのまま他武器に流用できる。


これ、今からホーミングミサイルのシーン構成案まで作って進める?
それやれば1個目から動かせるよ。

これ全部、画像なくても Polygon2D や Line2D で簡易表示可能だから、すぐ動作確認できるよ。
後からスプライトを読み込んで差し替える形でOK。


この順番で行くと、まずはホーミングミサイルからテストしながら進めるのがオススメ。
理由は敵グループと当たり判定の基盤を作れるから、そのまま他武器に流用できる。


これ、今からホーミングミサイルのシーン構成案まで作って進める?
それやれば1個目から動かせるよ。


武器切替システム案について

これそれぞれの tscn ファイルも必要なんじゃない?

あと それぞれの弾は 切替式 が良いよね
全部同時だとやっぱ変だよね
3つまでセットできるとかが良いのかな

その辺の挙動はどう考えてる?

※AIが.tscnファイルをGODOTのGUIを操作して作れと言ってくる場合があるけど、いやお前(AI)が作れと言えば作ってくれる。 それでもできませんというAIは使わない。(Geminiはこの.tscnを作ってと言う依頼を断るのでコード生成では使わない事にした。)

そうそう、今のスクリプト例は「弾の振る舞い」だけだから、実際に Godot で動かすには

  1. それぞれ専用の tscn ファイル(ルートノード・コリジョン・見た目)
  2. プレイヤー側の「武器管理システム」(切り替え/同時発射制御)

この2つを作る必要がある。


① 各武器の .tscn ファイル構成案

全部同じパターンで作れるから、最低限これで動作する。
例えば ホーミングミサイルならこう👇

res://scenes/weapons/homing_missile.tscn
└── Root: Area2D
    ├── CollisionShape2D (CircleShape2D 半径 4〜6)
    ├── Polygon2D(簡易的な弾頭表示)
    └── スクリプト: homing_missile.gd

同様に、スプレッド弾やレーザーも形だけ変えて同じ構造。
爆発系(ナパーム)は AnimationPlayer とか Particles2D を追加してもいい。


② 武器切り替えシステム案

  • プレイヤーに 現在の武器スロット配列 を持たせる
  • 最大スロット数:3([weapon1, weapon2, weapon3]
  • 発射時は現在選択中のスロットだけ撃つ(同時発射を避ける)
  • ゲーム中にパワーアップ取得 → スロットに追加 or 上書き

武器管理の例weapon_manager.gd

extends Node

# 武器スロット
var weapon_slots: Array = []
var current_slot: int = 0

func _ready():
	# 仮:最初は通常弾のみ
	weapon_slots = [
		preload("res://scenes/weapons/basic_shot.tscn"),
		null,
		null
	]

func switch_weapon(direction: int):
	current_slot = (current_slot + direction) % weapon_slots.size()
	if current_slot < 0:
		current_slot = weapon_slots.size() - 1
	print("Switched to slot %d" % current_slot)

func fire_weapon(position: Vector2, rotation: float):
	var scene: PackedScene = weapon_slots[current_slot]
	if scene:
		var weapon = scene.instantiate()
		weapon.global_position = position
		weapon.rotation = rotation
		get_tree().current_scene.add_child(weapon)

func add_weapon(new_weapon_scene: PackedScene):
	for i in range(weapon_slots.size()):
		if weapon_slots[i] == null:
			weapon_slots[i] = new_weapon_scene
			return
	# すべて埋まってたら上書き(仮ルール)
	weapon_slots[current_slot] = new_weapon_scene

③ 切替の操作イメージ

  • Qキー → 左のスロットに切り替え
  • Eキー → 右のスロットに切り替え
  • Spaceキー → 発射

この仕様なら、ステージクリアごとに武器追加していく流れも作りやすい。
(ロックマン方式)


④ 次のステップ

もしこれで進めるなら、

  • 全8武器の tscn を作るテンプレート
  • 武器管理をプレイヤーに組み込み

まで先に作って、1個ずつ動かしながら追加するのが安全。


このまま tscn の雛形と武器管理をセットで作るコードまで出しちゃう?
そうすれば君のプロジェクトにコピペで入れられる状態になるよ。

そうそう、今のスクリプト例は「弾の振る舞い」だけだから、実際に Godot で動かすには

  1. それぞれ専用の tscn ファイル(ルートノード・コリジョン・見た目)
  2. プレイヤー側の「武器管理システム」(切り替え/同時発射制御)

この2つを作る必要がある。


① 各武器の .tscn ファイル構成案

全部同じパターンで作れるから、最低限これで動作する。
例えば ホーミングミサイルならこう👇

res://scenes/weapons/homing_missile.tscn
└── Root: Area2D
    ├── CollisionShape2D (CircleShape2D 半径 4〜6)
    ├── Polygon2D(簡易的な弾頭表示)
    └── スクリプト: homing_missile.gd

同様に、スプレッド弾やレーザーも形だけ変えて同じ構造。
爆発系(ナパーム)は AnimationPlayer とか Particles2D を追加してもいい。


② 武器切り替えシステム案

  • プレイヤーに 現在の武器スロット配列 を持たせる
  • 最大スロット数:3([weapon1, weapon2, weapon3]
  • 発射時は現在選択中のスロットだけ撃つ(同時発射を避ける)
  • ゲーム中にパワーアップ取得 → スロットに追加 or 上書き


認識をすり合わせる

(同時発射を避ける)? 同時に発射できた方がいいでしょ

OK、じゃあ同時発射できる仕様にしましょう。
ロックマン方式だと「選択した武器だけ発射」が多いけど、
シューティングだとパワーアップ全部を同時に撒ける方が爽快感出ますしね。

OK、じゃあ同時発射できる仕様にしましょう。
ロックマン方式だと「選択した武器だけ発射」が多いけど、
シューティングだとパワーアップ全部を同時に撒ける方が爽快感出ますしね。


同時発射仕様の考え方

  • 武器スロットは「装備中の武器のリスト」になる
  • 発射コマンドを押すと、全スロットの武器をまとめて発射
  • 空スロットは無視
  • 特殊武器は弾数制限やクールダウンを付けてバランス調整

同時発射の武器管理例

extends Node

var weapon_slots: Array = []  # PackedSceneの配列
var fire_cooldowns: Array = [] # クールタイム管理用

func _ready():
	# 仮:通常弾とホーミングミサイルを装備
	weapon_slots = [
		preload("res://scenes/weapons/basic_shot.tscn"),
		preload("res://scenes/weapons/homing_missile.tscn"),
		null
	]
	fire_cooldowns.resize(weapon_slots.size())
	fire_cooldowns.fill(0.0)

func _process(delta):
	# クールタイム更新
	for i in range(fire_cooldowns.size()):
		if fire_cooldowns[i] > 0:
			fire_cooldowns[i] -= delta

func fire_all(position: Vector2, rotation: float):
	for i in range(weapon_slots.size()):
		if weapon_slots[i] and fire_cooldowns[i] <= 0:
			var weapon = weapon_slots[i].instantiate()
			weapon.global_position = position
			weapon.rotation = rotation
			get_tree().current_scene.add_child(weapon)
			# クールタイム(仮で0.2秒)
			fire_cooldowns[i] = 0.2

メリット

  • パワーアップが積み重なる爽快感
  • 武器ごとの発射間隔や特性を独立管理できる
  • 「基本弾を撃ちながら特殊弾を同時発射」みたいな多層攻撃が可能

もしこの仕様で行くなら、

  • 各武器の .tscn 雛形
  • 弾の挙動スクリプト
  • 発射位置の共通化(プレイヤー機のノード構成で Marker2D を使う)

まで一気に作った方が、後から面倒が少ないです。


このまま全8武器の .tscn テンプレートと発射管理システム、
まとめて実装案出しちゃいますか?
そうすれば君のプロジェクトに即投入できる形にできます。

所感

案を出す面ではいい感じで出してくれたなーと思います。
だけどこのコードを修正する形で動かすのはちょっと苦戦したので

案は採用して コードを動かすところまでは別のAIに完成させてもらいました
流れは動画で見てみてください

コメント

タイトルとURLをコピーしました