如何在Flutter Flame中处理角落上的角色碰撞

huangapple go评论121阅读模式
英文:

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.

如何在Flutter Flame中处理角落上的角色碰撞

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&lt;Vector2&gt; 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);
}

huangapple
  • 本文由 发表于 2023年7月11日 03:47:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76656884.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定