当前位置: 首页 > news >正文

游戏引擎学习第299天:改进排序键 第二部分

回顾并为当天内容做准备

我们会现场编写完整的游戏代码。回顾上周发现自己对游戏中正确的排序规则并没有清晰的理解。主要原因是我们更擅长三维游戏开发,缺乏二维游戏和二维游戏技术的经验,对于二维精灵排序、模拟三维效果的最佳方案等没有太多技巧和经验。

因此,今天的目标是专注于研究和理清二维游戏中的Z轴排序问题。我们希望通过深入思考,理解各种排序方案的权衡,找到在大多数情况下能够产生最佳效果且最少依赖临时解决办法的规则。

黑板讲解:瓦片的Z轴排序

目前我们关注的是在同一层内的排序问题,假设不同层可以单独排序。游戏中的房间被划分成若干离散的部分,这些部分会分别淡入显示。在一个具体的房间内,我们重点考虑瓷砖的排序方式。

开始思考时,我们想到了如何合理地对这些瓷砖进行排序,使得视觉上符合预期效果。重点是处理好瓷砖之间在同一层中的先后关系,而不是跨层排序。这样可以保证房间内部的图层渲染顺序正确,同时也方便整体房间在不同层之间进行排序和切换。

黑板讲解:从正上方俯视时如何进行排序

我们分析了从完全正上方(100%俯视角度)观察瓷砖时的排序规则。在这种视角下,我们可以非常清楚地知道,排序只需要根据物体的最高Z值来进行。因为瓷砖之间不会相互重叠,只会有高低关系,所以只要按照角色或精灵的最高点的Z值排序,就能得到正确的视觉效果。最高的Z点决定了哪个物体会被看到。

然而,情况变得复杂的是当摄像机稍微倾斜时。虽然在完全俯视时排序相对简单,但倾斜后物体会跨越多个瓷砖,导致排序不再那么直接。此时,我们可能会遇到精灵覆盖多个瓷砖的情况,不能单纯地按一个Z值排序。

尽管如此,大多数情况下还是可以通过对每个瓷砖和相关物体分别排序来解决问题。比如一个跨越多个瓷砖的地毯,在Z值排序中,地毯会相对这些瓷砖进行排序,任何Z值比地毯高的瓷砖会绘制在前,反之则绘制在后。虽然这可能导致一些看似不合逻辑的画面(比如地毯部分“穿透”瓷砖),但这是合理的渲染结果,因为如果地毯和瓷砖发生交叉,那就是模型本身的问题,而非渲染算法的问题。

总结来说,从正上方看,排序规则非常简单,只需按最高Z点排序;而倾斜视角带来了物体跨瓷砖的问题,但通过分别对每个瓷砖和物体排序,也能基本解决,虽然存在极少数不完美的边缘情况。

黑板讲解:相机倾斜带来的排序复杂性

问题的复杂性出现在我们不再是纯粹正上方观察物体,而是摄像机稍微倾斜的情况下。这样一来,单纯按最高Z值排序就不能保证得到正确的绘制顺序。

具体来说,虽然某个物体的最高Z值最大,按理应该最后绘制,但由于摄像机角度的变化,视线射线(viewing ray)会先遇到画面中靠前的物体,而后遇到靠后的物体。这样,单纯依据Z值排序会导致绘制顺序错误。

这个错误的原因在于,影响排序的关键维度不再只是Z轴,而是发生在Y轴方向上。假设摄像机是围绕X轴旋转的,实际上物体的距离远近更多取决于它们在Y轴上的位置。

之前尝试的解决思路是,既然摄像机倾斜,物体在Y轴上的位置其实反映了它们离摄像机的远近。最靠近的物体Y值较低,最远的Y值较高。因此,先按照Y轴从近到远排序,再按照Z轴排序,可能就能解决这个问题。

还可以进一步扩展这个排序规则,从物体离摄像机最近到最远,先根据Y值排序,再用Z值细化排序,这样有望得到合理的绘制顺序。之前对此考虑不足,这是现在需要补充和深入分析的地方。

黑板讲解:将实体量化到瓦片上

困扰我们的是,当游戏中有连续移动的实体时,排序变得复杂和混乱。因为这些实体的位置不断变化,很难判断某个实体相对于另一个实体应该如何排序。

为了解决这个问题,一个可能的办法是将实体的位置量化到它所处的瓦片(tile)中心。也就是说,在进行排序时,无论实体实际在瓦片内的哪个位置,都将其视为位于瓦片的中心点。这样,实体始终被归类到某个特定的瓦片列中进行排序。

在同一个瓦片列内,再按Z值升序排序,从而保证实体之间的正确绘制顺序。这个想法的灵感是在观察艺术资源时突然产生的,觉得或许可以解决连续移动实体排序难题。

关键点是,虽然视线会先遇到某些瓦片中的物体再遇到另一些瓦片的物体,但只要我们先将实体量化到瓦片中,然后在每个瓦片中根据Z值排序,就能较好地理清绘制顺序,避免排序混乱。

这意味着,为了让排序合理且易于管理,必须先把实体定位限制在瓦片级别,再在瓦片内进一步细化排序,这样才有可能得到一致且正确的视觉结果。

黑板讲解:地毯(Rug)问题

我们假设所有物体都被量化到瓦片大小,并且物体尺寸大致和瓦片一致,这种情况下排序应该是比较合理的。但问题在于,并不是所有物体都符合这个假设。

比如,有些物体会跨越多个瓦片,比如桌子或者地毯这样的地面覆盖物。特别是地毯这种东西,角色是可以站在它上面的,这样的物体就不能简单地被量化到单个瓦片中心去排序。

一种可能的量化方法是将这类跨瓦片的物体归到它最前面的瓦片去排序,不管具体是哪一个瓦片,关键是要和它前面的瓦片在同一行进行排序,因为X轴位置在这里是相关的。但是问题是,如果这样做,这个物体就会被绘制在后面那排瓦片的物体前面,这并不是我们想要的结果。

理想情况是,这种跨瓦片的物体应该覆盖后面那排瓦片的物体,但同时允许站在这些瓦片上的角色显示在它的上面,也就是仍然在视觉上覆盖住后面的瓦片但不遮挡站在其上的角色。

这个情况就很复杂,因为一旦涉及到跨越多个瓦片的物体,排序关系就变得难以用简单的规则表示。不能简单地说“这一堆物体都在前面,这一堆都在后面”,因为这些跨瓦片的物体实际上是在两个层次之间交叉,这种“交叉”的排序关系非常棘手。

我们可以尝试设计一种特殊的排序系统来处理这类情况,但理想的做法是找到一条智能的规则,能够合理且自动地处理这些跨越多个瓦片的物体,能够根据它们的空间关系正确地进行排序,而不是靠特殊处理。

总之,这个跨瓦片的排序问题非常复杂,现有的简单量化方案在这种情况下开始失效,需要更高级的思考和设计来解决。

黑板讲解:画家算法(Painter’s Algorithm)

我们想开始用更系统化的方法来考虑排序问题。想到的一种可能的思路是借鉴“画家算法”(Painter’s Algorithm),即排序时不仅仅简单比较Z值,而是考虑物体实际的空间形状和它们的平面如何延展,从而决定正确的绘制顺序。

具体来说,比如有一个平铺的物体,上面站着一个竖直的物体,我们可以通过知道这两个物体的Z坐标,以及它们所在的平面类型,来判断哪个应该先绘制,哪个应该后绘制。比如,竖直物体的高度随着向上延伸可能并不会变化太大,通过对平面方程的了解,我们可以更精确地进行排序。

这就回到了之前讨论的“竖直物体”和“非竖直物体”的分类问题。我们甚至可以进一步推广,给每个物体一个平面方程,根据这个方程来辅助排序。

不过,我们对这种方法是否划算持怀疑态度,感觉这条路可能比较复杂,且代价较大。我们希望能找到一种更巧妙、更聪明的排序方式,而不是简单粗暴地用物理平面计算来处理。

总之,这个思路在脑海中存在,但还不确定是否是最佳方案,仍需要进一步探索和尝试。

黑板讲解:地毯情况的多种场景

我们来详细列举一下关于地毯(rug)排序的具体情况。假设我们有四块地板瓷砖,分别标记为A、B、C、D,然后把一块地毯E放在它们上面,另外一个英雄角色F站在地毯上。理想的绘制顺序是从后到前依次绘制这些元素。具体来说:

  • A和B的绘制顺序相互之间不太重要,可以互换。
  • C和D的绘制顺序同样可以互换。
  • 但是整体排序需要保证A、B先绘制,接着是C、D,然后是地毯E,最后绘制站在上面的英雄F。

如果我们仅考虑按瓷砖分列进行排序,比如只看B这块瓷砖,那么排序规则依然成立,可以得到正确的局部顺序 B → E → F。

问题出现在C和D之间的排序。每个瓷砖内部的排序可能正确,但当试图将所有瓷砖的排序结果合并成一个整体绘制顺序时,可能出现冲突和矛盾。

举个更复杂的例子:假设一个3D视角中,块A竖直穿过地毯E,导致地毯和A相互穿插。地毯是平铺的,穿插的块A是竖直的实体,这会导致排序变得非常困难。因为:

  • 地毯E需要覆盖在C前面,
  • 但是在某些排序中,A可能被绘制在E之前,
  • 这就产生了不可能满足的排序冲突:E既要在C前面,又不能在A前面,这两者之间的顺序难以调和。

即使我们对每个瓷砖分别排序,整体合并时依然会遇到排序矛盾,导致无法确定一个唯一的正确绘制顺序。

可能的解决方案之一是把地毯“切割”成多块,分别排序。这虽然不一定是糟糕的主意,反而可能是合理的做法,但仍然增加了复杂性。

这也说明为什么很多2D游戏很少做复杂的3D排序。通常做法是:

  • 避免在地板上放置会导致穿插的覆盖物(比如禁止地毯跨越高低不同的地砖),
  • 或者根本不允许地板高度发生变化,
  • 这样只用简单的Z排序就可以解决问题。

总的来说,单纯靠Z值排序在完全顶视角下非常简单且有效,但一旦涉及复杂的覆盖和穿插,排序问题就变得棘手且难以优雅解决。

或许可以尝试将Y坐标与Z坐标结合,找到一个简化排序的办法,但目前还没有明确的好思路。

我们对这个问题依然持开放态度,还没有找到一个满意的、优雅的解决方案。

黑板讲解:顶视二维与三维的比较

我们从俯视角度来看这个问题。假设有一个英雄角色站在一个略微凹陷的区域里,地形高度不一,有的地方高,有的地方低。英雄站在相对低洼的位置。单纯用Z值排序,从纯顶视角看,这种排序对于大多数情况是可行的,虽然可能存在一些小瑕疵,但总体上是可以接受的。

但是一旦视角稍微倾斜,视线从侧面看时,原本后面的某个物体可能会遮挡前面的位置,这时候单纯用Z值排序就不够了。比如有个物体在更高的Z值处,它会正确地排在前面,遮挡后面的物体,这是符合预期的。但另一个问题是,低Z值但Y值更大的物体有可能错误地被排在高Z值物体前面,造成视觉上的错乱。

这时,Y坐标的排序就变得重要。如果先按Y排序,再按Z排序,可以保证:

  • 位于不同Y位置的物体有合理的层叠关系,
  • 而站在某个位置上方的英雄,其Z值较高,始终排在覆盖物的前面,避免被错误遮挡。

这种结合Y和Z排序的方式,对于局部瓷砖内的元素排序来说,是较为合理且有效的。

接下来考虑跨瓷砖的情况,比如有一张地毯或类似的覆盖物跨越多个瓷砖。此时,为了让跨瓷砖的覆盖物正确显示,地面必须相对平坦,各个瓷砖的Z值变化不大,否则无法合理叠放桌子或其他物品。

在这种较为平坦的情况下,覆盖物(如地毯)可以叠加在地面上。但问题出现在Y排序上。因为英雄站在地毯的某个后方瓷砖上时,按Y排序,地毯可能会被错误地分配到其他位置,导致排序出现矛盾:英雄应该排在地毯前面,但由于Y值排序,地毯反而被排在英雄前面或错位,造成视觉错误。

总结来说:

  • 纯Z排序在顶视图下大多数情况下可行,
  • 视角倾斜时,结合Y和Z排序能更合理处理遮挡关系,
  • 但跨瓷砖覆盖物导致的排序问题比较复杂,Y排序可能带来冲突,
  • 要求地面高度平坦才能较好处理跨瓷砖覆盖物的排序,
  • 依然存在英雄和覆盖物排序矛盾的问题,排序逻辑难以完全简单化。

整体来看,Y和Z的结合排序是当前较合理的解决方案,但仍有细节和特殊情况需要特别处理。

黑板讲解:使用平面数学方法

我们思考用平面排序的方法来处理复杂的排序问题。假设我们为每个物体定义一个平面方程,通过平面数学来判断两个物体在它们重叠的点上哪个应该排在前面。

这种思路在某种程度上是合理的:在它们相交的位置,我们可以判断哪个物体应该覆盖另一个,从而确定正确的绘制顺序。但困难在于,如果有多个物体分布在不同的位置,涉及的平面交叉会非常复杂。我们不仅要判断排序顺序,还可能需要裁剪物体的一部分来避免绘制错误。

例如,有时候我们希望某个瓷砖先绘制,但基于平面排序却显示另一个瓷砖应该先绘制,这会导致视觉上的干扰,物体“穿插”在不该穿插的位置。这种情况让平面排序的方案显得不够可靠。

因此,虽然理论上可以用平面排序并写出相应的规则,但在实际应用中,问题非常棘手。为了完全解决这类复杂的排序关系,可能必须真正地用3D模型表示所有物体,从3D视角来处理遮挡和排序。

如果不走3D的路,我们可能就必须放弃那些跨瓷砖铺设的覆盖物(比如地毯),要求所有东西严格按照瓷砖边界摆放,不允许跨越多个瓷砖。这无疑会限制设计的灵活性,令制作更大或跨多瓷砖的家具(例如沙发)变得困难。

总体来看,虽然平面排序方案有其逻辑基础,但它带来的复杂裁剪和不确定排序问题,让我们难以找到理想的解决方法。可能唯一的办法就是承认无法完全解决跨瓷砖复杂排序问题,要么限制设计,要么采用3D系统处理。

黑板讲解:将问题视为三维问题

我们把问题看作一个真正的三维排序问题。假设有两个瓷砖,每个瓷砖有中心点,从上方俯视它们。地毯叠加在瓷砖上面,英雄人物站在一边,每个对象都有它们的最高点。我们关注这些对象在视线方向上的投影位置和对应的Z值。

关键难点在于:不同选取物体上的点会导致排序结果不同。比如选取地毯的一个点,可能排在英雄前面;选另一个点,则可能在英雄后面。也就是说,排序依赖于选取的参考点,导致排序结果不稳定。而通常在渲染时,我们是基于每个像素的深度进行排序,因此不会遇到选择单点的问题。

为了解决这个问题,可以考虑物体的最低点和最高点(即物体在视线方向上的范围,称为投影范围),用物体的投影范围来判断排序。具体来说,观察两个物体在视线方向上的投影区间,可以归纳出几种情况:

  1. 不相交(投影区间不重叠)
    如果物体A的所有点都在物体B之前,那么A总是应该先绘制,B后绘制。这种情况排序非常明确。

  2. 部分重叠
    两个物体的投影区间有部分交叉,这种情况比较模糊,不容易判定谁先绘制。比如地毯和站在上面的英雄之间的关系,这时候存在一定的排序歧义。

  3. 完全包含
    一个物体的投影范围完全包含另一个物体。此时也比较难判断,排序会更加复杂。

举例来说,假设英雄站在地毯上,投影范围部分重叠,理论上英雄应该覆盖地毯被绘制在后面。但如果英雄向后移动,投影关系可能反转,导致排序出现问题。换句话说,单靠投影区间无法准确、稳定地判断正确绘制顺序。

总结来看,这种基于投影范围的排序方法虽然能在部分情况有效区分物体遮挡关系,但面对物体交叠或动态移动,依然存在明显的歧义和排序冲突,没有简单、通用的解决方案。除非采用更精细的每像素深度排序或者直接用三维渲染技术,否则难以解决复杂场景下的排序难题。

黑板讲解:平面实体与竖直实体的区别

我们考虑将场景中的物体分为两类:平面的和竖立的。针对这两种类型,排序问题可能会有所不同。对于竖立的物体和铺在地面上的平面物体,可以通过观察它们投影交汇处的高度(Z值范围)来判断哪个应该在前面绘制。也就是说,判断两者重叠时哪个在上方,依据它们在交汇点处的高度来确定绘制顺序。

这其实归结为:竖立的物体主要根据它们的Z值进行排序,而平面物体主要根据Y值进行排序。这样的划分和排序逻辑可以帮助解决两类物体混合时的遮挡问题。

但实际上,除了这种竖立和平面的区别之外,我们还是会遇到更复杂的情况,尤其是那些跨越多个格子的物体。对于单个格子里的物体,只要先按照Y排序格子,再在格子内部根据Z排序物体,排序问题大部分都能得到合理解决。

真正的难点还是跨格子的物体,它们会跨越多个格子,导致简单的Y+Z排序无法完美解决。针对这种情况,可以考虑限制跨格子的物体只能跨越固定大小的格子,但这种做法在实际应用中可能会显得比较笨拙、不够灵活,也不一定好实现。

综上,除了跨格子物体的情况之外,采用先按Y排序格子,再按Z排序格子内部物体的方式,配合竖立物体以Z为主,平面物体以Y为主的排序策略,整体排序问题基本可以得到有效处理。其他情况的排序难题较少,当前看来并没有更理想的排序算法。

黑板讲解:单个格子内Y轴排序的问题

在单个格子(cell)内部,我们仍然面临Y轴排序的问题。即使物体都在同一个格子里,我们也需要根据它们在Y方向上的位置来决定绘制顺序,比如从上方俯视图来看,Y值较小的物体应当先绘制,Y值较大的物体后绘制,这样视觉上才不会出现遮挡错误。

对于完全平面的物体,可以采用一种偏置的方法,比如将它们的排序点设在物体末端,从而在单格子内部实现合理的排序。这种偏置能帮助平面物体在Y排序中表现正确,避免被误判遮挡顺序。

不过,问题更复杂的是那些能在格子内自由移动的物体,比如飞行中的投射物(子弹、飞箭等)。由于通常一个格子内不会同时存在两个站立的角色,格子内的竖立物体不会堆叠,但这些小的浮动物体却会带来排序难题。它们的位置在Y轴上随时变化,排序不易准确处理。

最初提出的“竖立卡片(upright cards)”和“非竖立卡片”的分类,正是为了应对这种复杂的排序需求。竖立物体和非竖立物体需要采用不同的排序策略,但这仍然没有完全解决所有问题。

目前来看,纯粹靠二维排序难以完美解决这个问题。虽然考虑使用深度缓冲区(z-buffer)进行三维渲染可以避免排序问题,但这会带来额外的复杂性和资源浪费,尤其是在带宽和计算上,因为二维场景通常不需要完整的3D光栅化处理。

传统方法里,这类排序通常是手动固定好的,比如预先设定好物体的高度和遮挡关系,类似地毯这种东西直接“烘焙”到贴图里,不需要实时排序,简化了流程。

总结来说,单格子内的排序问题依然存在,尤其是动态移动的物体和完全平面的物体混合时的排序仍然棘手。传统2D排序方式有限,三维渲染能解决问题但代价大。手动预设物体层级和高度依然是业界常用的折中方案。

黑板讲解:倾斜相机俯视站在地毯上的角色的排序问题

我们从上方视角看一个场景,有一张地毯和一个英雄角色。如果使用z-buffer进行排序,英雄会显示在地毯前面,因为他们在三维空间中其实是无限薄的平面。在用3D卡片模拟时,这些平面会被正交投影到一个平面上。

在这种情况下,会把这些对象投影到某个轴线上,比如x轴或者y轴,然后观察它们投影的范围。英雄和地毯的投影区域会有重叠部分,正是这个重叠区域决定了它们的排序关系。

关键点是,我们只关心它们在屏幕上的重叠部分,也就是它们投影在同一条轴线上重合的区域。只要知道它们在屏幕上出现的具体位置,就能判断哪个应该绘制在前面。

所以,可以尝试用类似画家算法(painter’s algorithm)的思路,找到它们在某个轴上的投影范围重叠处,来确定排序关系。具体操作是将物体的范围投影到x轴或y轴,然后找出它们的交集区间,在这个区间内比较深度信息,从而决定绘制顺序。

这个方法的核心是,将三维排序问题简化成投影轴上的区间重叠比较,利用物体在屏幕上的投影位置来解决遮挡和排序问题。

黑板讲解:使用实体共有的最近点来确定排序

我们从视角出发,定义视图的Z轴和Y轴,区别于世界坐标的Z轴和Y轴,关注的是相对于观察者的坐标。考虑一个场景,有地毯和人物,我们用二维卡片表示它们,分别在Y轴上有各自的最小值和最大值,也就是它们在Y轴上的范围。

首先,我们知道这些精灵在Y轴上的位置范围。如果两个对象在Y轴上的范围有重叠,那么它们之间就存在排序的必要。如果不重叠,从理论上讲,它们的绘制顺序可以不影响最终效果,因为没有交集,不存在遮挡问题。但是,这里也存在潜在的问题:

如果两个对象在Y轴上不重叠,我们随意决定绘制顺序,可能会影响另一个同时与这两个对象有交集的第三个对象的绘制顺序。因为这个第三个对象需要依赖正确的排序顺序来决定自己该绘制在谁前面或后面,如果我们排序顺序错误,第三个对象的遮挡关系就会出错。

为了解决这个问题,我们提出了一个思路:找出两个对象在Y轴上“最近的共同点”,也就是说,要么是它们重叠的区域,要么是它们范围最接近的两个端点之间的点。在这个共同点处比较它们在Z轴上的深度值,深度小的先绘制,深度大的后绘制,从而确定绘制顺序。

进一步思考,这个过程实际上可以看作一种空间划分。每个精灵对应一个平面,我们可以通过判断实体相对于这些平面的位置,来确定谁离观察者更近。具体来说,如果一个实体位于某个平面的观察者一侧,那么它应该比位于另一侧的实体更靠近观察者,因而优先绘制。

唯一复杂的情况是实体“穿插”了平面,即部分实体位于平面一侧,部分位于另一侧,这种情况下很难确定绘制顺序,甚至无法保证绘制正确。这属于特殊情况,需要额外处理或拆分对象。

总的来说,这种排序规则基于每个精灵都有对应的平面方程,且平面的法线方向是固定的(例如世界坐标中的Z轴或Y轴),所以计算相对位置比较简单且高效。对于较厚的对象,虽然理论上可能需要多个平面来描述,但实际中可以用单一平面近似,效果应该也足够好。

这种方法的优点是:

  • 每个精灵只需知道自己的边界和对应的平面;
  • 利用简单的几何关系判断相对深度和绘制顺序;
  • 对大部分情况有效,只需特别处理穿插情况。

总之,通过视图坐标下的平面位置关系判断排序,是一种较为稳妥且易于实现的绘制顺序解决方案。

问答环节

如果只关注跨越多个格子的精灵,为什么不在格子边界处分割多边形?应该不多,也不太耗性能吧?

针对存在于多个格子(cell)中的精灵,有一种想法是将这些精灵的多边形沿着格子边界进行切分。理论上,这样做不会产生太多的多边形,计算开销也不一定很大。但是问题不完全在于计算成本,更重要的是这些精灵实际上并不是普通的多边形,而是“直立的假卡片”(upright fake cards)。这种情况下,切分操作不仅是几何上的拆分,还涉及到基于二维原始图形的切割和重组。

虽然从技术上讲,切割并分别排序是可行的,但即使这样做了,在单个格子内部仍然需要对切割后的部分进行排序。这意味着切分只是解决了跨格子排序的问题,但格子内的排序问题依然存在。

因此,虽然切割精灵以适应格子边界看似一种可行方案,但并没有彻底解决所有排序上的难题。内部排序依然需要处理,整体流程并没有因此变得简单。

总结来看,切割方法可能会增加处理流程的复杂度,而不是显著降低问题的复杂度。

相关文章:

游戏引擎学习第299天:改进排序键 第二部分

回顾并为当天内容做准备 我们会现场编写完整的游戏代码。回顾上周发现自己对游戏中正确的排序规则并没有清晰的理解。主要原因是我们更擅长三维游戏开发,缺乏二维游戏和二维游戏技术的经验,对于二维精灵排序、模拟三维效果的最佳方案等没有太多技巧和经…...

设计模式----软考中级软件设计师(自用学习笔记)

目录 1、设计模式的要素 2、设计模式的分类 3、简单工厂模式 4、工厂方法 5、抽象工厂 6、生成器 7、原型 8、单例模式 9、适配器 10、桥接 11、组合模式 12、装饰 13、外观 14、享元 15、代理 16、责任链 17、命令 18、解释器 19、迭代器 20、中介者 21、…...

uniapp如何设置uni.request可变请求ip地址

文章目录 简介方法一:直接在请求URL中嵌入变量方法二:使用全局变量方法三:使用环境变量方法四:服务端配置方法五:使用配置文件(如config.js):总结 简介 在uni-app中,uni.request 用…...

Centos上搭建 OpenResty

一、OpenResty简介 OpenResty 是基于 Nginx 的扩展平台,完全兼容 Nginx 的核心功能(如 HTTP 服务和反向代理),同时通过内嵌 LuaJIT 支持,允许开发者用 Lua 脚本灵活扩展业务逻辑。它简化了动态逻辑的实现。 二、安装…...

Kotlin与物联网(IoT):Android Things开发探索

在物联网(IoT)领域,Kotlin 凭借其简洁性、安全性和与 Java 生态的无缝兼容性,逐渐成为 Android Things 开发的有力工具。尽管 Google 已于 2022 年宣布停止对 Android Things 的官方支持,但其技术思想仍值得探索&#…...

WIFI信号状态信息 CSI 深度学习篇之CNN(Python)

本博客是一篇非新手导向的CNN处理CSI图像帧的教程,基于tensorflow框架构建CNN模型进行训练,训练对象依然是前述博客中所提到的CSI图像帧(500 x 90 x 1)。代码里用到了深度可分离卷积,这种结构在减少计算量和参数数量方…...

深度学习实战 04:卷积神经网络之 VGG16 复现三(训练)

在后续的系列文章中,我们将逐步深入探讨 VGG16 相关的核心内容,具体涵盖以下几个方面: 卷积原理篇:详细剖析 VGG 的 “堆叠小卷积核” 设计理念,深入解读为何 332 卷积操作等效于 55 卷积,以及 333 卷积操作…...

欧拉系统离线部署docker

https://www.cnblogs.com/hsh96/p/18150538 Docker 离线安装指南 本文介绍了如何在 Linux 系统上进行 Docker 的离线安装。首先,确保欧拉系统安装的是server版本,否则没有tar工具。 您需要下载 Docker 的离线安装包。您可以从以下链接获取所需的安装包&a…...

Java 中 final 与 static 的区别

Java 中 final 与 static 的区别 在 Java 中,final 和 static 是两个不同的关键字,它们的核心作用和不可变性特性有本质区别: 一、final 的核心作用 1. 变量(不可变引用) 不可重新赋值:final 修饰的变量…...

多模态实时交互边界的高效语音语言模型 VITA-Audio 介绍

介绍 VITA-Audio是由Zuwei Long等研究者提出的端到端大型语音语言模型,其核心目标是通过跨模态令牌生成技术,解决传统语音交互系统中首音频令牌生成延迟高的问题。该模型的创新点主要体现在: 低延迟:VITA-Audio 是首个能够在初次…...

LLM | 论文精读 | NAACL 2025 | Clarify When Necessary:教语言模型何时该“问一句”再答!

🔍 解读 NAACL 2025 重磅论文《Clarify When Necessary》:教语言模型何时该“问一句”再答! 🧩 一、现实问题:大模型“看不懂装懂”有多危险? 我们每天用的 ChatGPT、Claude 等大型语言模型(LL…...

MySQL 8.0 OCP 英文题库解析(七)

Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题51~60 试题51:…...

深度解析Vue项目Webpack打包分包策略 从基础配置到高级优化,全面掌握性能优化核心技巧

深度解析Vue项目Webpack打包分包策略 从基础配置到高级优化,全面掌握性能优化核心技巧 一、分包核心价值与基本原理 1.1 为什么需要分包 首屏加载优化:减少主包体积,提升TTI(Time to Interactive)缓存利用率提升&am…...

MySQL——基本查询内置函数

目录 CRUD Create Retrieve where order by limit Update Delete 去重操作 聚合函数 聚合统计 内置函数 日期函数 字符函数 数学函数 其它函数 实战OJ 批量插入数据 找出所有员工当前薪水salary情况 查找最晚入职员工的所有信息 查找入职员工时间升序排…...

实现图片自动压缩算法,canvas压缩图片方法

背景: 在使用某些支持webgl的图形库(eg:PIXI.js,fabric.js)场景中,如果加载的纹理超过webgl可处理的最大纹理限制,会导致渲染的纹理缺失,甚至无法显示。 方案 实现图片自动压缩算…...

零基础设计模式——创建型模式 - 单例模式

第二部分:创建型模式 - 单例模式 (Singleton Pattern) 欢迎来到创建型模式的第一站——单例模式!这是最简单也最常用的设计模式之一。 核心思想:关注对象的创建过程,将对象的创建与使用分离,降低系统的耦合度。 单例…...

数据挖掘:从数据堆里“淘金”,你的数据价值被挖掘了吗?

数据挖掘:从数据堆里“淘金”,你的数据价值被挖掘了吗? 在这个数据爆炸的时代,我们每天都在产生海量信息:社交媒体上的点赞、网购时的浏览记录,甚至是健身手环记录下的步数。这些数据本身可能看似杂乱无章…...

k8s1.27版本集群部署minio分布式

需求: 1.创建4个pv,一个pv一个minio-pod。使用sts动态分配pvc(根据存储类找到pv)。----持久化 2.暴露minio的9001端口。(nodeport)----管理界面 镜像:minio/minio:RELEASE.2023-03-20T20-16-18Z--->换国内源 说明…...

雷军:芯片,手机,平板,SUV一起发

大家好,我是小悟。 5月19日,雷军在微博上宣布,5月22日晚7点将举办小米战略新品发布会。 这场被官方称为“人车家全生态”战略升级的重要活动,一口气带来了小米手机SoC芯片“玄戒O1”、旗舰手机小米15S Pro、小米平板7 Ultra&…...

使用Dockerfile构建含私有Maven仓库依赖包的Java容器

背景 需要用JDBC方式访问ArgoDB星环提供了ArgoDB jar包应用将以Container的方式运行我希望打包成镜像之后&#xff0c;镜像启动就能测试连接是否成功连接URL串需要能够传递进去 失败的方案一&#xff1a;本地文件导入POM pom.xml 配置本地路径 <dependency><groupI…...

AI指令模板综述(Prompt Review)

文章目录 DeepSeek DeepSeek 参考&#xff1a;DeepSeek学术指令大全 找到有价值的研究方向 "作为我的学术研究助手&#xff0c;你需要基于以下要求为我生成5个具有学术价值的创新选题&#xff1a; 请聚焦于[具体研究领域&#xff0c;如’社交媒体用户行为’或’深度学习…...

软件架构之-论分布式架构设计及其实现

论分布式架构设计及其实现 摘要正文 摘要 2023年2月&#xff0c;本人所在集团公司承接了长三角地区某省渔船图纸电子化审查项目开发&#xff0c;该项目旨在为长三角地区渔船建造设计院、渔船审图机构提供一个便捷化的服务平台。在次项目中&#xff0c;我作为项目成员参与了整个…...

零售EDI:Belk Stores EDI需求分析

Belk Stores 成立于 1888 年&#xff0c;是美国历史最悠久的家族百货连锁品牌之一&#xff0c;总部位于北卡罗来纳州夏洛特市。作为美国东南部领先的零售企业&#xff0c;Belk 在16个州拥有近300家门店&#xff0c;主要经营服装、鞋履、美妆、家居用品等多个品类&#xff0c;服…...

LangChain4j入门(六)整合提示词(Prompt)

前言 提示词&#xff08;Prompt&#xff09;是用户输入给AI模型的一段文字或指令&#xff0c;用于引导模型生成特定类型的内容。通过提示词&#xff0c;用户可以告诉AI“做什么”、 “如何做”以及“输出格式”&#xff0c;从而在满足需求的同时最大程度减少无关信息的生成。有…...

【HarmonyOS 5】金融应用开发鸿蒙组件实践

【HarmonyOS 5】金融应用开发鸿蒙组件实践 一、鸿蒙生态观察 2024 年 1 月 18 日&#xff1a; 发布 原生鸿蒙操作系统星河版&#xff0c;面向开发者开放申请&#xff0c;余承东宣布鸿蒙生态设备数达 8 亿台&#xff1b;建设银行、邮储银行等完成鸿蒙原生应用 Beta 版本开发。 …...

cv2.VideoWriter_fourcc(*‘mp4v‘)生成的视频无法在浏览器展

看这个博主的博客&#xff0c;跟我碰到的问题的一致&#xff0c;都是使用AVC1写视频时报编码器不存在的异常&#xff0c;手动编译opencv-python或者使用conda install -c conda-forge opencv安装依赖即可。 博主博客&#xff1a;Python OpenCV生成视频无法浏览器播放问题说明及…...

MD编辑器推荐【Obsidian】含下载安装和实用教程

为什么推荐 Obsidian &#xff1f; 免费 &#xff08;Typora 开始收费了&#xff09;Typora 实现的功能&#xff0c;它都有&#xff01;代码块可一键复制 文件目录支持文件夹 大纲支持折叠、搜索 特色功能 – 白板 特色功能 – 关系图谱 下载 https://pan.baidu.com/s/1I1fSly…...

新书速览|GraphPad Prism图表可视化与统计数据分析:视频教学版

《GraphPad Prism图表可视化与统计数据分析:视频教学版 》 本书内容 《GraphPad Prism图表可视化与统计数据分析:视频教学版 》以GraphPad Prism 10为平台&#xff0c;讲述统计分析软件GraphPad Prism的具体应用方法。在介绍《GraphPad Prism图表可视化与统计数据分析:视频教学…...

波峰波谷策略

这是一个基于数据分布的峰度(kurtosis)和偏度(skewness)的交易策略。 当数据呈现趋势性,并且潜在趋势为正时,我们做多。 当数据呈现趋势性,并且潜在趋势为负时,我们做空。 当趋势发生反转后,我们平仓。 那么,我们如何确定趋势和趋势的强度呢?让我们先来复习一下峰…...

【综述】视频目标分割VOS

目录 1、Associating Objects with Transformers for Video Object Segmentation1&#xff09;背景知识2&#xff09;研究方法3&#xff09;实验结果4&#xff09;结论 2、Rethinking Space-Time Networks with Improved Memory Coverage for Efficient Video Object Segmentat…...

基于线性回归的数据预测

1. 自主选择一个公开回归任务数据集&#xff08;如房价预测、医疗数据、空气质量预测等&#xff0c;可Kaggle&#xff09;。 2. 数据预处理&#xff1a;完成标准化&#xff08;Normalization&#xff09;、特征选择或缺失值处理等步骤。 3. 使用线性回归模型进行建模。采用80…...

第5天-python饼图绘制

一、基础饼图绘制(Matplotlib) 1. 环境准备 python 复制 下载 pip install matplotlib numpy 2. 基础饼图代码 python 复制 下载 import matplotlib.pyplot as plt# 数据准备 labels = [1, 2, 3, 4] sizes = [30, 25, 15, 30] # 各部分占比(总和建议100) colors…...

c++学习方向选择说明

文章目录 前言一、什么样的人适合用c找编程相关工作二、c可以投递什么岗位三、应届生c怎么学才可以找到好工作那这样的话&#xff0c;校招生搞c应该怎么学才能凸显自己的优势呢&#xff1f;那有人就问了&#xff0c;那我应该学啥啊&#xff1f; 四、零基础学习c路线 前言 做了…...

采集需要登录网站的教程

有些网站需要用户登录才能显示相关信息&#xff0c;如果要采集这类网站&#xff0c;有以下几个方法&#xff1a; 1. 写发布模块来抓包获取post的数据&#xff1b; 2. 有些采集器内置浏览器获取这些信息&#xff0c;但是经常获取的不准确&#xff0c;可靠性太低&#xff1b; 3. …...

在hadoop中实现序列化与反序列化

在 Hadoop 分布式计算环境中&#xff0c;序列化与反序列化是数据处理的核心机制之一。由于 Hadoop 需要在集群节点间高效传输数据并进行分布式计算&#xff0c;其序列化框架不仅要支持对象的序列化与反序列化&#xff0c;还要满足高效、紧凑、可扩展等特殊需求。本文将深入探讨…...

数据结构*排序

排序的一些相关概念 稳定性 假设在待排序序列中&#xff0c;存在两个元素A和B&#xff0c;A和B的值相同。在排序后&#xff0c;A和B的相对位置没有变化&#xff0c;就说这排序是稳定的。反之不稳定。 内部排序与外部排序 内部排序&#xff1a;数据完全存储在内存中&#xf…...

新浪《经济新闻》丨珈和科技联合蒲江政府打造“数字茶园+智能工厂+文旅综合体“创新模式

5月14日&#xff0c;新浪网《经济新闻》频道专题报道珈和科技在第十四届四川国际茶业博览会上的精彩亮相&#xff0c;并深度聚焦我司以数字技术赋能川茶产业高质量发展创新技术路径&#xff0c;及在成都市“茶业建圈强链”主题推介会上&#xff0c;珈和科技与蒲江县人民政府就智…...

【Linux】第二十三章 控制启动过程

1. 请简要说明 RHEL9的启动过程。 &#xff08;1&#xff09;计算机通电。系统固件 (UEFI 或 BIOS) 开机自检 (POST)&#xff0c;并初始化部分硬件&#xff0c;然后&#xff0c;固件会寻找启动设备&#xff08;如硬盘、USB、网络等&#xff09;&#xff0c;并将控制权交给引导…...

深信服golang面经

for range 中赋值的变量&#xff0c;这个变量指向的是真实的地址吗&#xff0c;还是临时变量 不是真实地址&#xff0c;是临时变量 package mainimport "fmt"func main() {slice : []int{4, 2, 3}for _, v : range slice {fmt.Println(v, &v) // 这里的 v 是临…...

基于 Netty + SpringBoot + Vue 的高并发实时聊天系统设计与实现

一、系统架构设计 1.1 整体架构图 ------------------ WebSocket (wss) ------------------ Netty TCP ------------------ | Vue前端 | <-------------------------> | SpringBoot网关 | <------------------> | Netty服务集…...

根据当前日期计算并选取上一个月和上一个季度的日期范围,用于日期控件的快捷选取功能

代码如下&#xff1a; <el-date-picker v-model"value" type"monthrange" align"right" unlink-panels range-separator"至"start-placeholder"开始月份" end-placeholder"结束月份" :picker-options"pic…...

Spring Boot 使用 jasypt配置明文密码加密

引入依赖 <dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.4</version> </dependency>添加配置 jasypt:encryptor:password: pssw0rd&Hubt2ec…...

ubuntu下docker安装mongodb-支持单副本集

1.mogodb支持事务的前提 1) MongoDB 版本&#xff1a;确保 MongoDB 版本大于或等于 4.0&#xff0c;因为事务支持是在 4.0 版本中引入的。 2) 副本集配置&#xff1a;MongoDB 必须以副本集&#xff08;Replica Set&#xff09;模式运行&#xff0c;即使是单节点副本集&#x…...

科技赋能,开启现代健康养生新潮流

在科技与生活深度融合的当下&#xff0c;健康养生也迎来了全新的打开方式。无需传统医学的介入&#xff0c;借助现代科学与智能设备&#xff0c;我们能以更高效、精准的方式守护健康。​ 饮食管理步入精准化时代。利用手机上的营养计算 APP&#xff0c;录入每日饮食&#xff0…...

《安徽日报》聚焦珈和科技AI创新:智慧虫情测报护航夏粮提质丰产

5月7日&#xff0c;《安徽日报》焦点新闻版块以《高科技助力田管&#xff0c;确保夏粮丰收——为4300多万亩小麦守好防线》为题&#xff0c;深度报道了农业科技在夏粮生产中的关键作用。其中&#xff0c;珈和科技自主研发的AI虫情测报一体机作为绿色防控、农业智慧化的标杆被重…...

企业级 Go 多版本环境部署指南-Ubuntu CentOS Rocky全兼容实践20250520

&#x1f6e0;️ 企业级 Go 多版本环境部署指南-Ubuntu / CentOS / Rocky 全兼容实践 兼顾 多版本管理、安全合规、最小权限原则与 CI/CD 可复现性&#xff0c;本指南以 Go 官方 toolchain 为主&#xff0c;结合 asdf 实现跨语言统一管理&#xff0c;并剔除已过时的 GVM。支持 …...

MCP 协议传输机制大变身:抛弃 SSE,投入 Streamable HTTP 的怀抱

在技术的江湖里&#xff0c;变革的浪潮总是一波接着一波。最近&#xff0c;模型上下文协议&#xff08;MCP&#xff09;的传输机制就搞出了大动静&#xff0c;决定和传统的服务器发送事件&#xff08;SSE&#xff09;说拜拜&#xff0c;转身拥抱 Streamable HTTP&#xff0c;这…...

Windows 上配置 Docker,Docker 的基本原理和用途,以及如何在 Docker 中运行程序

Windows 系统上的 Docker 安装与使用指南 1. Windows 上配置 Docker 检查系统要求&#xff1a;使用 64 位 Windows 10/11&#xff0c;BIOS 已启用硬件虚拟化&#xff08;VT-x/AMD-V&#xff09;。Windows 版本最好更新到 2004 及以上&#xff08;内部版本19041&#xff09;&am…...

CBCharacteristic:是「特征」还是「数据通道」?

目录 名词困惑&#xff1a;两种中文译法的由来官方定义 & 开发者视角乐高类比&#xff1a;文件夹与文件智能手表实例&#xff1a;Characteristic 长什么样&#xff1f;iOS 代码实战&#xff1a;读 / 写 / 订阅小结 & Best Practice 1. 名词困惑&#xff1a;为什么有两…...

【JavaEE】多线程

线程 在Java中&#xff0c;鼓励多线程编程。进程可以满足并发编程&#xff0c;但是效率不高&#xff08;创建、销毁、调度时间都比较长&#xff0c;这些都消耗在申请资源上了&#xff09;&#xff0c;而线程就不一样。 线程也叫“轻量级进程”&#xff0c;创建、销毁、调度都更…...