游戏引擎学习第50天
仓库: https://gitee.com/mrxiao_com/2d_game
Minkowski 这个算法有点懵逼
回顾
基本上,现在我们所处的阶段是,回顾最初的代码,我们正在讨论我们希望在引擎中实现的所有功能。我们正在做的版本是初步的、粗略的版本,涵盖我们认为游戏正常运行所需的所有内容。这样一来,我们就有了一个基础框架,可以观察它如何工作,并确认每个部分的基本需求。
接下来,我们将根据这些代码做更加高效、工业化的版本。首先,我们还需要确保其他部分的代码已经就绪,这些代码可以在构建新组件时帮助我们确保整体功能的协调。这样,当我们开始开发新组件时,就能够以高质量的版本来实现,而不是脱离其他部分单独开发,因为在真空中开发往往会忽略与其他部分的接口,容易出错。
目前,我们已经达到了目标,碰撞系统已经基本运行了,比预期更好,尽管它可能没有预想中那么温和。接下来,我会为系统添加更多的特性,再进行一些调试,直到我们达到一个理想的版本。之后,最终版本会整合所有特性和功能。
另外,我们还需要添加一些东西,这些东西被认为是相对重要的,比如基础的颜色和纹理,这也是接下来要处理的内容。
好了,我们开始吧。
今天要做的事:滑行/滑冰和基于区域的碰撞检测
以下是内容的中文总结:
今天的目标有两个:
- 实现滑翔功能。希望能够沿着边缘滑动,而不是停下来。
- 实现基于区域的功能,这一点非常重要。现在角色的基础坐标只是bottom的位置,我们不希望它穿透其他物体。
首先,滑翔功能可能会比第二个功能更具挑战性,因为滑冰的数学原理已经讲解过了,所以可以比较容易地理解要做什么。现在需要讨论的是如何实现基于区域的功能。如果实现基于区域的功能需要花费大部分时间,那么滑翔功能可以推迟到周一来处理。
滑翔的实现并不会像预期的那样需要大量投入,因为数学原理已经处理过了。这不是一个巨大的挑战。
到目前为止碰撞检测回顾
我们曾经采用的方法是在碰撞检测中,只检查角色是否与墙壁发生接触,基本上是每一帧检查角色是否处于某个位置,并判断是否与其他物体发生碰撞。这样的方法有问题,因为它不能实现滑行效果,并且可能会导致类似隧道效应的问题(角色穿越物体)。此外,这样的方法也存在其他问题。
因此,决定改用一种新的方法,计算角色碰撞的具体时间点,即求解碰撞的交点。这样的方法可以让我们知道角色是否与墙壁发生碰撞。
为了简化计算,我们将碰撞检测简化为检查一条线段,假设角色只与四面墙发生碰撞。在这种简化的假设下,角色仅被视为一个点,而不是有面积的实体。这样,角色被认为沿着一条直线移动,这就是我们目前正在测试的情况。
接下来,我们需要讨论如何将其扩展,使角色不再是一个点,而是一个有面积的实体。
基于区域的碰撞检测(Minkowski 和积/差)
为了简化问题,我们将角色的形状设定为矩形,因为这样可以更容易实现。尽管实际上,我们讨论的理论对于不同形状是相同的,无论角色是矩形、圆形还是其他形状。然而,在实现时,不同的形状会需要使用更强大的算法进行处理。
接下来要讨论的内容是Minkowski算法,或者说是与Minkowski有关的差异。虽然Minkowski的工作非常重要,但并没有深入学习他的代数知识和形状处理方法。尽管如此,理解这些内容可以带来很多有趣的可能性,如果能深入理解这些概念,将能够在实际的碰撞检测中得到很大的帮助。
关于Minkowski的具体工作,简化地说,主要是用来进行碰撞检测的工作原理。在理解了这些内容后,我们将能够更好地进行游戏开发,尤其是在处理不同形状的碰撞时。
Minkowski是一个数学概念,通常用于几何和碰撞检测领域,尤其是在计算机图形学和物理模拟中。最常见的是Minkowski和(Minkowski Sum)和Minkowski差(Minkowski Difference)。这些概念广泛应用于形状组合和碰撞检测的计算中。下面是对它们的简要说明:
1. Minkowski 和(Minkowski Sum)
Minkowski和是两种几何形状(如多边形、圆形、矩形等)的"组合"。具体来说,它是通过对其中一个形状中的每一个点与另一个形状中的每一个点相加,生成一个新的形状。
- 定义:给定两个几何形状 A A A 和 B B B,Minkowski和 A + B A + B A+B 是由形状 A A A 中的每个点与形状 B B B 中的每个点相加所形成的所有点的集合。
- 公式:
A + B = { a + b ∣ a ∈ A , b ∈ B } A + B = \{ a + b \mid a \in A, b \in B \} A+B={a+b∣a∈A,b∈B}
其中, a a a 是形状 A A A 中的一个点, b b b 是形状 B B B 中的一个点, a + b a + b a+b 是两个点的向量和。
应用:在碰撞检测中,Minkowski和常常用来处理两个物体的碰撞。通过将两个物体的形状合并,可以更方便地判断它们是否发生碰撞,尤其是当物体是复杂形状时。
2. Minkowski 差(Minkowski Difference)
Minkowski差是另一种几何运算,它描述了两个形状之间的“差异”。它的结果是一个新形状,其中的每个点表示一个从一个形状(例如,物体1)到另一个形状(例如,物体2)的相对位置。
- 定义:给定两个几何形状 A A A 和 B B B,Minkowski差 A − B A - B A−B 是通过将形状 A A A 中的每个点与形状 B B B 中的每个点相减所形成的所有点的集合。
- 公式:
A − B = { a − b ∣ a ∈ A , b ∈ B } A - B = \{ a - b \mid a \in A, b \in B \} A−B={a−b∣a∈A,b∈B}
其中, a a a 是形状 A A A 中的一个点, b b b 是形状 B B B 中的一个点, a − b a - b a−b 是两个点的向量差。
应用:在碰撞检测中,Minkowski差常用于判断物体是否相交。当Minkowski差的结果包含原点时,说明两个物体发生了碰撞。它有助于简化复杂形状的碰撞检测,特别是在GJK算法中广泛应用。
3. Minkowski 和与碰撞检测
Minkowski和和差在碰撞检测中的应用非常重要,尤其是在处理复杂形状(例如多边形、圆形、凸形状)时。在这些应用中,通常会使用如下技术:
- GJK(Gilbert-Johnson-Keerthi)算法:这是一个基于Minkowski差的碰撞检测算法,用于判断两个凸形状是否相交。通过不断缩小搜索空间,GJK算法能够有效地检测复杂形状之间的碰撞。
- EPA(Expanding Polytope Algorithm):当GJK算法确定物体相交时,EPA可以进一步计算出碰撞点和最小穿透深度。
4. 应用实例
- 圆形与矩形的碰撞:可以通过计算Minkowski和将圆形和矩形合成一个新的形状,然后通过计算这个合成形状是否与其他物体相交,来检测它们之间的碰撞。
- 滑行与碰撞:Minkowski和也用于滑行和边缘检测,例如当角色沿墙滑行时,Minkowski和可以帮助确保角色和墙之间没有重叠,避免穿透和错误的物理表现。
总结
Minkowski运算在碰撞检测中是一个非常强大的工具,尤其是在处理复杂形状和高效碰撞检测算法时。它通过将形状转换为更加简单的几何形式(如线段、矩形、圆形等),使得碰撞检测过程变得更加可控和高效。
示例:玩家大小穿过两个方块
我们讨论了如何将碰撞检测从点到具有实际尺寸的对象进行扩展。假设有两面墙,中间有一个缺口,墙的大小可以用一个维度来表示。为了简化问题,我们将墙的尺寸看作是方形的,而每个墙的“半径”定义为某种形式的维度。我们还假设一个人物对象,它有一个半径 r r r,并且我们希望它通过这两个墙之间的缺口。
如果按照传统的碰撞检测方式,即将人物看作一个点进行检测,那么当人物缩小到一个点时,它可以通过缺口,这是没有问题的。但是,如果人物有实际的尺寸(即它的半径为 r r r),那么显然它无法通过这个缺口,因为缺口小于 2 r 2r 2r。因此,简单的点碰撞检测方法无法处理具有实际尺寸的对象。
问题在于,如何进行碰撞检测,使得我们不仅能够验证物体是否会碰撞,还能模拟物体沿路径的连续运动。为了做到这一点,我们需要考虑代数形式的解决方法,这涉及到用代数运算来判断物体是否会与墙壁发生碰撞,并能够处理物体的实际尺寸。
这个方法的核心是扩展传统的点碰撞检测模型,将物体的尺寸纳入计算,从而能够处理具有实际物理尺寸的对象。这种方式让我们能够不断沿路径进行碰撞检测,并确保物体不会穿透任何障碍物。
Minkowski代数介绍:形状代数
我们讨论了如何在碰撞检测中处理具有实际尺寸的物体,而不仅仅是一个点。为了简化问题,假设有一个形状,我们可以将其看作是一个点,并尝试将碰撞检测应用于这些形状。假设墙壁的尺寸有一个半径 s s s,而物体本身也有一个半径 r r r。通过这种方式,物体将不再是一个点,而是一个具有实际尺寸的对象。
为了解决这个问题,我们采用了一种方法:通过对形状进行扩展,使得它们能够像一个矩形一样移动。这意味着我们将物体的形状扩展到它的周围边界,这样在进行碰撞检测时,物体就可以像一个矩形一样与其他形状交互。
具体来说,我们通过想象一个矩形扫过整个形状,生成一个新的形状。这种扩展形状的方法让我们能够更好地模拟物体的实际尺寸,并进行碰撞检测。通过将物体的“半径”加到墙壁的尺寸中,我们可以生成一个新的形状,并通过这个新的形状来检查碰撞。
这种方法解决了以前单纯使用点进行碰撞检测时的限制,让物体能够沿路径移动,同时避免穿越任何障碍物。通过这种方式,我们不仅可以避免物体与墙壁重叠,还能确保物体沿着路径顺利通过这些障碍。
总之,使用这种基于形状扩展的碰撞检测方法,我们能够实现更精确的物理模拟和更可靠的碰撞检测,从而更好地处理具有实际尺寸的物体。
回到 Minkowski 和积:矩形 + 圆形
我们讨论了如何将一个形状扩展成一个可以进行射线投射的点,通过这种方式,我们能更好地处理碰撞检测。具体来说,当我们希望将形状从一个实际的物体简化为一个点时,我们会通过“扩展”来为这个点创建一个类似于矩形的边界。为了更直观地理解这一过程,可以想象在形状周围扫一个圆形,这样就形成了一个带有圆角的矩形。
这种处理方式实际上是通过一种称为“Minkowski和差”(Minkowski sum and difference)的方法来实现的。我们将形状进行扩展,使其形成一个新的几何形状,这样在进行碰撞检测时,可以像处理矩形一样处理这些形状。这是通过将一个点的形状扩展到一定大小,模拟物体与其他物体交互的方式。
然而,虽然这个方法从概念上看起来是合理的,但实际上让计算机执行这一操作会非常复杂。尽管人类可以很容易地想象在形状周围扫一个圆形,问题在于如何用代码实际执行这一过程。
相似的形状
当处理 Minkowski 和时,如果两个形状完全相同,操作会非常简单。只需要扩展它们的半径即可。比如,如果有两个相同的矩形或圆形,将它们的维度相加,得到的结果就是将每个形状的边界扩展或增大。对于矩形来说,如果两个矩形相同,Minkowski 和就相当于扩展它们的半径,得到一个新的矩形。对于圆形,假设有一个半径为 (r) 的圆与一个半径为 (s) 的圆,它们的 Minkowski 和就是得到一个半径为 (s + r) 的圆。
这种方法在形状完全相同的情况下非常直观,操作简单,只需调整半径的大小即可得到合适的结果。
不相似且复杂的凸形状:GJK算法
当遇到不完全相同的形状时,Minkowski 和的计算会变得更加复杂。例如,如果一个矩形和一个圆形相加,得到的形状就比单一的矩形或圆形更复杂。为了处理这种情况,可能需要使用专门的射线投射算法或者将这些形状组合成一个复合形状,然后进行碰撞检测等操作。
对于复杂的形状组合,尤其是非凸形状,可以采用将形状分解为凸块的方式。通过将复杂的形状拆解为凸形状,可以利用较为高效的凸形状处理方法,比如凸形状的碰撞检测。常见的做法是使用如 GJK(Gilbert-Johnson-Keerthi)算法等,处理凸形状的碰撞检测和射线投射等问题。
对于大多数游戏,虽然可能不涉及过多的凹形状,但即便如此,考虑到复杂性,分解形状为凸块仍然是一个更高效的做法。这种处理方式也有助于提高碰撞检测系统的性能,尤其是在需要处理多边形、圆形等复杂对象时。
通过这种方式,复杂的形状可以通过合理的算法分解和优化,使得游戏中的碰撞检测更加高效和精确。
仅矩形的碰撞检测
在处理矩形和其他形状时,碰撞检测的实现其实并不复杂。通过增加半径或修改形状的周长,可以很容易地将形状转换为矩形,进而进行碰撞检测。例如,如果我们有一个圆形或矩形,我们可以通过加上适当的半径值,将其扩展成一个区域,然后再进行碰撞检测。这个过程中,通常需要将半径与物体的宽度和高度相结合,从而得到正确的碰撞区域。
在代码实现中,可以通过调整实体的半径,或直接增加某些“空白”区域来处理碰撞区的大小。这样就可以通过几行简单的代码,使得不同形状的物体都能够正确地进行碰撞检测。
虽然在一些情况下,可能会遇到复杂的错误或实现问题,但这些通常都可以通过逐步检查代码和逻辑来解决。通过确保每个步骤都被正确执行,可以有效避免错误并确保碰撞检测系统的正常运行。
最后,值得注意的是,碰撞检测不仅仅局限于简单的形状,实际上在处理复杂形状时,也可以通过将形状分解为更小的凸块来提高效率,这也是大多数游戏引擎和物理引擎中常用的做法。
考虑实体大小
在处理碰撞检测时,存在一个重要问题,即如何考虑实体的大小。虽然我们通常会根据每个瓦片的MinTile和MaxTile位置来循环遍历瓦片,但我们必须注意,实体的实际尺寸可能超出这些位置范围。实体可能会撞击距离当前位置更远的墙壁,因此我们不能仅仅考虑实体的中心位置或是碰撞框的简单边界,而需要计算出实体扩展后的真实影响区域。
为了确保正确处理这种情况,我们必须在循环遍历时考虑到实体的大小。具体来说,我们需要检查实体所在的MinCorner和MaxCorner,确定哪些瓦片会与这些扩展的区域发生重叠。这个步骤对于准确检测碰撞非常关键,特别是在处理具有较大尺寸的实体时。
当我们进行碰撞检测时,首先会根据实体的尺寸来确定它覆盖的瓦片区域。通过计算实体的大小在瓦片上的映射,我们可以扩展该区域,确保检测的瓦片包括实体实际可能碰到的所有区域。
通过这些改进,我们能够更准确地进行碰撞检测,避免漏检潜在的碰撞情况,也能提高游戏性能,减少不必要的计算。
碰撞的问题解决了不过还有粘性墙壁 问题碰撞之后不能动了
粘性墙壁出现
在碰撞检测过程中,出现了一些奇怪的现象。首先,发现实体在与墙壁碰撞时会变得很粘,这种情况比较令人困惑,尤其是在碰撞发生的另一边也是如此。开发过程中,预计会出现类似的行为,尤其是在较早期的碰撞检测机制中,这种“粘性”问题已经被考虑到并预期会发生。
一个可能的原因是,当前的碰撞检测系统可能依然使用了epsilon值来处理实体与墙壁的接触,导致其在碰撞时仍然被“卡住”。如果回忆一下,实体的位置应该是在墙壁附近,但实际上它被稍微移动了,使得在尝试沿着另一个方向移动时,它并不应该与墙壁发生碰撞。
该问题也涉及到实体的中心点偏移,特别是实体的高度绘制时并没有正确对齐。原本,实体的中心点应该是矩形的核心位置,而高度应该从该点开始进行计算,然而在现有的绘制方法中,高度被认为是从矩形的底部开始绘制的。因此,当实体与底部碰撞时,它的运动会停止,而碰撞检测系统将其视为半径值,这种处理方式并未完全符合预期。
解决方案的一个方向是,将碰撞检测方式调整为从实体的实际中心开始,而不仅仅是基于底部开始进行计算。这样可以使碰撞检测更为精确,同时能够更好地处理实体的宽度和高度问题。
总体而言,当前的碰撞检测系统中存在一些问题,但这些问题并非不可解决。通过进一步调整实体的中心位置和碰撞检测的算法,可以消除粘性问题,确保实体的运动更符合预期。
更改玩家的原点
在调整碰撞检测的过程中,首先,我们发现通过绘制实体时,当前的高度计算并不正确。具体来说,实体的高度应该从其中心点计算,而不是从底部开始。这是为了让碰撞检测能够正确处理,确保实体在碰撞时停止在合适的位置。
为了改进这一点,我们决定将高度调整为半个实体高度,确保实体的中心点与碰撞区域对齐。这样,碰撞时,实体能够按照预期的方式停止。尽管目前这已经是一个更正确的处理方式,但我们仍然认为需要进一步调整实体的尺寸,以更符合游戏的需要。
目前我们设定的实体高度并非实际的显示高度,而是为了碰撞检测所用的碰撞高度。实际的高度可能与此不同,因此我们还需要考虑实体的实际尺寸和碰撞检测的尺寸之间的关系。
我们可能需要重新评估如何定义和使用这些尺寸,尤其是在不同的游戏视角和视图下。最终,我们计划通过调整实体的宽度和高度,使其更符合实际需求,例如宽度设置为1,长度设置为0.5。这样,实体的尺寸更接近我们预期中的游戏角色外形,确保碰撞检测能够准确地反映实体的实际运动和停留状态。
总体来说,当前的调整使得实体的碰撞检测更加准确,尽管尺寸还需要进一步的优化,以确保符合游戏视角和预期的表现。
更多粘性墙壁调试
目前,区域碰撞已正常工作,但我们仍然遇到了“粘住”的问题,导致实体无法顺利移动。这似乎与速度更新有关,尤其是在实现滑翔功能之前。我们发现,碰撞检测器无法正确更新速度,导致实体停滞不前。具体来说,速度没有及时更新,因为我们在处理滑翔时并没有及时调整速度。
为了解决这个问题,我们首先检查了“最大瓷砖”设置,确保它能正确反映实体的实际运动。然而,问题仍然出现在碰撞检测和速度更新的同步上。当我们添加了对速度的处理后,问题得到了改善,但这并不是我们预期的最理想的解决方案。
在进一步测试中,我们确认,实际上如果我们继续实现滑翔功能,速度更新会自然而然地解决当前的困境。关键是,滑翔实现的完成可以自动修复现有的问题,而不需要额外的处理逻辑。总的来说,虽然我们发现了问题的根源,并尝试了一些调整,但最终的解决方案还是依赖于完成滑翔代码的实现。这使得整个过程更加简化,也证明了滑翔实现的重要性。
实现滑行
我们目前的工作进展良好,区域已经顺利运行,接下来要实现滑翔功能。
为了解决滑翔的实现问题,我们采用了类似之前的方法。基本的思路是,通过移除反弹速度,只保留剩余的速度来模拟滑翔。虽然逻辑和之前类似,但我们要将代码调整得更清晰。
首先,我们处理速度更新的方式,与之前的做法相同,只是这次我们通过内积运算来调整速度。这样,无论是否与墙壁发生碰撞,只要设置墙壁的法线为零,速度就能正确更新。
接下来,我们的重点是将墙壁的法线更新为击中墙壁的方向。对于墙壁的法线,我们选择一种通用方式,假设不管墙壁的倾斜程度如何,我们都会通过设置一个任意墙法线来更新速度。尽管现有的代码对水平和垂直墙面有效,但若涉及到斜墙时,代码可能需要做出相应调整。
另外,我们在测试时,通过设置不同的角度来验证法线的方向,以确保滑翔能在不同的情况下正确执行。通过这些调整,速度应该会得到正确的更新,从而使角色能够在游戏中顺利滑翔。
最后,通过验证,发现滑翔机制已正确运行。
碰撞时修正速度
我们现在需要解决最后一个问题。当玩家滑行时,速度更新并未完全停下,只有在玩家继续向墙壁靠近时,才会出现停止的现象。
为了解决这个问题,我们需要添加一个循环来持续更新速度,并修正与墙壁的碰撞。每次碰撞后,我们更新速度并继续移动,直到滑行的剩余距离完成。
我们通过迭代的方式来处理这个问题。初始时,我们计算出玩家的移动距离(delta),然后根据碰撞的情况不断调整这个距离。为了防止无限循环,设定了一个最大迭代次数,通常是4次。每次迭代后,我们会减少剩余的移动距离,并更新玩家的位置和速度。
在处理过程中,我们通过检查是否还存在剩余的滑行距离,来判断是否完成整个移动。当剩余的距离(t)降至零时,滑行过程结束。如果在多次迭代后,t未降到零,则说明滑行已完成。
每次碰撞后,我们更新玩家的位置并调整速度,使其不再试图穿越墙壁。这时,我们需要通过计算墙壁的法线,修正玩家的PlayerDelta,确保玩家不会再进入墙体。
最后,更新后的玩家位置和速度会被应用到游戏中,确保滑行效果达到预期。尽管目前仍然有一些细微问题,但基本思路和代码框架已经搭建完毕。
调试最终粘性错误
为什么英雄的头直径是1.5米?
英雄的头部大小设定为1.5米(即150厘米),在设计时可能是为了突出其风格化的外观。这个头部直径在游戏中的表现比较夸张,因为英雄的设计风格偏向于动漫风格,通常这种风格会使角色的头部比现实世界中的正常比例要大很多。尽管如此,这个比例显得有些不自然,与游戏世界中其他物体的比例相比显得过大。因此,考虑到角色的外观和游戏整体的美术风格,计划对英雄进行一定的缩小处理,以便让他与周围的环境更协调。然而,角色本身依旧会保持这种夸张的动漫风格,头部大小仍会显得较为突出。
如何用 Minkowski 处理凹形物体?
在游戏开发中,通常会有关于如何处理碰撞检测的讨论,尤其是对于凸多边形和凹多边形的处理。对于凸多边形之间的碰撞,使用“Minkowski”作为解决方案是一个非常有效的方法,这种方法也适用于处理凹多边形,只要通过适当的策略将其转化为多个凸多边形。在处理凹多边形时,尽管可能会面临计算成本较高的问题,但将凹面多边形拆分成凸面多边形依然是一种普遍且高效的做法。
对于三维游戏,碰撞检测技术依然可以应用相同的思想,尽管三维的额外维度带来了更高的复杂度。为了有效处理三维中的碰撞检测,可以将复杂的凹面形状拆分成多个凸面形状,这样在计算过程中可以更简化操作。
总体来说,碰撞检测的常见做法是将凹多边形分解为凸多边形,因为这样处理的计算会更加高效,并且适用于大多数场景和游戏环境。通过拆分凹形状,可以使用已有的凸形碰撞检测技术来简化问题处理。
资产的 alpha 通道是由艺术家创建的吗?
关于艺术资源的处理,阿尔法通道(透明度)通常是在艺术设计工具中自动生成的。在艺术家绘制图像时,阿尔法通道和颜色信息一起生成,这一过程是自动完成的。这样,源资产在生成时已经包含了所需的透明度信息,无需额外处理。
你做游戏已经多少年了?
做游戏开发确实是一项挑战,尤其是涉及到游戏引擎的编程时。这不仅仅是简单的实例化对象和依赖引擎来处理其余部分,更需要了解背后的复杂逻辑和技术。虽然有时这些任务对于初学者来说可能显得过于复杂,但通过手工实现这些功能,可以更清楚地看到其中涉及的每一个细节。即使你并不完全理解所有的内容,至少会对每一部分有更深入的了解,这将使你在未来的开发中更加得心应手。
学习游戏编程是一个艰难但非常有价值的过程,特别是对于那些想成为引擎程序员的人来说。这个领域不仅需要大量的理论学习,还需要通过实践来不断提高技能。由于学习曲线陡峭,游戏引擎程序员的数量相对较少,而且能够做到非常熟练的人更是凤毛麟角。掌握这些技能需要付出大量时间和努力,但最终能带来巨大的成就感和技能提升。
我通常只是希望帧率足够高,速度不会太快
在碰撞检测中,有不同的方式来处理物理计算,主要包括帧内迭代和时间步细分的方法。通过保持较高的帧率,可以确保物体的速度不会超过碰撞的大小,这是一个有效的解决方案。然而,如果物体的尺寸非常小,或者速度较快,则可能需要细分时间步,以确保每帧内都能正确地处理碰撞。这种方式虽然能解决问题,但可能会导致额外的计算开销。
另一种方法是通过将物理计算分解为更小的迭代步骤来处理碰撞,而不仅仅依赖于每帧一次的计算。这样做可以减少每帧需要处理的工作量,因为较高的帧率对物理计算的要求较高,可能会影响性能。通过在碰撞系统内部进行迭代,可以使计算集中在较小的循环范围内,这样在每次迭代时只进行最少的计算,从而提高效率。
总的来说,优化碰撞检测时,减少每次迭代内的工作量,尽量在较小的时间尺度内完成计算,并将其他部分推向更大的时间尺度,能有效提升性能。
你能用 Minkowski 算法处理旋转和对角线物体吗?
处理旋转碰撞时,存在不同的挑战,尤其是在动画旋转与静态旋转之间。对于静态旋转,传统的碰撞检测方法,如旋转矩形的碰撞,仍然有效,可以通过常规的几何方法进行处理。而当物体发生动画旋转时,问题就变得复杂,因为物体在旋转过程中会生成一个新的几何体形状(例如,一个矩形旋转后变成了一个八边形)。
在处理旋转的碰撞时,如果物体的旋转是在静态时间步内完成的,依然可以通过交叉测试来有效检测碰撞。这种方法通过计算物体旋转的“扫过体积”来处理碰撞检测。然而,对于动画旋转,问题在于旋转产生的形状可能变成凹形(例如,旋转过程中物体的边缘弯曲)。这种凹形无法像凸形那样直接进行有效的碰撞分解,因此必须通过进一步细分时间步来处理,增加了计算的复杂度。
为了应对这种问题,通常会简化旋转过程,只考虑旋转的开始和结束状态,而忽略中间的小幅度旋转。这样,碰撞检测可以通过简化的旋转角度来完成,这种方法在多数情况下效果较好。但如果需要完全精确地处理动画旋转,传统的旋转处理方法就无法适用,需要使用更复杂的算法或策略。
总体来说,动画旋转的碰撞处理非常具有挑战性,特别是在需要完全精确地模拟旋转过程中所有细节的情况下。为了避免复杂性,建议尽量将旋转细分为几个离散的方向进行处理,这样可以通过检查这些方向来简化碰撞检测。
是否可以制作一个让你在失败时继续的断言?
关于断言,理论上是可以设置断言使得在断言失败时程序继续执行。尽管目前没有这么做,但这是可以实现的,只是在当前的工作中并没有实施。将来可能会考虑在某些流中使用这样的策略,但目前来看,这在政治上并不重要。
如何表示一个大的横向卷轴2D世界?
在设计一个横向滚动的开放世界时,角色沿着地面行走,但不是平台式的跳跃或攀爬。对于地图的表示,瓷砖地图可能在垂直空间上会浪费,因此需要考虑如何优化。在分支路径的节点上,使用双链表可能会遇到性能问题。因此,可能的解决方案是使用类似平台游戏的稀疏方式进行布局。具体来说,可以通过稀疏地放置世界中的元素来实现,这种方式在生成世界时比较常见,也可能是最有效的方式。虽然目前尚不确定最终的实现方式,但很可能会更接近平台游戏的设计方式。
是否可以确定碰撞点?
已经在处理并确定碰撞点。当前的代码实现能够准确地确定碰撞发生的具体位置,这是通过精确计算完成的。这项工作在之前的一夜之间得以实现,并已成功应用。
看起来无法表示凸形物体是物理学中的一个主要问题
在物理引擎中,旋转通常不是最糟糕的问题。更常见的问题是接触检测,它通常比旋转更复杂且更难处理。虽然旋转是一个大问题,但它的非线性特性,尤其是在应用于接触时,才是真正棘手的部分。接触检测本身可能带来更多的困难,而旋转问题则更多是基于其对接触的影响。
我的意思是用通用的 GJK 算法确定碰撞点
在处理碰撞检测时,使用 GJK(Gilbert-Johnson-Keerthi)算法可能是最有效的选择。然而,手工编码的碰撞检测方法也可以作为替代方案,尤其是在特定情况下,像是通过手动编写碰撞逻辑来处理圆形、正方形和圆角矩形等形状的碰撞。虽然手工编码可能需要更多的工作,但它也能提供较高的灵活性和控制,能够处理复杂的碰撞检测和重叠测试。虽然不确定最终会采用哪种方法,但在某些项目中,手工编码方法曾经表现得非常好。
环路复杂度:代码中独立路径数的直接度量
直观地衡量线性独立路径的数量并不是计划中的分析内容,也没有打算进行这类分析。看起来所有的问题已经讨论完毕,暂时没有更多的疑问。
相关文章:
游戏引擎学习第50天
仓库: https://gitee.com/mrxiao_com/2d_game Minkowski 这个算法有点懵逼 回顾 基本上,现在我们所处的阶段是,回顾最初的代码,我们正在讨论我们希望在引擎中实现的所有功能。我们正在做的版本是初步的、粗略的版本,涵盖我们认…...
前端部署实战:从人工发布到全自动化流程
"又发错环境了!"周四下午,测试同学小李急匆匆地找到我。原来是开发人员手动部署时,不小心把测试代码发布到了生产环境。这已经是本月第二次类似的事故了。 回想起每次发布时的场景:手动打包、手动上传、手动替换文件...每一步都战战兢兢,生怕…...
JVM系列之内存区域
每日禅语 有一位年轻和尚,一心求道,多年苦修参禅,但一直没有开悟。有一天,他打听到深山中有一古寺,住持和尚修炼圆通,是得道高僧。于是,年轻和尚打点行装,跋山涉水,千辛万…...
如何用3个月零基础入门网络安全?_网络安全零基础怎么学习
🤟 基于入门网络安全/黑客打造的:👉黑客&网络安全入门&进阶学习资源包 前 言 写这篇教程的初衷是很多朋友都想了解如何入门/转行网络安全,实现自己的“黑客梦”。文章的宗旨是: 1.指出一些自学的误区 2.提供…...
易语言OCR证件照文字识别
一.引言 文字识别,也称为光学字符识别(Optical Character Recognition, OCR),是一种将不同形式的文档(如扫描的纸质文档、PDF文件或数字相机拍摄的图片)中的文字转换成可编辑和可搜索的数据的技术。随着技…...
【人工智能】基于Python的自然语言处理:深入实现文本相似度计算
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 文本相似度计算是自然语言处理(NLP)中的核心任务,广泛应用于搜索引擎、推荐系统、问答系统等领域。本文全面解析文本相似度计算的核心技术,使用Python中的spaCy和sentence-transformers库实现多种方法,包括基…...
基于wifi的火焰报警系统设计(论文+源码)
1 总体方案设计 在本次基于wifi模板的火焰报警系统中,整个系统架构如图2.1所示,其采用STM32F103单片机作为控制器,并结合DS18B20温度传感器,火焰传感器,ESP8266 WiFi通信模块,蜂鸣器,OLED液晶构成整个系统,…...
【第三节】Git 基本操作指南
目录 前言 一、获取与创建项目 1.1 git init 1.2 git clone 二、基本快照操作 2.1 git add 2.2 git status 2.3 git diff 2.4 git commit 2.5 git reset HEAD 三、 文件管理 3.1 git rm 3.2 git mv 四、Git 文件状态 5.1 工作目录 5.2 暂存区 5.3 本地仓库 5…...
GaLore和Q-GaLore:一种记忆高效的预训练和微调策略,用于大型语言模型(LLMs)
GaLore和Q-GaLore:一种记忆高效的预训练和微调策略,用于大型语言模型(LLMs) GaLore和Q-GaLore的设计背景、工作原理及其优势 设计背景 随着大型语言模型(LLMs)的发展,模型的规模和复杂性不断…...
免费开源了一个图床工具 github-spring-boot-starter
文章目录 第一步,新建一个SpringBoot项目第二步,在pom文件里面引入jar包第三步,配置你的github信息github.authorization1、进入github官网,登录账号,点击头像,选择setting2、选择[Developer Settings](htt…...
Android显示系统(13)- 向SurfaceFlinger提交Buffer
Android显示系统(01)- 架构分析 Android显示系统(02)- OpenGL ES - 概述 Android显示系统(03)- OpenGL ES - GLSurfaceView的使用 Android显示系统(04)- OpenGL ES - Shader绘制三角…...
python小课堂(一)
基础语法 1 常量和表达式2 变量和类型2.1 变量是什么2.2 变量语法 3 变量的类型3.1 动态类型特性 4 注释4.1注释是什么 5 输入输出5.1 print的介绍5.2 input 6 运算符6.1 算术运算符在这里插入图片描述6.2 关系运算符6.3 逻辑运算符6.4赋值运算符 1 常量和表达式 在print()中可…...
【原创教程】西门子1500TCP_UDP通信说明大全(下篇)
2.3.3 TRCV故障说明 通讯无法正常连接时,ERROR引脚和STATUS引脚得状态有助于我们判断错误得原因,根据下表得提示,快速排除问题。 2.3.4 TRCV使用 点击TRCV指令得右上角蓝色图标,打开开始组态画面,按照控制要求填写 EN_R:用于激活接收的控制参数,及何时使用TRCV的接收功…...
【报错记录】Ubuntu22.04解决开机卡在 /dev/sda5 : clean , *files , *blocks
一个愿意伫立在巨人肩膀上的农民...... 一、错误现象 本人的电脑安装Windows10和Ubuntu22.04双系统,一次训练中电脑死机无法开机,重启之后便出现如下错误,在网上寻找过很多方法均无效,在root下禁用了samba服务,也无济…...
JumpServer开源堡垒机搭建及使用
目录 一,产品介绍 二,功能介绍 三,系统架构 3.1 应用架构 3.2 组件说明 3.3 逻辑架构 3.3 逻辑架构 四,linux单机部署及方式选择 4.1 操作系统要求(JumpServer-v3系列版本) 4.1.1 数据库 4.1.3创建数据库参考 4.2 在线安装 4.2.1 环境访问 4.3 基于docker容…...
libilibi项目总结(17)Elasticsearch 的使用
这段代码定义了一个 EsSearchComponent 类,主要用于与 Elasticsearch 进行交互,执行一些基本的操作,如创建索引、保存、更新和删除文档,及搜索操作。以下是对每部分代码的详细解释: 1. 类的依赖注入 Resource privat…...
C++ 模版函数 函数模版 区别
C中,函数模板(Function Template)和模板函数(Template Function)是同一个概念,通常没有区分,但为了避免混淆,有时我们可以从不同的角度来看待它们。 1. 函数模板 (Function Templat…...
SpringBoot 3.4.x踩坑记录及解决方案(持续更新)
废话 最近使用JDK17Spring Boot3.4.0 做新项目遇到的一些坑,记录并且给出一些实际的解决方案 一、集成Mybatis Plus 3.5.9的问题 第一:不能只引入mybatis-plus-spring-boot3-starter依赖了,需要配合mybatis-plus-jsqlparser <dependenc…...
Linux文件属性 --- 七种文件类型---文件.目录、软硬链接、字符设备文件
目录 七种文件类型 1、普通文件和目录 2、链接文件 2.1硬链接 2.2软链接 3、字符设备文件 一、七种文件类型 Linux的文件属性中一共有以下七种类型 : 符号类型含义解释-普通文件纯文本文件(ASCII)和二进制文件(binaryÿ…...
C# 读取EXCEL的数据批量插入单个PDF里的多个位置
C# 读取EXCEL的数据批量插入单个PDF里的多个位置 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; usin…...
ARM Linux 虚拟环境搭建
一、目标 在没有arm硬件的情况下,使用QEMU模拟器,在PC上模拟一块ARM开发板,对ARM Linux进行学习。 二、搭建步骤 首先先有一个Linux 开发环境,我目前使用的是Ubuntu20. 首先安装qemu,qemu的官网:https:…...
【功能安全】安全确认
目录 01 功能安全确认介绍 02 安全确认用例 03 安全确认模板 01 功能安全确认介绍 定义: 来源...
LruCache(本地cache)生产环境中遇到的问题及改进
问题:单机qps增加时请求摘要后端,耗时也会增加,因为超过了后端处理能力(最大qps,存在任务堆积)。 版本一 引入LruCache。为了避免数据失效,cache数据的时效性要小于摘要后端物料的更新时间&…...
【21天学习AI底层概念】day8 什么是类意识?
类意识(Quasi-Consciousness) 是一个用来描述人工智能或复杂系统表现出的类似意识的行为或特性的概念。虽然这种系统不具备真正的意识(即主观体验、情感和自我觉知),但在外部表现上,它们可能表现出与有意识…...
PostgreSQL JSON/JSONB 查询与操作指南
PostgreSQL 提供了强大的 JSON 和 JSONB 数据类型及相关操作,适用于存储和查询半结构化数据。本文将详细介绍其常用操作。 1. 基础操作 1.1 JSON 属性访问 ->: 返回 JSON 对象中的值,结果为 JSON 格式。 SELECT {"a": {"b": 1…...
SamOutV2 0.18B模型发布
项目地址 SamOutV2 0.18B模型 采取 em参数共享在参数量减半的情况下将维度从1024 拉升到了1536sft 单论对话 loss 保持1.8如果未来匹配state 推理代码性能不变的同时推理任意长度使用资源空间保持不变 模型代码 import torchclass MaxState(torch.nn.Module):def __init__(…...
〔 MySQL 〕事务管理
事务代码目录 1. 设置事务隔离级别 2. 开启事务 3. CRUD操作 3.1 创建(Create) 3.2 读取(Read) 3.3 更新(Update) 3.4 删除(Delete) 4. 提交或回滚事务 5. 示例:…...
centOS定时任务-cron服务
最近在训练模型的过程中,经常会因为内存爆炸而停止模型训练过程,而且因为内存占满停止的训练进程甚至都没有任何的报错提示。 1、需要减少num_worker的数量,降低需要占用内存的数据数量 2、可以通过free -h监控内存的占用情况 3、可以通过lin…...
ubuntu22.04.5本地apt源部署
很多情况下,内网服务器无法连接互联网,这样如果原始系统只是最基本的下载安装包,因为存在依赖包不全的情况,难以对其进行更新及通过apt安装包 所以为解决不能联网的问题,首先先通过可以联网的机器制造好源,…...
CSS 实现带tooltip的slider
现代 CSS 强大的令人难以置信 这次我们来用 CSS 实现一个全功能的滑动输入器,也就是各大组件库都有的slider,效果如下 还可以改变一下样式,像这样 特别是在拖动时,tooltip还能跟随拖动的方向和速度呈现不同的倾斜角度,…...
【LeetCode每日一题】——220.存在重复元素 III
文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时空频度】九【代码实现】十【提交结果】 一【题目类别】 数组 二【题目难度】 困难 三【题目编号】 220.存在重复元素 III 四【题目描述】 给你一个…...
Git命令
目录 一、创建版本库 二、pwd 命令是用于显示当前的目录 三、通过命令 git init 把这个目录变成git可以管理的仓库 四、ll 五、添加文件和修改提交文件 1.创建文件test.txt --- 此刻文件在工作区(WorkSpace) 2.使用命令 git add test.txt添加到暂…...
2024第十六届蓝桥杯模拟赛(第二期)-Python
# 2024第十六届蓝桥杯模拟赛(第二期)-Python题解 # 自己改注释# -----------------------1------------------------ # def prime(x): # if x < 2: # return 0 # for i in range(2, int(x ** 0.5) 1): # if x % i 0: # …...
数据结构:Win32 API详解
目录 一.Win32 API的介绍 二.控制台程序(Console)与COORD 1..控制台程序(Console): 2.控制台窗口坐标COORD: 3.GetStdHandle函数: (1)语法: (2)参数: 4.GetConsoleCursorInf…...
Hive-4.0.1数据库搭建(可选配置用户名密码远程连接,涵盖切换为tez引擎)
一、hive搭建(所依赖的Hadoop集群参照文章:最新版hadoop-3.4.0集群安装和配置(目前论坛的都是老古董了,看我的准没错!!!)这里以三台服务器为例_hadoop 3.4安装-CSDN博客)…...
【从零开始入门unity游戏开发之——C#篇13】命名规范——驼峰命名法和帕斯卡命名法,函数(方法)的使用介绍
文章目录 一、命名规范1、**驼峰命名法(Camel Case)**用途: 2、**帕斯卡命名法(Pascal Case)**用途: 3、**C# 中命名约定的最佳实践**3.1 **类、结构体、接口、枚举、委托**3.2 **方法、属性、事件**3.3 **…...
Android 写排行榜,顶部前三
activity_step_rank.xml <?xml version"1.0" encoding"UTF-8"?> <FrameLayout android:layout_height"match_parent" android:layout_width"match_parent" android:id"id/fragment_parent" android:orientation…...
sql server一些冷知识
1. Sql Server冷知识 (1) 删除表内容的方法 truncate table 表名 (清除表记录,这个快) (2) 列出所有数据库 sp_redatabases (3) 存储过程的参数命名 参数一定要以开头&am…...
【功能安全】随机硬件失效导致违背安全目标的评估(FMEDA)
目录 01 随机硬件失效介绍 02 FMEDA介绍 03 FMEDA模板 01 随机硬件失效介绍 GBT 34590 part5...
【Qt】信号、槽
目录 一、信号和槽的基本概念 二、connect函数:关联信号和槽 例子: 三、自定义信号和槽 1.自定义槽函数 2.自定义信号函数 例子: 四、带参的信号和槽 例子: 五、Q_OBJECT宏 六、断开信号和槽的连接 例子: …...
二叉树、平衡二叉树、红黑树、BTree、B+Tree的区别
一、二叉查找树 二叉树具有以下性质:左子树的键值小于根的键值,右子树的键值大于根的键值。 如下图所示就是一棵二叉查找树, 对该二叉树的节点进行查找发现深度为1的节点的查找次数为1,深度为2的查找次数为2,深度为n…...
【Rust自学】3.1. 变量与可变性
3.1.0. 写在正文之前 欢迎来到Rust自学的第三章,一共有6个小节,分别是: 变量与可变性(本文)数据类型:标量类型数据类型:复合类型函数和注释控制流:if else控制流:循环 通过第二章…...
如何使用生成式AI实现跨领域内容生成
文章目录 引言生成式AI的基本概念定义与分类技术发展现状 跨领域内容生成的技术实现数据准备模型选择与设计训练策略 应用案例分析教育培训新闻媒体文化创意产业 实践建议确定明确的目标构建合适的团队持续迭代改进遵守法律法规 结论 引言 在当今数字化时代,信息的…...
ubuntu无网络图标无法上网解决方案
1.打开/etc/resolv.conf,在其中添加需要配置的DNS地址,根据自己的电脑情况配置IP和网关 # interfaces(5) file used by ifup(8) and ifdown(8) auto lo iface lo inet loopback#网卡2,双网卡的话eth0、eth1 auto eth1 iface eth1 inet stat…...
手写Redis分布式锁+RedisUtil二次封装
文章目录 1.手写Redis分布式锁1.RedisShareLockUtil2.使用方式 2.RedisUtil二次封装1.RedisUtil2.使用案例 1.手写Redis分布式锁 1.RedisShareLockUtil package com.sunxiansheng.redis.util;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springfra…...
APP测试中ios和androis的区别,有哪些注意点
一、运行机制不同 IOS采用的是沙盒运行机制,安卓采用的是虚拟机运行机制。 1、沙盒机制: 概念:沙盒是一种安全机制,用于防止不同应用之间互相访问 作用:就是存储数据,每个沙盒就相当于每个每个应用的系…...
Qt编译MySQL数据库驱动
目录 Qt编译MySQL数据库驱动 测试程序 Qt编译MySQL数据库驱动 (1)先找到MySQL安装路径以及Qt安装路径 C:\Program Files\MySQL\MySQL Server 8.0 D:\qt\5.12.12 (2)在D:\qt\5.12.12\Src\qtbase\src\plugins\sqldrivers\mysql下…...
Springboot中使用Retrofit
Retrofit官网 https://square.github.io/retrofit/ 配置gradle implementation("com.squareup.okhttp3:okhttp:4.12.0")implementation ("com.squareup.retrofit2:retrofit:2.11.0")implementation ("com.squareup.retrofit2:converter-gson:2.11.0…...
字体子集化实践探索
最近项目rust生成PDF组件printpdf需要内嵌完整字体导致生成的PDF很大,需要做压缩,但是rust的类库allsorts::subset::subset不支持windows,所以做了一些windows下字体子集化的尝试 方案一:node.js做子集化 fontmin 缺点是也需要集…...
统计一个目录下的文件及目录数量-linux010
要统计一个目录下的文件数量(包括子目录中的文件),可以使用以下命令: 1. 统计所有文件数量(包括子目录) 在终端中运行以下命令: find /path/to/directory -type f | wc -l 解释:…...