SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Godot Engine 2Dゲーム開発入門

【詳細解説】Godot Engineで始める2Dゲーム開発──公式サンプルを試してみよう

Godot Engine 2Dゲーム開発入門 第2回

4.衝突の準備

シグナルの追加

 次におこなうのは衝突判定の準備です。Godot Engineの重要な要素となるシグナルをあつかいます。シグナルはノード間で情報をやり取りするためのルールです。

 まず、スクリプトの先頭にシグナルを追加します。extends Area2Dの後にhitというシグナルを書きます。

extends Area2D

signal hit

 このhitは、「Player」が敵と衝突したときに「Player」が発信するシグナルにします。

 「インスペクター」ドックがある右側サイドバーに「ノード」ドックがあるので開きます。

 「ノード」ドックに、Playerが発信可能なシグナルの一覧が表示されます。今追加したhitも入っています。

シグナルの一覧
シグナルの一覧

シグナルの接続

 シグナルは用意するだけでは駄目で、他のノードに接続する必要があります。接続する側では、_on_シグナル名関数を定義して、シグナルを受け取った際の処理を書きます。

 ここでは、hitではなく、別のシグナルを受け取った時の処理を書きます。hitシグナルを受け取った時の処理は、他の場所で書きます。

 「ノード」ドックに並ぶシグナル一覧から「Area2D」の「body_entered(body: Node2D)」を選んで右クリックします。そして「接続」を選びます。

body_entered(body: Node2D)
body_entered(body: Node2D)

 「メソッドにシグナルを接続」ダイアログが表示されます。そのまま「接続」ボタンをクリックします。

「メソッドにシグナルを接続」ダイアログ
「メソッドにシグナルを接続」ダイアログ

 player.gd_on_body_entered関数が追加されます。また「ノード」ドックの「body_entered(body: Node2D)」の配下に「.::_on_body_entered()」が追加されます。

_on_body_entered
_on_body_entered

 それぞれに緑色のアイコンが付いているのが分かると思います。緑のアイコンは、シグナルがこの関数に接続していることを示しています。

 少し私見を書きます。シグナルの処理は直感的ではなく、自分が何をやっているのか自信がなくなり混乱しやすい部分です。混乱しないようにしてください。

 シグナルを受け取るのが_on_~関数で、シグナルを発するのがシグナル.emit()です。そして、シグナルを受け取る際は、「ノード」ドックを使って接続します。

 この接続の仕方はいろいろあり、他の接続方法(スプリクトから接続する方法)は今後の連載で出てきます。

_on_body_enteredの実装

 それでは_on_body_entered関数の中身を書いていきましょう。

func _on_body_entered(body: Node2D) -> void:
	hide()	# 衝突したら、プレイヤーを隠す
	hit.emit()	# hitのシグナルを発信する
	$CollisionShape2D.set_deferred("disabled", true)	# フレーム最後に無効化する

 最初の処理はhide関数です。敵と衝突したらプレイヤーを隠します。

 次の処理はhit.emit関数です。hitのシグナルを発信します。どこかでhitに接続しているノードがあれば、ここで発信したシグナルを受信します。

 最後の処理は、set_deferred関数を使い、「CollisionShape2D」ノードのdisabledtrueに設定します。

 set_deferred関数は、現在のフレームの最後にプロパティーを書き換えます。「CollisionShape2D」を無効化すれば、衝突が起きなくなります。

 敵と衝突したら、このような手順でプレイヤーを隠して、シグナルを発信して、衝突処理を無効化します。

startの実装

 最後にもう1つだけ関数を末尾に追加します。新しいゲームを始める時に、「Player」の状態をリセットするための関数です。この関数を外部から呼び出すことで、「Player」の状態をゲーム開始時の状態に戻します。

func start(pos: Vector2) -> void:
	position = pos	# 初期位置を設定
	show()		# プレイヤーを表示
	$CollisionShape2D.disabled = false	# 無効化を解除

 最初の処理では、引数のpospositionに代入します。

 次の処理はshow関数です。「Player」を表示します。

 最後の処理は$CollisionShape2D.disabledの値をfalseにします。これで衝突範囲が有効に戻ります。ゲーム中とは違い、フレームの最後ではなく、即時に値を変更しています。

 Playerの作業はこれで終了です。

ここまでのスクリプト

 ここまでのスクリプトを掲載します。

player.gd
extends Area2D

signal hit

@export var speed = 400 	# プレイヤーが移動する速さ (pixels/sec)
var screen_size 	# ゲームウィンドウのサイズ


# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	screen_size = get_viewport_rect().size


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	# キー入力による速度の設定
	var velocity = Vector2.ZERO		# Playreの移動ベクター
	if Input.is_action_pressed("move_right"):
		velocity.x += 1
	if Input.is_action_pressed("move_left"):
		velocity.x -= 1
	if Input.is_action_pressed("move_down"):
		velocity.y += 1
	if Input.is_action_pressed("move_up"):
		velocity.y -= 1

	# 移動しているか、していなかで処理を分岐
	if velocity.length() > 0:
		# 移動しているなら、速度のベクトルを正規化したあと、係数を掛ける
		velocity = velocity.normalized() * speed
		$AnimatedSprite2D.play()	# AnimatedSprite2Dを再生
	else:
		$AnimatedSprite2D.stop()	# AnimatedSprite2Dを停止

	# 位置を更新、画面外にはみ出さないようにする
	position += velocity * delta
	position = position.clamp(Vector2.ZERO, screen_size)

	# 表示するアニメーションの種類と向きを設定
	if velocity.x != 0:
		$AnimatedSprite2D.animation = "walk"
		$AnimatedSprite2D.flip_v = false	# 縦方向の反転なし
		$AnimatedSprite2D.flip_h = velocity.x < 0	# 横方向の反転
	elif velocity.y != 0:
		$AnimatedSprite2D.animation = "up"
		$AnimatedSprite2D.flip_v = velocity.y > 0	# 縦方向の反転


func _on_body_entered(body: Node2D) -> void:
	hide()	# 衝突したら、プレイヤーを隠す
	hit.emit()	# hitのシグナルを発信する
	$CollisionShape2D.set_deferred("disabled", true)	# フレーム最後に無効化する


func start(pos) -> void:
	position = pos	# 初期位置を設定
	show()		# プレイヤーを表示
	$CollisionShape2D.disabled = false	# 無効化を解除

次のページ
5.敵の作成

この記事は参考になりましたか?

Godot Engine 2Dゲーム開発入門連載記事一覧

もっと読む

この記事の著者

柳井 政和(ヤナイ マサカズ)

クロノス・クラウン合同会社 代表社員http://crocro.com/オンラインソフトを多数公開。プログラムを書いたり、ゲームを作ったり、記事を執筆したり、マンガを描いたり、小説を書いたりしています。「めもりーくりーなー」でオンラインソフト大賞に入賞。最近は、小説家デビューして小説も書いています(『裏切りのプログラム』他)。面白いことなら何でもOKのさすらいの企画屋です。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/21370 2025/05/28 11:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー