Godot4 タイルマップのはしごを登り降りするスクリプトの例と実行結果

無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、キャラのいる場所のタイルのカスタムデータ can_climb (昇降可能かどうかの bool) の値が 1 つでも true の場合、上下移動の入力に応じてはしごなどを登り降りする処理のスクリプト例と、その実行結果を紹介します。

※ GodotEngine 4.3 を使用しています。.NET 版ではありません。
※スクリプトは自己責任でご使用ください。

関連記事

前回は、操作キャラクターが接触しているタイルに設定したカスタムデータを取得して、はしごのタイルにつけた昇降可能かどうかの値を取得する手順を紹介しました。

タイルセットリソースの各タイルへのカスタムデータの設定は以下の記事を参照してください。

はしごの昇降の処理を追加

前回の記事で、操作キャラクターがはしごなど昇降可能なタイルに触れている場合は can_climb 変数が true になる実装に続いて、その状態で上下キーを押された場合にはしごを上下に移動する昇降中の状態 is_climb 変数が true になる処理を実装します。

_draw イベント関数では、デバッグ用の表示情報をもとに、接触しているタイルまたはタイルがないセルの描画に加えて、昇降可能なカスタムデータのあるタイルに触れている場合は、操作キャラクターの上に^の文字を表示します。

Godot4 接触しているタイルが昇降可能なカスタムデータを持っていたら上下矢印キーで昇降します.はしまで登ると勢いでジャンプしてしまいます.SS3

_physics_process イベント関数では、以前に実装した左右移動とジャンプ・自由落下に加えて、昇降可能なタイル(例ではハシゴ)に触れている場合に上下キーを押された場合は上下に移動(昇降)する処理を加えました。

はしごの上り下りの重要な変数として、昇降可能かどうか(はしごに触れているかどうか)を毎フレーム判定した結果の bool 値 can_climb と、その昇降可能な状態で上下キーを押すことで昇降中の状態になったことを表す bool 値 is_climb があります。
はしごに触れていても、昇降中でなければ自由落下しますが、落下中にはしごのところで上下キーを押すことで昇降中になり落下は止まります。

前回の左右移動とジャンプと自由落下の処理に、さらに追加したはしごの昇降に関する処理は、ハイライトの行です。
詳細はコメントを参照してください。

extends CharacterBody2D

## 操作キャラクターが干渉するタイルマップを設定します。はしごの上り下りなどの条件をこのタイルマップから調べます。
@export var tilemap_layer: TileMapLayer = null
@export var SPEED: float = 300.0 # 左右入力により設定する水平方向の加速度
@export var SPEED_REDUCE: float = 300.0	# 入力がない場合に、水平方向の加速度を減らすフレームあたりの上限値。とまりにくいキャラは SPEED より小さく設定します。
@export var JUMP_VELOCITY: float = -700. # ジャンプの加速度です。

# のっている地形の加速度。動いている地形でジャンプする場合に慣性をつけます。
var platform_velocity = Vector2(0, 0)

# はしごなどをのぼる動作が可能な位置にいる場合に TilemapStage ノードから値を true にされます。
@export var can_climb: bool = false
# はしごなどをのぼりおりしている状態の際に true に設定されます。
@export var is_climb: bool = false

## _physics_process で行う昇降可能の判定をデバッグするための描画を _draw で行う場合は true を設定します。
var debug_can_climb = true

func _ready():
	if debug_can_climb:
		SakuraCrowdTileMapLayer.enable_debug_get_entered_tiles = true

func _draw():
	# デバッグのフラグが有効ならば、接触しているタイル(赤)またはタイルのないセル(青)の枠を描画します。
	if debug_can_climb:
		if SakuraCrowdTileMapLayer.enable_debug_get_entered_tiles:
			# デバッグ用。キャラクターが接触しているタイルの枠線を描画します。
			for draw_info in SakuraCrowdTileMapLayer.debug_get_entered_tiles_info:
				# 本ノードの原点がグローバル座標の (0, 0) と異なっていたり、 scale が 1.0 ではない場合、
				# debug_get_entered_tiles_info に格納されたグローバル座標の rect2 を描画すると
				# ローカル座標として扱ってしまい位置がずれて大きさの異なる矩形が描画されてしまうので
				# グローバル座標をローカル座標に変換します。
				var local_rect2: Rect2 = SakuraCrowdUtil.rect2_to_local(draw_info.rect2, self)
				draw_rect(local_rect2, draw_info.color, false, 3 / scale.x, false)
				SakuraCrowdUtil.debug_print(str(draw_info.rect2), 100)
		# デバッグ用。キャラクターが昇降可能な状態の場合は^を描画します。
		if can_climb == true:
			# _draw の描画で指定した座標は、ローカル座標として扱うので、グローバル座標はローカル座標に変換します。
			# 文字サイズもノードの scale に影響されるので、scale.x の逆数で意図したサイズで描画されるようにします。
			draw_string(ThemeDB.fallback_font, to_local(global_position + Vector2(0, -8)), "^", HORIZONTAL_ALIGNMENT_CENTER, -1, 16 / scale.x, Color.GREEN)
	
func _process(_delta):
	pass

func _physics_process(delta):
	# 現在接触しているタイル群のカスタムデータから、はしごなどの昇降や水中移動の動作が可能かを更新します。
	# $GodotSan の当たり判定領域に重なっている $TileMapLayer のタイル群を取得します。
	var enterd_tiles: Array[TileData] = SakuraCrowdTileMapLayer.get_entered_tiles(tilemap_layer, self)
	if debug_can_climb:
		queue_redraw()	# 接触しているタイルのデバッグ用の再描画を要求します。
		
	# 昇降可能なタイルに触れているかを確認します。
	can_climb = SakuraCrowdTileData.has_true_custom_data(enterd_tiles, "can_climb")
	
	# 着地しているかどうかを取得(複数回呼ぶのでキャッシュ変数に格納)
	var ret_is_on_floor:bool = is_on_floor()
	# Add the gravity.
	if not ret_is_on_floor and not is_climb:
		# 着地していない、はしごの昇降もしていない、空中にいる場合
		velocity += get_gravity() * delta # 重力により落下させます。

	# 着地しているかはしごなどを昇降中はジャンプの入力に対応します。
	if Input.is_action_just_pressed("ui_accept") and (ret_is_on_floor or is_climb):
		velocity.y = JUMP_VELOCITY
		velocity.x += platform_velocity.x # ジャンプ時に、のっている地形の水平方向の加速度を加えることで慣性のあるジャンプを表現します。
		is_climb = false	# はしごを昇降していた場合はその状態を無効にします。

	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction = Input.get_axis("ui_left", "ui_right") # 右入力: + の値, 左右入力なし: 0, 左入力: - の値
	if direction:
		# 左右どちらかに入力された場合
		velocity.x = direction * SPEED # 入力方向に加速
	else:
		# 左右の入力がない場合
		if ret_is_on_floor:
			# 左右移動せずに着地している場合
			
			# SPEED_REDUCE 単位で毎フレーム 0 に向けて減速します。
			# 氷の床などですべりやすくしたい場合、 SPEED_REDUCE をさらに減少させてください。
			velocity.x = move_toward(velocity.x, 0, SPEED_REDUCE) 

	# can_climb が false のエリアに移動した場合は、 is_climb の状態を無効にします。
	if can_climb == false:
		is_climb = false
	
	# can_climb が有効な場合、上下キーで昇降ができます。
	var direction_vertical = Input.get_axis("ui_up", "ui_down")
	if direction_vertical:
		if can_climb:
			is_climb = true	# 昇降可能なエリアにいて昇降の操作を行うと昇降中の状態になります。
			velocity.y = direction_vertical * SPEED  # 昇降速度を入力方向に応じて設定
	else:
		if is_climb:
			velocity.y = move_toward(velocity.y, 0, SPEED_REDUCE) # 昇降速度は 0 に向けて減速

	move_and_slide() # 現在の velocity (加速度)で移動して、衝突などの相互作用も行います。
	platform_velocity = get_platform_velocity() # のっている地形に加速度を更新します。move_and_slide() 後に有効です。
	return

テスト

F5 / F6 キーでタイルマップと操作キャラを配置したシーンを実行します。

接触しているタイルが昇降可能なカスタムデータを持っていたら、昇降可能 (can_climb = true) なので上下矢印キーで昇降して、昇降中 (is_climb = true) の状態になり、昇降中は落下しません。
一番上までで登ると勢いで飛び出してしまいます(次回、止まる処理を追加します)。

Godot4 接触しているタイルが昇降可能なカスタムデータを持っていたら上下矢印キーで昇降します.はしまで登ると勢いでジャンプしてしまいます.SS1

また、はしごから出ると、昇降中 (is_climb = true) の状態が解除 (is_climb = false) されるため、はしごのタイルに触れていても再び上下矢印キーで昇降動作をして、昇降中の状態にならないとはしごの位置にいても落下します。
昇降中ジャンプをしても、昇降中の状態解除されます。

Godot4 接触しているタイルが昇降可能なカスタムデータを持っていたら上下矢印キーで昇降します.はしまで登ると勢いでジャンプしてしまいます.SS2

以下は、前述の登っているはしごの先端から飛び出すシーンと、昇降中のはしごからジャンプするシーンを撮影した動画です。

まとめ

今回は、無料・軽快な 2D / 3D 用のゲームエンジン Godot Engine 4 で、キャラのいる場所のタイルのカスタムデータ can_climb (昇降可能かどうかの bool) の値が 1 つでも true の場合、上下移動の入力に応じてはしごなどを登り降りする処理のスクリプト例と、その実行結果を紹介しました。

次回は、はしごの一番上まで移動したら、飛び跳ねないようにするための判定処理を行います。

参照サイト Thank You!

記事一覧 → Compota-Soft-Press

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました