英文:
How to deal with character collision on corners in Flutter Flame
问题
我正在尝试创建一个小型的俯视视角游戏,其中一个角色在开放世界中移动。世界充满了障碍物。当我的角色与障碍物的角碰撞时,我无法弄清楚如何处理他的位置。我已经实现了以下的onCollision方法,当玩家垂直或水平地撞到墙壁时,当然是有效的。
然而,当角色撞到一个角落时,计算渗透深度的方式不合理,因此他会被卡住。
任何关于如何解决这个问题的帮助都将不胜感激。
英文:
I am trying to create little top view game with a character that moves around an open world. The world is filled with obstacles. I cannot figure out to handle my character position when he collides with corners of obstacles. I have the following onCollision method implemented, which ofcourse works just fine when the player hits a wall vertically or horizontally.
@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);
}
However, when the character hits a corner, the way the penetration depth is calculated does not make sense, and therefor he gets stuck.
Any help on how to approach this problem would be greatly appreciated.
答案1
得分: 1
我通过弄清楚交叉点的工作原理,并确定碰撞向量方向所在的象限来解决了这个问题。
在x或y方向上的绝对位移最小值确定了玩家从哪一侧撞到角落。 这样做起作用,所以我很高兴 :).
我还很好奇一个数学高手是否能在不做出所有这些假设的情况下做到这一点,并使用一些聪明的向量技巧。
英文:
I solved it by figuring out how the intersection points work and determining the quadrant of the collision vector's direction.
The smallest absolute displacement in either x or y direction determines from which side the player bumps into the corner. It works, so I am happy :).
Still very curious if a math wizz could do this without all these assumptions, and use some clever vector tricks.
@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);
}
}
答案2
得分: 0
首次尝试在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);
}
英文:
First time I try something for the game in Flutter. Could you please try this code for your need?
@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);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论