2020/11/30(月) [n年前の日記]
#1 [godot] Godot EngineでBGアタリについて実験中その2
Godot Engine 3.2.3 x64 を勉強中。BGアタリ処理について実験しているところ。
斜め床の上に着地した際に妙な動きになっちゃう問題が未解決だけど…。それ以外は一応らしく動いてる感じになったので試しにhtml5でエクスポートしてアップロード。Webブラウザ上で動くはず。(※ 2020/12/01追記。背景の奥にColorRectノードを置いて色替えする版で差し替えてみた。)
_parallax_test01.html
画面をクリックしないとキー入力が反応しないかもしれない。
使用画像は以下。CC0 / Public Domain ってことで。
_player_640x640_80x80.png (1キャラ: 80x80ドット, 8x8個, 画像サイズ: 640x640ドット)
_scifi_bg_chip_base.png (1セル: 64x64ドット, 8x8個, 画像サイズ: 512x512ドット)
斜め床の上に着地した際に妙な動きになっちゃう問題が未解決だけど…。それ以外は一応らしく動いてる感じになったので試しにhtml5でエクスポートしてアップロード。Webブラウザ上で動くはず。(※ 2020/12/01追記。背景の奥にColorRectノードを置いて色替えする版で差し替えてみた。)
_parallax_test01.html
- 左右の移動 : Left, Right (カーソルキーの左右), A, D
- ジャンプ : Z, W, Up (カーソルキーの上), Space
画面をクリックしないとキー入力が反応しないかもしれない。
使用画像は以下。CC0 / Public Domain ってことで。
_player_640x640_80x80.png (1キャラ: 80x80ドット, 8x8個, 画像サイズ: 640x640ドット)
_scifi_bg_chip_base.png (1セル: 64x64ドット, 8x8個, 画像サイズ: 512x512ドット)
◎ ノード構成やスクリプトについてメモ。 :
ノード構成は以下のようにした。
重力については、プロジェクト設定の中で値を指定することができる。
プロジェクト設定のインプットマップで、move_left, move_right, move_up も追加。
プレイヤーキャラを動かしてるスクリプトは以下。KinematicBody2D にスクリプトをアタッチした。
_KinematicBody2D.gd
move_and_slide_with_snap() に渡すパラメータは色々あってややこしいけど、おそらく以下のような内容かなと…。
- プレイヤーキャラは KinematicBody2D が担当。
- BGアタリを担当する TileMap は、背景の多重スクロールを担当する ParallaxBackground, ParallaxLayer の中に入れてしまうと正常動作しない。プレイヤーキャラと同階層に置いたら期待通りの動作をしてくれた。
- 単に表示するだけでアタリ判定をしないBGについては、ParallaxBackground, ParallaxLayer の中に入れてしまって問題無い。
重力については、プロジェクト設定の中で値を指定することができる。
プロジェクト設定のインプットマップで、move_left, move_right, move_up も追加。
プレイヤーキャラを動かしてるスクリプトは以下。KinematicBody2D にスクリプトをアタッチした。
_KinematicBody2D.gd
extends KinematicBody2D export var walk_force = 2000.0 export var walk_max_speed = 400.0 export var stop_force = 1600.0 export var jump_speed = 960.0 var velocity = Vector2() var gravity var jumping = false func _ready(): gravity = ProjectSettings.get_setting("physics/2d/default_gravity") #func _process(delta): # pass func _physics_process(delta): var right = Input.get_action_strength("move_right") var left = Input.get_action_strength("move_left") var input = right - left var walk = walk_force * input if abs(walk) < walk_force * 0.2: velocity.x = move_toward(velocity.x, 0, stop_force * delta) # velocity.x = 0 else: velocity.x += walk * delta # velocity.x = walk_max_speed * input velocity.x = clamp(velocity.x, -walk_max_speed, walk_max_speed) velocity.y += gravity * delta var snap = Vector2(0, 32) if is_on_floor(): jumping = false if Input.is_action_pressed("move_up"): velocity.y = -jump_speed jumping = true snap = Vector2.ZERO else: snap = Vector2.ZERO velocity = move_and_slide_with_snap(velocity, snap, Vector2.UP, true, 4, deg2rad(60)) # velocity = move_and_slide(velocity, Vector2.UP) _set_label_text("velo: (%.2f, %.2f)" % [velocity.x, velocity.y]) if right > 0.5: $Sprite.flip_h = false if left > 0.5: $Sprite.flip_h = true if jumping: $Sprite.frame = 2 elif is_on_floor(): $Sprite.frame = 0 else: $Sprite.frame = 1 func _set_label_text(t): $Label.text = t
- gravity = ProjectSettings.get_setting("physics/2d/default_gravity") で、プロジェクト設定の default_gravity を読み取ってる。
- KinematicBody2D は一定の時間間隔で _physics_process(delta) を呼び出すので、その中に移動処理を書く。
- _process(delta) も一定の時間間隔で呼ばれるけれど、状況によっては物理計算・衝突判定が正しく行われないのだとか。アタリを持ってるオブジェクトは _physics_process(delta) 内で処理をせよ、ということになっているらしい。
- Input.get_action_strength("xxx") で、xxxキーやxxxボタンを押したかどうかが 0 〜 1 の値で得られる。アナログジョイスティックを割り当てた時には、おそらく 0.n の値が返ってくるのではないか。たぶん。
- velocity = move_and_slide_with_snap() でBGアタリとの衝突判定+補正処理をする。内部で delta を使って計算しているらしいので、与えるベクトルに対して事前に delta を掛けておかなくてもいい。
- move_and_slide*() を呼んでおけば、is_on_floor() で床の上に立っているかどうかを調べられる。立っていたら true。立ってなかったら false。
- move_and_slide() と move_and_slide_with_snap() の違いは、前者が斜め床に非対応で、後者が斜め床に対応 ―― 床に吸着して移動ができるらしい。
- move_and_slide_with_snap() は斜め床にも対応しているけれど、ジャンプしようとした時も床に吸着されてジャンプできなくなるので、ジャンプ時は吸着用(?)ベクトルを 0 にする。(Vector2.ZERO = Vector2(0, 0))
move_and_slide_with_snap() に渡すパラメータは色々あってややこしいけど、おそらく以下のような内容かなと…。
Vector2 move_and_slide_with_snap ( Vector2 velocity, Vector2 snap, Vector2 up_direction, bool stop_on_slope, int max_slides, float floor_max_angle, bool infinite_inertia )
- velocity ... 移動ベクトル。単位はピクセル/秒。1秒で何ピクセル移動するか。
- snap ... 床への吸着用ベクトル。このベクトルの範囲内に床があった場合は床に吸着されるので、斜め床に張り付いたまま動ける。
- up_direction ... 上方向を指定する。Vector2.UP (= Vector2(0, -1)) を指定。省略時はデフォルト値 Vector2(0, 0) が入る。
- stop_on_slope ... true なら、Body(?)が静止してる場合に斜面の上で滑らなくなる。デフォルトは false。
- max_slides ... 衝突してから静止するまで何回スライドするか、らしい。デフォルト値は4。
- floor_max_angle ... 床として扱う角度を指定。デフォルトは 0.785398ラジアン(45度)。BGアタリに45度の床が混ざってると床として扱われなくなるので、その場合は 45度以上を指定してやると良いらしい。ちなみに、deg2rad(度) で度をラジアンに変換できる。
- infinite_inertia ... RigidBody2D への反映を変化させるらしいが…よくわからない。
◎ 参考ページ。 :
_2D移動の概要 - Godot Engine (stable)の日本語のドキュメント
_キネマティックキャラクター(2D) - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2Dの使用 - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2D - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2D の基本 - Qiita
_Godot Engine - Godot 3.1 will get many improvements to KinematicBody
_godot-demo-projects/player.gd at master - godotengine/godot-demo-projects
_【Godot】TileMapのコリジョンからタイル情報を検出する - 非常口blog
_Difference between move_toward() and lerp() - Godot Engine - Q&A
_Move_and_Slide_With_Snap Failing When Jump From Slope - Godot Engine - Q&A
_Move_and_slide_with_snap() is consistently inconsistent : godot
_Help with Move_and_Slide_with_snap. Wont stay on slope. : godot
_Problem with move and slide with snap function : godot
_move_and_slide_with_snap issue : godot
_KinematicBody2D: move_and_slide_with_snap won't snap to slopes - Issue #26274 - godotengine/godot
_Kinematic body slides off slopes that is supposed to snap to when landing - Issue #30777 - godotengine/godot
_move_and_slide_with_snap 3D KinematicBody not snapping on slopes - Issue #38564 - godotengine/godot
_KinematicBody player with RayShape does not respect snap argument in move_and_slide_with_snap() - Issue #34098 - godotengine/godot
_The player (kinematic body) continues to slide down the slope after I have stopped moving it - Godot Forum
_キネマティックキャラクター(2D) - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2Dの使用 - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2D - Godot Engine (stable)の日本語のドキュメント
_KinematicBody2D の基本 - Qiita
_Godot Engine - Godot 3.1 will get many improvements to KinematicBody
_godot-demo-projects/player.gd at master - godotengine/godot-demo-projects
_【Godot】TileMapのコリジョンからタイル情報を検出する - 非常口blog
_Difference between move_toward() and lerp() - Godot Engine - Q&A
_Move_and_Slide_With_Snap Failing When Jump From Slope - Godot Engine - Q&A
_Move_and_slide_with_snap() is consistently inconsistent : godot
_Help with Move_and_Slide_with_snap. Wont stay on slope. : godot
_Problem with move and slide with snap function : godot
_move_and_slide_with_snap issue : godot
_KinematicBody2D: move_and_slide_with_snap won't snap to slopes - Issue #26274 - godotengine/godot
_Kinematic body slides off slopes that is supposed to snap to when landing - Issue #30777 - godotengine/godot
_move_and_slide_with_snap 3D KinematicBody not snapping on slopes - Issue #38564 - godotengine/godot
_KinematicBody player with RayShape does not respect snap argument in move_and_slide_with_snap() - Issue #34098 - godotengine/godot
_The player (kinematic body) continues to slide down the slope after I have stopped moving it - Godot Forum
[ ツッコむ ]
以上です。