Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Перемещение в 2D пространстве

Введение

Каждый новичок задаётся вопросом: "Как я могу перемещать свой персонаж?". В зависимости от стиля игры, у тебя могут быть специальные требования, но в основном перемещения в большинстве 2D игр основаны на небольшом числе различных способов.

We'll use CharacterBody2D for these examples, but the principles will apply to other node types (Area2D, RigidBody2D) as well.

Настройка

Each example below uses the same scene setup. Start with a CharacterBody2D with two children: Sprite2D and CollisionShape2D. You can use the Godot icon ("icon.png") for the Sprite2D's texture or use any other 2D image you have.

Откройте Проект -> Настройки проекта и выберите вкладку "Список действий". Добавьте следующие действия (для справки InputEvent):

../../_images/movement_inputs.webp

8-стороннее движение

В этом примере мы хотим, чтобы игрок использовал четыре клавиши для выбора движения в заданном направлении (клавиши - стрелки: вверх/влево/вниз/вправо или W/A/S/D). Термин 8 - позиционное перемещение исходит из факта, что игрок может перемещаться по диагонали удерживая одновременно две клавиши.

../../_images/movement_8way.gif

Add a script to the character body and add the following code:

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()

In the get_input() function, we use Input get_vector() to check for the four key events and sum return a direction vector.

We can then set our velocity by multiplying this direction vector, which has a length of 1, by our desired speed.

Совет

Если вы никогда прежде не использовали векторную алгебру, или желаете освежить память, то можете посмотреть применение векторной алгебры в Godot Векторная математика.

Примечание

Если код выше ничего не делает при нажатии клавиш, проверьте заново установки входных действий как описано в Настройка части этого урока.

Вращение + перемещение

Этот стиль движения иногда называют "Астероид-стиль" потому что он похож на классическую аркадную игру. Нажатие влево/вправо вращает персонаж, вверх/вниз перемещает его вперёд или назад по направления персонажа.

../../_images/movement_rotate1.gif
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()

Here we've added two variables to track our rotation direction and speed. The rotation is applied directly to the body's rotation property.

To set the velocity, we use the body's transform.x which is a vector pointing in the body's "forward" direction, and multiply that by the speed.

Вращение + перемещение с помощью мыши

Этот стиль перемещения - вариация предыдущего. Сейчас направление устанавливается перемещением мыши а не клавиатурой. Благодаря функции "look at", персонаж будет всегда смотреть на курсор мыши. Перемещения вперёд/назад остаются прежними.

../../_images/movement_rotate2.gif
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()

Here we're using the Node2D look_at() method to point the player towards the mouse's position. Without this function, you could get the same effect by setting the angle like this:

rotation = get_global_mouse_position().angle_to_point(position)

Нажми и двигайся

В последнем примере для перемещения персонажа используется только мышь. Нажатие на экран заставит игрока двигаться в указанном направлении.

../../_images/movement_click.gif
extends CharacterBody2D

@export var speed = 400

var target = position

func _input(event):
    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()``заставит тело поворачиваться в направлении своего перемещения.

Совет

Этот приём ещё может использоваться как основа для "следящего" персонажа. Позицией цели может быть любой объект в направлении которого вы хотите перемещаться.

Подведение итогов

Вы можете найти эти примеры полезными как основа для вашего проекта. Не стесняйтесь использовать их и экспериментировать с ними, чтобы увидеть, что вы можете сделать.

You can download this sample project here: 2d_movement_starter.zip