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

游戏引擎学习第35天

开场介绍

今天的任务是继续改进一个虚拟的瓦片地图系统,使其适合处理更大的世界。我们希望这个系统能管理大范围的游戏世界,其中包含按需存储的小区域。昨天,我们介绍了“内存区域”的概念,用于管理持久性存储。我们计划今天继续这个主题,深入探讨它的工作原理及其可能的优化方向。

目前,我们的世界生成还相对简单,只是随机生成了一些内容。今天的目标是进一步完善这个过程,并实现一个可以存储和加载更大规模游戏地图的功能。

创建一些房间

我们开始设计一个简单的房间系统。为了让游戏中的小角色能够在这些房间里活动,我们需要设置一些墙壁来限制空间。最初,系统是随机生成的,屏幕大小为32x32,每个瓦片的值也都是随机设置的。为了改进这一点,我们决定在游戏中加入一些实际的墙壁。

在实现时,墙壁的放置方式是:如果某个瓦片的位置位于屏幕的边缘,我们就将这个瓦片的值设为1,这样它就会成为一个“拦截器”或者墙壁。这样做可以在屏幕的边缘生成水平墙壁,同时也可以生成垂直墙壁,从而有效地创建封闭的房间。

通过这种方式,我们能够创建出一个被墙壁围住的空间,使得角色无法轻易离开这个房间,直到墙壁的设置完成。最终,这种设置形成了一个简单的房间,角色被限制在其中,无法脱离该区域。通过这样的方式,我们为小角色提供了一个明确的活动空间。

在这里插入图片描述

创建一些门

目前已经有了基本的房间布局,但是还没有添加任何门。接下来需要做的是为这些房间添加门。门的生成有一些条件,首先需要检查是否满足条件才能在指定位置生成门。如果一个房间的高度大于 2,则不需要门;否则,若宽度超过 2,那么门会出现在中间位置。

这样就能在房间中生成门,使得玩家能够通过这些门穿越不同的房间。这样创建的世界会非常庞大,但目前它还只是一个简单的房间布局,里面没有其他特殊内容。通过这个过程,可以快速生成多个房间,但这些房间目前并没有充实的内容。

进一步的想法是测试地图的稀疏性,尝试进行优化或变化,例如引入一些可能影响帧率的测试。当前的实现方式可能会很慢,因为我们正在循环遍历所有的瓦片并对其进行操作,因此需要进一步优化来提升性能。
在这里插入图片描述

小房间和瓷砖 ID 值的处理

  1. 瓦片尺寸调整:

    • 假设我们将瓦片的尺寸做得非常小,这样在同样的屏幕空间内就能放置更多的瓦片。通过调整瓦片的大小,可以使得在屏幕上显示更多的瓦片,例如,可能将像素单位调整为更小的值,或者以更高的分辨率绘制瓦片地图。
  2. 调整世界的大小:

    • 通过改变瓦片的大小,可以改变游戏世界的规模。当前测试场景的像素数量会影响地图的大小。例如,将瓦片尺寸缩小,使得每个瓦片占据的空间减少,可以让地图的显示变得更大,绘制的瓦片数量也会增加。
  3. 绘制瓦片地图:

    • 初步目标是绘制一个较大的瓦片地图版本,而当前的绘制方法可能会导致帧率变慢,特别是如果我们没有进行优化时。例如,当瓦片数量增加,绘制的计算量增大时,性能可能会下降。
  4. 初始化瓦片地图:

    • 瓦片地图中的某些部分可能还没有初始化。如果某个瓦片区域没有内容(即未初始化),则需要使用不同的颜色或标记(例如灰色)来表示这些区域。这有助于在调试时看到哪些部分是空的,哪些部分是有效的。
  5. 处理无效瓦片:

    • 当访问瓦片地图时,如果某个区域没有被初始化或不包含任何内容,可以将其标记为无效瓦片。当前如果返回值为零,就意味着该位置没有瓦片。在绘制时,可以选择不绘制这些无效区域,避免浪费性能。
  6. 瓦片的不同值:

    • 当前的地图使用数值来表示不同类型的瓦片。例如,0 代表没有瓦片(空白区域),1 代表可行走区域(或地面),而 2 可能代表墙壁或不可通过的区域。这些值可以用来定义不同的瓦片类型和其行为。
  7. 存储和数据结构:

    • 讨论中提到,当前的瓦片存储方法并没有涉及到实际的存储结构和优化。瓦片存储需要更多的考虑,因为随着地图的复杂性增加,瓦片地图的存储需求和数据量也会变得更加庞大。可能需要考虑如何优化存储结构,以更高效地管理这些数据。
  8. 下一步工作:

    • 下一步可能是进一步考虑如何设计和优化这些瓦片地图,特别是在存储和访问瓦片数据时,如何平衡性能和可扩展性,避免无效区域的绘制,并使地图可以更高效地加载和渲染。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

仅在某些位置生成房间 - 随机数的使用

  1. 世界布局与坐标定义:

    • 当前世界的坐标系统定义了世界的范围,然而并没有对所有位置的瓦片进行定义。例如,某些区域可能没有瓦片或内容,返回值为零。
    • 提到世界是“环形的”(torodial),即如果从一边走出会从另一边重新出现,这种设计意味着世界的左右边界是连接的。
  2. 生成房间的策略:

    • 当前的想法是,只在某些地方生成房间,而不是遍历整个世界生成房间。这样可以减少计算量,并控制房间的分布,使世界变得更加有序和合理。
  3. 随机数的使用:

    • 在生成房间时,讨论了随机数的使用。计划使用某些方法生成随机数字来决定哪些位置生成房间或进行其他操作。
    • 提到可以通过使用 C 运行时库来生成随机数,但也在考虑其他方式来生成随机数字,不一定依赖 C 库。
  4. 屏幕绘制与布局:

    • 提到当前的屏幕布局是一个 32x32 的瓦片网格,而在优化时,考虑到画面显示数量增加的情况下,如何使得世界更加高效。
    • 计划将屏幕的生成从简单的循环播放改为更加动态的、基于随机数的方式生成屏幕。生成的屏幕数量将从 32 增加到 100,且不再按固定顺序排列。
  5. 选择和移动屏幕:

    • 采用随机方式选择屏幕的位置,而不是简单地按照索引顺序排列屏幕。例如,可以选择一个随机位置创建一个屏幕,并根据随机数字选择下一个屏幕的位置。
  6. 屏幕数量与逻辑:

    • 最初的设计使用了 32 个屏幕,但现在计划增加屏幕数量至 100。新的生成方法将基于随机数来决定屏幕的位置和生成的顺序,而不再是按固定的顺序进行。这种方法能够更灵活地布置屏幕,提高游戏世界的多样性和复杂性。

总的来说,这段内容主要讨论了如何通过改变屏幕的生成方式以及使用随机数来调整世界的布局和房间分布,以创建一个更加动态和复杂的游戏世界。

回到随机地图生成

  1. 场景描述

    • 首先,讲述了一个“数字屏幕”或者“房间”的设计过程,房间有门,可以随机生成或调整。
    • 随机性在布局过程中起着重要作用,可以通过增加或减少屏幕的X或Y坐标来生成不同的布局。
  2. 随机选择

    • 使用随机数生成器来决定选择房间的方向(例如,增加X或Y坐标)。
    • 采用mod操作符来通过取余数来决定随机选择的结果,这通常用于生成二选一的情况,例如取余2,得到0或1。
  3. 随机数生成

    • 提到了如何生成一个随机数表,并使用一个随机数索引来选择数字。
    • 生成器需要在后续的世界生成中发挥作用。
  4. 实现与调试

    • 随着系统开发,出现了一些编程问题和调试细节,例如代码缩进问题和性能问题。
    • 讨论中提到了生成随机数时遇到的一些困难,以及尝试使用不同的技术来提高代码效率。
  5. 代码和算法

    • 对话中涉及到使用宏(例如键盘宏)和文本模式来加速开发,并谈论了C++中的代码结构和调整。
    • 还讨论了如何有效地进行编辑、代码格式化和宏使用。

整体来看,这段对话涵盖了房间布局生成的基本原理,特别是在程序中如何通过随机数控制房间的排列,并且提到了生成器、调试过程以及优化方面的挑战。如果需要更详细的代码示例或进一步的解析,随时可以告诉我!

在这里插入图片描述

在这里插入图片描述

随机生成的房间
在这里插入图片描述

还没有达到稀疏的效果

如何将一个本来存储整个地图的做法,转变为一个更加稀疏的存储方式。起初,整个地图被预先分配了存储空间,但并没有实际填充任何数据,只是创建了一个巨大的区域。随着开发的推进,目标是让地图数据的存储更加高效,只在需要的地方分配存储空间。

在实现过程中,采用了16x16的块来划分地图区域,每个块只有在需要填充瓷砖时才会分配实际的存储空间。这种做法称为“懒加载”或“按需分配”,即只有在需要填充数据时才进行存储分配,而不是预先为整个地图分配大量内存。

为了实现这一点,首先会检查是否有瓷砖需要存储,如果没有,则不会为该区域分配存储空间。只有在访问某个区域并发现该区域没有初始化时,才会为其分配存储空间。这样,内存使用更加高效,避免了存储不必要的空白区域。

这种方法使得游戏世界可以更加庞大,因为不再需要为每个可能的区域预留大量的内存。只有实际可见或需要的数据才会被存储,其他地方则不占用内存。这种“稀疏存储”的方法减少了内存的浪费,并且可以轻松扩展世界的规模。

最终,通过这种方法,存储变得更加高效,玩家也不会察觉到世界的其他部分的存在,除非他们实际进入并加载这些区域。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

制作门

在这个逻辑中,主要任务是实现一个系统,管理屏幕之间的门生成和墙绘制逻辑,并且确保这些门和墙的布置能够动态地适应屏幕的布局和随机选择。


  1. 门的位置随机性

    • 在进入屏幕时,系统会随机选择门的位置。
    • 每个屏幕的门布置需要根据相邻屏幕的门状态来动态调整。例如,如果左侧有一扇门,那么这个屏幕的右侧也需要有一扇门以保持连通性。
  2. 门和墙的初始化

    • 使用逻辑判断,确定当前屏幕的边界(顶部、底部、左侧、右侧)是否需要绘制墙或生成门。
    • 如果边界在中心区域且需要生成门,那么会绘制一扇门;否则会绘制一堵墙。
  3. 逻辑设计要点

    • 在生成门时,必须确保上一屏幕的门状态被正确传递到下一屏幕。例如,如果当前屏幕右侧有门,那么相邻屏幕的左侧也需要有对应的门。
    • 对于顶部和底部边界,同样的逻辑适用。
  4. 代码的改进点

    • 初始逻辑是基于条件判断和剪切复制的代码,虽然可以工作,但不够优雅。
    • 可以通过优化条件判断,减少重复代码,使逻辑更加简洁和清晰。
  5. 测试与调试

    • 在完成基础功能后,对生成的门和墙的布局进行测试。
    • 确保门的生成逻辑与相邻屏幕的需求一致。
    • 修正了一个门生成错误,具体问题在顶部门的条件判断中,因符号错误导致逻辑失效。
  6. 实际运行结果

    • 完成了基本的门和墙绘制功能,能够根据屏幕布局生成合理的门。
    • 系统可以动态调整屏幕间的连接,确保每个屏幕的布局与随机性生成逻辑匹配。

这个逻辑主要实现了屏幕布局的动态生成,并通过门的随机性增强了地图的可玩性,同时保证了屏幕之间的连通性。
在这里插入图片描述

回到显示单个房间的状态

从一个近距离的视角观察,可以想象如果摄像机被锁定在某个位置,玩家只能看到摄像机前的区域。在这种情况下,玩家不会意识到世界的外部是如何被存储的,因为他们永远看不到世界之外的部分。实际上,虽然世界的外部并未被存储在玩家视野中,但玩家会被引导去认为这个世界是无缝存在的,实际上世界的外部并没有被完全渲染出来。

为了避免让玩家察觉这一点,如果需要让摄像机平滑滚动至其他区域,我们可以通过设计一个“围绕房间”的空间填充来确保无论摄像机如何移动,都有东西供玩家查看。通过填充这些空白区域,可以使玩家始终看到一些内容,即使他们看不到实际的世界。

如果不想这样做,也可以采取另一种策略。当到达某些没有内容的区域时,可以随机生成一些图像或背景来填充这些区域,而不是让玩家看到空白区域。这样做可以在视觉上维持一致性,并给玩家一种完整世界的错觉。

在设计这些瓦片地图时,目标是通过平铺数据来填充世界,即使这个世界并不完全被储存,也能让玩家认为它是无缝的。通过精心设计这些瓦片,可以确保当玩家走到某个地方时,他们不会注意到世界的边界。

整体而言,通过这种设计,可以确保玩家在探索虚拟世界时,体验到一个流畅且持续的游戏环境,而不必担心地图的大小或设计上的限制。通过对空间和视觉的精心布局,可以保持游戏的沉浸感。

此时的地图已经相当大,虽然在测试时,穿越一百个屏幕需要相当长的时间,但这也展现了游戏世界的广阔。而这些测试图形本身,更像是展示游戏核心功能的工具。它们提醒人们,曾经的经典冒险游戏也用了类似的技术。那些早期的游戏在视觉上看起来简单,但依然能够给玩家带来深刻的体验。尤其是“冒险”这款经典游戏,它通过非常简单的图形和有限的资源,依然能够吸引玩家投入大量时间,探索这个简单但充满乐趣的世界。

瓦片地图的回顾

现在,瓦片地图已经基本完成,接下来是讨论如何优化和改进这一实现。首先,瓦片地图的尺寸可以灵活调整。一个关键点是,我们不再需要将瓦片大小与像素大小绑定在一起,因为瓦片地图本身不需要关心像素的具体细节,它只是一个抽象的表示。瓦片的大小和像素之间的关系不再重要,因此应该将这种绑定关系移除。通过这样做,我们能让瓦片地图独立于实际的像素渲染,从而让地图的存储和渲染变得更简洁。

接下来,考虑到存储效率,提出了一个虚拟化的瓦片存储方式。当前的系统在处理瓦片时仍存储一个包含指针的数组,而这些指针指向实际的瓦片数据。这样,尽管整个世界的大小可以非常庞大,但实际上我们只存储了小块区域。存储时,世界的每个区域并不是全尺寸的,而是分成了较小的“块”进行存储,类似于一个二维指针数组来表示世界的瓦片。

通过这种方法,可以在有限的存储空间内管理一个非常大的世界。例如,如果当前世界的大小是四十亿瓦片,那么只存储16x16的区域块。这种分块存储的方式大大减少了内存占用,因为我们只存储必要的区域数据而非整个世界的每个瓦片。

然而,尽管这种方式节省了大量内存,但仍然有优化空间。如果能进一步减少存储的数据量,系统将变得更加高效。为了达到更高的稀疏性,可以考虑进一步优化存储方法,例如通过“真正的稀疏存储”方式,仅在需要时动态加载和存储数据,而不是将每个可能的区域都事先分配好。这种方式可以极大减少内存消耗,尤其是在处理大规模世界时。

最终,虽然当前的存储方式已经通过指针数组减少了内存占用,但为了达到最优的稀疏性,可能还需要进一步探索不同的存储策略,比如基于空间位置的稀疏查找方法。这些方法可以确保只在必要时加载和存储瓦片数据,从而最大化内存利用率和处理效率。

在这里插入图片描述

添加上下楼梯的功能

在开发城市地图时,添加了对Z轴的支持,以便能处理上下层次。这个修改的目标是使地图能够处理多个高度层次,在这种情况下,Z轴代表着垂直维度。增加Z轴的功能不难,主要是通过给地图增加一个“上下”移动的能力来实现。最初,Z轴只是一个附加的概念,用来支持更复杂的地图层次结构。

这个过程中,Z轴并不会像X轴或Y轴那样直接影响地图的存储方式,因为通常我们不需要在任何时刻查看多个Z层。对于大多数情况来说,Z轴层是分离的,与X和Y轴的操作有所不同,通常代表着“上下”之类的层次移动,而不是二维空间中那样的平面划分。

接着,修改了地图存储的方式,将Z轴作为一个附加的维度来处理。具体来说,存储时,Z轴会对每个瓦片进行标记,将其与X和Y坐标结合,使得每个瓦片都能具备一个高度属性。这样,Z轴的操作和存储方式需要特别处理,尤其是在获取或设置瓦片值时,每次都会附加Z轴信息。

这个过程中,为了便于操作,采用了三维坐标的存储方式,而不是简单的二维平面。将X、Y和Z结合后,形成了一个三维空间,使得可以更清晰地表示不同层次的瓦片。在存储时,X轴表示横向,Y轴表示纵向,而Z轴则用于表示上下的层级关系。每次移动Z轴时,都会跨越一整块X和Y的区域。也就是说,Z轴的移动代表着在三维空间中的“跳跃”,每次上升一个Z层就会改变当前可见的瓦片。

总体来说,添加Z轴的支持能够为地图带来更多的层次结构,使得城市地图更加立体和复杂。而这个修改并不会引入太多新的复杂性,因为主要的操作还是围绕着传统的二维瓦片地图展开。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

继续疯狂地增加一些楼梯

这段文本描述了一段代码调试的过程,涉及到随机选择和门状态控制等问题。下面是详细的总结和复述:

  • 开始时,主要关注的是一个与随机选择相关的逻辑,用于处理某种网格或地图系统。随机选择操作从三个选项中选择一个,每个选项代表一种可能的动作或结果。根据随机选择的结果,触发不同的条件。

  • 尝试根据随机选择的结果设置不同的动作和条件,具体条件与门的状态相关。例如,当条件等于“二”时,执行某些特定操作;否则,根据不同的条件切换样式或其他变量。条件似乎关注门是否存在,以及门的“向上”或“向下”状态,这可能是与游戏机制或关卡元素相关的设置。

  • 在某一时刻,逻辑涉及设置门的状态,确保某个房间内没有出口,或者根据需要调整瓦片或其他对象的状态。

  • 接下来,代码检查某些属性(如库存)是否相等,并根据条件触发相应的操作。代码中出现了一个明显的错误,导致门的状态出现异常行为,可能是由于设置不当或逻辑流程错误。

  • 还有对网格中的瓦片位置(X、Y、Z坐标)进行处理,处理“向上”和“向下”门的状态。问题在于确保状态正确转换,避免门被错误地放置或操作。

  • 调试过程中发现与“门”状态相关的错误,门的状态切换似乎存在故障,导致一些预期条件没有得到满足。

  • 在回顾这些行为后,认为问题可能出在门的切换逻辑上,或者是某些条件值(如库存或瓦片条件)的设置错误。尽管面临这些挑战,仍在尝试通过追踪逻辑找到问题的根源并解决它。

  • 调试过程涉及大量的试错,目标是修正因随机选择逻辑和瓦片处理导致的错误,尤其是与门状态和瓦片条件相关的问题。

核心问题是确保门的放置和状态转换符合预期,同时排查在随机选择和瓦片管理中的错误。整个过程强调了在处理网格或系统中的状态变化和交互时的复杂性,特别是当涉及随机结果和特定条件时。

在这里插入图片描述

你会使用德摩根定律(DeMorgan’s Laws)吗?

这段对话讨论了布尔表达式的简化,特别是涉及德摩根定律真值表的使用。以下是详细总结:

  1. 德摩根定律和简化布尔表达式

    • 德摩根定律指出一些常见的布尔表达式等价关系,例如:not (A and B) 等同于 not A or not B,这可以帮助简化复杂的布尔表达式。尽管这是一种有效的简化方法,但实际中不常用,尤其是在编写代码时。
  2. 实践中的做法

    • 在实际编程中,简化布尔表达式并不是常见的做法。通常情况下,开发者倾向于将代码保持简洁和直观,尽量通过清晰的表达式让代码易于理解,而不是为了优化布尔运算的数量去做过多简化。
    • 在很多情况下,编译器会自动优化这些布尔表达式,因此手动简化的必要性较小。
  3. 编译器的优化作用

    • 开发者倾向于依赖编译器来处理这类优化工作。编译器通常能够自动执行这些优化,从而减少开发者的工作量。因此,简化布尔表达式的主要工作交给编译器完成,而开发者则更多关注代码的可读性和表达清晰性。
  4. 语言学简化的优先级

    • 开发者更注重语言表达的简洁性,而不是优化布尔运算的数量。清晰的表达式让代码更易于理解和维护,因此在写代码时,开发者倾向于使用更直观的表达式。
  5. 真值表的使用

    • 真值表是一种帮助分析和简化布尔表达式的工具,通过列出所有可能的输入条件并计算每种情况下的输出,帮助了解布尔逻辑的行为。尽管这是一种理论上有效的方法,但实际上并不常用。
    • 真值表类似于电子表格,其中列出所有条件,并分析每种条件组合下的布尔表达式结果。
  6. 总结

    • 总体来说,虽然德摩根定律和真值表是有用的工具,但在实际编程中,简化布尔表达式更多依赖编译器的优化,而开发者则倾向于关注代码的清晰表达,而不是手动进行布尔运算的简化。

将瓦片地图放入 3D 维度,这是否与体素八叉树算法有关?

  1. 三维空间和算法

    • 提到将时间纳入三维空间,虽然这种想法可能不直接相关于某个特定算法(如 “Vauxhall Autrey Algorithm”),但讨论的重点是如何理解空间的分割与优化。
    • 在三维空间中,提到可以将一个体积分割为多个部分,例如将一个立方体划分成八个较小的立方体。这种操作有点像魔方的分割,可以进一步提升每个小立方体的分辨率。
  2. 在三维空间中填充

    • 讨论了在三维空间中如何以无偏的方式进行空间填充,即确保在所有维度中都有均匀分布。这种方法在某些情况下非常有效,尤其是在处理三维空间时,避免某一维度不均匀填充。
  3. 游戏世界的空间划分

    • 对于游戏世界,尤其是在二维游戏的上下文中,这种三维分割的概念并不总是适用。二维游戏通常会集中于几个“切片”或“视图”,而不是三维空间的完整填充。
    • 游戏的世界划分通常依赖于视角和地牢布局。例如,可能会查看地牢的底层或顶部,或者观察一定数量的“切片”而不是全景。
  4. 二维和三维视角的差异

    • 在二维游戏中,三维的空间划分并不总是有意义,因为大多数游戏世界的视角和层次结构较为简单,通常只处理较少的高度或深度。这里的讨论强调了二维与三维游戏中空间处理的差异。
  5. 树形结构的局限性

    • 提到在游戏世界划分中,使用树形结构来分割空间并不总是最优选择,特别是当游戏涉及到复杂的世界结构时。树形结构可能在某些三维游戏中有效,但在处理大规模、复杂的二维或多维地图时可能并不高效。

总的来说,这段讨论将三维空间的划分和优化技术与游戏世界的设计进行了对比,探讨了在不同类型的游戏中如何有效地应用这些概念。

为什么区块大小设置为 2 的幂次?

这段对话深入探讨了算法优化和存储结构,特别是在处理数据块大小和查找操作时的选择。以下是详细总结:

  1. 块大小与2的幂

    • 讨论了使用2的幂作为块大小的原因。这样做是因为在查找操作中,使用移位和掩码(shift and mask)可以高效地分割数据。这种方法仅在块大小为2的幂时有效,因为移位和掩码操作能够快速地提取数据的高低位部分。
    • 如果块大小不是2的幂,就无法使用这种优化方法,可能需要使用常规的除法和余数操作(divide and remainder)来代替。这样的方法虽然能完成相同的任务,但效率较低,因为需要进行除法运算。
  2. 移位与掩码

    • 通过移位操作,可以将数据分割成两个部分:一个是块的高位部分,另一个是低位部分。这个过程依赖于块大小是2的幂的前提,因为这使得移位操作变得简单且高效。
    • 这使得块的划分非常清晰,且能高效地进行索引。每次取余数来确定某一部分的数据(比如瓷砖的索引),而通过移位操作来确定数据的其他部分。
  3. 替代方案:除法与余数

    • 如果不使用2的幂,理论上可以通过常规的除法和余数操作来进行划分。虽然这种方法可以工作,但其性能通常不如移位和掩码高效,尤其是在需要频繁进行查找操作时。
  4. 性能调优与选择

    • 讨论了在性能优化过程中做出的决策,强调在开发游戏引擎时要尽量避免做出那些会限制未来选择的设计决策。例如,某些操作可能并不需要特别快,但在某些情况下为了更好的存储和灵活性,采用简单的除法和余数操作也是可行的。
    • 重要的是,在开发过程中要确保能够保持灵活性,以便未来能够根据需要调整优化方案,避免过早地做出决策导致无法后续调整。
  5. 存储与操作的平衡

    • 在决定使用哪种优化方法时,需要权衡存储的效率和操作的速度。如果存储是主要考虑因素,那么可以接受稍慢的操作,以减少对存储空间的需求。
    • 反之,如果操作速度更为重要,可能需要继续使用2的幂作为块大小,利用移位和掩码来优化性能。

总之,这段讨论的核心在于如何平衡存储优化与操作效率。在设计和开发时,必须考虑性能需求,同时保持灵活性,以便在实际实现中根据具体情况做出最佳选择。

什么时候会使用 #define 而不是局部变量?

这段对话探讨了使用全局变量的情况及其优缺点,尤其是如何在不同的情境下决定是否定义全局变量。以下是详细总结:

  1. 定义全局变量的时机

    • 使用全局变量是否合适,取决于具体的需求和情况。在某些情境下,使用全局变量可能是一个很好的选择,但没有唯一的“正确”或“错误”的答案。关键在于理解使用它们的差异,并据此做出选择。
  2. 全局变量的类型问题

    • 无类型变量(如常量):在某些情况下,使用没有类型的全局变量(例如常量值)可能是有利的。这样做的一个好处是这些变量可以在任何地方使用,而不需要明确的类型定义。对于一些不需要类型约束的操作,这种方式非常灵活。
    • 有类型的变量:然而,如果你需要对数据进行类型控制,尤其是需要确保某些操作只在特定类型(如无符号整数、浮点数等)下进行时,定义全局变量的类型是非常重要的。一个例子是,如果你希望某个值只能在特定情况下(如只有在 UN32 的情况下)使用,明确的类型定义可以避免错误发生。
  3. 移除类型的优缺点

    • 优点:没有类型的全局变量可以直接插入表达式中,使得代码更加灵活。这种方法适用于那些不需要对数据进行类型严格控制的情况。
    • 缺点:没有类型也意味着在某些情况下,可能会导致数据使用错误。例如,如果一个无符号 32 位数(UN32)被错误地用于不适合的场景,可能会导致程序错误。为了避免这种情况,可能需要对变量进行类型转换或额外的类型检查。
  4. 全局变量的具体应用场景

    • 在某些情况下(例如使用浮点数后缀或需要特定的类型),全局变量可以帮助确保变量有一个明确的类型。例如,如果想要一个八位类型的全局变量,可能就需要通过显式定义类型来确保其大小和特性。
    • 例子:如果需要使用某些操作(如浮点数运算)而该操作只适用于某种类型,定义类型明确的全局变量就能够确保数据的正确性。
  5. 灵活性与限制

    • 全局变量有助于在不需要特别精细控制类型的情况下实现灵活性,但有时需要明确类型以避免潜在的错误。在某些复杂场景中,无法简单地依靠类型推断,必须使用强类型定义。
  6. 总结

    • 总的来说,使用全局变量是否合适取决于应用场景。如果不需要严格的类型控制,使用无类型的全局变量可以提高灵活性;如果需要控制数据类型,则需要明确地定义全局变量的类型。每种方法都有其适用的场景,且没有绝对的“正确”与“错误”。

为什么会偏好使用瓷砖区块数组?

  1. 内联变量的使用

    • 对于内联变量的问题,提到并未使用内联变量。没有明确说明为何不使用内联变量,主要是因为相关的概念并不在当前讨论范围内。
  2. 为什么不用位标志(bit flags)表示门的状态

    • 标志通常用于表示二进制状态,但当前的游戏设计并不适用这种方法。原因是,目前的地图还未完成设计,也未明确如何存储这些地图信息。门只是用一个数字表示,以便进行测试,并未深入实现。
  3. 为什么不使用简单的传送门

    • 在某些情况下,传送门可以简化游戏的设计,使玩家在地图的不同部分之间移动。但如果只是使用传送门,无法满足更复杂的游戏需求。例如,传送门无法处理玩家看到的世界几何形状与实际地图之间的关系。想要展示多个房间或不同楼层之间的联系,简单的传送门机制就不够用了。
    • 游戏需要一个更加持续和一致的世界,其中的每个部分都能通过几何方式进行查询,从而保证更复杂的互动和场景切换。例如,玩家可以从一层看到另一层的内容,这种设计无法通过简单的传送门来实现。
  4. 游戏世界的几何结构

    • 游戏世界的设计应允许玩家在一个连贯的几何世界中自由移动,这样不仅能够显示多个区域,还能处理复杂的互动。例如,假设游戏中有一个角色能破坏墙壁,产生洞口,玩家能看到并进入这些新的空间。为了实现这一点,游戏需要知道这些空间是如何通过地图相连的,而不是依赖于传送门或其他不反映真实地理关系的设计。
  5. 关于声音传播的例子

    • 声音传播是另一个体现游戏世界几何结构的重要元素。假设玩家站在墙壁旁,能听到另一房间内的声音,尤其是像老板怪物这样的强大存在。如果系统仅仅依赖于传送门,那么就无法处理这种墙壁穿透声音传播的问题。因此,游戏设计必须具备能够处理空间连接的几何方式,以便在复杂的环境中进行正确的声音传播。
  6. 为什么使用“块”(Chunks)而不是简单的传送门

    • 游戏设计希望能以一种几何化的方式查询和展示世界。使用“块”可以将虚拟世界分成较小的单元,在需要时可以通过几何方法查询这些单元。而不必担心将整个世界存储为一个庞大的数组或数据结构。这样设计的优势是既能保持世界的一致性,也能让世界保持更大的扩展性。

是否计划按需加载/卸载瓦片区块?

这段讨论主要涉及了内存管理、分页策略和游戏世界的加载与卸载。以下是详细总结:

  1. 加载和卸载世界数据

    • 关于游戏世界的内存管理,提到世界的数据(如瓦片块)可能会保留在内存中,但也有可能根据需求进行加载和卸载。加载和卸载的操作对当前设计而言非常简单,因为系统已经为这一点做好了准备。
    • 如果某个瓦片块没有在内存中,可以通过分页将其加载到内存中。这种加载方式非常灵活,且几乎不影响性能。
  2. 分页方案

    • 分页(paging)指的是按需加载数据块的方式。在当前方案中,数据块的加载与卸载几乎是无成本的,但仍有一些复杂的操作需要避免过于简单地进行分页。
    • 如果需要更复杂的分页方案,比如根据需求动态加载或卸载数据(需求分页),这个过程理论上非常简单,只需大约30分钟的时间进行调整。然而,目前尚不确定是否真的需要实施这种复杂的分页策略。

是否计划让瓦片地图分层?

这段讨论涉及到代码的复杂性和未来的计划,特别是在生成游戏世界时的临时解决方案。以下是详细总结:

  1. 代码的复杂性

    • 游戏的最终程序代码看起来非常复杂,尤其是语言层面的改动非常难以实施。这可能指的是代码的现有结构或设计,使得任何语言上的修改都需要较大的工作量。
  2. 临时的农村生成代码

    • 在开始进行世界生成(尤其是乡村区域)之前,现有的代码只是作为一个临时解决方案存在。当前的目的是为测试城市地图(town map)提供一个简单的基础,确保能够在更广泛的世界范围内进行测试。
    • 目前的代码并没有做任何实际的删除或优化,只是用来进行初步的测试。这段代码并不代表最终的设计方案,而只是暂时的过渡阶段。
  3. 未来的计划

    • 这段代码被称为“垃圾”,意味着它在实际项目中不会被使用。它只是一个过渡性工具,用于测试和验证某些功能,比如城市地图的表现。

基本稀疏瓦片地图存储是否需要压缩?

  1. 图形、物理和逻辑的分层

    • 对于游戏的图形、物理和逻辑系统的分层,虽然可能存在不同的系统设计,但这些系统可能并不会完全分开,而是有一定程度的合并。例如,图形和物理系统虽然是不同的部分,但它们之间不一定会有完全分离,可能会在实现时合并在一起。这样做是为了灵活性和便于修改。
  2. 资源切换和类型定义

    • 在类型定义方面,倾向于使用较为简化的方法。例如,不使用特定的布尔类型,而是采用整数类型来表示数据池,这样可以避免频繁的转换,减少性能开销。这种方式源自过去的习惯,即避免过多定义和视觉化的类型,从而简化了代码的书写和理解。
  3. 声音和平台的隔离

    • 在声音管理方面,游戏的声音部分需要独立管理,以便在开始播放更多的声音时能有效地处理这些数据。同时,也有一定的隔离意识,避免过多依赖平台特定的实现,保持一定的灵活性,以便更好地控制声音资源。
  4. 资源压缩和内存管理

    • 对于资源大小的担忧,尤其是关于地图和艺术资产的大小,虽然考虑过压缩策略,但由于游戏资产(如大规模的地图和图像资源)可能非常庞大,压缩可能不会带来显著的效益。尤其是如果瓷砖地图本身造成了内存压力,压缩才可能成为一个值得考虑的方案。总体来说,艺术资产的大小可能会限制压缩的有效性,因此压缩方案不一定是优先选项。
  5. 内存压力和性能

    • 对于游戏世界的大小,预计不会对内存产生巨大的压力,但如果瓷砖地图的内存需求超出了预期,那么可以考虑使用一些技术来优化内存使用,例如压缩。这些决策将依据实际的资源需求和内存使用情况来调整。
      方法。

房间是否应该仅在玩家接近时才创建?

是否担心内存泄漏?

三目运算符不好吗?

为什么无法保存完整地图?

主要观点:

  1. 稀疏存储的挑战

    • 稀疏存储(Sparse Storage)是指只在需要时才分配内存,避免预先分配过多空间。尽管这种方法可以节省内存,但其代价是需要额外的计算和内存管理开销。随着资源减少,稀疏存储的密集度会增加,这意味着管理变得更复杂,效率下降。
  2. 计算复杂度与存储的权衡

    • 在大世界设计中,如果希望通过稀疏存储减少内存占用,那么在存储管理方面需要付出更高的代价。直接存储和访问稀疏世界中的数据可能会导致性能问题,尤其是在动态改变世界(如可破坏环境)时,存储需求会激增。
  3. 优化的重点是最坏情况

    • 游戏开发中,通常优化的焦点应该是“最坏情况”,即当玩家处于复杂的环境中,屏幕上显示的内容是最为密集和复杂的,而不仅仅是优化那些玩家几乎不接触的区域。例如,尽管优化那些不需要渲染的部分(如被墙壁遮挡的区域)看起来有意义,但如果忽视了最坏情况的优化(如大规模渲染的复杂环境),反而可能导致游戏性能问题。
  4. 内存泄漏与资源管理

    • 在内存管理上,有些时候不需要过于担心内存泄漏的问题,尤其是当所有的数据都存储在永久存储中,而不常驻内存时。此时内存泄漏的风险较低,但如果在游戏中涉及到动态修改(如破坏环境),那么数据存储和内存管理的策略就需要更加细致。
  5. 巨型纹理(Mega Texture)

    • 在设计大规模世界时,可能会考虑使用“巨型纹理”来存储完整的世界地图。但这种方法在内存中无法完全保存整个纹理,而是通过分页的方式,将需要的部分动态加载到内存中。巨型纹理的处理方式和存储方法,要求在运行时将纹理分割并根据需要加载部分数据,避免了将整个地图都加载到内存中的问题。
  6. 存储空间与游戏设计的平衡

    • 在游戏设计中,必须在存储空间、内存管理和计算成本之间找到平衡。例如,使用稀疏存储可以减少内存占用,但也可能导致存取速度的下降,特别是在大规模动态世界中。当房间或环境发生变化时,存储和管理这些变化的数据会变得更加复杂,甚至可能导致性能问题。因此,尽管理论上可以保存整个地图,但由于内存限制和计算成本,实际开发中通常选择动态加载和部分存储的方法。

总结:

这段内容深入探讨了大规模游戏世界中如何处理存储和内存问题。关键在于如何在保持游戏世界动态和可变的同时,优化内存使用和计算复杂度,特别是在需要存储稀疏数据和应对动态变化时。

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

相关文章:

游戏引擎学习第35天

开场介绍 今天的任务是继续改进一个虚拟的瓦片地图系统,使其适合处理更大的世界。我们希望这个系统能管理大范围的游戏世界,其中包含按需存储的小区域。昨天,我们介绍了“内存区域”的概念,用于管理持久性存储。我们计划今天继续…...

Python 3 和 MongoDB 的集成使用

Python 3 和 MongoDB 的集成使用 MongoDB 是一个流行的 NoSQL 数据库,以其灵活的数据模型和强大的查询功能而闻名。Python 3 作为一种广泛使用的编程语言,与 MongoDB 的集成变得日益重要。本文将介绍如何在 Python 3 环境中集成和使用 MongoDB&#xff…...

MperReduce学习笔记下

自定义InputFormat合并小文件 案例需求 无论hdfs还是mapreduce,对于小文件都有损效率,实践中,又难免面临处理大量小文件的场景,此时,就需要有相应解决方案。 案例分析 小文件的优化无非以下几种方式: …...

react + antd desgin 使用form功能时upload,radio,checkbox不能回显的问题

最近使用react开发 遇到form回显的问题 ,处理upload回显的问题,提示 react-refresh:160 Warning: [antd: Upload] value is not a valid prop, do you mean fileList? 查看文档后,在form.item 组件下有一个特殊属性 valuePropName 子节点的值…...

【NLP修炼系列之Bert】Bert多分类多标签文本分类实战(附源码下载)

引言 今天我们就要用Bert做项目实战,实现文本多分类任务和我在实际公司业务中的多标签文本分类任务。通过本篇文章,可以让想实际入手Bert的NLP学习者迅速上手Bert实战项目。 1 项目介绍 本文是Bert文本多分类和多标签文本分类实战,其中多分…...

OpenSSL 自建CA 以及颁发证书(网站部署https双向认证)

前言 1、前面写过一篇 阿里云免费ssl证书申请与部署,大家可以去看下 2、建议大家看完本篇博客,可以再去了解 openssel 命令 openssl系列,写的很详细 一、openssl 安装说明 1、这部分就不再说了,我使用centos7.9,是自…...

YOLOv11改进,YOLOv11添加U-Netv2分割网络中SDI信息融合模块,助力小目标检测

摘要 理论介绍 SDI模块的架构: 平滑卷积(SmoothConv):用于平滑特征图,帮助减少噪声并使得特征更加稳定。Hadamard积:用于在特征图中进行逐元素相乘(点乘),以加强语义信息和细节信息的融合。通道注意力(ChannelAttention):利用通道注意力机制来自动关注重要的特征通…...

flex布局 flex-end为什么overflow无法滚动及解决方法

flex-end为什么overflow无法滚动及解决方法 在使用Flexbox布局时,我们经常使用justify-content和align-items属性来定位子元素。其中,align-items属性用于控制子元素在交叉轴上的位置,例如顶部对齐、底部对齐或居中对齐等。当我们将align-it…...

从ground_truth mask中获取图像的轮廓图

引言 在图像取证领域,主要分为检测和定位两个方面。检测就是判断一张图片是否为伪造图,定位与传统意义上的语义分割任务相近,就是定位伪造像素的区域。如果单纯使用语义分割网络训练,只能获得次优解,而像多任务学习那样…...

Java项目实战II基于微信小程序的旅游社交平台(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 随着移动互联网的迅猛发展,旅游已经成为人…...

开源即时通讯与闭源即时通讯该怎么选择,其优势是什么?

在选择即时通讯软件时,应根据企业的经营领域来选择适合自身需求的开源或闭源方案。不同领域对开源和闭源即时通讯的理念存在差异,因此总结两个点简要分析这两种选择,有助于做出更明智的决策。 一、开源与闭源的根本区别在于软件的源代码是否…...

【计算机网络】实验15:VLAN间通信的实现方法“单臂路由”

实验15 VLAN间通信的实现方法“单臂路由” 一、实验目的 加深对VLAN间通信的实现方法“单臂路由”的理解。 二、实验环境 Cisco Packet Tracer模拟器 三、实验过程 1.构建网络拓扑,并配置好主机的IP地址、子网掩码、默认网关,如图1,2所…...

数据库学习记录04

DDL【数据定义语言】 MySQL命名规则 数据库名不得超过30个字符,变量名限制为29个必须只能包含A-Z,a-z,0-9,_共63个字符不能在对象名的字符间留空格必须不能和用户定义的其他对象重名必须保证你的字段没有和保留字、数据库系统或常用方法冲突保持字段名和类型的一致…...

PDF文件打开之后不能打印,怎么解决?

正常的PDF文件是可以打印的,如果PDF文件打开之后发现文件不能打印,我们需要先查看一下自己的打印机是否能够正常运行,如果打印机是正常的,我们再查看一下,文件中的打印功能按钮是否是灰色的状态。 如果PDF中的大多数功…...

A* 算法 是什么?

A*(A-star)算法是一种启发式搜索算法,用于在图或网格中找到从起点到目标的最短路径。它被广泛用于路径规划问题,例如导航、游戏开发中的角色移动,以及机器人路径规划。 1. A 算法的基本概念* A* 算法结合了两种经典搜…...

ORM框架详解:为什么不直接写SQL?

想象一下,你正在开发一个小型的在线书店应用。你需要存储书籍信息、用户数据和订单记录。作为一个初学者,你可能会想:“我已经学会了SQL,为什么还要使用ORM框架呢?直接写SQL语句不是更简单、更直接吗?” 如…...

厘米级高精度RTK手持终端北斗卫星定位手持pda

RTK是一种测量技术叫“载波相位差分技术”,是实时处理两个测量站载波相位观测量的差分方法,将基准站采集的载波相位发给用户接收机,进行求差解算坐标,以此得到高精度坐标。随着技术的不断革新,GPS接收机也由原来只能用…...

Kafka-Connect源码分析

一、上下文 《Kafka-Connect自带示例》中我们尝试了零配置启动producer和consumer去生产和消费数据,那么它内部是如何实现的呢?下面我们从源码来揭开它神秘的面纱。 二、入口类有哪些? 从启动脚本(connect-standalone.sh&#…...

【STM32 Modbus编程】-作为主设备读取保持/输入寄存器

作为主设备读取保持/输入寄存器 文章目录 作为主设备读取保持/输入寄存器1、硬件准备与连接1.1 RS485模块介绍1.2 硬件配置与接线1.3 软件准备2、读保持寄存器2.1 主设备发送请求2.2 从设备响应请求2.3 主机接收数据3、读输入寄存器4、结果4.1 保持寄存器4.2 输入寄存器在前面的…...

Kubesphere上搭建redis集群

Kubesphere上搭建redis集群 版本:redis:6.2.3 1)挂载配置 redis.conf: cluster-enabled yes cluster-config-file nodes.conf cluster-node-timeout 5000 cluster-require-full-coverage no cluster-migration-barrier 1 appendonly yes …...

learn-(Uni-app)跨平台应用的框架

使用 Vue.js 开发所有前端应用的框架,开发者编写一份代码,可发布到iOS、Android、Web(包括微信小程序、百度小程序、支付宝小程序、字节跳动小程序、H5、App等)等多个平台。 跨平台:Uni-app 支持编译到iOS、Android、W…...

target_compile_definitions

这个接口给目标定义的宏,不能像C中定义的宏一样,尝试利用宏进行替换: cmake_minimum_required(VERSION 3.8) project(compile_definitions_pro)add_executable(main_exec src/main.cpp)set(SYSTEM_NAME "") if(CMAKE_SYSTEM_NAME S…...

浏览器同源策略、跨域、跨域请求,服务器处理没、跨域解决方案

目录 什么是同源策略什么是跨域发生跨域时,服务器有没有接到请求并处理响应:(两种情况) 如何解决跨域 什么是同源策略 概念: 同源策略是浏览器的一种安全机制,用于防止恶意网站对用户的敏感数据进行未经授…...

深入理解网络安全等级保护:保障信息安全的关键策略与实践

随着信息技术的飞速发展,网络安全问题日益凸显。为了应对这一挑战,网络安全等级保护制度应运而生,旨在确保不同等级的信息和信息系统的安全。本文将探讨网络安全等级保护的基本概念、重要性及其实践方法。 一、信息安全等级保护的基本概念 1…...

MySQL

InnoDB 引擎底层存储和缓存原理 到目前为止,MySQL 对于我们来说还是一个黑盒,我们只负责使用客户端发 送请求并等待服务器返回结果,表中的数据到底存到了哪里?以什么格式存放的? MySQL 是以什么方式来访问的这些数据&…...

新书速览|循序渐进Node.js企业级开发实践

《循序渐进Node.js企业级开发实践》 1 本书内容 《循序渐进Node.js企业级开发实践》结合作者多年一线开发实践,系统地介绍了Node.js技术栈及其在企业级开发中的应用。全书共分5部分,第1部分基础知识(第1~3章)&#xf…...

2024三掌柜赠书活动第三十五期:Redis 应用实例

目录 前言 Redis操作都会,却不知道怎么用? 关于《Redis 应用实例》 编辑推荐 内容简介 作者简介 图书目录 《Redis 应用实例》全书速览 拓展:Redis使用场景 实例1:缓存应用 场景描述 实现方法 具体代码示例 实例2&a…...

Android 第三方框架:RxJava:源码分析:观察者模式

文章目录 观察者模式RxJava中的观察者模式总结 ​​​​​​​​​​​​​​观察者模式​​​​​​​ RxJava中的观察者模式 以Observable、ObservableOnSubscribe、Observer为例 Observable是被观察者 负责发射事件或数据 Observer是观察器 负责对从被观察者中获取的数…...

开源模型应用落地-安全合规篇-用户输入价值观判断(四)

一、前言 在深度合规功能中,对用户输入内容的价值观判断具有重要意义。这一功能不仅仅是对信息合法性和合规性的简单审核,更是对信息背后隐含的伦理道德和社会责任的深刻洞察。通过对价值观的判断,系统能够识别可能引发不当影响或冲突的内容,从而为用户提供更安全、更和谐的…...

【js逆向专题】13.jsvmp补环境篇一

目录 一.了解jsvmp技术1. js虚拟机保护方案2.jsvmp实现原理3. 模拟jsvmp执行过程 二.环境检测1. 什么是环境检测2.案例讲解 三. 项目实战1. 案例11.逆向目标2. 项目分析1.补第一个referrer2. 调试技巧13. 调试技巧24. 补充sign5. 补 length6. 参数长短补充 3. 逆向结果 2. 案例…...

Java---每日小题

题目1-极大极小游戏 给你一个下标从 0 开始的整数数组 nums ,其长度是 2 的幂。 对 nums 执行下述算法: 设 n 等于 nums 的长度,如果 n 1 ,终止 算法过程。否则,创建 一个新的整数数组 newNums ,新数组长度…...

leetcode 23. 合并 K 个升序链表

给你一个链表数组,每个链表都已经按升序排列。 输入:lists [[1,4,5],[1,3,4],[2,6]] 输出:[1,1,2,3,4,4,5,6] 解释:链表数组如下: [1->4->5,1->3->4,2->6 ] 将它们合并到一个有序链表中得到。 1->…...

Windows 小记 6 -- 为什么我的全局消息钩子卸载不掉?

Hook dll 在其消息循环中被卸载。强制它们进入消息循环有助于卸载它们。在 UnhookWindowsHookEx 之后添加此代码以强制唤醒所有消息循环: DWORD dwResult; SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 1000, &a…...

Python+onlyoffice 实现在线word编辑

onlyoffice部署 version: "3" services:onlyoffice:image: onlyoffice/documentserver:7.5.1container_name: onlyofficerestart: alwaysenvironment:- JWT_ENABLEDfalse#- USE_UNAUTHORIZED_STORAGEtrue#- ONLYOFFICE_HTTPS_HSTS_ENABLEDfalseports:- "8080:8…...

LC低通滤波器Bode图分析(传递函数零极点)

LC低通滤波器 我们使得L4.7uH,C220uF;电感L的阻抗为Xl;电容C的阻抗为Xc; 传递函数 H ( s ) u o u i X C X C X L 1 s C 1 s C s L 1 1 s 2 L C (其中 s j ω ) H(s)\frac{u_{o} }{u_{i} } \frac{…...

【机器学习】机器学习的基本分类-无监督学习(Unsupervised Learning)

无监督学习(Unsupervised Learning) 无监督学习是一种机器学习方法,主要用于没有标签的数据集。其目标是从数据中挖掘出潜在的结构和模式。常见的无监督学习任务包括 聚类、降维、密度估计 和 异常检测。 1. 无监督学习的核心目标 1.1 聚类…...

六、docker compose单机容器编排工具

六、docker compose单机容器编排工具 6.1 compose简介 Compose是一个用于定义和运行多容器Docker应用程序的工具。您可以使用Compose文件来配置应用程序的服务,然后使用单个命令从配置中创建并启动所有服务。compose的配置文件示例如下 compose的github网址&#…...

Python3 operator 模块

Python2.x 版本中,使用 cmp() 函数来比较两个列表、数字或字符串等的大小关系。 Python 3.X 的版本中已经没有 cmp() 函数,如果你需要实现比较功能,需要引入 operator 模块,适合任何对象,包含的方法有: o…...

沪合共融 “汽”势如虹 | 昂辉科技参加合肥上海新能源汽车产业融合对接会

为积极响应制造业重点产业链高质量发展行动号召,促进合肥、上海两地新能源汽车产业链上下游企业融合对接、协同发展,共同打造长三角世界级新能源汽车产业集群,11月28日,合肥市工信局组织部分县区工信部门及全市30余户新能源汽车产…...

访问http网页强制跳转到了https的解决办法

目录 解决浏览器自动从 HTTP 重定向到 HTTPS 的问题问题原因:HSTS(HTTP Strict Transport Security)什么是 HSTS?HSTS 的工作原理 如何解决?1. 清除浏览器的 HSTS 信息在 Chrome 中清除 HSTS 信息:在 Firef…...

PDF处理的创新工具:福昕低代码平台尝鲜

在当今数字化时代,PDF文件的处理和管理变得越来越重要。福昕低代码平台是新发布的一款创新的工具,旨在简化PDF处理和管理的流程。通过这个平台,用户可以通过简单的拖拽界面上的按钮,轻松完成对Cloud API的调用工作流,而…...

EmoAva:首个大规模、高质量的文本到3D表情映射数据集。

2024-12-03,由哈尔滨工业大学(深圳)的计算机科学系联合澳门大学、新加坡南洋理工大学等机构创建了EmoAva数据集,这是首个大规模、高质量的文本到3D表情映射数据集,对于推动情感丰富的3D头像生成技术的发展具有重要意义…...

SpringMVC ——(1)

1.SpringMVC请求流程 1.1 SpringMVC请求处理流程分析 Spring MVC框架也是⼀个基于请求驱动的Web框架,并且使⽤了前端控制器模式(是⽤来提供⼀个集中的请求处理机制,所有的请求都将由⼀个单⼀的处理程序处理来进⾏设计,再根据请求…...

测试工具LoadRunner Professional脚本编写-脚本设置

勾选扩展日志-全选 原因:在并发完成后,通过抽查关键用户日志的方式,检查参数化是否如预期一致,比如抽查用户1(仓库一,物品一),用户11(仓库二,物品一),用户100(仓库十,物品十) 设置忽略思考时间 原因:是否忽略思考时间,请求数可能会有几十倍的差距…...

运用蓝光三维扫描仪的艺术与科技的完美融合-石膏头像模型3D扫描真实复刻

石膏头像具有独特的魅力,每一处细节都彰显着艺术之美。无论是深邃的眼神,还是精致的轮廓,都让人陶醉其中。 随着雕塑形式的日渐丰富,越来越多的新材料和新的塑造手法被运用到雕塑创作中,蓝光三维扫描技术的应用&#…...

文本域设置高度 加上文字限制并show出来:

文本域设置高度 :rows"4" 加上文字限制并show出来&#xff1a; maxlength"30" show-word-limit 效果: <el-form-item label"产品备注" prop"remark"><el-input v-model"form.remark" type"textarea"…...

探索数据确权、隐私保护、安全共享等方面的挑战与解决方案

在数据确权、隐私保护、安全共享等方面&#xff0c;当前确实面临着诸多挑战&#xff0c;同时也存在一些有效的解决方案。以下是对这些方面的详细探讨&#xff1a; 一、数据确权 挑战 权属关系模糊&#xff1a;由于数据具有复杂性和隐蔽性等特点&#xff0c;使得数据的权属关…...

麒麟 V10(ky10.x86_64)无网环境下 openssl - 3.2.2 与 openssh - 9.8p1 升级【最全教程】

目录 背景 安装包下载 上传解压安装包 安装zlib 安装OpenSSL 安装OpenSSH 验证 背景 近期&#xff0c;项目上线已进入倒计时阶段&#xff0c;然而在至关重要的安全检查环节中&#xff0c;却惊现现有的 OpenSSH 存在一系列令人担忧的漏洞&#xff1a; OpenSSH 资源管理错…...

前端技术(23) : 聊天页面

来源: GPT生成之后微调 效果图 HTML代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>聊天</t…...

ArcMap 处理河道坡度、计算污染区、三维爆炸功能

ArcMap 处理河道坡度、计算污染区、三维爆炸功能今天分析 一、计算河道方向坡度 1、折线转栅格 确定 2、提取河道高程值 确定后展示河流的高程值 3、计算坡向数据 确定后展示 4、计算坡度数据 确定后展示 二、计算上游集水区污染值 1、填挖处理 确定 2、计算流向 确定 3、计算…...