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

游戏引擎学习第43天

仓库 https://gitee.com/mrxiao_com/2d_game

介绍运动方程

今天我们将更进一步,探索运动方程,了解真实世界中的物理,并调整它们,以创建一种让玩家感觉愉悦的控制体验。这并不是在做一个完美的物理模拟,而是找到最有趣的控制方式。我们会通过试错来探索这些运动方程,并找到让英雄角色运动感觉最佳的方式。我们不提前知道这些答案,我们将通过尝试和错误的方式来发现。

昨天的回顾。

我们在开发过程中将玩家的位置结构转化为一个联合体,简单来说,这就是一个包含xy坐标的对。我们通过将其与所有相关的代码结合起来,使得这些代码更加简洁和直观。然而,我们仍然保留了一些原始的数学处理方式,如处理xy分量作为独立的标量。虽然这并不是必要的,但它提供了一种更清晰的方式来理解和处理玩家位置。

运行游戏后,我们立即感受到的问题是角色的运动感觉不太好。角色在移动时缺少加速和减速,停止得太快,没有任何动量反馈。这种情况让控制体验显得很生硬,也不符合我们希望的游戏感觉。为了改善这一点,我们需要给角色添加一些基本的运动感,如轻微的加速和减速效果。这不仅能增加游戏的可玩性,还能让玩家感觉更有控制感,同时保持动作游戏的紧凑性,不至于让玩家感到困扰。

动作深入分析:刚体动力学。

在我们讨论对象如何在现实世界中移动时,重力是一个常见的力,它对所有物体产生的向下作用力至关重要。这种力使得任何物体在没有其他外力作用时会逐渐下落。就像一个保龄球,它会一直受到重力的作用,并形成一种自然的运动模式。另一方面,还有线性和角度运动两种基本的运动类型。线性运动涉及物体在空间中平移,而角度运动则涉及物体的旋转,这两种运动在物理学上并无不同,都是由微观物理原理(如原子和夸克运动)决定的。

在我们的模拟过程中,我们主要关注的是这些宏观运动,而不是微观的原子级别行为。因此,无论球是如何旋转或移动的,这些都不需要在图形上详细展示,重要的是我们如何用这些运动来表现物体在空间中的状态。这种理解帮助我们简化了模拟和控制,使得玩家在游戏中的操作更加直观和自然。

线性动力学。

在讨论物体如何在现实中移动时,我们主要关注物体的线性部分。任何物体的运动都受到外力的影响,比如重力和其他可能的外力,如风。这些力作用在物体上并决定其运动方式。为了简化物理模型,我们可以将物体的复杂性减少到一个中心质量点,这就是质心。这一中心点代表了物体的整体质量分布的平均位置。

根据牛顿第二定律,力等于质量乘以加速度,即 F = m a F = ma F=ma。这表明,重物需要更大的力才能产生相同的加速度。我们可以利用这一方程来计算物体的加速度,当我们知道所有作用于物体的力后,再根据这些力来推断物体的位置。这样,我们就能将物理规律与渲染和碰撞检测等计算任务联系起来,从而在虚拟环境中表现物体的运动。

基本运动方程。

当我们讨论运动时,我们谈论的是物体的位置、速度和加速度之间的关系。这三者的相互依赖性定义了物体在任何给定时间的运动方式。例如,速度是位置的变化率,而加速度则是速度的变化率。因此,加速度直接影响物体的位置和运动路径。

在实现这些概念时,我们使用一个时间差的计算,即 delta t,这是帧之间的时间差。这使得我们能够计算物体的移动距离。例如,在游戏开发中,每帧我们会基于物体的当前方向和速度来更新其位置。通过将方向乘以时间增量,我们可以计算出在该时间段内物体的实际移动距离。这些计算反映了物体如何在屏幕上从一个位置移动到另一个位置,并考虑了时间对物体运动的影响。

这些基本的物理方程帮助我们理解和实现物体的运动模拟,在计算机图形学中,这些模拟技术使得物体的运动更加真实和流畅。

如何计算运动。

向量可以看作是一种具有大小的数学实体。我们使用向量来表示物体在一个特定方向上的运动。在计算中,向量的大小是由其长度决定的,通常通过勾股定理来计算。例如,如果一个物体在两个方向上分别移动10米和6米,我们可以使用勾股定理来计算其实际运动的总距离(向量的大小)。

然后,我们结合了物体的速度,每秒移动多少米,以及时间步长来确定实际的运动距离。速度与时间乘积等同于物体在一秒钟内的运动量。这些计算实际上是利用了积分,反映了速度如何累积到一个新的位置。因此,向量和速度的结合帮助我们更清晰地描述物体在时间中的位移。

一些微积分。

我需要从高中微积分课程中的思维方式中转变,这可能并不那么有用,即使所有的工具都在那里。我们不再仅仅依赖于固定的方程,而是要理解和处理不断变化的动态情况。例如,在游戏中,角色的位置和速度并不是固定的,而是随着时间的推移而变化。这就需要我们重新思考和计算这些关系,如位置的导数为速度,速度的导数为加速度。这种方法更符合实际应用的需求,并能够灵活处理各种复杂的动态情境。

以不同方式计算运动。

探讨了如何通过对时间步进行简化的方式,来模拟物体的运动。这些模拟并不需要复杂的常数方程,而是通过在每个时间步上应用一个简单的分段函数来实现。这种方法允许我们在不考虑每一个具体情况的情况下,对物体的运动进行粗略的建模。这实际上是对物理定律的一种简化假设,使得计算更加高效,避免了过多的复杂度。

目前代码的实现。

我们已经有一个方程用于计算物体的位置,这个方程结合了速度与时间的乘积和物体在上一个时间点的位置。这部分的计算其实是我们在写游戏代码时所熟悉的直觉。为了更准确地模拟物体的运动,我们需要考虑速度作为一个独立的量来进行存储。速度的变化需要累积,这意味着物体在每个时间步长中的运动状态都需要反映出来,这样在更新物体位置时才能使用到最新的速度信息

我们打算如何修改它以使用新的方程。

在这段讨论中,我们谈论了从一帧到一帧的更新过程。为了准确地模拟物体的运动,我们需要考虑加速度的累积影响,而不仅仅是瞬时的作用。这意味着在每一帧的开始时,我们需要更新物体的速度,以便将其累加到当前位置。这样做能够更真实地反映物体在整个时间段内的运动,而不仅仅是在单一时刻的加速度。对于写游戏代码的人来说,这意味着不只是简单地把这些物理细节处理掉,而是要仔细思考这些影响和所使用的方程。虽然可以简单地忽略一些细节来优化性能,但如果要做更真实的物理模拟,了解这些细节是非常重要的。只有当这些方程和原理被理解并应用时,才能确保物体在游戏中有可信的行为。

关于时间增量的讨论。

在这段讨论中,我们探讨了如何处理时间步长(delta t)在运动方程中的作用。我们将函数视为在每一帧内的瞬时计算,这些函数将加速度和位移整合到整个时间段内。例如,当计算物体的最终位置时,我们需要考虑在当前帧内加速度的累积影响,而不仅仅是单个时刻的瞬时加速度。每一帧都重新计算这个函数,利用之前计算的值和新的时间步长delta t,来更新物体的速度和位置。这使得我们能够在游戏中更准确地模拟物体的运动,而不是假设加速度仅在某一瞬间作用。通过这种方式,我们不断把握每一帧的运动变化,确保物体在整个时间内的行为是连续和可信的。

分段函数。

在这段讨论中,我们探讨了在游戏编程中如何处理物体的运动函数。在游戏中,当玩家控制某个物体时,物体的加速度在每一帧都是不同的,这意味着需要重新计算并调整函数。这些函数并不像数学中的连续函数那样可以进行线性分析,而是被称为“分段函数”。这些函数是由若干独立的部分组成的,每一部分代表物体在不同时间段内的运动方式。这种方法更能反映游戏中的实际情况,因为物体的运动不一定是平滑的,它可能包含急转弯或其他不连续的动作。这些“分段”之间可能有突出的曲线弯曲点,这种方式可以更好地模拟真实的物理效果,同时也能让游戏中物体的运动更加动态和多样化。

实现。

我们正在处理物体的速度和加速度问题。我们需要存储这些量以便从一帧到下一帧进行更新。速度的变化和加速度都是根据时间的变化计算出来的。为了简化这些计算,我们可以使用一个平方函数来直接将速度和加速度的变化进行处理。这样做不仅可以节省代码量,还能减少出错的可能性。我们假设物体在平滑的运动中加速,不考虑碰撞等细节。这就是我们现在的主要工作。
在这里插入图片描述

在这里插入图片描述

在数学上,一阶导(速度)和二阶导(加速度)与位移 s 的关系如下:

1. 一阶导(速度):

  • 定义:速度 v 是位移 s 随时间 t 的变化率。
  • 数学公式
    v = d s d t v = \frac{ds}{dt} v=dtds
    这里, d s ds ds 是位移的微小变化, d t dt dt 是时间的微小变化。速度 v 表示物体在给定时间内的位移变化。

2. 二阶导(加速度):

  • 定义:加速度 a 是速度 v 随时间 t 的变化率。
  • 数学公式
    a = d v d t a = \frac{dv}{dt} a=dtdv
    这里, d v dv dv 是速度的微小变化, d t dt dt 是时间的微小变化。加速度 a 表示物体速度的变化量,即每单位时间内速度的变化率。

3. 位移公式(s):

  • 定义:位移 s 是物体在给定时间 t 内的路径长度。
  • 数学公式
    s = 1 2 a Δ t 2 + v 0 Δ t + s 0 s = \frac{1}{2} a \Delta t^2 + v_0 \Delta t + s_0 s=21aΔt2+v0Δt+s0
    其中:
    • s 0 s_0 s0 是初始位置,
    • v 0 v_0 v0 是初始速度,
    • a a a 是加速度,
    • Δ t \Delta t Δt 是时间。

这个公式综合了物体的初始位置、初始速度和加速度的影响,用来计算物体在任意时刻的位移。

4. 当前瞬时速度:

在代码中,当前的瞬时速度加速度上次速度的关系是基于运动学公式:

v new = a ⋅ Δ t + v old v_{\text{new}} = a \cdot \Delta t + v_{\text{old}} vnew=aΔt+vold

总结:

  • 加速度控制速度的变化率。
  • 当前帧的瞬时速度是基于上次的速度,加上加速度在这一帧的贡献。

在这里插入图片描述

看一下现在的游戏。我们注意到玩家没有摩擦力。

我们现在实现了一个对象的运动方程,并且这个对象的行为完全符合预期。当前的实现中没有引入摩擦力,因此对象具有类似滑冰运动员或漂浮在太空中的小行星的行为方式。当他移动时,他会以动量为主导,没有任何外部的摩擦力对其速度产生影响。

对象的速度更新是通过叠加加速度和上一帧速度完成的,这是一种基于物理的合理方式。然而,当对象与墙壁发生碰撞时,我们的碰撞检测机制会阻止对象穿过墙壁,这一点已经正确实现,但目前并没有将对象的速度调整为零,而是继续保存其原本的速度。这导致了一种现象,即对象看似仍然在沿着某个方向加速。

这种设计对于玩家体验来说可能不够友好,因为当对象与墙壁接触后,如果玩家想反方向推动对象,他们需要花费一些时间来逆转速度。为了改善体验,我们可能需要在碰撞发生后立即调整速度,这样对象的行为会更加符合直观预期。

接下来可以考虑:

  1. 引入摩擦力,用于逐渐减小对象的速度,使其停止。
  2. 更新碰撞检测后的速度,使对象与墙壁接触时速度立即调整到零,从而避免出现虚假的速度。
  3. 可能在界面上展示速度的可视化效果,让玩家直观地了解对象的运动状态。

当前的实现虽然物理上正确,但对于玩家操作的体验来说可能需要进一步优化。我们需要确保速度的更新逻辑不仅仅是物理上的合理,同时也符合游戏体验的需求。

实现一些摩擦力。

我们尝试在运动中引入摩擦力。假设角色在场景中移动时,我们会受到速度的影响,因此需要某种摩擦或拖拽效应来模拟现实的阻力。

首先,为了简化,我们通过一个近似方法实现摩擦力,而不是完全精确的数学建模。实现时,我们通过计算加速度的反方向分量来模拟摩擦力。这种方法可以使角色在停止时显得更自然。

在代码中,我们调整了加速度的值,以实现合理的摩擦效应。例如,我们尝试将摩擦力的影响降低至速度的一部分(如0.5倍),逐步调整以观察效果。发现随着加速度的增加,角色的运动逐渐趋于自然,停止的响应也更快。

调整与测试

  • 初步测试:角色的运动显得太生硬,因此降低了摩擦强度。
  • 进一步优化:调整摩擦系数和加速度,找到一个平衡点,使角色的运动显得顺滑但不失阻力效果。
  • 最终结果:在不同参数的尝试后,找到了使角色运动更流畅的设置,既保留了惯性,又能迅速减速。

后续改进方向

目前的实现只是一个粗略近似,未来可以通过引入微分方程等更复杂的数学模型,精确模拟力与运动的关系。此外,碰撞检测功能仍需进一步完善,以保证角色在场景中的交互更加自然流畅。

通过这种方式,我们不仅提高了角色的操作手感,还为未来的改进和功能扩展奠定了基础。

在这里插入图片描述

公式(模拟中常用)


这段代码对应的物理模型是速度相关阻力,摩擦力的形式为:
F friction = − k ⋅ v F_{\text{friction}} = -k \cdot v Ffriction=kv
其中:

  • F friction F_{\text{friction}} Ffriction 是摩擦力或阻力,方向与速度 v v v 相反。
  • k k k 是与系统相关的比例系数(这里为 0.75 0.75 0.75)。
  • v v v 是当前速度(在代码中为 GameState->dPlayerP)。

根据牛顿第二定律 F = m a F = ma F=ma,加速度 a a a 和阻力之间的关系为:
a friction = F friction m = − k m ⋅ v a_{\text{friction}} = \frac{F_{\text{friction}}}{m} = -\frac{k}{m} \cdot v afriction=mFfriction=mkv

在代码中,ddPlayer(加速度)增加了一个阻力项:
d d P l a y e r → d d P l a y e r − k ⋅ v ddPlayer \rightarrow ddPlayer - k \cdot v ddPlayerddPlayerkv
这里的 − 0.75 f -0.75f 0.75f 实际上可以看作 − k m -\frac{k}{m} mk 的值。


为什么要使用真实物理,而不是可以手动调校的自定义物理?

在游戏开发中,选择使用真实的物理公式,而不是完全自定义的、手动调整的方式,背后有重要原因。尽管我们可以对参数进行手动调整,并不意味着从头到尾依赖直觉设计是最佳选择。以下是详细的复述与总结:

使用物理公式的核心原因

  1. 基础的重要性

    • 真实物理的基础为开发提供了可靠的起点,这些方程描述了物体在现实中运动的基本规律。
    • 人类对物体运动的直觉是与生俱来的。如果游戏中的运动模式偏离这种直觉,玩家会感到不自然,甚至觉得游戏“手感糟糕”。
    • 基于物理的系统能让玩家更容易理解游戏中的互动,并对操作结果做出合理预测。
  2. 避免低效的开发方式

    • 完全依赖自定义输入或手动调整的运动逻辑,容易因为缺乏对物理基础的理解而失败。
    • 开发者可能花大量时间试图手动优化,却难以获得自然的手感,这种方式风险高且不可控。
  3. 改进体验的灵活性

    • 以物理公式为基础开发后,可以根据需要在特定场景调整或偏离这些规则(如加入空气控制、双跳等)。
    • 这种方法在保持直觉自然的同时,允许高度的定制化,满足设计需求。

物理公式的好处

  1. 自然且真实的运动感

    • 使用物理方程,跳跃、移动等动作会遵循抛物线等自然轨迹,玩家可以更好地预判和适应。
    • 例如,当角色撞到墙上时,现实中的动量会导致滑动或反弹,而不是突然停止。这种符合直觉的细节大幅提升了沉浸感。
  2. 提升玩家体验

    • 如果运动逻辑直观,玩家会更快掌握游戏的操作。
    • 反之,如果运动规则不符合预期,玩家会因为不适应而放弃游戏,即使游戏本身有其他优秀的设计。
  3. 避免破坏感受的设计问题

    • 比如,墙面“粘性”导致角色在墙边停顿或卡顿,这样的体验会让游戏感觉生硬而不流畅。
    • 通过基于物理的调整,可以让角色在接触边缘时滑动、转移,获得更自然的手感。

开发建议

  1. 从真实物理开始

    • 不论最终目标是什么,都建议从最接近实际情况的物理方程开始,并根据需要逐步调整。
    • 这种方式能确保设计的基础是可靠且直观的。
  2. 精益求精,确保“核心感觉”正确

    • 游戏中的“核心感觉”必须准确,如角色的跳跃、移动等主要交互。即使游戏其他方面设计出色,但如果角色移动的体验很差,玩家可能根本不会深入体验游戏。
  3. 学习基础物理编程

    • 理解基本的物理方程是开发者的重要技能。一旦掌握这些规则,可以根据设计需求自由调整,而不会损失基础的自然感。

总结

将物理方程融入游戏开发不是为了实现完全模拟,而是为了打造符合玩家直觉的操作体验。真实物理提供了一个稳定的起点,确保玩家能快速适应游戏逻辑。同时,开发者可以在基础之上添加复杂的自定义效果,而不必担心手感失衡。忽视这一点可能会使玩家因控制体验糟糕而放弃游戏,从而影响游戏整体的成功潜力。

为什么不在碰撞发生时添加一个反向方向的减速度?

当角色碰撞发生时,可以考虑添加基于初始速度 v i v_i vi 的反向减速机制,这样角色在接近墙壁时可以逐渐减速,最终平滑地到达墙体边缘的最后一个像素位置。这种方法的好处在于提供了一种更自然且直观的控制方式。

在设计与墙壁相关的碰撞机制时,这部分非常关键,因此需要深入研究和优化。未来将会专注于这方面的细节,使墙壁交互能够达到理想的效果。通过适当的碰撞处理方式,既能让角色运动自然,也能避免运动的突兀和停滞感。

总结来看,这种基于反向减速的机制可以:

  1. 优化角色靠近墙体的运动

    • 角色在接近墙体时逐渐减速,不会突然停止,从而避免了生硬感。
    • 角色可以流畅地贴近墙体边缘,而不是产生明显的“粘滞”或“卡顿”现象。
  2. 增强玩家的操作反馈

    • 玩家可以更好地控制角色靠近墙体的行为,从而提升交互体验。
    • 碰撞时的平滑运动让玩家更直观地理解角色与墙壁的关系。
  3. 为进一步优化墙壁交互打基础

    • 后续设计中可以结合这种机制,加入更多墙体相关的功能(如壁滑、壁跳),让角色的操作更加丰富和自然。

未来的工作将会围绕墙壁互动展开,确保碰撞的物理表现和控制手感达到最佳状态。这一过程可能需要反复调试和测试,但能够显著提升整体的游戏体验。

是否担心实际物理会削弱世界上最伟大的跳跃代码的美学和优雅?

虽然实际的物理模拟可能会让某些非常规的代码设计显得不再那么纯粹,但这也是为了提升游戏的真实感和玩家体验。开发者在做这些决策时,常常需要权衡各种因素,包括物理模拟对游戏的影响和如何最大化保留游戏设计的独特性和美感。这种平衡可以影响游戏的操作感觉,控制手感以及最终玩家的体验。

如果你想要像Braid那样倒转时间,你需要存储什么?

对于游戏开发和物理模拟来说,涉及到的很多问题是不可逆的。物理学中的非反向能力主要是因为系统中的能量丢失。举个例子,如果一个物体滑动或撞击,会导致能量散失,如摩擦力或空气阻力。即使你尝试倒回这个过程,恢复到原来的状态,许多信息都已经丢失,因此不可能简单地将过程反向播放。为了实现“逆转时间”的效果,必须记录系统中的重要状态点,并理解这些信息在反向播放时的重要性。然而,这种方法无法完全恢复到过去的状态,而只是重新构建一个大致相似但不可逆的模拟。

角色是位图吗?

我们在加载角色时使用了位图,并将其分割为三个部分。这些部分使得角色具有一定的弹性,能够进行一些弹跳和移动的动作。虽然希望在周末之前完成这些工作,但如果不是,下个周末也会完成。接下来,我们还会对这些部分进行更多操作,进一步探索和优化角色的表现。

我们是否会对输入进行归一化,而不是为对角线情况特设?

我们可能会在某些情况下开始对输入矢量进行规范化,而不是仅仅依赖于一个特殊的主角。虽然现在还没有实现这个功能,但我们计划很快就会开始进行这一操作。这将使我们的处理更加标准化和一致。

会不会有一个映射函数来帮助确定摩擦和碰撞的地形?

目前尚未确定是否会有大量滑动或减速的元素,尽管这是这类游戏的典型特征。因此,虽然在脑海中有类似的设想,但还没有特别考虑这些机制带来的独特体验。可能会在未来加入这一类功能,但现在还没有明确的计划。

为什么使用v2而不是vec2或vector2?

通常他们更喜欢名字具有描述性,并在使用时简化它们。对于向量,他们习惯性地使用“v”而不是“vector”,因为它更短、更简洁。虽然目前没有完成过这一点,但他们可能会考虑未来改用更短的命名方式,比如“32”代替“thirty two”,以便使名称更为简洁。

为什么不把代码分成更小的函数?

在编写代码时,不要过早地将代码分解成函数,直到明确知道这些函数应该完成什么任务。这是因为提前将代码分解成函数可能会浪费时间,因为它们可能需要重写或合并到更大的功能中。当一个功能的确立不明朗时,将这些代码块提前拆分可能会增加代码的复杂性,使其更难以阅读和维护。将代码单独放入函数中并命名可能只是简单地增加了语法糖,而并不实际改进代码的可读性。最重要的是,在知道具体需求和功能后,合理地将代码分解成方法,可以提高代码的可维护性和可读性。

难道不应该使用一个最大速度变量吗?

使用一个最大速度变量可能是一个人为的设计决策,因为它限制了游戏中的玩家角色的速度。然而,这种限制不一定是有趣的或需要的。可能希望玩家能够在游戏环境中受到各种力的影响,并自由地以最快的速度移动,而不必受限于一个最大速度。这样设计可以让游戏更具真实性和可探索性。例如,如果玩家在太空中漂浮,他们可以以最快的速度前进,因为没有摩擦力的影响。因此,把最大速度看作是一种人工构造,可能不适合所有的游戏设计需求。

摩擦的负加速度基于当前速度会感觉更好。

有人提到,基于当前速度的摩擦负加速度会显得更自然。对此,我们的设计就是实现了这一点。负加速度与当前的速度相关联,这样摩擦力在玩家的运动过程中逐渐减少,从而产生更自然的减速感觉。这是代码的一部分体现,所以不太理解该提问的具体意思。这就是我们目前使用的设计。

你认为像bullet或box2d这样的东西适合用于玩家运动吗?

我理解你的困惑,像bullet或box2d这样的物理模拟通常会让游戏响应变得很麻烦,无法得到稳定的效果。这主要是因为真实物理模拟很难控制和调试,它们可能会过于复杂且不稳定。一般来说,我倾向于使用一种基础物理模型,确保运动的基本逻辑是正确的,然后再进行游戏设计调整,避免完全依赖复杂的物理模拟。这可以在不影响游戏体验的情况下,提供较为稳定的响应。因此,找到一种折中的方法来处理物理交互问题通常是一个更好的选择。

当何时使用其他积分方法?

数值积分和欧拉法的使用以及它们在不同场景中的应用。用户提到的欧拉法的局限性,尤其是在面对复杂系统时,说明了向后欧拉法的优势,它在逆向求解运动方程时能够避免数值积分的稳定性问题。这种方法能够更好地保持系统的能量稳定,避免数值飞溅问题。虽然向后欧拉法更具挑战性和成本,但在特定复杂的物理系统中,它能够提供更精确的解。这一对话展示了在数值集成中,正确的集成方法和算法选择对于获得稳定和准确的结果是多么重要。

即使英雄已经有弹跳了,我们还会使用刚体吗?

在游戏开发中如何处理物理模拟,特别是刚体(rigid body)的行为和一些非物理效果。即使英雄角色获得了弹性效果,它的物理模拟仍然会基于不同的差分方程,而不是解决与物理材质相似的实际问题,如凝胶状的物质。这意味着这些效果主要是作为视觉和动作上的图形效果,而不是物理行为上的模拟。

相关文章:

游戏引擎学习第43天

仓库 https://gitee.com/mrxiao_com/2d_game 介绍运动方程 今天我们将更进一步,探索运动方程,了解真实世界中的物理,并调整它们,以创建一种让玩家感觉愉悦的控制体验。这并不是在做一个完美的物理模拟,而是找到最有趣…...

NVM:安装配置使用(详细教程)

文章目录 一、简介二、安装 nvm三、配置 nvm 镜像四、配置环境变量五、使用教程5.1 常用命令5.2 具体案例 六、结语 一、简介 在实际的开发和学习中可能会遇到不同项目的 node 版本不同,而出现的兼容性问题。 而 nvm 就可以很好的解决这个问题,它可以在…...

matlab测试ADC动态性能的原理

目录 摘要: 简介: 动态规范和定义 动态规格: 双面到单边的功率谱转换 摘要: 模数转换器(adc)代表了接收器、测试设备和其他电子设备中的模拟世界和数字世界之间的联系。正如本文系列的第1部分中所概述…...

PostgreSQL JSON/JSONB 查询与操作指南

PostgreSQL 提供了强大的 JSON 和 JSONB 数据类型及相关操作,适用于存储和查询半结构化数据。本文将详细介绍其常用操作。 1. 基础操作 1.1 JSON 属性访问 ->: 返回 JSON 对象中的值,结果为 JSON 格式。 SELECT {"a": {"b": 1…...

【Isaac Lab】Ubuntu22.04安装英伟达驱动

目录 1.1 禁用nouveau驱动 1.2 安装必要的依赖项 1.3 下载安装 1.4 查看是否安装成功 1.5 安装CUDA 1.5.1 下载 1.5.2 按照提示进行下载安装 1.5.3 添加环境变量 1.5.4 测试CUDA是否安装成功 1.1 禁用nouveau驱动 输入以下命令打开blacklist.conf文件 sudo vim /etc…...

JS,递归,处理树形数据组件,模糊查询树形结构数据字段

JS递归如何模糊查询树形结构数据,根据数据中的某一个字段值,模糊匹配 直接拿去使用就行 function filterTreeLabel(arr, label) {let result []arr.forEach((item) > {// if (String(item.POBJECT_NAME).toLowerCase().indexOf(label)!-1) {if (String(item.P…...

神州数码DCME-320 online_list.php 任意文件读取漏洞复现

0x01 产品描述: ‌神州数码DCME-320是一款高性能多业务路由器,专为多用户、多流量和多业务种类需求设计‌。它采用了...

nginx的内置变量以及nginx的代理

nginx的内置变量 客户端 命令含义$uri可以获取客户端请求的地址,包含主机和查询的参数$request_uri:获取客户端的请求地址,包含主机和查询参数。$host:请求的主机名,客户端—发送请求的url地址$http_user_agent获取客户端请求的浏览器和操作…...

ubuntu监测硬盘状态

安装smartmontools smartctl -l error /dev/sdk smartctl -i /dev/sda lshw -class disk smartctl -H /dev/sd 结果1: 结果2:PASSED,这表示硬盘健康状态良好 smartctl -a /dev/sdb sdk lsblk blkid 测试写入速度 time dd if/dev/zero of…...

3.2.1.2 汇编版 原子操作 CAS

基本原理说明 在 x86 和 ARM 架构上,原子操作通常利用硬件提供的原子指令来实现,比如 LOCK 前缀(x86)或 LDREX/STREX(ARM)。以下是一些关键的原子操作(例如原子递增和比较交换)的汇…...

InnoDB事务系统(二):事务的实现

事务隔离性由锁来实现。原子性、一致性、持久性通过数据库的 redo log 和 undo log 来完成。 redo log 称为重做日志,用来保证事务的原子性和持久性。undo log 用来保证事务的一致性。 有的 DBA 或许会认为 undo 是 redo 的逆过程,其实不然。redo 和 u…...

xdoj :模式匹配

模式匹配 题目描述: 接收信号中包含特定的信号模式,对接收信号进行检测,以统计特定模式出现的次数。 例如接收信号为 9 3 5 7 5 8 6 3 5 7 1 9 3 5 7,如果特定信号为 3 5 7,则接收信号中包含了 3 个特定模式。通过键…...

Redis的基本使用命令(GET,SET,KEYS,EXISTS,DEL,EXPIRE,TTL,TYPE)

目录 SET GET KEYS EXISTS DEL EXPIRE TTL redis中的过期策略是怎么实现的(面试) 上文介绍reids的安装以及基本概念,本章节主要介绍 Redis的基本使用命令的使用 Redis 是一个基于键值对(KEY - VALUE)存储的…...

LruCache(本地cache)生产环境中遇到的问题及改进

问题:单机qps增加时请求摘要后端,耗时也会增加,因为超过了后端处理能力(最大qps,存在任务堆积)。 版本一 引入LruCache。为了避免数据失效,cache数据的时效性要小于摘要后端物料的更新时间&…...

智慧公交指挥中枢,数据可视化 BI 驾驶舱

随着智慧城市的蓬勃发展,公共交通作为城市运营的核心枢纽,正朝着智能化和数据驱动的方向演进。通过整合 CAN 总线技术(Controller Area Network,控制器局域网总线)、车载智能终端、大数据分析及处理等尖端技术,构建的公交“大脑”…...

【计算机网络】期末考试预习复习|上

作业讲解 物理层作业 共有4个用户进行CDMA通信。这4个用户的码片序列为: A: (–1 –1 –1 1 1 –1 1 1);B: (–1 –1 1 –1 1 1 1 –1) C: (–1 1 –1 1 1 1 –1 –1);D: (–1 1 –1 –1 –1 –1 1 –1) 现收到码片序列:(–1 1 –…...

YOLOv8目标检测(四)_图片推理

YOLOv8目标检测(一)_检测流程梳理:YOLOv8目标检测(一)_检测流程梳理_yolo检测流程-CSDN博客 YOLOv8目标检测(二)_准备数据集:YOLOv8目标检测(二)_准备数据集_yolov8 数据集准备-CSDN博客 YOLOv8目标检测(三)_训练模型:YOLOv8目标检测(三)_训…...

AI工具如何深刻改变我们的工作与生活

在当今这个科技日新月异的时代,人工智能(AI)已经从科幻小说中的概念变成了我们日常生活中不可或缺的一部分。从智能家居到自动驾驶汽车,从医疗诊断到金融服务,AI正以惊人的速度重塑着我们的世界。 一、工作方式的革新…...

springboot中——Logback介绍

程序中的日志&#xff0c;是用来记录应用程序的运行信息、状态信息、错误信息等。 Logback基本使用 springboot的依赖自动传递了logback的依赖&#xff0c;所以不用再引入依赖 之后在resources文件下创建logback.xml文件&#xff0c;写入 <?xml version"1.0" …...

【Tomcat】第一站:理解tomcat与Socket

目录 1. Tomcat 1.1 Tomcat帮助启动http服务器。 1.2 tomcat理解&#xff1a; 2. 计算机网络最基本的流程 2.1 信息是怎么来的&#xff1f; 2.2 端口是干什么的&#xff1f; 3. 简单的Socket案例 服务端 客户端 启动&#xff1a; 3.2 在Tomcat发送信息&#xff0c;看…...

TQ15EG开发板教程:使用SSH登录petalinux

本例程在上一章“创建运行petalinux2019.1”基础上进行&#xff0c;本例程将实现使用SSH登录petalinux。 将上一章生成的BOOT.BIN与imag.ub文件放入到SD卡中启动。给开发板插入电源与串口&#xff0c;注意串口插入后会识别出两个串口号&#xff0c;都需要打开&#xff0c;查看串…...

Java从入门到工作4 - MySQL

一&#xff1a;检测数据库网络 telnet 127.0.0.1 3306 注意ip和端口后之间是空格&#xff0c;不需要引号 二&#xff1a;SQL语法 1、创建结果集 SELECT 电视机 AS typeUNION SELECT 电冰箱UNION SELECT 洗衣机UNION SELECT 空调UNION SELECT 电脑UNION SELECT 热水器UNION…...

OpenShift 4 - 多云管理(2) - 配置多集群观察功能

《OpenShift / RHEL / DevSecOps 汇总目录》 本文在 OpenShift 4.17 RHACM 2.12 环境中进行验证。 文章目录 多集群观察技术架构安装多集群观察功能监控多集群的运行状态监控多集群的应用运行在被管集群监控应用运行在管理集群监控被管集群的应用运行 参考 多集群观察技术架构…...

【鸿睿创智开发板试用】RK3568 NPU的人工智能推理测试

目录 引言 驱动移植 例程编译 修改build.sh 执行编译 运行测试 部署libc的库文件 执行测试程序 结语 引言 鸿睿创智的H01开发板是基于RK3568芯片的&#xff0c;瑞芯微芯片的一大特色就是提供了NPU推理的支持。本文将对其NPU推理进行测试。 驱动移植 H01的开发板已经…...

iOS swift开发系列 -- tabbar问题总结

1.单视图如何改为tabbar&#xff0c;以便显示2个标签页 右上角➕&#xff0c;输入tabbar 找到控件&#xff0c;然后选中&#xff0c;把entrypoint移动到tabbar控件 2.改成tabbar&#xff0c;生成两个item&#xff0c;配置各自视图后&#xff0c;启动发现报错 Thread 1: “-[p…...

四、CSS3

一、CSS3简介 1、CSS3概述 CSS3 是 CSS2 的升级版本&#xff0c;他在CSS2的基础上&#xff0c;新增了很多强大的新功能&#xff0c;从而解决一些实际面临的问题。 CSS在未来会按照模块化的方式去发展&#xff1a;https://www.w3.org/Style/CSS/current-work.html …...

Three使用WebGPU的关键TSL

Three.js 使用 WebGPU 的关键 TSL TSL: three.js shader language 介绍 three.js 材质转为webgpu的关键流程, 从而引出 TSL. 1、关键类关系 WebGPURenderer|-- library: StandardNodeLibrary|-- _nodes: Nodes|-- _objects: RenderObjects|-- createRenderObject()StandardN…...

ESP32-S3模组上跑通ES8388(30)

接前一篇文章:ESP32-S3模组上跑通ES8388(29) 二、利用ESP-ADF操作ES8388 2. 详细解析 上一回终于解析完了es8388_init函数的所有代码。本回回到调用它的地方,继续往下讲解。 我们是从ESP32-S3模组上跑通ES8388(7)-CSDN博客开始进入es8388_init函数,展开对于它的解析的…...

概率论得学习和整理24:EXCEL的各种图形,统计图形

目录 0 EXCEL的各种图形&#xff0c;统计图形 1 统计图形 / 直方图 / 其实叫 频度图 hist最合适(用原始数据直接作图) 1.1 什么是频度图 1.2 如何创建频度图&#xff0c;一般是只选中1列数据&#xff08;1个数组&#xff09; 1.3 如何修改频度图的宽度 1.4 hist图的一个特…...

WPF中依赖属性的底层和普通属性的底层有什么不一样

WPF中依赖属性的底层 在 WPF 中&#xff0c;依赖属性&#xff08;Dependency Property&#xff09;是 WPF 属性系统的核心&#xff0c;它支持功能强大的特性&#xff08;如数据绑定、动画、样式等&#xff09;。其底层实现是围绕 DependencyObject 类展开的。以下是 WPF 中依赖…...