2D / 3D ゲームを作成できる無料・オープンソースの軽快なゲームエンジン「Godot Engine 4」で、最初から使える Tween 機能を使って、円の大きさをなめらかに変化させます。
※この記事の内容は、アプリ タップ The 宝箱 の開発でも使用しています。
※ GodotEngine のバージョンは 4.2.1 です。 .NET 版ではありません。
※記事で紹介するスクリプト / プログラム / コードは自己責任で使用してください。
前回の記事
円を描画する関数と await を組み合わせて一定時間ごとに大きくなる円のアニメーションを作成しました。
Tween とは
Tween は、指定した変数の値を、指定した時間で少しずつ、指定した値に変化させます。
例えば、今回ならば円の半径を表す変数 radius の値を、1秒間で半径 3 ピクセルから 320 ピクセルになめらかに変化させます。
位置を表す Vector2 型の変数を Tween の対象とすれば、A地点とB地点を指定するだけで、時間経過に応じてA地点からB地点へと座標をなめらかに移動させます。
Tweens are mostly useful for animations requiring a numerical property to be interpolated over a range of values. The name tween comes from in-betweening, an animation technique where you specify keyframes and the computer interpolates the frames that appear between them. Animating something with a Tween is called tweening.
トゥイーンは、値の範囲にわたって数値プロパティを補間する必要があるアニメーションに主に役立ちます。トゥイーンという名前は、キーフレームを指定すると、それらの間に表示されるフレームをコンピュータが補間するアニメーション手法であるインビトゥイーンに由来しています。トゥイーンを使って何かをアニメーション化することをトゥイーンと呼びます。
Tween — Godot Engine (4.x)の日本語のドキュメント
Tween をスクリプト内で作成
Tween は、ノードに割り当てた GD スクリプトで簡単に作成できます。
以下の例では、2行目で tween メンバ変数を定義して、 7 行目でその tween メンバ変数に get_tree().create_tween() によって Tween を作成して格納しています。
# radius メンバ変数の値を指定した時間で変化させる際に使用します。
var tween
# radius を tween によって少しずつ変化させます。
func animation_ripple():
# Tween を生成します。
tween = get_tree().create_tween()
Tween で変化させたい変数と変化後の値、遷移時間を指定
作成した Tween が変化させる対象は 11 行目の tween_property 関数の 1 番目と 2 番目の引数で指定しています。
例では、self 、このノード自身の、 radius という名前の変数を対象にします。
tween_property 関数の 4 番目の引数では、変化に要する時間を指定します。
3 番目の引数では、変化後の値を指定します。
例では、このノードのメンバ変数 radius の値を 1 秒後に 60 に到達するように徐々に変化させます。
9 行目では、その radius メンバ変数に初期値を設定しています。
これにより、radius メンバ変数を 1 秒間で 3 から 60 に少しずつ変化させます。
# radius メンバ変数の値を指定した時間で変化させる際に使用します。
var tween
# radius を tween によって少しずつ変化させます。
func animation_ripple():
# Tween を生成します。
tween = get_tree().create_tween()
# Tween で変化させる対象の変数の初期値を設定します。
radius = 3
# Tween で徐々に変化させるパラメータを設定して、変化を開始します。
tween.tween_property(
self, # 自分自身を登録
"radius", # positionパラメータを制御
60, # 変化後の値
1, # 1秒間で変化
)
return
再描画を毎フレーム要求する
Tween により円の半径を表す radius メンバ変数の値は 3 から 60 に 1 秒間で変化しますが、それを描画しないとアニメーションは表示されません。
毎フレーム呼び出される _process イベント関数に CanvasItem クラス(Node2D の継承元)の queue_redraw メンバ関数を呼び出すことで、再描画を要求します。
この結果、毎フレーム _draw イベント関数が呼び出され、その中で radius メンバ変数を半径とした円が描画されます。
※ Ripple ノードは Node2D クラスをベースにして作成しているので、その継承元のクラスである CanvasItem のメンバ関数も呼び出すことができます。
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
# 毎フレームごとノードの再描画を要求して、 _draw イベント関数を呼び出させます。
queue_redraw()
# _draw() 関数は一度だけ呼び出され、その後は描画コマンドがキャッシュされて記憶されるため、それ以上の呼び出しは不要です。
# 再描画が必要な場合は CanvasItem.queue_redraw() を呼び出してください。
func _draw():
# 色の変数に白色を設定します。
var white : Color = Color.WHITE
# 円を指定した座標を中心に、指定した半径と指定した色で描画します。
sc_draw_arc(center, radius, 0.0, 360.0, white, 3, true)
return
今回作成した Ripple.gd スクリプト全文
以下は、今回説明した動作を行う Ripple.gd スクリプトの全文です。
※冒頭にも書いた通りスクリプトは自己責任でご利用ください。
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秒間で変化
)
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
テスト
ripple シーンを開いた状態で、F6 キーを押して ripple シーンを再生すると、1秒間でスムーズに円が大きくなるアニメーションが描画されました。
※テストでは、わかりやすくするために、tween_property 関数の変化後の値の引数を 60 から 320 に変化させました。
まとめ
今回は、2D / 3D ゲームを作成できる無料・オープンソースの軽快なゲームエンジン「Godot Engine 4」で、最初から使える Tween 機能を使って、円の大きさをなめらかに変化させました。
GD スクリプトで create_tween() 関数を使うことで簡単に作成でき、 tween_property 関数で指定した変数を指定した時間で指定した値に遷移させられることがわかりました。
再描画を要求する queue_redraw についても紹介しました。
参照サイト Thank You!
- Godot Engine – Free and open source 2D and 3D game engine
- Custom drawing in 2D — Godot Engine (stable) documentation in English
- Tween — Godot Engine (4.x)の日本語のドキュメント
記事一覧 → Compota-Soft-Press
コメント