この記事は Godot Engine について個人的に残しておきたい情報のメモ書きとなります
剛体の種類
- Area2D: 衝突検出のみ
- KinematicBody2D: 衝突検出と応答を行う。直接 positionを変更せずに、move_and_slide() / move_and_collide() を使って移動処理を行う
- RigidBody2D: 衝突検出と応答が自動で行われる。移動させる場合は add_force() などを現実世界に近い剛体
- StaticBody2D: 移動しない床や壁など。衝突検出と応答が自動で行われる
マウスの座標とクリック判定
get_viewport()
を使用する
# マウスのX座標
var mx = get_viewport().get_mouse_position().x
# マウスのY座標
var my = get_viewport().get_mouse_position().y
_input()
で判定を行う方法
func _input(event):
if event is InputEventMouseButton:
# マウスイベントが発生
if event.pressed:
# クリックしたときの処理
var b = Block.instance()
# クリックの位置にブロックを発生させる
b.position = event.position
add_child(b)
インプットマップを追加する方法
- メニューから
プロジェクト > プロジェクト設定
を選ぶ。 -
インプットマップ
タブを選んで、アクションに "ui_click" と入力して、「追加」ボタンをクリック - 追加された "ui_click" の行の右側にある「+」をクリックして
マウスボタン
を選択 - 「左ボタン」を選んで「追加」ボタンをクリック
この設定をすることで、以下のコードでクリック判定ができる
func _process(delta: float) -> void:
if Input.is_action_just_pressed("ui_click"):
print("クリックしました")
プロパティの実装方法
変数に setget
キーワードを指定することでプロパティの setter/getterを指定できる
# "id" には 0〜52が指定可能
export(int, 0, 52) var id = 0 setget _set_id, _get_id
# 値を設定するときに呼び出される関数
func _get_id():
return id
# 値を取得する場合に呼び出される関数
func _set_id(v):
id = v
画像リソースの動的読み込み
load()
で画像リソースのパスを指定することで動的読み込み(※同期ロード)することができる
var id = 12
# 画像リソースへのパス "res://assets/cards/012.png" を作成する
var path = "res://assets/cards/c%03d.png"%id
# 子ノードに "Sprite" が存在する前提
$Sprite.texture = load(path)
四角形をとりあえず表示したい
画像リソースを用意せずに、ひとまず四角形を表示したい場合、ColorRect
ノードを追加すると四角形を表示できます。
ColorRect の色を変更したい
colorプロパティから変更できます
# 緑色に変更する
$ColorRect.color = Color.green
Sprite関連
Spriteの色を変更したい
Sprite
ノードの色は modulate
となります
## スプライトの頂点カラーを緑色にする
$Sprite.modulate = Color.green
Spriteが消えるだけのエフェクトを作る
Spriteが消えるだけのエフェクト(当たり判定がない)場合は、Spriteノードだけ作成して、テクスチャを設定するだけでよい。Spriteが Node2D を継承しているので Area2D を使わなくても良い
(※スプライトシート[連番画像。等間隔でパターンが並んだ画像] を使わないのであれば、TextureRect
の方がパフォーマンスが良いかも?)
0.5秒で消えるスクリプトの例
extends Sprite
# 0.5病で消える
var _time = 0.5
func start(pos:Vector2, color:Color) -> void:
# 起動パラメータ
position = pos # 座標
modulate = color # 色
func _process(delta):
_time -= delta
# アルファ値を 0.5 -> 0.0 にする
var rate = 0.5 * _time / 0.5
modulate.a = rate
# 0.5秒経過したら消える
if _time <= 0:
queue_free()
Spriteのパターンアニメーションをしたい
Sprite
のスプライトシートの機能、もしくは AnimatedSprite
を使う。
詳細は以下のページにまとめました
enum を定義する
# 場所
enum ePlace {
Deck, # 山札
Pyramid, # ピラミッド
Hand, # 手札
HandToDiscard, # 捨札
}
enum 定義を外部から利用する場合はクラス定義する必要がある
# 外部からアクセスする場合はこの定義が必要
class_name MyCard
# 場所
enum ePlace {
Deck, # 山札
Pyramid, # ピラミッド
Hand, # 手札
HandToDiscard, # 捨札
}
これにより外部のクラスから呼び出しが可能となる
if card.place == MyCard.ePlace.Deck:
# 山札にカードが存在する
switch〜case文の書き方
var v = 0
match v:
0:
# vが0のときの処理
1:
# vが1のときの処理
_:
# それ以外
数値だけでなく、文字列や配列、連想配列などを条件に使うことができる
Area2Dのマウスクリックイベントがうまく動かない場合
*Rect
系ノード (TextureRect
や ColorRect
)を使っているとそちらにマウスイベントを取られてしまうことがあるので、もし *Rect
系ノードを使っている場合は Mouse > Filter
を Ignore
にする
Arrayでの独自のソート処理
Array.sort()
は標準の比較演算子によるソートとなるので、独自のソート処理を行いたい場合には、Array.sort_custom()
を使用する
# カードを "pos_index" でソートするクラス
class CardSorter:
static func sort_ascending(a:Card, b:Card) -> bool:
# 昇順ソート
if a.pos_index < b.pos_index:
return true
return false
static func sort_descending(a:Card, b:Card) -> bool:
# 降順ソート
if a.pos_index > b.pos_index:
return true
return false
呼び出しは、以下のように行う
func get_pyramid_list():
# ピラミッドに含まれるカードのリストを返す
var ret = []
for c in cards:
var card:Card = c
if card.place == Card.ePlace.Pyramid:
ret.append(card)
# 昇順ソート
ret.sort_custom(CardSorter, "sort_ascending")
return ret
そのスクリプト内でしか使用しなければ、self
を使っても良い
func sort_ascending(a:Card, b:Card) -> bool:
# 昇順ソート
if a.pos_index < b.pos_index:
return true
return false
# 呼び出し
var arr = []
arr.sort_custom(self, "sort_ascending")
描画順の制御
z_index
の値で描画順を制御できる。
この値を大きくするほど手前に描画される
# ピラミッドに追加
for i in range(6):
var card = deck.pop_back()
card.set_next_position(get_pyramid_position(i))
card.z_index = i # 下にあるカードが手前に描画する
card.place = Card.ePlace.Pyramid
card.pos_index = i
2021.2.22 追記
描画順の制御方法について、さらに調べてみました
→【Godot】2Dゲームの描画順の制御方法
CanvasLayer
を使うことで、描画順の制御が柔軟に行えるようになります。
とりあえずダイアログを表示したい
デバッグ用にとりあえずダイアログを表示するには OS.alert()
を使う
func _ready() -> void:
OS.alert("hoge", "piyo")
ポーズメニューを表示したい
get_tree().paused
に true
を指定すると、ゲーム全体が停止します。
使い方の詳細は以下のページにまとめました。
イージング関数を使いたい
ease()
という関数が用意されていて単純な曲線であればこれで実装できます。
ただ、パラメータの指定が独特なのでこのグラフを見てどの値を指定するのかを検討する必要があります。
https://github.com/godotengine/godot/issues/10572
# cube in
var d = ease(t, 0.4)
# cube out
var d = ease(t, 4.6)
# expo in
var d = ease(t, 0.2)
# expo out
var d = ease(t, 4.8)
常にグリッドが表示されてしまってエディタが重たい
2Dエディタにグリッドを表示していると処理落ちが起きる場合は、ビュー > 常にグリッドを表示
のチェックを外すと処理が軽くなることがあります
この設定を行うと、グリッドスナップが無効の場合にはグリッドが表示されなくなります
加算ブレンドモードでSpriteを描画したい
CanvasItem > Material > 新規CanvasItemMaterial でMaterialを作成し、Blend Mode
に Add
を指定すると加算ブレンドモードで Sprite を描画できるようになります。
出力ウィンドウの制御
主張の激しい「出力ウィンドウ」の制御方法について
ひとまずここをクリックすれば表示・非表示は切り替えられますが、初期設定ではデバッグ実行時に常に表示されてしまいます
一般 > Run > Output
から出力ウィンドウの設定を
- Always Open Output On Play: デバッグ起動時に出力ウィンドウを自動で表示する
- Always Close Output On Stop: デバッグ停止時に出力ウィンドウを自動で非表示にする
個人的には出力ウィンドウが常に必要ではなく、必要なときだけ表示したいので、Always Open Output On Play
のチェックは外しています
三角形を動的に描画する
_draw()
をオーバーライドして、draw_polygon()
で三角形が描画されます。
func _draw():
var points = PoolVector2Array()
var colors = PoolColorArray([Color(0, 1, 0, 0.5)])
points.push_back(Vector2(50, 0))
points.push_back(Vector2(0, 200))
points.push_back(Vector2(200, 200))
draw_polygon(points, colors)
ただ、この描画コマンドはキャッシュされる(開始時に1度しか呼び出されない)ため、位置を変更したい場合は、描画情報が変更されたタイミングでupdate()
を呼び出して draw()
を再び呼び出すようにします。
未使用変数の警告を消したい
関数の引数で未使用変数の警告を消したい場合がたまにあります。
例えば _process(delta)
の delta
が未使用である場合です
func _process(delta):
pass
こんな感じで警告が出てしまうのですが、引数の変数名の前に「_」をつけると未使用変数として警告を抑制することができます。(_deltaなど)
func _process(_delta):
pass
サウンドを再生したい
プロジェクトに *.wav または *.ogg を追加
再生したいシーンまたはノードに AudioStreamPlayer2D
を追加
ノード名を 「AudioDrawCard」とした場合、スクリプトで以下のように記述する
# 再生
$AudioDrawCard.play()
1つの AudioStreamPlayer2D に対し、1つの再生のみとなる(再生中に play() を呼び出すと、再生中のサウンドは停止する)
再生中は再生しない、という処理は以下のように行う
if $AudioDrawCard.playing == false:
# 再生していないときのみ再生する
$AudioDrawCard.play()
サウンドを動的に読み込みたい
AudioStreamPlayer2D.stream
にサウンドリソースを指定すると、動的な読み込みができます。
詳細は以下のページにまとめました。
ウィンドウのリサイズ
スクリプトから画面サイズを変更するには OS.set_window_size()
を使用します
# ウィンドウを 480x320 に変更する
OS.set_window_size(Vector2(480, 320))