Движение и попадание по игроку
Полный DodgePlayer.cs: движение без ускорения по диагонали, границы поля и одно событие попадания.
Прикрепите Scripts/DodgePlayer.cs к корню CharacterBody2D из префаба игрока. Имя класса и файла должно совпадать. Используйте класс целиком:
using Reckfell;
public partial class DodgePlayer : CharacterBody2D
{
[Signal] public delegate void HitEventHandler();
[Export] public float Speed { get; set; } = 220.0f;
public bool Active { get; set; } = true;
public override void _Draw()
{
DrawRect(new Rect2(-14, -14, 28, 28), new Color(0.2f, 0.4f, 1.0f));
}
public override void _PhysicsProcess(double delta)
{
if (!Active)
{
Velocity = Vector2.Zero;
return;
}
Velocity = Input.GetVector("move_left", "move_right", "move_up", "move_down") * Speed;
MoveAndSlide();
Position = new Vector2(
Mathf.Clamp(Position.X, 14, 626),
Mathf.Clamp(Position.Y, 14, 346));
}
public void StartAt(Vector2 position)
{
Position = position;
Velocity = Vector2.Zero;
ResetPhysicsInterpolation();
Active = true;
}
public void TakeHit()
{
if (!Active)
return;
Active = false;
Velocity = Vector2.Zero;
EmitSignal(SignalName.Hit);
}
}Как выполняется движение
Input.GetVector() читает четыре настроенных действия и ограничивает длину вектора единицей. Speed — скорость в пикселях в секунду. MoveAndSlide() учитывает физический шаг сам: повторно умножать Velocity на delta нельзя.
После движения позиция ограничивается прямоугольником: X от 14 до 626, Y от 14 до 346. Отступ 14 — половина стороны игрока. Эти значения подходят только полю 640 × 360; это явная граница прототипа, а не автоматическая адаптация к любому размеру мира.
Здесь нет твёрдых стен. CharacterBody2D даёт готовый API перемещения; границу экрана задаёт Clamp, а попадание обнаруживает отдельный Area2D противника.
Начало и завершение раунда
StartAt() задаёт начальное положение, сбрасывает скорость и интерполяцию, затем разрешает управление. Вызывайте его после добавления игрока в дерево. TakeHit() выключает Active до сигнала Hit, поэтому несколько пересечений не создают несколько поражений подряд. Контроллер уровня подписывается на этот сигнал.
Когда Active = false, скрипт не опрашивает движение и обнуляет скорость. Интерфейс сам по себе не блокирует Input: отключение управления сделано явно.
Ожидаемый результат
После общей сборки и F6 у Player.rprefab квадрат двигается WASD / стрелками и целиком остаётся внутри окна. Отпущенные клавиши останавливают его. Если движения нет, проверьте фокус игрового окна, привязки Input Map и прикреплённый класс. В полном уровне управление включится только после кнопки начала.