游戏引擎学习第75天
仓库:https://gitee.com/mrxiao_com/2d_game_2
Blackboard: 处理楼梯通行
为了实现楼梯的平滑过渡和角色的移动控制,需要对楼梯区域的碰撞与玩家的运动方式进行优化。具体的处理方式和遇到的问题如下:
-
楼梯区域的过渡:
- 在三维空间中,楼梯的形状是一个从下到上的坡道,通常用两个关键点表示:底部楼梯和顶部楼梯。玩家在进入楼梯区域时,系统需要根据玩家的位置和楼梯的高度变化,平滑调整玩家的高度,使其能够顺利上升或下降楼梯。
- 当玩家从楼梯的底部向上移动时,需要调整玩家的高度,使其按比例增加,直到达到楼梯的最高点;而当玩家从楼梯的顶部向下移动时,调整高度使其逐渐下降,直到到底部。
-
楼梯区域的具体实现:
- 玩家进入楼梯区域时,系统会检测玩家当前的位置,并根据楼梯的几何形状调整玩家的高度,使其沿着楼梯平滑移动。假设楼梯是斜坡形状,玩家的高度会根据位置变化而调整。
- 这种调整虽然在理论上可以实现平滑过渡,但在实际执行中遇到了一些问题。特别是当玩家速度较快时,玩家可能会“跳过”楼梯,即快速通过楼梯区域而未能正确地下降,这导致了物理上不真实的行为,像是“曲线跳跃”现象。
-
楼梯的速度和角色大小问题:
- 当前角色的速度和体型没有被很好地调整到与楼梯的比例上,这意味着角色在楼梯上的运动速度过快,导致未能准确地与楼梯的高度变化匹配。因此需要对角色的速度和大小进行调整,以便能够更精确地适应楼梯的大小。
-
玩家碰撞处理的问题:
- 现有的碰撞处理方式存在问题,主要是当玩家接近楼梯时,会由于地面检测的方式(即不断将玩家位置调整到地面)造成玩家位置被错误地处理。例如,玩家可能会一直被推到楼梯的下方,再被推回地面,这会导致玩家“卡住”或者始终无法正确进入楼梯区域。
- 这个问题的根本原因是,当前楼梯区域的碰撞检测并没有正确扩展到玩家进入区域的深度,因此玩家有时会被错误地放置在楼梯下方,导致无法进入楼梯。
-
实体边界的处理:
- 为了解决这些问题,需要对玩家实体的边界进行调整。实体的边界需要考虑到楼梯的具体尺寸和玩家与楼梯之间的交互方式。通过精确计算和调整边界,可以避免玩家进入楼梯时发生的不合理行为,确保碰撞检测和运动过渡更加流畅和自然。
sed
Blackboard: Z轴上的碰撞检测
当前的碰撞检测只在二维空间中进行,这意味着当玩家在移动时,如果有物体位于玩家的上方或下方,玩家仍然会与其发生碰撞。为了实现更自然的碰撞处理,需要对碰撞检测进行优化,确保物体在玩家上方或下方时不会与玩家发生碰撞,从而允许玩家能够通过物体的下方或上方自由移动。
具体的优化方案包括:
-
排除上下方物体的碰撞:
- 需要调整碰撞检测机制,使其能够区分物体是否位于玩家的上下方。对于位于玩家上方或下方的物体,应该将其排除在碰撞检测之外,这样玩家就可以自由地穿越它们,无论是从下方经过还是从上方通过。
-
改进工程实现:
- 需要对工程实现进行调整,确保碰撞检测不仅仅限于二维,而是能够在考虑上下方向的情况下进行。这样可以避免不必要的碰撞检测,从而提高系统的效率和准确性。
这种调整的目的是为了让玩家的运动更加流畅和自然,同时避免因不合适的碰撞检测导致的卡顿或不合理的行为。
Blackboard: 合理绘制
除了碰撞检测之外,还希望能够加入一些功能,使得绘制更加合理。这意味着需要改进渲染部分,使其能够根据场景和物体的实际位置进行更准确的绘制。这可能涉及到更精细的图形表现,确保物体在游戏世界中的显示效果更加真实和一致。
运行游戏展示多个可见楼层
目前,碰撞检测存在问题,导致两个楼层堆叠在一起,这在视觉上显得很混乱,很难理解。虽然还没有完成游戏的渲染部分,但需要提前规划一下如何在渲染中解决这个问题。当前的效果是,玩家进入楼梯时会碰到地面然后被弹回,这种情况看起来不自然,需要改善。
考虑到这一点,应该从基础的楼梯碰撞和地面处理做起。需要避免玩家进入地面并弹回的现象,思考如何让角色在楼梯上移动时显得更加平滑和合理。在这方面,还需要进一步的实验和调整,以确保碰撞和运动的处理更符合实际需求。
另外,尽管目前对游戏的渲染处理还没有进行很深入的设计,但至少需要思考如何在最终实现时让画面更加清晰,避免两个楼层在视觉上的重叠和混淆。
目前的关键挑战是如何处理玩家与楼梯之间的交互,并改善碰撞检测机制,使其能够更自然地处理楼梯上的上升和下降。
game_sim_region.cpp: 防止实体在地面上被重力加速
希望能够实现一个机制,当角色站在地面上时,不会因为重力而加速进入地面。换句话说,当角色站在地面时,应该有一个正常的力阻止角色向下加速,避免出现角色陷入地面的问题。角色应该能够平稳地沿着地面移动,只有在地面低于角色时,才会受到重力加速度的影响。
为了实现这个目标,考虑引入一个能量存储的机制,比如使用一个标志来表示角色是否当前处于地面上。这意味着在上一个时间步骤结束时,如果角色是站在地面上的,那么就不会应用重力加速度。这是一个简单有效的方案。
为了避免频繁地进行重叠检查,决定尽量减少重叠检查的次数,尤其是避免在每帧的开始和结束时都进行这些检查,因为这样做会浪费性能。可以通过快速检查的方式来确定角色是否接触到地面,从而决定是否需要应用重力。这种方法对于当前的游戏需求来说,应该是足够的,毕竟该游戏并没有过多依赖于重叠检查。
game_sim_region.h: 引入 EntityFlag_ZSupported
可以引入一个标志,例如“在地面上”(onground)或者“受支持”(supported),表示角色是否在垂直方向上受到支持。这个标志意味着如果角色在Z轴方向上有支持(即接触到地面),则不再应用重力。
具体来说,可以通过一个简单的标志检查来实现这一点,判断角色是否处于“受支持”状态。如果是受支持状态,就不应用重力;如果不是,则正常应用重力。这个标志检查可以通过一个设置好的标志进行处理,确保在角色没有接触地面时才会受到重力影响。
game_sim_region.cpp: 使用 EntityFlag_ZSupported
在这个实体的处理上,如果角色是Z轴受支持的状态,则不需要处理重力;如果没有Z轴支持,则正常应用重力。可以使用一个标志来表示是否受Z轴支持(例如“z supported”),并根据角色是否接触地面来调整这个标志。
每当角色接触到地面时,就会设置这个标志,表示角色已站在地面上;如果角色处于自由下落状态,则清除该标志。这样可以避免角色“下沉”到地面下,确保角色能够正确地沿地面运动。
这个方法通过设置和清除标志来帮助角色与地面交互,解决了角色穿透地面的问题,同时也避免了角色“掉进”地面的问题。接下来,检查这种方法是否能够解决之前遇到的楼梯问题,即是否需要调整楼梯的大小才能让角色正确地走上楼梯。
game.cpp: 移除楼梯高度填充
暂时移除这个标志后,问题仍然没有得到解决,导致结果并没有预期的那样工作。接下来需要检查具体的问题所在,可能是因为某些细节没有正确处理,因此还是没有达到预期的效果。为了解决这个问题,计划设置一个断点,专门调试角色(英雄)部分,看看是否能找到更具体的原因,从而确保实现正确的行为。
game_sim_region.cpp: 在 MoveEntity 中添加 BreakHere 变量
为方便调试,决定给自己设置一个简单的方法,以便随时在代码中设置断点。具体做法是,如果实体类型等于“英雄”,就能够触发断点,这样可以帮助更好地定位问题。
调试: 步入 MoveEntity 中的这一点
为了调试方便,使用了一种技巧,通过设置特定条件来触发断点,确保在调试版本中能够暂停代码执行,查看变量值等调试信息。这些条件在优化后的构建版本中会被编译器移除,不会影响性能。当前的调试目的是查看英雄角色的移动情况。通过检查重叠测试,确认了重力是否被正确跳过,且Z轴位置为零。发现角色的X、Y和Z坐标都为零,原因是摄像机一直在移动,并且角色位置被设置为零,始终位于摄像机的中心。因此,角色实际位置并未反映在调试中。
调试: 注意到 EntityFlag_ZSupported 仅在我们处于地面下方时被设置
问题在于,当角色不在地面下时,清除了“ZSupported”标志。这个清除操作导致了标志没有正确反映角色的地面状态,从而影响了重力的应用。
game_sim_region.cpp: 更改该 if 语句以包含地面
当前的问题是,当角色仍然站在地面上时,应该将角色视为“地面支撑”。之前的逻辑错误在于清除了这个标志,而当角色在地面上时,应该保留该标志。修正后的逻辑是,只有当角色的高度小于或等于地面时,才认为角色处于地面支撑状态。
调试: 步入这一点在 MoveEntity 中
问题出在角色和楼梯的碰撞检测上,发现角色的碰撞体积(entity)没有正确地设置高度,导致其在Z轴上没有深度。楼梯的碰撞体积也没有延伸到地面,造成无法正确检测到碰撞。这表明在处理三维碰撞时,缺少对Z轴深度的考虑,需要修复角色的Z轴设置,并确保楼梯碰撞体积正确地延伸到地面。
game.cpp: 给楼梯增加一些 Z 轴深度
发现问题的根源在于楼梯的碰撞体积(stairwell)没有正确设置Z轴深度,导致无法进行有效的碰撞检测。原本应该设置的代码行被意外删除了,造成楼梯区域没有正确包含需要检测的Z轴空间。
运行游戏并跳跃穿越楼层,发现现在我们与楼梯发生碰撞
目前存在的问题是角色可以通过跳跃无限向上浮动,导致楼梯区域的行为异常。这种现象与平台层的设计有关,平台层的处理方式导致了这种“漂浮”效果。为了修复这个问题,首先需要确保角色在上升和下降时更符合预期行为,特别是在上升时需要更加准确地把角色保持在楼梯的正确位置,而不是让角色漂浮下来。
game_sim_region.cpp: 指定另一个标准来确定何时希望保持固定在地面
在当前的设计中,当角色在地面上时,如果角色处于地面以下并且标记显示角色处于支持状态(例如“z支持”标记被激活),则会将角色“固定”在地面上,不允许它通过跳跃或其他动作离开地面。这样做的目的是确保角色在地面上时能够保持稳定,防止意外的漂浮或错误的加速度行为。这种方法能够帮助修复跳跃行为不当的问题,尤其是在上下楼梯时,角色应该始终保持在预定的地面位置,避免出现不必要的漂浮或跳跃。
game.cpp: 停止伙伴跟随我们
当前的设计中,角色(如伙伴)并不会主动进行碰撞检测或找到其他物体,而是保持在其当前的位置。此行为不包括角色主动寻找到达某些目标的位置,而是更多地依赖于角色在游戏世界中的静态表现,保持在预定的区域内。
在楼梯上上下行走
目前在楼梯系统中,角色的高度是根据其在楼梯中的水平位置来确定的。如果角色进入楼梯的最顶部,角色会立即上升到顶端。这种方式可能会导致玩家在接触到楼梯顶端时瞬间被推到最高点,进而影响游戏的流畅性。解决这个问题的思路之一是控制角色与楼梯的互动方式,避免这种“直接碰撞”导致的突然上升,可能考虑通过一些限制措施让玩家能够更自然地与楼梯进行交互。但也有可能为了游戏性,直接允许角色碰到楼梯顶部时立刻上升。
game.cpp: 让楼梯稍微长一点
为了更好地观察楼梯的互动效果,决定将楼梯的长度增加一些,并将其位置稍微调整。楼梯的高度增加到两块砖的长度,位置也调整到了更低的地方。调整过程中遇到了一些问题,比如楼梯被放置在门的上面,导致了冲突,因为系统不允许物体重叠在门的位置上。经过修正后,楼梯被调整为单块砖宽度,并且重新定位后可以顺利放置。
现在,楼梯长度增加后,角色可以顺利走上去,且在中间位置时,楼梯的高度层级会发生变化。整体来看,楼梯系统运行正常,效果也较为可靠。
运行游戏并演示传送到楼梯顶部
目前正在考虑改进楼梯系统的设计,以便让角色更自然地上楼而不是直接瞬移到顶部。可以通过将楼梯构建成由多个实体组成的方式来实现。具体来说,可以将楼梯设计成一个主实体,并为楼梯两侧添加两个额外的实体,一个用来阻止角色从下方穿过楼梯,另一个用来阻止角色从上方通过。这样做的目的是让角色能够从楼梯的中间进入,同时防止角色穿过楼梯的上下部分。
然而,问题在于,如果将这些实体设为墙壁,可能会导致角色的头部碰撞,因此需要对这些阻挡实体进行调整,使它们在适当的位置形成隐形墙,从而避免不必要的碰撞。
尽管这种方法看起来可以解决问题,但也有些矛盾之处,因为这种设计可能会过度增加楼梯系统的复杂性,使其需要特别的处理。最终是否采取这种方案仍在考虑中。
Blackboard: 考虑用多个组件构建楼梯
为了改善楼梯的设计,考虑将楼梯构建为由多个实体组成,其中包括一个主楼梯实体,以及两个其他实体,一个用于阻止角色从楼梯下方通过,另一个用于阻止角色从楼梯上方通过。这样可以避免角色直接穿越楼梯两侧,同时允许角色进入楼梯的中间部分。虽然这种设计可能会导致角色的头部与楼梯碰撞,但可以通过设置不可见的墙壁来避免这一问题。不过,是否采用这种方案还有些犹豫,因为这样会增加楼梯处理的复杂性,需要权衡是否值得这样做。
game_sim_region.cpp: 考虑在楼梯上进行预测碰撞测试
考虑在角色进入楼梯时限制其z轴高度变化。可以在角色移动过程中,通过碰撞检测来决定是否允许角色继续变化z轴高度。具体思路是,在每次碰撞检测中判断角色与楼梯的高度差,如果差距较小,允许角色继续移动,如果差距较大,则阻止角色继续上升或下降。
这种方式要求在每次碰撞检测后,计算角色和楼梯的高度差,并决定是否允许角色继续移动。虽然这个方法可以解决问题,但可能会使楼梯的碰撞检测逻辑更加复杂,需要评估是否值得增加这样的高度判断。
这个方法并不难实现,但仍需要考虑它是否是最合适的解决方案。
game_sim_region.cpp: 引入 TestWallNormal, TestHitEntity 和 SpeculativeCollide 来进行这些预测测试
为了处理楼梯的碰撞检测问题,首先提出了一个推测性的碰撞处理方法。基本的思路是通过模拟检测在碰撞发生时,角色是否能够通过楼梯。如果角色的高度差不大,且符合一定的步高限制,允许角色通过楼梯。如果步高差异太大,则阻止角色移动。
-
推测性检测:
- 在每次碰撞检测时,首先计算一个“测试位置”(
TestP
),这是角色在假设某个时间点上,如果发生碰撞时,会到达的位置。 - 然后通过一个名为
SpeculativeCollide
的函数来检查角色是否能通过这个测试位置与楼梯发生碰撞。如果检测到碰撞,就会更新当前的碰撞信息,如时间点tMin
和墙面法线WallNormal
,以及发生碰撞的实体HitEntity
。
- 在每次碰撞检测时,首先计算一个“测试位置”(
-
高度差检测:
- 在处理楼梯时,需要检查角色的高度差。如果角色的高度差小于一个设定的最大步高(例如 0.1 米),则允许角色通过楼梯。
- 计算方法是,通过比较角色当前的 Z 值与楼梯的地面高度差值,如果差值小于或等于步高,就允许角色通过。
-
碰撞规则的调整:
- 目前楼梯没有设置碰撞标志(即楼梯和角色之间只有重叠检测,而没有实际的碰撞检测)。为了允许角色通过楼梯,需要在楼梯对象中添加一个碰撞标志。
- 这样在处理碰撞时,如果遇到楼梯,会根据设定的碰撞规则判断是否允许角色通过。
-
停止碰撞处理:
- 在碰撞处理的过程中,如果角色与楼梯发生碰撞,应该允许角色继续通过,而不是停止。为此,需要在碰撞处理逻辑中添加一个特殊条件,识别是否是楼梯。如果是楼梯,则忽略碰撞停止的逻辑,允许角色通过。
-
遇到的问题:
- 在实际运行时,发现角色可以正常上下楼梯,但问题在于角色能否正确地进入楼梯。这个问题出在游戏开始时没有设置好楼梯的碰撞标志,导致检测时出现问题。
- 因此,需要确保在游戏开始时,楼梯对象已经具备正确的碰撞标志,以确保碰撞检测的正确性。
总结而言,通过增加推测性碰撞检测,调整楼梯的碰撞标志,改进步高判断等方法,可以让角色正确地在楼梯上移动,避免不合适的碰撞和阻止移动的问题。
调试: 步入 SpeculativeCollide,发现我们没有与楼梯发生碰撞
考虑对楼梯的碰撞处理进行改进,目标是限制角色在进入楼梯时的Z轴高度变化。为了实现这一点,可以在碰撞检测中加入一种“猜测性”碰撞逻辑,通过预计算角色在碰撞发生时可能的坐标位置,来判断是否允许角色继续移动。
具体实现步骤是:
- 碰撞测试:在碰撞检测循环中,首先进行一次“猜测性”碰撞计算,确定角色碰撞后可能到达的坐标。
- 高度差判断:在计算完成后,如果角色的Z轴高度变化较小(例如小于某个设定的“步高”值),则允许角色通过楼梯,否则阻止角色继续上升或下降。
- 标记碰撞:在完成碰撞检测后,调整角色的最终位置,确保角色只会在允许的条件下进入楼梯。
- 优化和调整:虽然这种方法可以限制不合理的高度变化,但它的实现比较复杂,需要针对不同情况进行适当调整。
这个方法可以解决角色进入楼梯时出现的Z轴跳跃问题,但实现时可能需要考虑楼梯的特殊碰撞逻辑,确保角色在移动过程中始终符合游戏的物理规则。
game_sim_region.cpp: 翻转 SpeculativeCollide 的逻辑
实际上,问题出在步幅设置的高度过高,导致了碰撞。最终的目标是要判断是否发生了碰撞,答案是当步幅过高时发生了碰撞。
运行游戏并发现楼梯表现符合预期,除了我们没有沿着楼梯滑行,以及现在我们没有与墙壁碰撞
现在应该能够上下走动,但不能直接走到顶部,这是不允许的。只允许在最底部和最顶部走动,这一部分工作得很好。然而,问题在于无法沿着它滑行,似乎还有一些怪异的现象,不确定具体原因。可能是碰撞检测出了问题,无法正常滑行。看起来现在不再与墙壁发生碰撞,这可能是一个bug。
game_sim_region.cpp: 调整 SpeculativeCollide 的逻辑
看起来,猜测性碰撞通常是有效的,但在楼梯这种情况下需要特殊处理。问题出在猜测性碰撞导致所有碰撞检测都无法正常工作,尽管在其他表面上滑行正常。现在无法滑行的原因可能与楼梯的特殊性有关。可能是因为在某些情况下,碰撞处理没有按预期进行,尤其是当碰撞标志被设置为false
时,可能会停止处理碰撞。
法向量设置错误
上下楼梯并注意到感觉很好
game.h: 处理待办事项列表
其实,处理这些碰撞检测问题相对简单。首先,想要做的是清理碰撞检测中的谓词,使规则更加简洁明了,方便理解。希望能够创建一套干净、清晰的标志和规则集,使特殊处理更容易理解。这可能涉及到将迭代过程集中处理,而不是在外部处理重叠等问题。
虽然目前已经解决了上下楼梯的问题,但渲染部分仍然需要处理。接下来,也许可以尝试在接下来的时间里做一些碰撞检测的工作。
game_sim_region.cpp: 在 sim_region 中添加 DefaultGroundLevel
问题在于,地面的位置依赖于相机的高度,z=0
只是相机所在的位置,这显然不对。正确的做法是将地面定义为始终处于一个固定的z
平面上。这个平面可以是堆叠在一起的多个z
平面,取决于不同的地面层级。虽然目前还不确定如何准确地确定地面的具体位置,但可以设定一个地面高度的参数,使得模拟区域中的地面始终按照这个参数来定义,并为其设置一个默认的地面高度。
game_sim_region.cpp: 根据 BeginSim 中的信息计算 DefaultGroundLevel
当获取到世界位置时,需要根据该位置来计算默认的地面高度。基于这些信息,应该根据地面高度来进行角色的移动。这样可以确保地面高度的正确性并根据当前位置进行调整。不过,这里可能会有一些复杂的情况,需要仔细处理。
Blackboard: 指定给定 sim 区域中的地面水平
问题的关键在于,地面高度并非统一的默认值,而是需要根据不同角色所在的具体地面层级来确定。在同一个区域内,不同角色可能处于不同的地面层级上,例如一个英雄站在高处,而怪物可能站在低处。因此,不能仅仅依赖默认的地面高度,而是需要根据每个角色的具体位置来确定他们的z
值。
要做到这一点,需要一个基于z
轴的基准,以便能够确定每个角色所在的地面层级。在这个基准上,可以计算角色在当前z
平面上的位置,进而判断他们处于哪个层级。具体来说,需要能够识别每个层级的高度,并根据角色的z
坐标判断他们的位置。这样才能正确处理每个角色的地面层级,并实现精确的碰撞和移动处理。
game_sim_region.cpp: 将 DefaultGroundLevel 重命名为 GroundZBase
核心思路是,需要一个类似“地面基准”的东西,来准确确定每个角色的地面层级。为了找出当前的地面高度,可以将角色当前位置的z
坐标截断,得到一个新的z
值,这个值代表角色所处的地面层级。通过这个“地面基准”,可以确定角色的底部支撑面,并据此确定其地面高度。这样就能清楚地知道角色站在哪个地面层级上,从而正确处理碰撞和移动。
Blackboard: 快速跳到正确的地面高度
在楼梯的处理上,简单的截断方法并不适用,因为当角色从楼梯上走下时,需要将其位置“吸附”到最近的地面层。对于这种情况,截断只对某些情况有效,但无法处理所有场景,特别是在角色走出楼梯时,地面高度应该根据具体情况进行调整。为了正确处理楼梯,应该在角色离开楼梯时,将其地面层级“吸附”到最近的地面层。如果角色走出楼梯或从楼梯顶部跳下来,我们希望角色的地面高度能够调整到接下来的有效地面,而不是简单地沿用旧的地面层级。
如果没有特殊的处理,角色可能会错误地“跳”到不合适的地面层,导致问题。因此,在处理楼梯时,需要加入智能的地面调整规则,确保当角色从楼梯顶端走下来时,能够正确地对接到下一个地面层。
game.h: 需要对地面高度进行概念化,以便相机可以自由地放置在 Z 轴上,并在一个 sim 区域中拥有多个地面高度
这部分处理确实很复杂,目前还没有找到一个理想的解决方案,而时间也所剩不多。因此,暂时先放下这个问题,将其作为待办事项。接下来的任务是需要明确地面层级的概念,确保相机可以自由地放置在z
轴上,并且在同一个模拟区域内能够处理多个地面层级。这是当前需要解决的主要问题。
运行游戏并注意到熟悉物和怪物错误地被吸附到我们的 Z 轴位置
目前已经存在一个与地面层级相关的bug。具体来说,当熟悉的角色和怪物一起向上移动时,它们被错误地“吸附”到z=0
,这意味着它们被认为是站在地面上。实际上,这两个角色应该保持在同一个z
层级上,而不是随着地面高度变化。因此,在解决这个问题后,角色的z
层级应该保持一致。这个问题非常重要,因为它影响到角色与环境的交互。除此之外,其他部分看起来都还好,没有特别奇怪的情况。
game.cpp: 根据 Z 轴高度调整实体位置
在渲染时,可以尝试通过调整z
值来改变物体的x
和y
坐标,以模拟不同层级之间的视觉效果。例如,可以为每个实体根据其z
位置应用一个“偏移因子”(例如z * 常数
),将这个因子应用到实体的x
和y
坐标上。这样,实体在不同的高度层之间会有更明显的区分,帮助更好地理解物体的位置关系。
这种方法可以让多个平面上的物体看起来有明显的上下层次,尤其是在可以看到透视的情况下。此外,这种渲染方法能够帮助识别物体是否处于玩家的上方或下方。然而,由于当前缺乏3D碰撞检测,无法直接通过碰撞判断物体的遮挡和交互,但这种渲染调整为后续实现3D碰撞检测提供了直观的视觉反馈。
我猜你们的引擎会管理任意高度的地面水平?你们真的需要这样做吗?像是向下投射攻击到一个怪物下面,听起来挺有趣的
总结一下,用户正在确保引擎能够支持任意的地面高度,适应不同的游戏玩法,包括处理楼梯、地面上的洞以及其他地形特征。主要工作集中在碰撞检测和响应方面,因为绘制部分相对简单。目标是确保引擎足够灵活,可以处理涉及地面互动的各种游戏场景。
为什么不直接使用 X 和 Y 屏幕坐标来检测 sim 区域?
正在探索使用屏幕上的 x 和 y 坐标来检测模拟区域,但不确定具体的实现方法或如何处理这一问题。
你是否也应该检查楼梯顶部的“阶梯步骤”?看起来你可以比在楼梯底部提前退出
发现当前在处理楼梯的碰撞检测时存在问题。现有的处理方法只检查玩家是否踏上楼梯,但并没有检查玩家是否能够从楼梯上离开。为了修复这一点,用户建议在玩家离开楼梯时,检查其 z 坐标,以确保玩家不会在未到达楼梯底部时就离开楼梯,进而防止楼梯出口提前触发。
你能否在黑板上做一个关于“实体位置系统”的概览吗?现在它已经“完成”了?我有些理解困难(希望你明白我的问题)
该系统的世界和实体位置管理采用了稀疏世界存储结构,目的是有效地存储和模拟一个大的世界。具体来说,世界被分割成不重叠的块(chunk),每块只包含实际存在的数据。这种方式避免了像传统的大型数组那样的存储浪费,使得即使世界呈现出长条或螺旋形等复杂形状,也能高效存储。
在进行模拟时,会选择一个特定的区域来进行处理,通常这个区域是围绕某个点,形成一个三维的框来模拟所有与之相关的实体和几何数据。这个框包含了摄像头当前可见的区域,并且还会包括一个更大范围的区域以进行模拟。实体在这些区域中的位置是以它们所在块的索引加上在该块内的偏移量来存储的。
模拟过程中,实体的位置是基于该块的中心点偏移来计算的,模拟结束后,将它们的位置数据重新写回世界。具体来说,实体的偏移量会根据新的块进行更新,如果实体迁移到新的块,需要将其从原来的块移除并放入新块,同时更新其相对于新块的偏移量。
总的来说,这种方法通过分块和偏移存储的方式,使得大世界能够高效存储和更新,同时保持较低的计算和存储成本。
为什么屏幕上绘制的东西的顺序有些杂乱(一些树木重叠,另一些则正常)?
问题出在屏幕上显示的顺序不正确,原因是尚未进行排序。
难道按照顺序绘制它们不是很简单吗——每一层从左到右,从上到下绘制实体?
虽然看起来按层次从左到右、从上到下绘制实体似乎很简单,但实际上还涉及到Z轴排序问题。绘制顺序不仅仅是按水平和垂直方向排序,还需要考虑实体的Z轴位置。当前的问题是,尚未进行排序,因此无法正确绘制。
排序的实现需要等到渲染阶段再进行,因为在那之前,必须先缓存所有实体的状态,之后才能进行排序。由于目前排序并不会影响其他工作进度,因此不急于实现排序,等到渲染阶段再处理更为合适。
不同楼层的东西看起来好像被上移了,是不是渲染时 Z 偏移造成的?
不同层次的实体在渲染时看起来有些偏移,是因为Z轴的偏移造成的。可以通过调整实体的偏移量来解决这个问题,避免实体在渲染时出现不必要的上移。如果不希望看到这种上移效果,可以通过修改偏移方式来实现,这样实体就不会被“推”上去。具体来说,通过调整Z轴的偏移量,可以控制实体的显示位置,从而避免这种问题。
这个问题的根源在于Z轴偏移量,因此可以通过调整来消除这种偏移效果,虽然目前尚未完全确定是否需要这样做,但这就是偏移现象的原因。
这会导致顶部的墙壁在相机锁定时被绘制在屏幕上方,而不是跟随角色吗?
这个问题可能会导致顶部的墙壁在摄像机固定时被绘制到屏幕上方,而不是跟随角色。虽然目前可能不完全确定如何处理,但可以通过调整相关设置来优化这一点。
至于墙壁的位置,确实还没有最终确定如何定位它们。随着更多世界构建工作的进行,应该能够更清楚地决定墙壁的正确位置和行为。
当你使用自定义内存分配器分配所有东西时,你仅将指针存储在栈上吗?
关于使用自定义内存分配器时,是否只使用栈来分配指针的问题,实际上,自定义内存分配器仍然可以用指针,只是分配的内存来源不同。栈内存和堆内存是两种不同的内存分配方式,栈内存通常用于局部变量,而堆内存则适用于动态分配的内存。自定义内存分配器的使用并不限制只能使用栈内存,它依然可以使用指针来操作自定义分配的内存。
你不担心三维会让实体的 AI 变得复杂,从而影响性能吗?
对于三维空间是否会使实体的AI变得复杂,进而影响性能的问题,实际上并不太担心。AI的调优通常相对简单,性能上也不会产生太大影响,尤其是当AI主要与玩家直接互动时。
问题的关键在于如何处理大规模的世界和其他不在玩家周围的实体。为了避免性能问题,如果需要模拟大量的其他实体,可以简化这些实体的AI。当玩家不与它们互动时,可以让它们执行更粗略的行为,不需要复杂的决策过程。这样可以在保证性能的同时,避免过多的计算负担。
你什么时候会切换回居中相机?看起来它没有出现在待办事项列表上
关于摄像机是否会切换回中心位置的问题,目前还没有明确的决定。已经展示过两种方式都能正常工作,因此不太需要再进行额外的测试。摄像机的对齐方式会根据游戏开发的进展进行调整,具体的设定将在游戏开发过程中通过实验来决定。
为什么要将块的原点设为块的中心,而不是设为其中一个角落?
将区块的原点设为区块中心而不是某个角落,并没有特别的理由。曾经使用过角落作为原点,但后来看不出任何非得使用其中一个的特别原因。一个可能的原因是,使用中心可以更容易地处理一些较大的实体。例如,如果实体跨越区块的边界或稍微插入区块内,使用中心作为参考点更直观,因为它不对称,而如果使用角落则更难以管理。总体来说,选择中心可能在某些情况下更方便,但从整体来看,这个选择可能是任意的。
抱歉让你不清楚。当你使用自定义内存分配器时,栈上除了指针之外还存储其他东西吗?
关于是否只能在栈上存储指针,实际上,栈不仅仅存储指针,还存储许多其他内容,比如屏幕上显示的所有东西。例如,界面上的坐标、状态信息等,都会存储在栈上。栈用于存储线程中的所有局部变量及临时数据。所以,并不是所有东西都只存储指针,栈的作用是存储各种数据,而不仅仅是指针。对于问题本身,可能并没有完全理解其含义。
如果相机足够远离玩家,玩家是否会进入像其他实体一样更简单的例程?
如果摄像机离玩家足够远,玩家是否会进入类似其他实体的简化流程,实际上不太可能发生,因为摄像机是设定为始终跟随玩家的。所以,即使摄像机远离玩家,这种简化的行为也不会发生。
可能的碰撞测试是否应该使用 TestHitEntity 而不是 TestEntity,还是它们是相同的?你能简要回顾一下 HitEntity 更改的流程吗?
在碰撞测试中,TestHitEntity
和 TestEntity
实际上是相同的。最初,碰撞检测只会直接设置被碰撞的实体,以标记是否发生了碰撞。然而,后来添加了一个中间步骤,通过“试探性碰撞”来检查碰撞是否有效,只有在验证通过后,才会正式记录碰撞结果。这样做是为了避免在初步检测到碰撞时立即确认结果,而是通过额外的检查来决定是否接受这一碰撞。
具体而言,当检测到初步碰撞时,会暂时记录这个碰撞,但不会立刻处理它。然后,系统会执行试探性碰撞,看看是否应该接受这个碰撞,如果试探性碰撞的结果表明可以继续处理,才会正式记录并处理这个碰撞。这种方式增加了一个层次,确保碰撞检测更为精确。
此外,对于楼梯的处理,当角色从楼梯上移动时,需要做进一步的处理。可以通过检查角色与楼梯的相对位置来判断是否允许角色上下楼梯。例如,只有当角色的Y坐标处于楼梯的开始和结束之间时,才能允许角色从楼梯上下。这种方式可以防止角色在楼梯的中间位置上或下楼,确保碰撞逻辑更合理。
然而,这样的处理需要额外的工作,尤其是楼梯的实际碰撞区域需要比绘制的宽度小,因为碰撞检测只会检查楼梯的内部区域。这个方法解决了在楼梯上或下楼时的行为问题,但仍然需要进一步改进,例如在楼梯的两端进行更多的限制,防止角色在不合适的位置上下楼。
你现在可以取消掉第一个 HitThis == true,避免进行其他检查
在讨论碰撞检测的优化时,有人建议可以通过在首次碰撞检查时直接跳过其他检查(即,如果HitThis
为true
,就不再做后续检查)。然而,这种优化并不成立,因为碰撞检测的目标是找到最早发生的碰撞。因此,不能跳过后续的碰撞检测,因为可能存在一个比当前碰撞更早发生的碰撞。为了确保计算最早碰撞,必须执行所有的检查,以确定最终哪个碰撞发生得更早。
总的来说,提前跳过碰撞检测的优化会导致结果不准确,因此这种优化不适用。
相关文章:

游戏引擎学习第75天
仓库:https://gitee.com/mrxiao_com/2d_game_2 Blackboard: 处理楼梯通行 为了实现楼梯的平滑过渡和角色的移动控制,需要对楼梯区域的碰撞与玩家的运动方式进行优化。具体的处理方式和遇到的问题如下: 楼梯区域的过渡: 在三维空间中&#x…...
Java 23 集合框架详解:Set 接口及实现类(HashSet、TreeSet、LinkedHashSet)
📚 Java 23 集合框架详解:Set 接口及实现类(HashSet、TreeSet、LinkedHashSet) 📖 概述 Set 是 Java 集合框架中用于存储 无序、不重复元素 的接口。它的实现类包括 HashSet、TreeSet 和 LinkedHashSet,它…...

ARMv8架构 CortexR52+ 内核 coresight_soc400介绍
前言:笔者在工作中接触到了一款多核芯片,其采用的处理器为CortexR52,使用的架构为ARMv8,我通过CoreSight SOC-400组件完成了对该芯片烧录代码的开发。这里芯片型号就不透露了,本文仅介绍我自己从ARM官网上提供的R52核等…...

1.Python浅过(语法基础)
1.简介 Python是一种面向对象的解释型高级编程语言,是强类型的动态脚本语言。 解释型语言跨平台性比编译型语言(如c语言)好。 print("hello world")2.Bug,Debug 多看,多思考,多尝试、查资料、记录 3.prin…...
ioremap_nocache函数
ioremap_nocache 是 Linux 内核中用于将物理地址映射到内核虚拟地址空间的函数,特别是用于 I/O 内存映射,并且禁用缓存。 一、基本语法 void __iomem *ioremap_nocache(phys_addr_t phys_addr, size_t size); 二、基本功能 将物理内存地址映射到内核虚拟…...

【235. 二叉搜索树的最近公共祖先 中等】
题目: 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一…...

构建智能企业:中关村科金大模型企业知识库的技术解析与应用
在数字化转型的浪潮中,企业对智能化知识管理的需求日益增长。知识作为企业的核心资产,其高效管理和应用对于提升企业运营效率和决策质量至关重要。中关村科金大模型企业知识库凭借其强大的技术架构和广泛的应用场景,成为构建智能企业的重要工…...

C++进阶——用Hash封装unordered_map和unordered_set
目录 前言 源码怎么说 为什么要兼容? 兼容的具体做法? 为什么要把Key转为整数(HashFcn)? 模拟实现 一、建立框架 二、迭代器 运算符重载 迭代器兼容大法 三、[ ]重载 四、实现不能修改key 实现及测试代码 …...

b612相机 13.5.5解锁会员hook
工具 lspatch(点击选最新版本下载) shizuku(点击选最新版本下载) SimpleHook(点击选最新版本下载) b612(自行百度下载) 效果图 教程 [{"packageName":"com.camp…...
iOS - 弱引用表(Weak Reference Table)
1. 基本数据结构 // 弱引用表的基本结构 struct weak_table_t {weak_entry_t *weak_entries; // 保存所有的弱引用对象size_t num_entries; // 当前存储的弱引用数量uintptr_t mask; // 哈希表大小掩码uintptr_t max_hash_displacement; /…...
C#语言的网络编程
C#语言的网络编程 引言 随着互联网的飞速发展,网络编程成为了软件开发中的一个重要领域。C#语言作为一种现代编程语言,凭借其丰富的类库、良好的可读性和强大的功能,广泛应用于开发各种网络应用程序。无论是Windows应用、Web应用还是云服务…...

【操作系统】课程 4调度与死锁 同步测练 章节测验
4.1知识点导图 处理机调度与死锁相关内容的文字整理: 基本准则 资源利用率:使系统中的处理机和其他所有资源都尽可能地保持忙碌状态。系统吞吐量:单位时间内系统所完成的作业数。公平性:使各进程都获得合理的CPU时间,而…...

如何查看已经安装的python版本和相关路径信息
如何查看已经安装的python版本和相关路径信息 本文目录: 一、通过命令行模式查询 1、通过命令where python 2、通过命令print(sys.executable) 二、在 Anaconda Navigator 中 三、只安装python的环境下 一、通过命令行模式查询 同时按windowR键,输入cmd&#x…...
设计模式-结构型-适配器模式
在软件开发中,随着系统的不断扩展和模块的不断增加,往往会遇到不同模块之间接口不兼容的情况。此时,如果我们能通过某种方式将一个接口转化为另一个接口,那么开发工作将变得更加灵活和高效。适配器模式(Adapter Patter…...
鸿蒙操作系统(HarmonyOS)
鸿蒙操作系统(HarmonyOS)是华为公司推出的一款面向未来、面向全场景的分布式操作系统。它旨在为用户提供一个更加智能、便捷和安全的操作环境,支持多种终端设备之间的无缝协作。在鸿蒙应用开发中,ArkUI作为官方推荐的用户界面开发…...

基于海思soc的智能产品开发(camera sensor的两种接口)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 对于嵌入式开发设备来说,除了图像显示,图像输入也是很重要的一部分。说到图像输入,就不得不提到camera。目前ca…...
解密LLM结构化输出:代码示例与原理分析
解密LLM结构化输出:代码示例与原理分析 一、LLM结构化输出概述 1. 结构化输出的定义与优势 结构化输出指的是语言模型(LLM)生成的遵循特定格式(如JSON、XML)的数据,这些数据易于解析和处理。相较于非结构…...
Go语言的数据类型
Go语言的数据类型详解 Go语言是一门具有简洁、高效并且强类型的编程语言。它的设计理念之一是让程序员能够以清晰、简明的方式表达自己的意图。在Go语言中,数据类型是其基础构建块之一,理解不同数据类型的特点和使用场景对于编写高效的Go程序至关重要。…...

复杂园区网基本分支的构建
目录 1、各主机进行网络配置。2、交换机配置。3、配置路由交换,进行测试。4、配置路由器接口和静态路由,进行测试。5、最后测试任意两台主机通信情况 模拟环境链接 拓扑结构 说明: VLAN标签在上面的一定是GigabitEthernet接口的,…...

如何很快将文件转换成另外一种编码格式?编码?按指定编码格式编译?如何检测文件编码格式?Java .class文件编码和JVM运行期内存编码?
如何很快将文件转换成另外一种编码格式? 利用VS Code右下角的"选择编码"功能,选择"通过编码保存"可以很方便将文件转换成另外一种编码格式。尤其,在测试w/ BOM或w/o BOM, 或者ANSI编码和UTF编码转换,特别方便。VS文件另…...

VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

vulnyx Blogger writeup
信息收集 arp-scan nmap 获取userFlag 上web看看 一个默认的页面,gobuster扫一下目录 可以看到扫出的目录中得到了一个有价值的目录/wordpress,说明目标所使用的cms是wordpress,访问http://192.168.43.213/wordpress/然后查看源码能看到 这…...