74 lines
1.8 KiB
C#
74 lines
1.8 KiB
C#
using Godot;
|
||
using System;
|
||
|
||
public partial class Joystick : Control
|
||
{
|
||
private Vector2 _startTouchPos = Vector2.Zero;
|
||
private Vector2 _currentTouchPos = Vector2.Zero;
|
||
private bool _touching = false;
|
||
|
||
[Export] public float DeadzoneRadius = 40f;
|
||
[Export] public float MaxRadius = 100f;
|
||
|
||
public override void _Ready()
|
||
{
|
||
// 设置控件最小尺寸(Godot 4 使用 CustomMinimumSize)
|
||
CustomMinimumSize = new Vector2(MaxRadius * 2, MaxRadius * 2);
|
||
}
|
||
|
||
public override void _GuiInput(InputEvent @event)
|
||
{
|
||
if (@event is InputEventScreenTouch touch)
|
||
{
|
||
if (touch.Pressed)
|
||
{
|
||
_touching = true;
|
||
_startTouchPos = touch.Position;
|
||
_currentTouchPos = touch.Position;
|
||
}
|
||
else
|
||
{
|
||
_touching = false;
|
||
}
|
||
}
|
||
else if (@event is InputEventScreenDrag drag && _touching)
|
||
{
|
||
_currentTouchPos = drag.Position;
|
||
}
|
||
}
|
||
|
||
public Vector2 GetDirection()
|
||
{
|
||
if (!_touching) return Vector2.Zero;
|
||
|
||
Vector2 offset = _currentTouchPos - _startTouchPos;
|
||
float distance = offset.Length();
|
||
|
||
if (distance < DeadzoneRadius) return Vector2.Zero;
|
||
|
||
float ratio = Mathf.Clamp(
|
||
(distance - DeadzoneRadius) / (MaxRadius - DeadzoneRadius),
|
||
0, 1
|
||
);
|
||
return offset.Normalized() * ratio;
|
||
}
|
||
|
||
public override void _Draw()
|
||
{
|
||
Vector2 center = new Vector2(CustomMinimumSize.X / 2, CustomMinimumSize.Y / 2);
|
||
Vector2 handleOffset = _touching ?
|
||
(_currentTouchPos - _startTouchPos).Normalized() *
|
||
Mathf.Min((_currentTouchPos - _startTouchPos).Length(), MaxRadius) :
|
||
Vector2.Zero;
|
||
|
||
DrawCircle(center, MaxRadius, new Color(1, 1, 1, 1), false);
|
||
DrawCircle(center, DeadzoneRadius, new Color(1, 1, 0, 1), false);
|
||
DrawCircle(center + handleOffset, DeadzoneRadius, new Color(1, 1, 1, 0.3f), false);
|
||
}
|
||
|
||
public override void _Process(double delta)
|
||
{
|
||
QueueRedraw();
|
||
}
|
||
}
|