監聽玩家的輸入
延續先前的課程,建立腳本,讓我們看看任何遊戲的另一個重要功能:將控制權交給玩家。要加入這個功能,我們需要修改我們的 sprite_2d.gd 程式碼。
在 Godot 中,你有兩個主要工具來處理玩家的輸入:
內建的輸入回呼函式,主要是
_unhandled_input()。像_process(),它是一個內建的虛函式,Godot 每次在玩家按下一個鍵時都會呼叫。它是你想用來對那些不是每一影格都發生的事件做出反應的工具,比如按 Space 來跳躍。要瞭解更多關於輸入回呼函式的資訊,請參閱 使用 InputEvent 。Input單例。單例是一個全域可存取的物件。Godot 在腳本中提供對幾個物件的存取。它是每一影格檢查輸入的有效工具。
我們這裡將使用 Input 單例,因為我們需要知道在每一影格中玩家是否想轉身或者移動。
對於轉彎,我們應該使用一個新的變數: direction 。在我們的 _process() 函式中,將 rotation += angular_speed * delta 替換成以下程式碼。
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
我們的 direction 區域變數是一個乘數,代表玩家想要轉向的方向。 0 的值表示玩家沒有按左或右方向鍵。 1 表示玩家想向右轉,而 -1 表示他們想向左轉。
To produce these values, we introduce conditional statements and the use of Input.
A conditional statement starts with the if keyword in GDScript and ends with a colon. The
condition is specifically the expression between the keyword and the colon at
the end of the line.
為了檢查目前影格玩家是否按下了某個鍵,我們需要呼叫 Input.is_action_pressed() 。這個方法使用一個字串來表示一個輸入動作。當該按鍵被按下時,函式返回 true ,否則這個函式將返回 false 。
上面我們使用的兩個動作,“ui_left”和“ui_right”,是每個 Godot 專案中預定義的。它們分別在玩家按鍵盤上的左右箭頭或遊戲手柄上的左右鍵時觸發。
備註
打開“專案 -> 專案設定”並點擊“輸入對應”分頁,就可以查看並編輯專案中的輸入動作。
最後,當我們更新節點的 rotation 時,我們使用 direction 作為乘數: rotation += angular_speed * direction * delta 。
將 var velocity = Vector2.UP.rotated(rotation) * speed 和 position += velocity * delta 這幾行程式碼註解掉,像這樣:
#var velocity = Vector2.UP.rotated(rotation) * speed
#position += velocity * delta
//var velocity = Vector2.Up.Rotated(Rotation) * _speed;
//Position += velocity * (float)delta;
這會忽略前一個練習中,在沒有使用者輸入的情況下,讓圖示以圓形路徑移動位置的程式碼。
如果你用這段程式碼運作場景,當你按下 左方向鍵 和 右方向鍵 時,圖示應該會旋轉。
按“上”時移動
若要僅在按下按鍵時移動,我們需要修改計算速度的程式碼。取消註解該段程式碼,並將以 var velocity 開頭的那一行替換為以下程式碼。
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
我們將 velocity 的值初始化為 Vector2.ZERO ,這是內建 Vector 型別的一個常數,代表長度為 0 的二維向量。
如果玩家按下“ui_up”動作,我們就會更新速度的值,使精靈向前移動。
GDScript 範例
這是完整的 sprite_2d.gd 檔案,僅供參考。
extends Sprite2D
var speed = 400
var angular_speed = PI
func _process(delta):
var direction = 0
if Input.is_action_pressed("ui_left"):
direction = -1
if Input.is_action_pressed("ui_right"):
direction = 1
rotation += angular_speed * direction * delta
var velocity = Vector2.ZERO
if Input.is_action_pressed("ui_up"):
velocity = Vector2.UP.rotated(rotation) * speed
position += velocity * delta
using Godot;
public partial class MySprite2D : Sprite2D
{
private float _speed = 400;
private float _angularSpeed = Mathf.Pi;
public override void _Process(double delta)
{
var direction = 0;
if (Input.IsActionPressed("ui_left"))
{
direction = -1;
}
if (Input.IsActionPressed("ui_right"))
{
direction = 1;
}
Rotation += _angularSpeed * direction * (float)delta;
var velocity = Vector2.Zero;
if (Input.IsActionPressed("ui_up"))
{
velocity = Vector2.Up.Rotated(Rotation) * _speed;
}
Position += velocity * (float)delta;
}
}
如果你運作這個場景,你現在應該能夠用左右方向鍵進行旋轉,並通過按 Up 向前移動。
總結
總之,Godot 中的每個腳本都代表一個類別,並繼承引擎內建的其中一個類別。您的類別繼承的節點類型讓您可以存取屬性,例如我們精靈範例中的 rotation 和 position 。您也會繼承許多函式,但在這個範例中我們沒有用到。
在 GDScript 中,放在檔頂部的變數是類的屬性,也稱為成員變數。除了變數之外,您還可以定義函式,在大多數情況下,這些函式將是類的方法。
Godot 提供了幾個虛函式,您可以定義這些函式來將類與引擎連接起來。其中包括 _process() ,用於每影格將更改應用於節點,以及 _unhandled_input() ,用於接收使用者的輸入事件,如按鍵和按鈕。還有很多。
Input 單例允許您在程式碼中的任何位置對玩家的輸入做出反應。 尤其是,你在 _process() 迴圈中使用它。
在下一個單元,繫結訊號,我們將透過讓節點觸發腳本中的程式碼,來進一步探討腳本和節點之間的關聯。