プレイヤーのスクリプトを書こう
スクリプトの作成
続いて「Player」ノードにスクリプトをアタッチします。
「Player」ノードを右クリックして「スクリプトをアタッチ」を選択します。「ノードにスクリプトをアタッチする」ダイアログが表示されますので「テンプレート」にチェックを入れて、そのまま「作成」ボタンを押します。
res://scn/player/player.gdと保存されたはずです。
このplayer.gdをScriptビューで開き、次のようにスクリプトを書き換えます。
extends CharacterBody2D
const SPEED = 150.0
var is_act = true # クリア後の停止用フラグ
@onready var size = get_viewport_rect().size
func _ready() -> void:
$AnimatedSprite2D.play()
func _physics_process(_delta: float) -> void:
# クリア後の停止処理
if ! is_act:
return
# キー入力から方向を得る
var x = Input.get_axis("ui_left", "ui_right")
var y = Input.get_axis("ui_up", "ui_down")
var direction = Vector2(x, y)
# マウスのクリック位置から方向を得る
if Input.is_mouse_button_pressed(MouseButton.MOUSE_BUTTON_LEFT):
var m_pos = get_viewport().get_mouse_position()
direction = m_pos - Vector2(size / 2)
# 移動があるなら速度を変更、ないなら減衰
if direction.length() > 0:
velocity = direction.normalized() * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
velocity.y = move_toward(velocity.y, 0, SPEED)
# 自動移動
move_and_slide()
# 衝突の検出
#var collider = get_last_slide_collision()
#if collider:
# print("Collider Name: %s" % collider.get_collider().name)
新しい内容が出てきているので、1つずつ解説していきます。
スクリプトの解説
まずはconstです。定数を作ります。
const SPEED = 150.0
続いて@onreadyアノテーションです。このアノテーションが付いた変数の宣言は、_ready関数が実行される直前に行われます。そのため、ノードツリーにぶら下がった状態でのビューポートサイズなどを得ることができます。
@onready var size = get_viewport_rect().size
_ready関数では、「AnimatedSprite2D」のアニメーションを開始します。
func _ready() -> void: $AnimatedSprite2D.play()
_physics_process関数は初めて出てきました。この関数は、プロジェクト設定のFPS(フレーム・パー・セコンド)に合わせて、一定の間隔で呼び出されます。
func _physics_process(_delta: float) -> void:
この呼び出し間隔は_process関数よりも正確です。_process関数は描画に合わせて呼び出されるため、性能の低い実行環境では呼び出し回数が減ります。
方向キーからの入力は、次のようなスクリプトで得られます。左右で1つの軸、上下で1つの軸として値を得て、Vector2を作成します。
# キー入力から方向を得る
var x = Input.get_axis("ui_left", "ui_right")
var y = Input.get_axis("ui_up", "ui_down")
var direction = Vector2(x, y)
少し注意点を述べます。
キー入力は、ゲーム画面にフォーカスが当たっている時しか得られません。
そして、実行時に表示されるデバッグ用のUIが付いたウィンドウと、ゲーム画面は異なる画面です。重ねて表示してあるだけで別のウィンドウです。
外側のウィンドウにフォーカスが当たっている時は、内側のウィンドウでキー操作ができません。ゲーム画面を一度クリックして、ゲーム画面にフォーカスを合わせてからキー操作をしてください。
次に、マウスが画面のどこをクリックしているかで、移動方向を得る処理です。
# マウスのクリック位置から方向を得る if Input.is_mouse_button_pressed(MouseButton.MOUSE_BUTTON_LEFT): var m_pos = get_viewport().get_mouse_position() direction = m_pos - Vector2(size / 2)
ここでは、ビューポートの中心からの方向で、移動方向を計算しています。
こうした処理にしているのは理由があります。このあと、プレイヤーが移動する代わりにカメラを移動させます。そして、プレイヤーは中央に留まったままにします。そのため、中心に対するクリック位置で、移動方向を計算しています。
さて、スクリプトを見ていきましょう。スクリプトはそれほど複雑ではありません。
最初のif文で、マウスの左ボタンが押されているかを判定します。次の行では、ビューポート上のマウスの位置を得ます。
最後の行のVector2(size / 2)は少し説明が必要です。冒頭のget_viewport_rect().sizeで得た値はVector2i(整数のVector)です。get_viewport().get_mouse_position()で得た値はVector2(小数点数のVector)です。
そのままでは計算できないので、Vector2にしてから計算しています。
次は速度の変更です。
# 移動があるなら速度を変更、ないなら減衰 if direction.length() > 0: velocity = direction.normalized() * SPEED else: velocity.x = move_toward(velocity.x, 0, SPEED) velocity.y = move_toward(velocity.y, 0, SPEED)
方向を表すベクトルを正規化してSPEEDを掛けて、「CharacterBody2D」のvelocity(速度)として設定します。
また、キー操作もマウス操作もない場合は、0に近づけるように速度を減衰させます。
move_toward関数は、第1引数から第2引数に向かって、第3引数の値だけ数値を変化させます。この戻り値は、第2引数を超えて変化することはないです。
自動移動と衝突の検出
「CharacterBody2D」が便利なのは、速度のベクトルに合わせて移動を自動で行い、衝突の検出もできることです。
移動はmove_and_slide関数を実行するだけで終わりです。障害物があれば、きちんと止まります。
# 自動移動 move_and_slide()
衝突の検出はget_last_slide_collision関数で行えます。今回は使用していないのでコメントアウトしていますが、コメントを解除すれば、壁に衝突するたびに衝突相手を出力します。
# 衝突の検出
#var collider = get_last_slide_collision()
#if collider:
# print("Collider Name: %s" % collider.get_collider().name)
実行確認
player.tscnを開いた状態で、「F6」を押すか、画面右上の「カチンコの中に▶のアイコン」
(現在のシーンを実行)ボタンを押してください。
左上隅にプレイヤーの画像が表示されてアニメーションします。キーボードの操作か、マウスのクリックでプレイヤーを移動できます。
マウスによる操作は、プレイヤーに対してのクリック位置ではなく、画面中央に対してのクリック位置なので注意が必要です。
もし、キーボードでもマウスでも動かせない場合は、デバッグウィンドウの左上にある「入力」ボタンがオンになっているか確認してください。このボタンがオンになっていないと、マウスやキーボードによる操作はできません。
何かの拍子に操作をしてしまい、隣の「2D」が選択状態になっていることもあります。
