当前位置: 首页 > 知识库问答 >
问题:

冲突检测和响应的正确操作顺序是什么?

李锦
2023-03-14

我正在尝试制作一个2D游戏引擎,但我似乎无法让碰撞一直起作用(通常情况下,物体会卡住或相互穿过)。在不太深入代码的情况下,下面是我更新的顺序。

  1. 获取用户输入并更新玩家速度
  2. 保存每个实体的位置,然后移动速度/更新间隔单位
  3. 检查每个可移动实体是否与所有其他实体发生碰撞。如果图元与某物碰撞,则会将其移动到其旧位置,并为两个碰撞图元设置新的速度。

碰撞冲量在此函数中计算:

private static void CollisionImpulse(PhysicsEntity a, PhysicsEntity b)
    {
        var relative = b.Velocity.Vector - a.Velocity.Vector;
        var normal = Vector2.Normalize(relative);
        var e = Math.Min(a.Material.Elasticity, b.Material.Elasticity);
        var j = (-(1 + e) * Vector2.Dot(relative, normal)) /
                (Vector2.Dot(normal, normal) * (a.InverseMass + b.InverseMass));
        if (double.IsNaN(j)) return;

        var velocityA = normal * (float) (j / a.Mass);
        var velocityB = normal * (float) (j / b.Mass);

        a.Velocity.X -= velocityA.X;
        a.Velocity.Y -= velocityA.Y;

        if (!b.Movable) return;
        b.Velocity.X += velocityB.X;
        b.Velocity.Y += velocityB.Y;
        b.Position = b.OldPosition;
    }

这是检查碰撞的函数:

public override void Update()
        {
            foreach (var entity in Universe.PhysicsEntities)
            {
                if (entity.Equals(this) || entity.Collided) continue;
                CollisionResolution.ResolveCollision(this, entity);
                if (!Collided) continue;
                Position = OldPosition;
                break;
            }
        }

几天来,我一直在尝试调整代码,但我无法找出问题所在。我希望一些新的眼光可以揭示我的困境。

共有1个答案

冀景明
2023-03-14

第3步“如果实体与某物碰撞,它将移动到其旧位置……”有一个基本问题——因为您现在再次移动该实体,您需要针对该实体重新运行所有先前实体的冲突检测,否则您可能会导致重叠。

E、 例如,如果你有3个台球(A、B、C),你将所有3个球移动到它们所需的新位置到A'、B'、C'(在步骤2中)。现在对于步骤3,你检查A'B'和A'C'没有碰撞,它们也没有碰撞,但你检查B'C',它们确实碰撞,所以在你的解决方案中,你把B',C'移回B,C-但是现在技术上你可能已经移动了B和/或C,所以它现在与A相交。

要使您的第3步工作,您需要:

1)确保在开始时没有对象重叠,并且每当您在步骤3中检测到碰撞时,要么(a)在我们之前说过没有与这些对象碰撞的每个先前对象上重新运行碰撞,或者继续重新运行整个步骤3,直到最后一个循环中没有对象被重置。如果您有很多对象并且它们都开始相互重置,这可能会变得昂贵。

或:

2)不是每次都将对象重置到其最后一帧的“安全”位置,而是合力(因此是加速度,而不是速度)与对象渗透的程度有关。这在3D物理引擎中很常见,如果穿透过多,会导致对象爆炸。

另请注意,如果您在1帧中将物体移动得很远(例如,远超过其大小的一半),它可能会穿过另一个物体而不会发生碰撞重叠检测。这通常被称为子弹穿纸问题

 类似资料:
  • 短版 Spotify Android应用程序在最近的一个版本中引入了一个“设备广播状态”开关,我想在我的应用程序中接收那些广播。有哪些广播可用,我应该如何配置我的广播接收器? 我从Spotify应用程序本身中使用了设备广播状态开关,我很高兴该开关取消/激活了这些广播事件。 我现在遇到的问题是,这些信息似乎只是零星地发送。我接收playstatechanged事件(播放、暂停、下一个、上一个),但它

  • 问题内容: 如何检测两个元素是否发生冲突? 这两个div是简单的彩色框,彼此垂直,因此没有复杂的形状或角度。 问题答案: 一般思路-获得框的偏移量和尺寸,并检查它们是否重叠。 如果要更新,可以使用: 另外,请注意,您可以针对特定示例优化功能。 因为它们是固定的,所以您不必重复读取框的尺寸(就像我在代码中一样)。您可以在页面加载时读取它们(将其读取到变量中),然后仅读取变量 小盒子的水平位置不会改变

  • 我正在尝试为我的大学工作制作一个基于2D平台的游戏(在SFML)。我不是要求任何人为我编写一些代码,但如果有人能提供一些指示,我将非常感激:) 目前我有大约13门课,包括: BaseEntity(大多数游戏对象都是由此派生的) 玩家(继承自BE) 魔法宝石(玩家需要这些来通过关卡晋级) 平台 SolidBlock(从平台继承) 可以说,我已经构建了大部分的游戏“积木”--每个类都有自己的更新函数,

  • 我们的LinkedIn APP不再适用于V2的演变。我已经尝试了几次,但未能创建正确的令牌。我正在寻求帮助以创建正确的授权链接以获取令牌。应用程序的错误目前是“清空开放2访问令牌” 我创建了一个新的LinkedIn应用程序来取代我们的旧应用程序。我试着按照LinkedIn和微软的指示去做,但是我的努力产生了下面的错误 我最近的尝试是: https://www.linkedin.com/oauth/

  • 什么是REST API响应结构和布局的最佳实践? Scrath示例: 成功回应: 失败响应:

  • 我是pygame的新手,我做了一个屏幕边框检测,但它不起作用 并检查它是否接触到边缘 但如果我们使用它就会坏掉/播放器就会卡住 整个代码是