我正在尝试创建一个小型顶视图游戏,其角色可以在开放世界中移动。世界充满了障碍。当我的角色与障碍物的角落相撞时,我无法弄清楚如何处理他的位置。我实现了以下 onCollision 方法,当玩家垂直或水平撞到墙壁时,该方法当然可以正常工作。
@override
void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
if (other is Wall) {
if (intersectionPoints.length == 2) {
var pointA = intersectionPoints.elementAt(0);
var pointB = intersectionPoints.elementAt(1);
final mid = (pointA + pointB) / 2;
final collisionVector = absoluteCenter - mid;
double penetrationDepth = (size.x / 2) - collisionVector.length;
collisionVector.normalize();
position += collisionVector.scaled(penetrationDepth);
}
}
super.onCollision(intersectionPoints, other);
}
但是,当角色碰到角落时,计算穿透深度的方式就没有意义,因此他会被卡住。
任何有关如何解决此问题的帮助将不胜感激。
我通过弄清楚交点如何工作并确定碰撞矢量方向的象限来解决这个问题。 x 或 y 方向上的最小绝对位移决定了玩家从哪一侧撞到角落。它有效,所以我很高兴:)。 仍然很好奇数学奇才是否可以在没有所有这些假设的情况下做到这一点,并使用一些聪明的向量技巧。
@override
void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
if (other is Wall) {
if (intersectionPoints.length == 2) {
var pointA = intersectionPoints.elementAt(0);
var pointB = intersectionPoints.elementAt(1);
final mid = (pointA + pointB) / 2;
final collisionVector = absoluteCenter - mid;
if (pointA.x == pointB.x || pointA.y == pointB.y) {
// Hitting a side without touching a corner
double penetrationDepth = (size.x / 2) - collisionVector.length;
collisionVector.normalize();
position += collisionVector.scaled(penetrationDepth);
} else {
position += _cornerBumpDistance(collisionVector, pointA, pointB);
}
}
}
super.onCollision(intersectionPoints, other);
}
Vector2 _cornerBumpDistance(
Vector2 directionVector, Vector2 pointA, Vector2 pointB) {
var dX = pointA.x - pointB.x;
var dY = pointA.y - pointB.y;
// The order of the two intersection points differs per corner
// The following if statements negates the necessary values to make the
// player move back to the right position
if (directionVector.x > 0 && directionVector.y < 0) {
// Top right corner
dX = -dX;
} else if (directionVector.x > 0 && directionVector.y > 0) {
// Bottom right corner
dX = -dX;
} else if (directionVector.x < 0 && directionVector.y > 0) {
// Bottom left corner
dY = -dY;
} else if (directionVector.x < 0 && directionVector.y < 0) {
// Top left corner
dY = -dY;
}
// The absolute smallest of both values determines from which side the player bumps
// and therefor determines the needed displacement
if (dX.abs() < dY.abs()) {
return Vector2(dX, 0);
} else {
return Vector2(0, dY);
}
}
我第一次在 Flutter 中尝试游戏。您可以根据您的需要尝试一下此代码吗?
@override
void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
if (other is Wall) {
if (intersectionPoints.length == 2) {
final wallCorner = intersectionPoints.elementAt(0);
final collisionVector = position - wallCorner;
final penetrationDepth = size.x / 2 - collisionVector.length;
collisionVector.normalize();
position += collisionVector * penetrationDepth;
}
}
super.onCollision(intersectionPoints, other);
}
我长期以来一直在尝试处理碰撞,这是我找到的最接近的解决方案。但我注意到,如果我将方向保持在碰撞墙上,精灵有时会完全穿过墙壁到达另一侧。另外,这不适用于非常小的物体?这是一个用碰撞来解决的奇怪问题,特别是当使用具有超过 4 或 8 个方向的操纵杆时。