📝

【Godot Engine】フラッピーバードを作るチュートリアル (Part.4)

2021/03/10に公開

概要

この記事は Godot Engineでのフラッピーバードを作る方法を解説する記事の続きとなります。

前回の記事はこちらから
https://zenn.dev/syun77/articles/3bc3387030a376

土管を生成する

土管が連続で出現するようにします。

土管が消える処理を実装する

まずは土管側を修正します。土管スクリプトDokan.gdを開きます。

そして以下のように修正します。

Dokan.gd
extends StaticBody2D

-var velocity = Vector2(-100, 0)
+var velocity = Vector2(-150, 0)

+# 開始処理
+func start(pos, speed_rate):
+	position = pos
+	velocity *= speed_rate

func _process(delta):
	position += velocity * delta
+	if position.x < -128:
+		# 画面外に出たら消える
+		queue_free()

移動速度を調整し、開始処理の start() を追加。そして位置が「-128」になったら queue_free() を呼び出してシーンから削除するようにしました。

土管を生成する処理を実装する

Mainシーンを開く

タブから Mainシーンを選択します。

またはファイルシステムにある「Main.tscn」をダブルクリックしてもMainシーンを開くことができます。

Dokanノードを削除する

Mainシーンを開いたら、「Dokan」ノードを右クリックして「ノード削除」から削除します。

削除確認ダイアログが表示されますが、そのまま「OK」をクリックして削除します。

Mainノードにスクリプトをアタッチする

次にMainノードを選択した状態で、「スクリプトアイコン」をクリックします。

スクリプト作成画面が表示されるので、そのまま「作成」ボタンをクリックします。

Mainシーンのスクリプト Main.gd には以下のように記述します。

Main.gd
extends Node2D

# 土管オブジェクト
var Dokan = preload("res://Dokan.tscn")

# 出現間隔(最初は3秒)
var interval = 3

# 生成タイマー
var timer = interval

# 土管出現回数
var dokan_cnt = 0

func _ready():
	# 乱数を初期化
	randomize()

func _process(delta):
	timer += delta
	if timer > interval:
		# インターバルを超えたら土管を出現させる
		timer -= interval
		_add_dokan()

func _add_dokan():
	# 出現回数をカウントアップ
	dokan_cnt += 1

	# 高さを決める
	var xbase = 800 + 120
	var ybase = rand_range(32, 400-32)
	
	# 土管を上下に生成
	for i in range(2):
		var dokan = Dokan.instance()
		var py = ybase
		if i == 0:
			# 上のドカン
			py += -320
		else:
			# 下のドカン
			py += 320 + 160

		# 土管の出現回数が増えるとスピードアップ
		var speed_rate = 1 + 0.5 * dokan_cnt
		dokan.start(Vector2(xbase, py), speed_rate)
		add_child(dokan)
	
	# インターバルを減らす
	interval = max(0.5, interval-0.2)

簡単に説明すると

  1. _ready() で乱数を初期化
  2. _process() で 経過時間deltatimeに足し込んでいき、intervalを超えたら _add_dokan() で土管を生成
  3. _add_dokan() では、上下に土管を生成し、再びインターバルを開始

となります。

土管を生成している部分の説明です。

ドカン画像の高さの半分がおおよそ 320px (正確には 305.5px) なので、その高さだけ上下に移動させて、160px の間隔を開けています。

では実行して動作を確認します。

ひとまずゲームとして成立してきたように見えます。

衝突の不具合を修正する

衝突時の処理ですが、若干見た目に不具合があります。
横からぶつかった場合は気にならないのですが、上下からぶつかったときにおかしな挙動となります。

面白い挙動なのでアリ……としてもいいかもしれませんが、物理的におかしな動きをしているので修正します。

Player.gdを開いて_update_collision()を以下のように修正します。

Player.gd
# 衝突処理を行う
func _update_collision(delta):
	# 移動と衝突処理を行う
	var collision = move_and_collide(velocity * delta)
	if collision:
		# 衝突したのでジャンプできなくする
		can_jump = false
		# 左方向に吹き飛ばす
		velocity.x -= 300
+		if position.y < collision.position.y:
+			# ドカンより上にプレイヤーがいる
+			velocity.y = -300
+		else:
+			# ドカンより下にプレイヤーがいる
+			velocity.y = 300
		# さらに移動量を加える
		move_and_collide(velocity * delta)

衝突した土管に対する位置で、上下方向の移動量を設定しています。

では実行して、上や下から土管にぶつかってもおかしな挙動とならないことを確認します。

次回

第5回(最終回)に続きます
https://zenn.dev/syun77/articles/e9dae8c15c977a

Discussion