mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-07 02:12:07 +03:00
Updated "2D movement overview" (#6423)
* Update tutorials/2d/2d_movement.rst Co-authored-by: Raul Santos <raulsntos@gmail.com>
This commit is contained in:
@@ -25,7 +25,7 @@ for the Sprite2D's texture or use any other 2D image you have.
|
|||||||
Open ``Project -> Project Settings`` and select the "Input Map" tab. Add the following
|
Open ``Project -> Project Settings`` and select the "Input Map" tab. Add the following
|
||||||
input actions (see :ref:`InputEvent <doc_inputevent>` for details):
|
input actions (see :ref:`InputEvent <doc_inputevent>` for details):
|
||||||
|
|
||||||
.. image:: img/movement_inputs.png
|
.. image:: img/movement_inputs.webp
|
||||||
|
|
||||||
8-way movement
|
8-way movement
|
||||||
--------------
|
--------------
|
||||||
@@ -36,77 +36,52 @@ fact that the player can move diagonally by pressing two keys at the same time.
|
|||||||
|
|
||||||
.. image:: img/movement_8way.gif
|
.. image:: img/movement_8way.gif
|
||||||
|
|
||||||
Add a script to the kinematic body and add the following code:
|
Add a script to the character body and add the following code:
|
||||||
|
|
||||||
.. tabs::
|
.. tabs::
|
||||||
.. code-tab:: gdscript GDScript
|
.. code-tab:: gdscript GDScript
|
||||||
|
|
||||||
extends CharacterBody2D
|
extends CharacterBody2D
|
||||||
|
|
||||||
export (int) var speed = 200
|
@export var speed = 400
|
||||||
|
|
||||||
var velocity = Vector2()
|
|
||||||
|
|
||||||
func get_input():
|
func get_input():
|
||||||
velocity = Vector2()
|
var input_direction = Input.get_vector("left", "right", "up", "down")
|
||||||
if Input.is_action_pressed("right"):
|
velocity = input_direction * speed
|
||||||
velocity.x += 1
|
|
||||||
if Input.is_action_pressed("left"):
|
|
||||||
velocity.x -= 1
|
|
||||||
if Input.is_action_pressed("down"):
|
|
||||||
velocity.y += 1
|
|
||||||
if Input.is_action_pressed("up"):
|
|
||||||
velocity.y -= 1
|
|
||||||
velocity = velocity.normalized() * speed
|
|
||||||
|
|
||||||
func _physics_process(delta):
|
func _physics_process(delta):
|
||||||
get_input()
|
get_input()
|
||||||
velocity = move_and_slide(velocity)
|
move_and_slide()
|
||||||
|
|
||||||
.. code-tab:: csharp
|
.. code-tab:: csharp
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
public class Movement : CharacterBody2D
|
public partial class Movement : CharacterBody2D
|
||||||
{
|
{
|
||||||
[Export] public int speed = 200;
|
[Export]
|
||||||
|
public int Speed { get; set; } = 400;
|
||||||
public Vector2 velocity = new Vector2();
|
|
||||||
|
|
||||||
public void GetInput()
|
public void GetInput()
|
||||||
{
|
{
|
||||||
velocity = new Vector2();
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("right"))
|
Vector2 inputDirection = Input.GetVector("left", "right", "up", "down");
|
||||||
velocity.x += 1;
|
Velocity = inputDirection * Speed;
|
||||||
|
|
||||||
if (Input.IsActionPressed("left"))
|
|
||||||
velocity.x -= 1;
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("down"))
|
|
||||||
velocity.y += 1;
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("up"))
|
|
||||||
velocity.y -= 1;
|
|
||||||
|
|
||||||
velocity = velocity.Normalized() * speed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _PhysicsProcess(float delta)
|
public override void _PhysicsProcess(double delta)
|
||||||
{
|
{
|
||||||
GetInput();
|
GetInput();
|
||||||
velocity = MoveAndSlide(velocity);
|
MoveAndSlide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
In the ``get_input()`` function, we check for the four key events and sum them
|
In the ``get_input()`` function, we use :ref:`Input <class_Input>` ``get_vector()`` to check for the
|
||||||
up to get the velocity vector. This has the benefit of making two opposite keys
|
four key events and sum return a direction vector.
|
||||||
cancel each other out, but will also result in diagonal movement being faster
|
|
||||||
due to the two directions being added together.
|
|
||||||
|
|
||||||
We can prevent that if we *normalize* the velocity, which means we set
|
We can then set our velocity by multiplying this direction vector, which has a
|
||||||
its *length* to ``1``, and multiply by the desired speed.
|
length of ``1``, by our desired speed.
|
||||||
|
|
||||||
.. tip:: If you've never used vector math before, or need a refresher,
|
.. tip:: If you've never used vector math before, or need a refresher,
|
||||||
you can see an explanation of vector usage in Godot at :ref:`doc_vector_math`.
|
you can see an explanation of vector usage in Godot at :ref:`doc_vector_math`.
|
||||||
@@ -131,78 +106,54 @@ while up/down moves it forward or backward in whatever direction it's facing.
|
|||||||
|
|
||||||
extends CharacterBody2D
|
extends CharacterBody2D
|
||||||
|
|
||||||
export (int) var speed = 200
|
@export var speed = 400
|
||||||
export (float) var rotation_speed = 1.5
|
@export var rotation_speed = 1.5
|
||||||
|
|
||||||
var velocity = Vector2()
|
var rotation_direction = 0
|
||||||
var rotation_dir = 0
|
|
||||||
|
|
||||||
func get_input():
|
func get_input():
|
||||||
rotation_dir = 0
|
rotation_direction = Input.get_axis("left", "right")
|
||||||
velocity = Vector2()
|
velocity = transform.x * Input.get_axis("down", "up") * speed
|
||||||
if Input.is_action_pressed("right"):
|
|
||||||
rotation_dir += 1
|
|
||||||
if Input.is_action_pressed("left"):
|
|
||||||
rotation_dir -= 1
|
|
||||||
if Input.is_action_pressed("down"):
|
|
||||||
velocity = Vector2(-speed, 0).rotated(rotation)
|
|
||||||
if Input.is_action_pressed("up"):
|
|
||||||
velocity = Vector2(speed, 0).rotated(rotation)
|
|
||||||
|
|
||||||
func _physics_process(delta):
|
func _physics_process(delta):
|
||||||
get_input()
|
get_input()
|
||||||
rotation += rotation_dir * rotation_speed * delta
|
rotation += rotation_direction * rotation_speed * delta
|
||||||
velocity = move_and_slide(velocity)
|
move_and_slide()
|
||||||
|
|
||||||
.. code-tab:: csharp
|
.. code-tab:: csharp
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
public class Movement : CharacterBody2D
|
public partial class Movement : CharacterBody2D
|
||||||
{
|
{
|
||||||
[Export] public int speed = 200;
|
[Export]
|
||||||
[Export] public float rotationSpeed = 1.5f;
|
public int Speed { get; set; } = 400;
|
||||||
|
|
||||||
public Vector2 velocity = new Vector2();
|
[Export]
|
||||||
public int rotationDir = 0;
|
public float RotationSpeed { get; set; } = 1.5f;
|
||||||
|
|
||||||
|
private int _rotationDirection;
|
||||||
|
|
||||||
public void GetInput()
|
public void GetInput()
|
||||||
{
|
{
|
||||||
rotationDir = 0;
|
_rotationDirection = Input.GetAxis("left", "right");
|
||||||
velocity = new Vector2();
|
Velocity = Transform.x * Input.GetAxis("down", "up") * Speed;
|
||||||
|
|
||||||
if (Input.IsActionPressed("right"))
|
|
||||||
rotationDir += 1;
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("left"))
|
|
||||||
rotationDir -= 1;
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("down"))
|
|
||||||
velocity = new Vector2(-speed, 0).Rotated(Rotation);
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("up"))
|
|
||||||
velocity = new Vector2(speed, 0).Rotated(Rotation);
|
|
||||||
|
|
||||||
velocity = velocity.Normalized() * speed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _PhysicsProcess(float delta)
|
public override void _PhysicsProcess(double delta)
|
||||||
{
|
{
|
||||||
GetInput();
|
GetInput();
|
||||||
Rotation += rotationDir * rotationSpeed * delta;
|
Rotation += _rotationDirection * RotationSpeed * (float)delta;
|
||||||
velocity = MoveAndSlide(velocity);
|
MoveAndSlide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Here we've added two new variables to track our rotation direction and speed.
|
Here we've added two variables to track our rotation direction and speed.
|
||||||
Again, pressing both keys at once will cancel out and result in no rotation.
|
|
||||||
The rotation is applied directly to the body's ``rotation`` property.
|
The rotation is applied directly to the body's ``rotation`` property.
|
||||||
|
|
||||||
To set the velocity, we use the ``Vector2.rotated()`` method, so that it points
|
To set the velocity, we use the body's ``transform.x`` which is a vector pointing
|
||||||
in the same direction as the body. ``rotated()`` is a useful vector function
|
in the body's "forward" direction, and multiply that by the speed.
|
||||||
that you can use in many circumstances where you would otherwise need to apply
|
|
||||||
trigonometric functions.
|
|
||||||
|
|
||||||
Rotation + movement (mouse)
|
Rotation + movement (mouse)
|
||||||
---------------------------
|
---------------------------
|
||||||
@@ -218,56 +169,41 @@ is set by the mouse position instead of the keyboard. The character will always
|
|||||||
|
|
||||||
extends CharacterBody2D
|
extends CharacterBody2D
|
||||||
|
|
||||||
export (int) var speed = 200
|
@export var speed = 400
|
||||||
|
|
||||||
var velocity = Vector2()
|
|
||||||
|
|
||||||
func get_input():
|
func get_input():
|
||||||
look_at(get_global_mouse_position())
|
look_at(get_global_mouse_position())
|
||||||
velocity = Vector2()
|
velocity = transform.x * Input.get_axis("down", "up") * speed
|
||||||
if Input.is_action_pressed("down"):
|
|
||||||
velocity = Vector2(-speed, 0).rotated(rotation)
|
|
||||||
if Input.is_action_pressed("up"):
|
|
||||||
velocity = Vector2(speed, 0).rotated(rotation)
|
|
||||||
|
|
||||||
func _physics_process(delta):
|
func _physics_process(delta):
|
||||||
get_input()
|
get_input()
|
||||||
velocity = move_and_slide(velocity)
|
move_and_slide()
|
||||||
|
|
||||||
.. code-tab:: csharp
|
.. code-tab:: csharp
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
public class Movement : CharacterBody2D
|
public partial class Movement : CharacterBody2D
|
||||||
{
|
{
|
||||||
[Export] public int speed = 200;
|
[Export]
|
||||||
|
public int Speed { get; set; } = 400;
|
||||||
public Vector2 velocity = new Vector2();
|
|
||||||
|
|
||||||
public void GetInput()
|
public void GetInput()
|
||||||
{
|
{
|
||||||
LookAt(GetGlobalMousePosition());
|
LookAt(GetGlobalMousePosition());
|
||||||
velocity = new Vector2();
|
Velocity = Transform.x * Input.GetAxis("down", "up") * Speed;
|
||||||
|
|
||||||
if (Input.IsActionPressed("down"))
|
|
||||||
velocity = new Vector2(-speed, 0).Rotated(Rotation);
|
|
||||||
|
|
||||||
if (Input.IsActionPressed("up"))
|
|
||||||
velocity = new Vector2(speed, 0).Rotated(Rotation);
|
|
||||||
|
|
||||||
velocity = velocity.Normalized() * speed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _PhysicsProcess(float delta)
|
public override void _PhysicsProcess(double delta)
|
||||||
{
|
{
|
||||||
GetInput();
|
GetInput();
|
||||||
velocity = MoveAndSlide(velocity);
|
MoveAndSlide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Here we're using the :ref:`Node2D <class_Node2D>` ``look_at()`` method to
|
Here we're using the :ref:`Node2D <class_Node2D>` ``look_at()`` method to
|
||||||
point the player towards a given position. Without this function, you
|
point the player towards the mouse's position. Without this function, you
|
||||||
could get the same effect by setting the angle like this:
|
could get the same effect by setting the angle like this:
|
||||||
|
|
||||||
.. tabs::
|
.. tabs::
|
||||||
@@ -293,10 +229,9 @@ on the screen will cause the player to move to the target location.
|
|||||||
|
|
||||||
extends CharacterBody2D
|
extends CharacterBody2D
|
||||||
|
|
||||||
export (int) var speed = 200
|
@export var speed = 400
|
||||||
|
|
||||||
var target = Vector2()
|
var target = position
|
||||||
var velocity = Vector2()
|
|
||||||
|
|
||||||
func _input(event):
|
func _input(event):
|
||||||
if event.is_action_pressed("click"):
|
if event.is_action_pressed("click"):
|
||||||
@@ -305,36 +240,36 @@ on the screen will cause the player to move to the target location.
|
|||||||
func _physics_process(delta):
|
func _physics_process(delta):
|
||||||
velocity = position.direction_to(target) * speed
|
velocity = position.direction_to(target) * speed
|
||||||
# look_at(target)
|
# look_at(target)
|
||||||
if position.distance_to(target) > 5:
|
if position.distance_to(target) > 10:
|
||||||
velocity = move_and_slide(velocity)
|
move_and_slide()
|
||||||
|
|
||||||
.. code-tab:: csharp
|
.. code-tab:: csharp
|
||||||
|
|
||||||
using Godot;
|
using Godot;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
public class Movement : CharacterBody2D
|
public partial class Movement : CharacterBody2D
|
||||||
{
|
{
|
||||||
[Export] public int speed = 200;
|
[Export]
|
||||||
|
public int Speed { get; set; } = 400;
|
||||||
|
|
||||||
public Vector2 target = new Vector2();
|
private Vector2 _target;
|
||||||
public Vector2 velocity = new Vector2();
|
|
||||||
|
|
||||||
public override void _Input(InputEvent @event)
|
public override void _Input(InputEvent @event)
|
||||||
{
|
{
|
||||||
if (@event.IsActionPressed("click"))
|
if (@event.IsActionPressed("click"))
|
||||||
{
|
{
|
||||||
target = GetGlobalMousePosition();
|
_target = GetGlobalMousePosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _PhysicsProcess(float delta)
|
public override void _PhysicsProcess(double delta)
|
||||||
{
|
{
|
||||||
velocity = Position.DirectionTo(target) * speed;
|
velocity = Position.DirectionTo(_target) * Speed;
|
||||||
// LookAt(target);
|
// LookAt(target);
|
||||||
if (Position.DistanceTo(target) > 5)
|
if (Position.DistanceTo(_target) > 10)
|
||||||
{
|
{
|
||||||
velocity = MoveAndSlide(velocity);
|
MoveAndSlide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
BIN
tutorials/2d/img/movement_inputs.webp
Normal file
BIN
tutorials/2d/img/movement_inputs.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
Reference in New Issue
Block a user