我看了几个教程,并try 将onCollision方法的代码组合到我的Player类中.辅导人员的解释很好,但我仍然不明白它到底是如何工作的.Vector2中间表示中间,如下图所示

enter image description here

直观地说,我可以理解如何获得重叠部分的长度(图片中的x)并将其添加到代表玩家位置的Vector2上,这样玩家就不能通过平台行走/摔倒/ skip .然而,有些Vector2数学超出了我的能力范围.我已经通读了这description of linear algebra for game dev行代码,它有概念行规范化,但在应用它来具体理解这些代码行时遇到了困难:

    Vector2 collisionNormal = absoluteCenter - mid;
    final seperationDist = (size.x / 2) - collisionNormal.length;
    collisionNormal.normalize();
    if (Vector2(0, -1).dot(collisionNormal) > 0.9) {
      _isOnGround = true;
    }
    position += collisionNormal.scaled(seperationDist);

有没有人能帮我理解这个问题,或者在游戏开发中,这个问题是如何为平台解决的?

我的播放器类(onCollision方法是相关部分):

class Player extends SpriteAnimationGroupComponent with HasGameRef<Gain>, KeyboardHandler, CollisionCallbacks {
  String character;
  Player({pos, this.character = "Ninja Frog"}) : super(position: pos);

  final double stepTime = 0.05;

  ...
  @override
  void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
    if (other is Platform) {
      if (intersectionPoints.length == 2) {
        Vector2 mid = (intersectionPoints.elementAt(0) + intersectionPoints.elementAt(1)) / 2;
        Vector2 collisionNormal = absoluteCenter - mid;
        final seperationDist = (size.x / 2) - collisionNormal.length;
        collisionNormal.normalize();
        if (Vector2(0, -1).dot(collisionNormal) > 0.9) {
          _isOnGround = true;
        }
        position += collisionNormal.scaled(seperationDist);
      }
    }
    super.onCollision(intersectionPoints, other);
  }
}

我的平台类代表游戏的墙壁、地面、天花板:

class Platform extends PositionComponent with CollisionCallbacks {
  bool canJumpThrough;
  Platform({required Vector2 position, required Vector2 size, this.canJumpThrough = false}) : super(position: position, size: size);

  @override
  FutureOr<void> onLoad() {
    add(RectangleHitbox(collisionType: CollisionType.passive));
    return super.onLoad();
  }
}

推荐答案

这是从球的中心指向两个交点中间点的向量:

Vector2 collisionNormal = absoluteCenter - mid;

这将获得从中间交点到球底部的距离,即球与平台重叠的程度:

final seperationDist = (size.x / 2) - collisionNormal.length;

这将使长度为1的collisionNormal向量,但仍指向同一方向:

collisionNormal.normalize();

他们正在做的这一部分可能是为了能够在本教程的后面部分确定碰撞来自哪个方向. 这里的collisionNormal(如果平台总是在我们下面,并且我们在碰撞前不会超出球的中心)将始终是Vector2(0, -1)(如果我们不在Y轴翻转的屏幕坐标系中,它将是Vector2(0, 1)).

这里的dot乘积是用来确保碰撞是从下面来的,如果collisionNormalVector2(0, 1),那么球就会从上面击中什么东西,点积应该是-1,而不是现在的1.

if (Vector2(0, -1).dot(collisionNormal) > 0.9) {
  _isOnGround = true;
}

在这里,他们调整位置,使球再次在平台的顶部,而不是在它的内部. 他们通过将其与collisionNormal相结合来调整位置,collisionNormal乘以(zoom )到碰撞点(separationDist)中间的长度.

position += collisionNormal.scaled(seperationDist);

因此,如果球的中心在(1,1),交点的中间(1,2),球的半径为2(大小为x/2),则碰撞法线将为(0,-1),分离距离为1,此计算将为:

(1,1) += (0,-1)*1
(1,1) += (0,-1)
(1,0)

因此,因为球的锚是中心,所以它的中心位置现在应该是Vector2(1,0),它的底部只是接触地面而不重叠.

Flutter相关问答推荐

飘动的文本用/字符绕转

当MyChangeNotifier更改时如何计算函数,而无需在构建方法中进行不必要的调用- Flutter

自动测试Flutter应用程序进行QA的最佳方法是什么?

如果文档确实存在,则FiRestore将";False";返回到";if-Document-Existes";...还是我说错了?

如何在WidgetRef引用外部的函数中使用Riverpod刷新数据

出现异常.RangeError(RangeError(index):无效值:有效值范围为空:0).分度误差

如何在容器小部件中的图像旁边添加文本?

在Flutter 小部件测试中找不到框中的AssetImage装饰

创建仅定义导出的文件是否有意义?

Dart 和 flutter 错误无法在您的 PATH 中找到 git

如何从列表中更新provider变量:Flutter列表和Provider优化指南

允许文本小部件在容器之间溢出

如何计算 Firestore 集合中的文档数量?

使 Row 中的元素保持在中间的空间,如果它们太大,则将它们包裹起来

我的第一个 flutter 项目出错,启动时为空值?

如何在 Flutter 中测试动画图标

如何在 flutter 中使用带有有效负载数据的重定向来执行 firebase 推送通知.?

Listview 如何转到下一行/新行?

有没有办法为文本中的下划线创建自定义样式?

将 onSaved(value) 从自定义 TextFormField 小部件传递给另一个?