2D / 3D ゲームを作成できる無料・オープンソースの軽快なゲームエンジン「Godot Engine 4」で、作成したシーンを、子ノードとして GD スクリプトで動的に生成、メンバ変数の設定、シーンへの配置、削除の手順を紹介します。
※この記事の内容は、アプリ タップ The 宝箱 の開発でも使用しています。
※ GodotEngine のバージョンは 4.1.2 です。 .NET 版ではありません。
※記事で紹介するスクリプト / プログラム / コードは自己責任で使用してください。
前回の記事
前回は「Godot Engine 4」で、最初から使える Tween 機能を使って、円の大きさをなめらかに変化させました。
ripple シーンをスクリプト内で生成・メンバ変数の設定
章末の GameManger.gd スクリプトの一部を説明しながら、スクリプトで子ノードを作成する手順を紹介します。
4 行目で sceneRipple メンバ変数を定義しています。
9 行目で sceneRipple メンバ変数は ripple シーンのファイル ripple.tscn を preload 関数で読み込み、PackedScene を格納します。
これにより ripple シーンを子ノードとして作成する準備ができました。
クリックイベントは、左マウスボタンを離した瞬間としました。
21 行目から始まる _input イベント関数で、マウスの左ボタンが離されたかを調べて、クリックしたかどうかを判定します。
その判定の後の 33 行目で、先ほど読み込んでおいた sceneRipple で PackedScene.instantiate メンバ関数を呼び出して、スクリプトの中で ripple 子ノードを動的に作成します。
34 行目では、作成した ripple 子ノードの位置を表す position 変数に、マウスの位置を設定して初期化しています。
作成した ripple 子ノードの初期化を行ったら、36 行目で add_child 関数に ripple 子ノードを渡して、game_manager シーンに追加します。
これにより ripple 子ノードはクリックされた座標に配置されて、そこを中心にした波紋のアニメーションを描画します。
extends Node
# 波紋を描画するシーンを子ノードとして生成する際に用います。
var sceneRipple
# Called when the node enters the scene tree for the first time.
func _ready():
# Ripple ノードを生成するために必要な ripple シーンを読み込んでおきます。
sceneRipple = preload("res://ripple.tscn")
return
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass
# ドラッグ中ならば true です。 _input イベントで扱います。
var dragging = false
# 入力イベントが発生するたびに呼び出されるイベント関数です。
func _input(event):
# 入力の例 — Godot Engine (4.x)の日本語のドキュメント - https://docs.godotengine.org/ja/4.x/tutorials/inputs/input_examples.html#mouse-motion
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
# Start dragging if the click is on the sprite.
if not dragging and event.pressed:
dragging = true
# 左ボタンを押した瞬間の処理
# Stop dragging if the button is released.
if dragging and not event.pressed:
dragging = false
# ボタンを離した瞬間の処理
# 波紋シーンの生成と配置
var nodeRipple = sceneRipple.instantiate()
nodeRipple.center = event.position # 描画する中心座標にクリックした位置を設定します。
add_child(nodeRipple) # シーンに子ノードとして追加します。
# While dragging, move the sprite with the mouse.
if event is InputEventMouseMotion and dragging:
# ドラッグ中の処理
pass
return
ripple 子ノードの削除
動的に作成した ripple 子ノードは、波紋のアニメーションが完了したら削除します。
子ノードの削除は、 ripple 子ノード自身が行います。
前回紹介した Ripple.gd の Tween による処理の後に、 Tween による値の遷移が完了した後に、処理を再開して自身のノードを消去する処理を追加しました。
※ 33 ~ 34 行目に追加しただけで、他は前回紹介したスクリプトと同じです。
33 行目で await を使い、 Tween による半径の変化が完了した後にその後の処理を再開します。
処理を再開した時点ですでに波紋のように円が拡大するアニメーションは完了しています。
34 行目で自身のノードを削除するために queue_free メンバ関数を呼び出します。
extends Node2D
# 描画する円の半径です。時間経過で変化します。
var radius = 3
# 描画する円の中心座標です。
var center = Vector2(320, 240)
# radius メンバ変数の値を指定した時間で変化させる際に使用します。
var tween
# Called when the node enters the scene tree for the first time.
func _ready():
animation_ripple()
return
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# 毎フレームごとノードの再描画を要求して、 _draw イベント関数を呼び出させます。
queue_redraw()
# radius を tween によって少しずつ変化させます。
func animation_ripple():
# Tween を生成します。
tween = get_tree().create_tween()
# Tween で変化させる対象の変数の初期値を設定します。
radius = 3
# Tween で徐々に変化させるパラメータを設定して、変化を開始します。
tween.tween_property(
self, # 自分自身を登録
"radius", # positionパラメータを制御
60, # 変化後の値
1, # 1秒間で変化
)
await tween.finished # tween が完了したら処理を再開します。
queue_free() # 自身のノードを消去します。
return
# _draw() 関数は一度だけ呼び出され、その後は描画コマンドがキャッシュされて記憶されるため、それ以上の呼び出しは不要です。
# 再描画が必要な場合は CanvasItem.queue_redraw() を呼び出してください。
func _draw():
# 色の変数に白色を設定します。
var white : Color = Color.WHITE
# 円を指定した座標を中心に、指定した半径と指定した色で描画します。
#sc_draw_circle(center, radius, white)
#draw_arc(center, radius, 0.0, 360.0, 60, white, 3, true)
sc_draw_arc(center, radius, 0.0, 360.0, white, 3, true)
return
# 円弧を描画します。 draw_arc 関数の point_count (頂点数) を自動計算して呼び出します。
# center : 中心の座標
# radius : 半径
# start_angle, end_angle : 円弧の開始と終了の角度
# color : 色
# width : 線の太さ
# antiariased : アンチエイリアスの有無. 詳しくは CanvasItem — Godot Engine (4.x)の日本語のドキュメント - https://docs.godotengine.org/ja/4.x/classes/class_canvasitem.html#class-canvasitem-method-draw-arc
func sc_draw_arc(center, radius, start_angle, end_angle, color, width, antialiased):
# 円周(2*PI+r)の距離に比例した個数の頂点を結ぶ線分で円を描画します。
# 試した結果、円周÷6 の頂点数だとあまり角が目立たないと思いました。
var numof_points = ceili(2 * PI * radius / 6)
# 円周が短く、頂点数が 12 個より小さい場合は角が目立つので 12 に補正します。
if numof_points < 12:
numof_points = 12
print("radius = ", radius, ", numof_points = ", numof_points)
draw_arc(center, radius, 0.0, 360.0, numof_points, color, width, true)
return
テスト
game_manager シーンを開いて、 F6 キーでシーンを再生しましょう。
ウィンドウのクライアント領域をクリックすると、その場所に ripple ノードが配置されて、波紋のアニメーションが表示されました。
まとめ
今回は 2D / 3D ゲームを作成できる無料・オープンソースの軽快なゲームエンジン「Godot Engine 4」で、作成したシーンを、子ノードとして GD スクリプトで動的に生成、メンバ変数の設定、シーンへの配置、削除の手順を紹介しました。
クリック時のイベント処理を _input イベント関数で行うスクリプトも紹介しました。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- Custom drawing in 2D — Godot Engine (stable) documentation in English
- Godot: new()とinstantiate() – kidooom’s Scrapbox
- PackedScene — Godot Engine (4.x)の日本語のドキュメント#instantiate
- Node — Godot Engine (4.x)の日本語のドキュメント#add_child
- Node — Godot Engine (4.x)の日本語のドキュメント#queue_free
- @GDScript — Godot Engine (4.x)の日本語のドキュメント#preload
- ロジックの設定 — Godot Engine (4.x)の日本語のドキュメント
記事一覧 → Compota-Soft-Press
コメント