Godot角色移动

简单使用向量输入处理

1
2
3
4
5
6
7
8
9
public float moveSpeed = 20;

public override void _PhysicsProcess(double delta)
{
float moveHorizontal = Input.GetAxis("left", "right");
float moveVertical = Input.GetAxis("up", "down");
Vector2 moveVec = new Vector2(moveHorizontal, moveVertical).Normalized();
this.Position += moveVec * (float) delta * moveSpeed;
}

引进加速度与减速度,使得运动平滑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[Export]
public float moveAcceleration = 20;
private Vector2 moveVector = Vector2.Zero;
Export]
public float maxVelocity = 300;

private void AdvanceMove(double delta)
{
float moveHorizontal = Input.GetAxis("left", "right");
float moveVertical = Input.GetAxis("up", "down");
Vector2 inputVector = new Vector2(moveHorizontal, moveVertical).Normalized();

//如果用户没有输入
if (inputVector.IsZeroApprox())
{
//速度还很大的情况下就减速
if (moveVector.Length() > moveAcceleration)
{
moveVector -= moveVector.Normalized() * moveAcceleration;
}
//特别小的时候直接等于零
//否则在速度特别小的时候不会减速,而会极慢的永久滑行
else
{
moveVector = Vector2.Zero;
}
}
//用户有输入
else
{
//在最大速度的范围内逐渐增加
if(moveVector.Length() < maxVelocity)
{
moveVector += inputVector * moveAcceleration;
}
}
this.Position += moveVector * (float)delta;
}

精雕细琢

左右为难

正常来说,按下左键往左走,按下右键往右走似乎天经地义,上面的代码也可以实现这些功能

但现在存在一个问题:

例如我们正在往左走,玩家遇到紧急情况(子弹糊脸了!)想要更改方向,于是按下右键,慌忙下来不及松开左键,那么!!!玩家就会小丑般一动不动

为了解决这种情况的代码如下:(以左右为例)

为yux1为游戏行业原创的伟大的死键机制献上礼炮!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//代表左右的死键,约定-1表示左,1表示右,0表示无
private int deadKey;

private void AdvanceMove(double delta)
{
float moveHorizontal = Input.GetAxis("left", "right");

//死键处理:
//首先获得哪个是死键
if (Input.IsActionPressed("left") && !Input.IsActionPressed("right"))
{
deadKey = -1;
}
else if (!Input.IsActionPressed("left") && Input.IsActionPressed("right"))
{
deadKey = 1;
}
else if (!Input.IsActionPressed("left") && !Input.IsActionPressed("right"))
{
deadKey = 0;
}

//根据死键种类决定左右为难时该往哪走
if (deadKey == -1 && Input.IsActionPressed("right"))
{
moveHorizontal = 1;
}
if (deadKey == 1 && Input.IsActionPressed("left"))
{
moveHorizontal = -1;
}


......

if (inputVector.IsZeroApprox())
{
if (moveVector.Length() > moveAcceleration)
{
///
}
else
{
if((moveVector + inputVector * moveAcceleration).Length() < maxVelocity || moveVector.Length() < maxVelocity)
{
moveVector += inputVector * moveAcceleration;
}

}

this.Position += moveVector * (float)delta;

}

幽灵行者

注意到如果上下移动与左右移动间衔接的过快的话坑可能会导致在希望的移动方向以外开始游荡

并且只要衔接够快,玩家能在按住上下键的同时持续左右移动

检查后发现咱们的上下减速和左右减速应该分开检测

小小修改一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
if (inputVector.IsZeroApprox())
{
...
}
else
{
if((moveVector + inputVector * moveAcceleration).Length() < maxVelocity || moveVector.Length() < maxVelocity)
{
moveVector += inputVector * moveAcceleration;
}
//重点ishere
if (inputVector[1] == 0)
{
if (Math.Abs(moveVector[1]) > moveAcceleration)
{
moveVector[1] -= moveVector.Normalized()[1] * moveAcceleration;
}
else
{
moveVector[1] = 0;
}
}
if (inputVector[0] == 0)
{
if (Math.Abs(moveVector[0]) > moveAcceleration)
{
moveVector[0] -= moveVector.Normalized()[0] * moveAcceleration;
}
else
{
moveVector[0] = 0;
}
}
}

变向!

在上方的代码逻辑中如果我们已经在左右方向上移动到最大速度,此时在上下方向上我们就不能做额外的移动

用硬编码帮帮忙

(上面的死键在这里起作用了,难道他真的是天才?)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
if(deadKeyHorizontal == 1 && moveVector.Normalized() == Vector2.Right && inputVector == new Vector2(1, -1).Normalized())
{
moveVector = moveVector.Rotated((float)-Math.PI / 4);
}
else if (deadKeyHorizontal == 1 && moveVector.Normalized() == Vector2.Right && inputVector == new Vector2(1, 1).Normalized())
{
moveVector = moveVector.Rotated((float)Math.PI / 4);
}
else if (deadKeyHorizontal == -1 && moveVector.Normalized() == Vector2.Left && inputVector == new Vector2(-1, -1).Normalized())
{
moveVector = moveVector.Rotated((float)Math.PI / 4);
}
else if (deadKeyHorizontal == -1 && moveVector.Normalized() == Vector2.Left && inputVector == new Vector2(-1, 1).Normalized())
{
moveVector = moveVector.Rotated((float)-Math.PI / 4);
}
else if (deadKeyVertical == 1 && moveVector.Normalized() == Vector2.Down && inputVector == new Vector2(1, 1).Normalized())
{
moveVector = moveVector.Rotated((float)-Math.PI / 4);
}
else if (deadKeyVertical == 1 && moveVector.Normalized() == Vector2.Down && inputVector == new Vector2(-1, 1).Normalized())
{
moveVector = moveVector.Rotated((float)Math.PI / 4);
}
else if (deadKeyVertical == -1 && moveVector.Normalized() == Vector2.Up && inputVector == new Vector2(1, -1).Normalized())
{
moveVector = moveVector.Rotated((float)Math.PI / 4);
}
else if (deadKeyVertical == -1 && moveVector.Normalized() == Vector2.Up && inputVector == new Vector2(-1, -1).Normalized())
{
moveVector = moveVector.Rotated((float)-Math.PI / 4);
}