游戏引擎学习第62天
回顾
我们目前正在开发一把虚拟剑,目的是让角色可以用这把剑进行攻击。最初的工作中,我们使用了一个摇滚位图作为虚拟剑的模型,并且实现了一个基本的功能:角色可以丢下剑。但这个功能并没有达到预期的效果,因为我们想要的行为是角色能够投掷剑,而不是简单地放下它。
接下来的目标是完善这一功能,使得剑能够像《塞尔达传说》中的剑一样被投掷出去。为此,我们计划进一步修改代码,使得剑不仅仅是一个物品,而是一个有效的抛射物,可以像其他游戏中的投掷武器一样被投掷并做出合理的反应。
在这个过程中,我们发现目前的实现有些荒谬,因为丢下剑的方式并没有达到预期的投掷效果。因此,接下来的工作是使得这一行为更加合理,确保剑可以像项目物一样被投掷并且能合理地与其他实体互动。昨天我们完成了大部分工作,接下来只需要继续调整,使这个功能顺利实现。
game.cpp:让剑实际被投掷出去
首先,我们讨论了如何让剑出现在指定位置。接下来,我们考虑了如何给剑添加速度,使其能够在某个方向上飞行。这是通过将剑的速度设置为投掷方向来实现的,目的是让剑能够移动一段距离。
为了限制剑的飞行距离,我们考虑了设置一个最大飞行距离,这样剑不能无限远地飞行。比如,设定剑只能飞行五米,超过这个距离后,剑就停止移动。为了实现这一点,我们在实体中添加了一个“剩余距离”属性,并初始化为一个合理的数值,比如五米。
此外,为了管理剑的速度,剑需要被添加到高优先级实体集合中,确保它能够受到控制并参与到游戏的物理系统中。虽然我们还没有具体操作,但设置剑的速度和管理它的实体位置仍然是接下来的工作。
讨论令人烦恼且丑陋的实体使用方式
目前,虽然低端部分的实现对功能没有问题,但在代码结构上存在一些烦人的地方,尤其是涉及指针和索引的部分,造成了大量的打字工作,且代码的可读性变差。虽然这些问题并没有引发错误,但打字过多和结构不简洁使得开发进程变得缓慢,并且影响了代码的清晰度。因此,考虑到这一点,计划将这些结构简化,使代码更标准化,减少冗余和不必要的复杂性,从而提升代码的可读性和维护性。虽然目前没有遇到严重的错误,但这种冗余的打字和代码结构仍然需要在未来的开发中进行优化和改进。
回到实现剑的投掷功能
目前,已经决定将剑作为高频更新实体,并且需要设置其速度。预计剑的速度为每秒两米,尽管这一数值可能会根据需要进行调整。接下来,需要确保剑在发射后朝预定方向移动,但目前尚未实现实体的实际更新。进一步检查发现,实体的移动功能尚未完全实现。接下来需要在代码中加入适当的更新机制,使得剑能够按照设定的速度和方向正确移动。
game.cpp:UpdateSword
在更新过程中,剑实体并不会自动更新位置,除非明确调用更新函数。当前的设计中,剑实体没有单独的更新调用,这意味着它不会自行移动。为了使剑能够移动,必须在适当的时候调用“更新实体”函数。
这部分代码设计考虑了是否需要特殊处理剑实体的更新。虽然可以通过类似投射物的通用更新方法来处理剑,但当前的目标是逐步确定实体系统的工作方式。因此,当前所有的更新都显式写出,并根据实际情况进行优化,以避免在游戏构建中出现不合适的基础设计。
目前,剑的移动并没有涉及加速度,保持恒定速度。类似塞尔达风格的剑通常会维持恒定速度。在这种情况下,基本上只需要调用已有的“移动实体”函数,该函数应该能正常工作,尽管目前还需要进一步检查是否有其他问题。
仅在当前阶段,如果实体不发生碰撞,就关闭碰撞检测
在当前的实现中,需要对剑的碰撞检测进行暂时关闭。首先,将剑标记为不进行碰撞检测,以便它能够自由地穿过物体。在未来,会对这种行为进行进一步处理。通过这种方法,可以使得被标记为非碰撞的剑能够顺利穿过其他物体。对于暂时关闭碰撞检测的具体操作,如果发生碰撞,才会进行碰撞测试,否则不会进行任何测试。这种做法是为了更好地处理剑的行为,并让它在游戏中表现得更加灵活。接下来,计划完成相关代码,确保能够更新剑的状态,并传递游戏状态和实体信息。
运行游戏,发现剑减速了
目前,剑的运动效果并不令人印象深刻,尽管剑确实移动了,但它的速度正在减慢。看起来问题仍然存在,且这正是一个好时机来解决这个问题。事实上,之前并未完全解决与“Familiar”相关的部分,因此现在是时候将这些问题抽象出来,进行进一步处理和修复。
把移动概念分离到 move_spec 中,并引入 DefaultMoveSpec
目前存在一个问题,即玩家的速度、加速度、阻力等参数都被内置在系统中,这样每个对象都无法根据自己的需求调整这些参数。尤其是对于像剑这样的物体,它们不应该受到与玩家相同的空气阻力影响,因此需要对这些参数进行调整。
为了解决这个问题,首先要做的是确保加速度不再与玩家的速度直接相乘,因为这样是不正确的。加速度应该是由调用者传入的有效值,MoveEntity
只负责根据这些加速度响应运动。
此外,还需要对阻力系数进行调整,确保其也可以作为参数传入。这个参数会影响加速度,并且需要在运动方程中处理。为了方便管理这些参数,可以引入一个 (move_spec
),其中包括加速度和阻力系数。这样,我们就可以通过 MoveEntity
函数传入这些参数,从而灵活控制运动和加速度。
具体来说,添加一个默认的 (move_spec
) 作为参数,可以让对象的加速度和阻力值按照需求初始化,而不是硬编码在每个对象中。例如,剑的初始速度为零,且没有阻力,这样它就能自由地移动而不受其他物体影响。
这种方式的好处是,它使得每个对象的物理行为更加灵活和可配置,不同的对象可以根据自己的需求调整加速度和其他运动参数。最终,系统会支持通过这种“移动规格”参数来控制运动行为,确保物理模拟更符合实际需求。
运行游戏,发现剑依然很慢
验证了一下,系统中的所有功能似乎都在正常工作。熟悉的物体(头部)仍然在跟随我们,这是预期的结果。我们的剑(或所谓的剑)也成功地掉落,表现如我们所愿。然而,剑的移动速度看起来有些慢,这可能需要进一步优化或调整,至少可以说,速度表现并不理想。
加快剑的速度,并确保剑只能在特定距离内移动
我们可能需要确保剑的速度在未来可以稍微提高一些。接下来,我们的目标是实现一个功能,让剑在一定距离后消失。首先,我们需要更新一些参数,并设置一个剩余距离变量,作为一个计时器。通过计算实体当前的位置与其原始位置的差值,我们可以得出实体已移动的距离。
当剩余距离减少到零时,剑应该消失。因此,我们需要更新剑的实体位置,使其不再存在,实际上是将其位置设置为“无处可去”。这可以通过更改实体的位置来实现。
此外,我们还需要解决一个问题,就是我们现在缺少一个准确计算矢量长度的函数。目前我们有计算长度平方的功能,但缺少计算实际长度的部分。这并不复杂,因为我们可以通过对长度平方结果进行平方根运算来得到实际长度。
值得注意的是,矢量长度的计算中,两个相同向量的点积结果总是一个正数或零,因此不会出现负数的情况,也就不需要担心平方根计算失败的问题。
最后,我们还需要确保在代码中正确处理了位置更新和平方根运算的问题,虽然这些都是技术性的细节,但确保这些函数正常工作至关重要。
运行游戏,触发了断言错误
在实现过程中,发现如果在实体移动完成后尝试更改位置,可能会引发错误,特别是在发生断言失败时。问题的根源在于,函数并未考虑到将实体从一个有效的位置移动到无效的位置(例如将实体移动到零位置)。断言指出,传递的参数并非规范的,可能是由于试图将实体的位置更改为零位置,但程序没有处理这种情况。
在此情形下,断言实际上是在检查是否允许实体从一个有效位置移动到一个无效位置。解决方案是检查两个位置是否有效,并确保如果位置无效,则处理逻辑应单独进行处理,而不是直接进行位置更改。
该错误可能是由于没有为新的位置(例如零位置)做适当的验证,导致程序试图在无效位置进行操作。此时,必须确保断言逻辑可以正确捕捉这种情况,并在处理位置移动时做出相应的调整。
Assert导致断言错误的原因
在这个过程中,问题出现在实体的位置变更后,仍然可能会出现在错误的实体集合中。具体来说,在我们移动实体时,如果它仍然存在于“高频实体”集合(high set)中,它可能会被重复移动,这会引发问题。我们怀疑,实际上是实体被移出“高频实体”集合后,并没有及时地从集合中移除,因此它仍然处于集合中并被更新,导致其状态变得无效。
当改变实体位置时,应该首先检查该实体是否仍然属于“高频实体”集合。如果它已经不在正确的位置,应该从集合中删除,并确保不会继续被更新,直到下一次位置变化或其他条件被满足。特别是在移动实体出当前相机视野范围外时,它应该被及时移出“高频实体”集合。
然而,目前代码中没有处理这种情况的机制。当我们只更改低频位置(Low P)时,并没有执行从“高频实体”集合中移除实体的操作,导致实体仍然存在于集合中并可能会被重复处理。因此,问题的核心在于缺乏及时的移除操作,特别是在实体位置发生变化时。
为了解决这个问题,应该加入一段代码来处理从高频实体集合中移除无效实体。这样可以避免实体状态不一致,并确保其正确地更新或移除。
使用一种临时方法解决这个问题
问题在于当实体移出相机边界后,它是否应该被从高频集合中移除。虽然可以采用一些权宜之计,例如将实体的高频位置设置为某种极端的无效值,尽管这种做法可能勉强解决问题,但存在不优雅且容易出错的隐患。
当前问题的根源在于,当实体从低频位置中被移动到一个“不可存在的位置”后,没有任何机制能够将它从高频集合中移除。这导致了实体仍然留在高频集合中被更新,就好像它还在原来的位置。这种行为会带来潜在的逻辑错误。
为了解决此问题,需要一种更智能和更可靠的方式来处理这种情况,而不是依赖临时的技巧。尤其是,当涉及到两种频率更新机制(高频和低频)时,问题的复杂性加剧。如果基本逻辑没有处理好,这种问题可能会频繁出现,造成难以察觉的错误,不仅会影响开发效率,还会导致代码维护困难。
需要认真设计一种机制,确保在实体移出高频集合的边界后,能够正确地将其从高频集合中移除。这种机制必须易于理解和维护,以避免未来因类似问题而浪费时间。正确处理这一逻辑,对于确保更新机制的可靠性和优化开发流程至关重要。
尝试更合理地处理这个问题
我们对敌人系统的工作机制进行了一些回顾。当前的实现中,没有一个严格意义上的“敌人系统”,而是通过迭代高频实体并在每帧中更新它们的状态来运行。当更新某个实体(例如一把剑)时,在某些条件下,这把剑会被移出存在范围。
当实体被移出存在范围后,它不应再参与当前帧或后续帧的任何更新逻辑。因此,我们需要在更新循环中标记这些实体进行删除,或者在循环的一部分中将其移除。例如,可以引入一种控制流机制,跟踪需要移除的实体,并在循环结束后处理这些删除操作。
当前的一种可能的实现方法是在 SetCamera
调用中完成移除逻辑。这个函数会根据实体的当前位置和频率判断它们是否仍然处于活动范围内。如果可以扩展它来检查某些高频实体是否仍然有效,就能更智能地处理移除逻辑。例如,可以基于低频实体的有效位置来判断高频实体是否需要保留。
如果低频实体的位置无效(表示实体已经移出活动范围),我们就可以将该高频实体从高频集合中移除。这种处理方式相较于当前的实现更为合理,但可能需要额外的查询操作来确认低频实体的状态。如果这些额外的查询影响性能,可以稍后优化这一点。
在实现过程中还需注意,在移除操作执行之前,可能会存在一些边界情况。例如,即使实体已被标记为移除,但在当前循环结束之前,它可能仍然会被检查到。这种行为未必是错误,但需要关注可能由此引发的逻辑问题。
综上,我们需要为移出存在范围的实体设计一个更强健的移除逻辑,同时保证性能和代码的清晰性。这将有助于减少系统中可能产生的潜在错误,并提升开发效率。
运行游戏,发现剑的速度被设置为零的奇怪问题
在进行调整后,可以观察到问题确实得到了有效解决。然而,存在一个奇怪的现象,即剑仍然表现得非常缓慢。这种速度异常缓慢的行为令人疑惑,似乎与预期结果不符。
进一步观察发现,剑似乎没有获得任何速度增量,这种现象显得尤其奇怪。对于这种异常情况,尚不清楚原因所在,但这一点与系统行为的预期有明显偏差,需要进一步的分析和排查。
目前还无法确定是什么具体导致了这种情况,但这一点值得重点关注,以确保相关逻辑和速度更新机制的正常工作。
运行游戏,进行一些钩爪相关的操作
钩爪操作 是游戏技能发射一条绳索或钩
我们实际上正在处理一些问题。当前,我们发现一个快速解决方案被意外地保留在了代码中,尽管我们之前明确表示这只是一个临时补丁,但却没有将其删除。这种情况非常滑稽,同时也让人觉得无奈。
在编写代码的过程中,偶尔会犯一些错误,比如打错字,这在实时流中尤为常见。尽管也存在一些真实的代码错误,但修复这些错别字浪费了很多时间。为了能够一边讲话一边专注于代码,似乎需要找到更好的解决方法。
现在,我们正试图重新修复之前发现的一个错误,这个问题很可能完全是因为保留了那个临时补丁造成的。与此同时,我们注意到另一个细节:在某些情况下,代码并没有确保将位置重置到原来的状态。这种情况导致有时会意外触发一个类似“钩爪”的操作,这虽然看起来很酷,但并不是预期的结果。
接下来,我们将重点检查代码逻辑,确保位置在某些操作后能够正确还原,从而避免类似问题的再次发生。
解释这些钩爪操作是如何实现的
钩爪操作 是游戏技能发射一条绳索或钩
我们当前处理的问题涉及操作顺序的复杂性,这也是我们一直需要解决的事情。第一次发现这个问题是因为操作的顺序安排存在一定的不连贯性。具体来说,我们在处理输入数据时,没有确保某些操作的执行顺序。例如,一些与实体位置相关的操作,比如剑的位置更新,可能会在预期的时间点之前或之后发生。这导致了实体位置在高频空间和低频空间之间出现不同步的情况。
目前的代码中存在两个主要问题:
- 操作顺序的问题:在现有的实现中,某些操作被分散完成,这使得整体流程缺乏连贯性。例如,用户输入的处理与玩家位置的更新在不同的时机完成,这种分散的流程可能导致问题发生。
- 同步问题:当我们更改实体的位置时,如果该实体在高频空间中有一个表示,我们需要确保这些表示之间保持同步。而当前的系统中,这种同步容易被打破。
为了优化系统,我们需要解决这些问题:
- 统一输入与更新流程:收集用户输入后,以连贯的方式完成玩家更新,从而确保操作逻辑的一致性。
- 位置同步机制:设计一种机制,使得实体在高频空间和低频空间中的表示始终保持同步,避免因不同步引发的潜在错误。
此外,为了构建可扩展的系统,我们需要一个更加合理的设计。尽管当前的做法会导致代码更加复杂,但这样的复杂性有助于解决更大规模的实体更新问题。通过研究如何处理这些复杂情况,我们希望能够为处理大规模实体系统提供可行的解决方案。
接下来的任务包括:
- 提取当前代码中与位置相关的逻辑,并将其简化和优化,创建一个合理的定位系统。
- 基于现有的实际使用场景,进一步完善系统,使其在大规模使用时更加稳定和高效。
总结目标是通过精简和优化代码,提高系统在处理位置和实体移动方面的可靠性和可用性。
为什么你为每种向量类型创建了一个结构,而不是使用简单的浮点数组?
使用结构体而非普通的浮点数组来表示矢量类型,主要是为了能够重载数学运算符,使代码更加易读。通过重载运算符,例如*
和+
,可以使表达式如a * b
和3 + c
变得更加简洁和直观,而使用浮点数组时,代码会变得非常难以阅读。数组的方式需要使用临时变量进行多次运算,不仅复杂,而且可读性差。因此,使用结构体和重载运算符的方式,更加符合可读性和维护性的需求。
你对向量乘法运算符执行点积操作的看法是什么?
关于矢量乘法算子执行点积的做法,虽然它在着色器语言中常见(通常使用Hadamard积),但这种做法存在潜在问题,因为它容易让人误以为这是点积操作。建议将矢量乘法定义为Hadamard积,并且明确区分点积与Hadamard积,以避免错误。
为什么不将每种实体类型封装到各自的类中?
目前还没有做出具体的系统设计,所以还没有考虑将每种实体类型封装到独立的类中。即使倾向于面向对象编程和继承等概念,也不会在此时这样做,因为现在太早了,无法决定哪些内容应成为实体类,或者各个类应该如何设计。等到更多工作完成后,再决定如何拆分系统和设计类。
此外,对于像“剑”这样的实体有独立的类这一概念,认为这不是一个好的编程模型,也认为这种做法在游戏开发中效率不高。因此,在目前的开发阶段,不会采取这种方式。如果想深入讨论这个问题,最好等到稍后的阶段再进行。
XML 在这个项目中算合理选择吗?它不是库,但可能还不够 game?
关于XML文件,如果是自己写解析器并手动解析XML文件,这仍然符合当前游戏的标准,因此在这个项目中是可以接受的,只要不使用现成的库。
你不觉得 Low 实体已经包含了太多额外的内容,是时候分拆了吗?而且像剑这样的东西可能根本不需要低部分。
当前,低频实体可能已经包含了太多不相关的内容,因此有可能需要进行拆分。然而,目前没有足够的类型和复杂性支持这种拆分。计划在实体系统中实现更多的功能,特别是一些转移属性(例如,赋予物体特定的属性,如“蓝色火焰”)。例如,投掷剑可以获得“蓝色火焰”属性,击中怪物时造成相应的伤害。
在拆分实体系统之前,想先确保已经实现了这些功能,并确保实体系统中有足够的复杂性,否则拆分可能会基于错误的简化假设。因此,在目前的阶段,更希望继续将所有内容放在一个系统中,直到想到更多的类型和特性,再考虑是否进行拆分。此时并不需要担心内存占用,内存优化可以留到后续阶段进行。
我想到的不仅仅是内存占用,而是潜在的副作用,例如与属性传递相关的代码会引发定位等方面难以调试的问题。
当前的关注点不仅仅是内存占用,还包括潜在的不必要副作用。例如,处理转移属性的代码可能会引发难以调试的定位问题,或者其他一些问题。虽然现在调试确实较为困难,因为缺乏系统和调试工具,但这仍然是可以接受的,尤其是很多问题其实是打字错误,且当前很难完全解决。
目前,不值得投入时间去拆分低频实体,因为这项工作很可能会是无用功,尤其是当更多的内容尚未加入时,拆分的假设可能会是错误的。因此,暂时不进行这些工作是更好的选择,尽管这在某些情况下是一个艰难的决定。
仓库: https://gitee.com/mrxiao_com/2d_game
相关文章:

游戏引擎学习第62天
回顾 我们目前正在开发一把虚拟剑,目的是让角色可以用这把剑进行攻击。最初的工作中,我们使用了一个摇滚位图作为虚拟剑的模型,并且实现了一个基本的功能:角色可以丢下剑。但这个功能并没有达到预期的效果,因为我们想…...

LeetCode - Google 校招100题 第6天 回溯法(Backtracking) (8题)
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/144743505 LeetCode 合计最常见的 112 题: 校招100题 第1天 链表(List) (19题)校招100题 第2天 树(Tree) (21题)校招100题 第3天 动态规划(DP) (20题)...

C项目 天天酷跑(下篇)
上篇再博客里面有,接下来我们实现我们剩下要实现的功能 文章目录 碰撞检测 血条的实现 积分计数器 前言 我们现在要继续优化我们的程序才可以使这个程序更加的全面 碰撞的检测 定义全局变量 实现全局变量 void checkHit() {for (int i 0; i < OBSTACLE_C…...
达梦数据守护搭建
主备库初始化 ./dminit path/dmdata/data db_nameDM01 instance_nameDMSVR01 port_num5236 page_size16 extent_size32 log_size500 case_sensitive1 SYSDBA_PWDDM01SYSDBA ./dminit path/dmdata/data db_nameDM02 instance_nameDMSVR02 port_num5236 page_size16 extent_size3…...

记录一次前端绘画海报的过程及遇到的几个问题
先看效果 使用工具 html2canvas import html2canvas from html2canvas// 绘画前的内容 我就不过多写了<div class"content" ref"contentRef" v-show"!imgShow"><img :src"getReplaceImg(friendObj.coverUrl)" alt"&qu…...

24.12.26 SpringMVCDay01
SpringMVC 也被称为SpringWeb Spring提供的Web框架,是在Servlet基础上,构建的框架 SpringMVC看成是一个特殊的Servlet,由Spring来编写的Servlet 搭建 引入依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc<…...

一分钟快速了解Ecovadis认证等级划分
Ecovadis认证等级划分,作为评估企业社会责任表现的重要标尺,其细致而严谨的体系为全球范围内的企业提供了一个可量化的衡量标准。这一认证等级不仅彰显了企业在环境保护、劳工权益、商业道德以及可持续发展等方面的努力与成就,更是企业向国际…...

科技云报到:人工智能时代“三大件”:生成式AI、数据、云服务
科技云报到原创。 就像自行车、手表和缝纫机是工业时代的“三大件”。生成式AI、数据、云服务正在成为智能时代的“新三大件”。加之全球人工智能新基建加速建设,成为了人类社会数字化迁徙的助推剂,让新三大件之间的耦合越来越紧密。从物理世界到数字世…...
【网络云计算】2024第52周-每日【2024/12/26】小测-理论实操-备份MySQL数据库并发送邮件-解析
文章目录 1. 编写备份脚本2. 设置定时任务3. 注意事项 【网络云计算】2024第52周-每日【2024/12/26】小测-理论&实操-备份MySQL数据库并发送邮件-解析 为了实现您提出的Discuz数据库备份任务,包括备份脚本、定时任务、备份成功邮件确认、脚本运行时长、备份后的…...

菜鸟带新鸟——基于EPlan2022的部件库制作(3D)
设备逻辑的概念: 可在布局空间 中和其它对象上放置对象。可将其它对象放置在 3D 对象上。已放置的对象分到组件的逻辑结构中。 将此属性的整体标识为设备逻辑。可使用不同的功能创建和编辑设备逻辑。 设备的逻辑定义 定义 / 旋转 / 移动 / 翻转:组…...

Level DB --- MemTable
MemTable是Level DB中重要的组件,它主要处理Level DB内存级别的增删查改。 基本数据结构 基础的存储数据结构如图1所示,这是一个存储单元的结构。其中1是internal key size,这里面包括两部分,一部分我们Level DB存储key-value中…...

【山西长治】《长治市市直部门政务信息化建设项目预算编制规范和预算编制标准》(长财行[2022]25号)-省市费用标准解读系列32
《长治市市直部门政务信息化建设项目预算编制规范和预算编制标准(试行)》(长财行[2022]25号)于2022年8月1日开始试行,此标准由长治市财政局、长治市行政审批管理局编制,是对信息化建设项目预算管理的基本要求,主要适用…...
海格通信嵌入式面试题及参考答案
计算电路的最高工作频率如何计算? 计算电路的最高工作频率主要考虑电路中的关键路径延迟。关键路径是指在整个电路中,信号传播延迟最长的路径。电路的最高工作频率的倒数就是时钟周期,而时钟周期必须大于关键路径的延迟时间。 首先要确定电路中各个模块的延迟。比如对于组合…...

前端学习DAY27(盒子模型内边距)
内边距(padding),指的是盒子的内容区与盒子边框之间的距离 一共有四个方向的内边距, 可以通过: padding-top padding-right padding-bottom padding-left <!DOCTYPE html> <html lang"en"> <head><meta charset"U…...

基于cobra开发的k8s命令行管理工具k8s-manager
基于cobra开发的k8s命令行管理工具k8s-manager 如果觉得好用,麻烦给个Star!通用配置1 node 分析所有node的资源情况2 analysis 分析Node节点上的资源使用构成3 image 获取指定namespace的所有镜像地址4 resource 获取指定namespace的所有limit 与 Requests大小5 top…...
scala基础学习(数据类型)-数组
文章目录 数组 Array创建数组直接定义fillofDimtabulate range打印数组toSeqdeepforeach(println) length获取长度indexOf 获取元素索引获取元素/修改元素遍历数组数组内元素转换filter 过滤found 查找元素数组折叠 foldLeft切片拼接排序拷贝copyclone 数组 Array Array是一个…...

uniapp 微信小程序 页面部分截图实现
uniapp 微信小程序 页面部分截图实现 原理都是将页面元素画成canvas 然后将canvas转化为图片,问题是我页面里边本来就有一个canvas,ucharts图画的canvas我无法画出这块。 想了一晚上,既然canvas最后能转化为图片,那我直接…...

C语言从入门到放弃教程
C语言从入门到放弃 1. 介绍1.1 特点1.2 历史与发展1.3 应用领域 2. 安装2.1 编译器安装2.2 编辑器安装 3. 第一个程序1. 包含头文件2. 主函数定义3. 打印语句4. 返回值 4. 基础语法4.1 注释4.1.1 单行注释4.1.2 多行注释 4.2 关键字4.2.1 C语言标准4.2.2 C89/C90关键字…...

直流无刷电机驱动原理3-驱动板硬件设计
六步换向原理 检测转子角度,知道什么时候是60度,什么时候应该换向。 逆时针旋转 三相逆变器,mos管,半桥驱动电路。 PWM调制 不对称半桥调制例程使用第(2)种。对上桥臂PWM调制,下桥臂全部导通。这时候由上桥臂的PWM的占空比决定电机的旋转速度。驱动器电路硬件框图--实…...

攻防世界web第三题file_include
<?php highlight_file(__FILE__);include("./check.php");if(isset($_GET[filename])){$filename $_GET[filename];include($filename);} ?>惯例: 代码审查: 1.可以看到include(“./check.php”);猜测是同级目录下有一个check.php文…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...

Linux基础开发工具——vim工具
文章目录 vim工具什么是vimvim的多模式和使用vim的基础模式vim的三种基础模式三种模式的初步了解 常用模式的详细讲解插入模式命令模式模式转化光标的移动文本的编辑 底行模式替换模式视图模式总结 使用vim的小技巧vim的配置(了解) vim工具 本文章仍然是继续讲解Linux系统下的…...