3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Godot EngineAdvent Calendar 2024

Day 22

GDScriptの関数「あっ!これ便利!」

Posted at

まえがき

GodotEngineを触り初めて3年くらいが経ちましたが、未だに「あんた今日までこんな事も知らなかったの!?」の連続。毎日がエブリディ。驚きの日々です。これに関しては「ちゃんとGodotDocs読め」に尽きると思います。 ちゃんとGodotDocs読め。しかしながら「他人に厳しく自分に甘く」これが長生きのコツだそうですので、小生今後も反省せず、右から左、ごまかしごまかし生きていこうと思います。テヘペロ。

という事で今回、私が個人的に最近知って、且つみんなは既に知ってそうなGDScriptの関数などをまとめてみました。

CanvasItem.get_global_mouse_position() -> Vector2

CanvasItemを継承したノードならこれでマウスカーソルの座標がわかるんですって。知らなかったです。

func _process(_delta):
    # $PlayerはSprite2D
    $Player.position = get_global_mouse_position()

ac2024_01.gif

これでもう何でも作れるんじゃねぇかと思いました。

Rect2.intersects(b: Rect2) -> bool

Rect2同士の重なりはこれでわかるんですって。知らなかった。対象が点ならhas_point(point: Vector2)だそうです。他にも「そう言われればそりゃあるよなぁ」という超便利メソッドがRect2には沢山ありました。
でも回転には弱いぽい。

func _process(_delta):
    # $PlayerはTextureRect, $WallはColorRect
    $Player.position = get_global_mouse_position() - $Player.size
    if $Player.get_rect().intersects($Wall.get_rect()): #PlayerとWallは重なってる?
        $Player.modulate = Color.RED # trueなら赤でmodulate
    else:
        $Player.modulate = Color.WHITE # falseなら白で。

ac2024_02.gif

Area2D要らず。とまでは言わないけど、Area2Dをつけるほどでもないちょっとした用事。みたいなのはたまにある気がしなくもない。個人的にはマウスドラッグでの範囲選択とか作るときに便利でした。

補足のSprite2D.get_rect() -> Rect2

上の項は実はちょっとインチキをしていて、GobotちゃんがTextureRectノードなんすね。
GobotちゃんにはSprite2D使いたいじゃん!って思うのですがSprite.get_rect()ではおそらく希望とは違う結果(下のgifの黄色い矩形)になりますので困りました。正解はtransform * get_rect()みたいです。(下のgifの赤い矩形)。それでも間違っていますけど。
つか、Sprite2Dなら普通にArea2Dを使うべよ。
でもこれはこれでちょっと面白い。インチキ当り判定。

# $PlayerはSprite2D
func _process(delta: float) -> void:
	var viewport_rect = get_viewport_rect()
	var ticks = Time.get_ticks_msec()
	$Player.position.x = pingpong(ticks / 20.0, viewport_rect.size.x)
	$Player.position.y = pingpong(ticks / 30.0, viewport_rect.size.y)
	$Player.rotation += 0.5 * delta
	$Player.scale.x = pingpong(ticks / 2000.0, 1.0)
	$Player.scale.y = pingpong(ticks / 3000.0, 1.0)
	queue_redraw()

func _draw() -> void:
    # 黄色い矩形が$Player.get_rect() のRect2
    # 赤い矩形は$Player.transform * $Player.get_rect() のRect2
    
	draw_rect($Player.get_rect(), Color(Color.YELLOW, 0.5))
	draw_rect($Player.transform * $Player.get_rect(), Color(Color.RED, 0.5))

ac2024_06.gif

Dictionary.keys() -> Array

これは知ってたけど、なんとenumでも使えるんですって。 知らなかった。
つか、

enum State {NONE, LEFT, RIGHT}

は、

const State {"NONE": 0, "LEFT": 1, "RIGHT": 2}

と同じ意味なので、Dictionaryのconstなメソッドなら何でも使えるんですと。

enum State {NONE, LEFT, RIGHT}
var state := State.IDLE

func _process(_delta):
    # いろいろあって
    $Player/DebugLabel.text = State.keys[state] 

ac2024_03.gif

stateのデバッグ、いままでmatch(state)いっぱい書いてました。もう超ラク。さすがにちょっと反省しました。

Array.assign() -> void

子のノードのうち、ColorRectノードだけを配列で欲しい。とかいう時にfilter便利なので結構使うんです。

# 子ノードのうち、is ColorRectなものをArrayで得る
var color_rects: Array = get_children().filter(func(node): return node is ColorRect)

でも折角だからArray[ColorRect]とか使いたいー。と思って、

var color_rects: Array[ColorRect] = []
color_rects = get_children().filter(func(node): return node is ColorRect)

ってするんだけど、これはエラーになっちゃう。filter()の戻り値はArrayなので惜しいけどダメ。
こういう時はassign()を使うんですって。知りませんでした。

var color_rects: Array[ColorRect] = []
var _ary = get_children().filter(func(node): return node is ColorRect)
color_rects.assign(_ary)

型を変える以外にもなんか使い方があるっぽいですがよくわかりませんでした。

Object.connectの時のbind()

知らなかった訳では無いけど、いまいちピンとこない感じだったんですが、最近ようやく慣れてきました。

func _ready() -> void:
	for child in get_children():
		if child is ColorRect:
			child.mouse_entered.connect(_on_color_rect_mouse_entered.bind(child))
			child.mouse_exited.connect(_on_color_rect_mouse_exited)

func _on_color_rect_mouse_entered(color_rect):
	$Label.text = "Name: %s\nColor%s" % [color_rect.name, color_rect.color]

func _on_color_rect_mouse_exited():
	$Label.text = ""

ac2024_04.gif

なんか、とりあえず自身への参照渡しておけば、後はなんとかなる気がする。

今年も大変お世話になった関数

  • clamp(min, max, value)
  • lerp(from, to, weight)
  • inverse_lerp(from, to, weight)
  • Array.sort_custom(func: Callable)
  • Array.shuffle()
  • Array.map(func: Callable)
  • Array.reduce(method: Callable, accum: Variant = null)

説明は省略

おまけ

この記事を書くにあたり

  • 1ゲームにつき1つのgdファイル
  • コメント除いて80行以内
  • Area2D禁止
  • 自作シグナル禁止

という縛りでGDScript再入門を兼ねたゲームを色々作ってみたので、よかったら遊んでみてください。

HottestGames8in1 @ GodotPlayer
https://godotplayer.com/games/gac_2024_8in1

ソースコード
https://github.com/sanitygames/GodotEngineAdventCalendar2024

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?