2D 運動概述

前言

每個初學者都曾遇過同樣的情況:「我要怎麼控制我的角色?」根據你想做的遊戲風格,你可能會有特殊的需求。但普遍來說,大部分2D遊戲的操控是以少數幾種設計為基礎的。

這裡我們用 CharacterBody2D 當作範例,不過其他型別的節點(Area2D、RigidBody2D)也適用相同原則。

設定

以下每個範例都使用相同的場景設定。請先建立一個 CharacterBody2D,並加上兩個子節點:Sprite2DCollisionShape2D。你可以使用 Godot 預設圖示(「icon.png」)作為 Sprite2D 的貼圖,或是用你自己的 2D 圖片。

開啟「專案 -> 專案設定」,切換到「輸入對應」分頁。新增下列輸入動作(詳情請參考 InputEvent):

../../_images/movement_inputs.webp

八向移動

在這個情境中,你希望玩家可以按上下左右(或 W/A/S/D)來移動角色。所謂的「八向移動」,就是因為玩家可以同時按下兩個方向鍵,讓角色斜向移動。

在角色節點新增腳本,填入下列程式碼:

extends CharacterBody2D

@export var speed = 400

func get_input():
    var input_direction = Input.get_vector("left", "right", "up", "down")
    velocity = input_direction * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

get_input() 函式中,我們用 Inputget_vector() 來檢查四個方向鍵,回傳一個方向向量。

然後我們可以將這個長度為 1 的方向向量乘上我們想要的速度,來設定速度。

小訣竅

如果你沒學過向量數學或需要複習,可以參考 向量數學 了解 Godot 裡的向量用法。

備註

如果你按下按鍵時上述程式碼沒反應,請再次確認你是否按照本教學 設定 的說明正確設定了輸入動作。

旋轉+移動

這種移動方式有時被稱為「Asteroids 風格」,因為這很像經典街機遊戲 Asteroids 的移動方式。按左右鍵讓角色旋轉,按上下鍵則讓角色往面對的方向前進或後退。

extends CharacterBody2D

@export var speed = 400
@export var rotation_speed = 1.5

var rotation_direction = 0

func get_input():
    rotation_direction = Input.get_axis("left", "right")
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    rotation += rotation_direction * rotation_speed * delta
    move_and_slide()

在這裡我們新增了兩個變數來記錄旋轉方向和速度。旋轉會直接套用到角色的 rotation 屬性上。

要設定速度,我們利用角色本身的 transform.x,這是指向角色「前方」的向量,然後乘上速度。

旋轉+移動(滑鼠)

這種移動方式是前面 Asteroids 式的變體。這次方向是由滑鼠位置決定,角色會一直「朝向」滑鼠游標。前進/後退的操作則不變。

extends CharacterBody2D

@export var speed = 400

func get_input():
    look_at(get_global_mouse_position())
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

這裡我們用 Node2Dlook_at() 方法讓角色朝向滑鼠游標。如果不用這個方法,也可以直接這樣設定角度:

rotation = get_global_mouse_position().angle_to_point(position)

點擊並移動

最後這個範例完全用滑鼠來控制角色。點擊畫面就會讓角色移動到指定位置。

extends CharacterBody2D

@export var speed = 400

var target = position

func _input(event):
    # Use is_action_pressed to only accept single taps as input instead of mouse drags.
    if event.is_action_pressed(&"click"):
        target = get_global_mouse_position()

func _physics_process(delta):
    velocity = position.direction_to(target) * speed
    # look_at(target)
    if position.distance_to(target) > 10:
        move_and_slide()

請注意我們在移動前加上的 distance_to() 檢查。若沒有這一判斷,角色抵達目標時會因為超過目標又回頭,造成一直來回「抖動」。

如果你想讓角色朝運動方向轉向,可以把 look_at() 那一行取消註解。

小訣竅

這個技巧也可以當作「跟隨」角色的基礎,target 目標位置可以是你想追蹤的任何物件。

總結

這些範例程式碼非常適合當作你自己專案的起點,歡迎自由使用或改造。

您可以在此處下載這個範例專案:2d_movement_starter.zip