LoginSignup
20
7

More than 1 year has passed since last update.

【Godot】Godot EngineのTIPS

Last updated at Posted at 2021-02-06

この記事は 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)

インプットマップを追加する方法

  1. メニューから プロジェクト > プロジェクト設定 を選ぶ。
  2. インプットマップ タブを選んで、アクションに "ui_click" と入力して、「追加」ボタンをクリック
  3. 追加された "ui_click" の行の右側にある「+」をクリックして マウスボタン を選択
  4. 「左ボタン」を選んで「追加」ボタンをクリック

Godot_Engine_-_TestTree.png
Godot_Engine_-_TestTree____.png
Godot_Engine_-_TestTree____.png

この設定をすることで、以下のコードでクリック判定ができる

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 ノードを追加すると四角形を表示できます。

Godot_Engine_-_gd_pyramid_-_Card_tscn.png
Godot_Engine_-_gd_pyramid_-_Card_tscn____.png

ColorRect の色を変更したい

colorプロパティから変更できます

# 緑色に変更する
$ColorRect.color = Color.green

Sprite関連

Spriteの色を変更したい

Spriteノードの色は modulate となります

## スプライトの頂点カラーを緑色にする
$Sprite.modulate = Color.green

Spriteが消えるだけのエフェクトを作る

Spriteが消えるだけのエフェクト(当たり判定がない)場合は、Spriteノードだけ作成して、テクスチャを設定するだけでよい。Spriteが Node2D を継承しているので Area2D を使わなくても良い
(※スプライトシート[連番画像。等間隔でパターンが並んだ画像] を使わないのであれば、TextureRect の方がパフォーマンスが良いかも?)

Godot_Engine_-_gd_pyramid_-_CardEffect_tscn.png
このような縁がぼやけているエフェクトの画像を用意する

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()

shot.gif

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 系ノード (TextureRectColorRect)を使っているとそちらにマウスイベントを取られてしまうことがあるので、もし *Rect 系ノードを使っている場合は Mouse > FilterIgnore にする
Godot_Engine_-_gd_pyramid_-_Card_tscn____.png

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

gd_pyramid__DEBUG_.png

2021.2.22 追記

描画順の制御方法について、さらに調べてみました
【Godot】2Dゲームの描画順の制御方法

CanvasLayer を使うことで、描画順の制御が柔軟に行えるようになります。

とりあえずダイアログを表示したい

デバッグ用にとりあえずダイアログを表示するには OS.alert() を使う

func _ready() -> void:
    OS.alert("hoge", "piyo")

gd_pyramid__DEBUG_.png

ポーズメニューを表示したい

get_tree().pausedtrue を指定すると、ゲーム全体が停止します。
使い方の詳細は以下のページにまとめました。

イージング関数を使いたい

ease() という関数が用意されていて単純な曲線であればこれで実装できます。
ただ、パラメータの指定が独特なのでこのグラフを見てどの値を指定するのかを検討する必要があります。
29590477-56c5b672-879a-11e7-9d25-67c562a66093.png
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エディタにグリッドを表示していると処理落ちが起きる場合は、ビュー > 常にグリッドを表示 のチェックを外すと処理が軽くなることがあります

Godot_Engine_-_gd_pyramid_-_Main_tscn____.png

この設定を行うと、グリッドスナップが無効の場合にはグリッドが表示されなくなります
Godot_Engine_-_gd_pyramid_-_Main_tscn____.png

加算ブレンドモードでSpriteを描画したい

CanvasItem > Material > 新規CanvasItemMaterial でMaterialを作成し、Blend ModeAdd を指定すると加算ブレンドモードで Sprite を描画できるようになります。
Godot_Engine_-_gd_pyramid_-_Card_tscn.png

出力ウィンドウの制御

主張の激しい「出力ウィンドウ」の制御方法について

ひとまずここをクリックすれば表示・非表示は切り替えられますが、初期設定ではデバッグ実行時に常に表示されてしまいます
Godot_Engine_-_gd_pyramid_-_Main_tscn_と_「【Godot】GodotのTIPS」を編集_-_Qiita.png

メニューから エディタ > エディタ設定 を選択
Godot_Engine_-_gd_pyramid_-_Main_tscn.png

一般 > Run > Output から出力ウィンドウの設定を

Godot_Engine_-_gd_pyramid_-_Main_tscn.png

  • 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

Godot_Engine_-_TestAdv_-_AdvMoveCursor_tscn.png

こんな感じで警告が出てしまうのですが、引数の変数名の前に「_」をつけると未使用変数として警告を抑制することができます。(_deltaなど)

func _process(_delta):
  pass

サウンドを再生したい

プロジェクトに *.wav または *.ogg を追加

再生したいシーンまたはノードに AudioStreamPlayer2D を追加
Godot_Engine_-_gd_pyramid_-_Main_tscn.png

ノード名を 「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))
20
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
7