咸阳做网站公司电话,企业网站需要的模块,互联网行业有哪些公司,株洲的网站建设仓库:https://gitee.com/mrxiao_com/2d_game_2
我们正在试图弄清楚如何完成我们的世界构建
上周做了一些偏离计划的工作#xff0c;开发了一个小型的背景位图合成工具#xff0c;这个工具做得还不错#xff0c;虽然是临时拼凑的#xff0c;但验证了背景构建的思路。这个过…仓库:https://gitee.com/mrxiao_com/2d_game_2
我们正在试图弄清楚如何完成我们的世界构建
上周做了一些偏离计划的工作开发了一个小型的背景位图合成工具这个工具做得还不错虽然是临时拼凑的但验证了背景构建的思路。这个过程虽然是一个小插曲但确实为背景构建提供了一个思路。
另外不要问为什么屏幕上有这么多浮动的头像有时候就会出现这些头像。为了避免混淆现在先把这些头像关闭恢复到一个浮动的头像这样更容易处理。
目前的主要任务是完成世界构建特别是地面部分以确保我们能够继续推进标志着 Z 轴的处理已经完成。现在系统在单一层级上运行良好但我们已经开始着手实现多层次的功能这样就可以支持角色走上想象中的楼梯目前只有矩形表示。接下来的步骤是实现地面并确保能够正确显示两个层级之间的关系尤其是在一个层级遮挡另一个层级时能够正确呈现。
我们还没有修改碰撞检测系统来确保角色能够在地面上行走目前系统只是默认地面在零高度并且虽然已经标记了地面位置但并未真正利用这些标记。因此下一步需要处理的工作就是确保既能绘制地面又能准确地识别地面的位置这是当前的关键任务。 思考如何处理地面
目前已经完成了一个能够合成背景中地面的系统但问题在于这个地面还没有真正被引入到世界中。它只是在主循环中被调用所以它只停留在右上角并没有实际影响游戏世界。因此下一步的目标是将这个地面纹理实际应用到游戏世界中让它随着玩家的移动而移动。
为了实现这个目标可能需要在系统中创建一个实体这个实体将使用该地面纹理。当这个实体进入视野时它就会被绘制出来显示为地面。虽然具体如何实现这一点还没有定下来但可以先回顾一下当前地面元素的规格看看是否可以找出一种合理的方法将这个功能整合进现有系统以避免它成为一个浮动的、独立的部分。
看看我们当前如何指定地面
目前已知系统中有一个“space实体”的概念它可以描述世界中的space。space实体可以放置在世界中用来指示玩家能够走动的区域。任何存在space的地方玩家都可以行走而space下方没有更多space的地方则定义为地面。
接下来的问题是如何绘制这些地面区域。是否应当将地面绘制与space实体直接关联还是将其作为独立的绘制元素来处理这一点还不确定考虑起来有些复杂。因此决定使用黑板来讨论这一想法以便进一步理清思路。
黑板我们定义地面的系统
目前系统具有灵活的地面定义方式使用“空间实体”来定义可行走区域。空间实体并不一定是具体的房间它们可以是室外区域表示这是一个可以行走的地方且底部被视为地面除非有其他的边界体积重叠。
一种可能的地面定义方式是将地面图像绘制在底部的“平面”上但这存在问题尤其是当需要创建更复杂的形状如挖掘坑洞时地面图像的绘制会出现重叠或错误的问题。因此考虑避免直接存储大规模的地面位图而是存储重叠的“地面涂抹”信息。通过这种方法可以从涂抹信息中轻松地重新生成地面纹理避免存储巨大图像数据集。
此外考虑到可能存在相邻区域的情况比如两个房间之间有一个门或是完全开放的连接区域平滑滚动时不希望在边界处出现硬性的接缝。需要确保这些区域的地面涂抹能够无缝连接形成连续的纹理。
黑板引擎架构设计的潜在计划和指导原则
目前的设计考虑到如何处理地面涂抹splat问题。涂抹不一定需要作为实体存在因为它们只是用来生成地面纹理作为实体管理会引入不必要的复杂性。例如不需要对涂抹进行销毁操作也不必像实体一样修改它们的属性。涂抹可能只是通过位图覆盖来展示效果比如显示焦痕而不会像实体那样进行位置调整。
在架构设计时需要做出合理的初步判断并且始终准备好面对可能的错误。在引擎设计中最重要的是依据游戏实际需求来驱动架构而不是选择最简单的方案或忽视问题。目标是尽早设想如何使游戏功能有效运行并通过合理的设置来支持这些需求确保引擎能够为未来的生产做好准备。
黑板弄清楚地面的形状
存储涂抹列表的方式可以很简单基本上可以通过定义一个涂抹区域和涂抹的种类来进行。具体来说不需要存储所有具体的涂抹内容如草丛、石头等而是存储生成这些内容所需的参数。通过这些参数可以重新生成涂抹内容从而避免存储大量冗余的数据。
更复杂的部分在于确定地面的位置。地面的位置涉及到空间实体这些空白空间实体定义了可行走的区域并且需要根据这些空间实体的设置来决定地面的形状。在渲染时需要知道哪些空间实体与屏幕区域重叠并根据这些空间实体生成地面。通过将世界划分为多个Z轴层可以更高效地处理不同层次的地面并为每个Z轴层单独缓存区域数据。当玩家移动时可以根据需要重新生成对应的地面区域而不是一直存储完整的地面数据。
黑板考虑多个 Z 级别/深度
当处理不同高度的区域时需要考虑不同的层级和视图。例如当玩家站在一个平台上而平台下方有一个悬崖时地面会被分为不同的Z层分别表示玩家站立的区域和下方的区域。如果这些区域有不同的Z层高度那么就需要使用两个独立的缓冲区来处理而不能将它们合并在同一个缓冲区中。原因在于不同Z层的区域在渲染时会以不同的速度移动如果想要实现视差效果玩家移动时上层区域会比下层区域移动得更快。因此为了避免合并不同高度的区域需要为每个层次定义单独的缓存。
为了简化这种处理可以将空间划分为有限数量的深度层每个深度层对应一个具体的区域类似于Z层但实际上更多是表示层级的深度。例如深度0层代表玩家站立的位置深度1层可能表示玩家上方的区域深度2层可能表示更低的区域。这样每个层级在渲染时可以独立处理避免在不同的深度层之间产生混乱。
在进行地面生成时如果存在空洞或悬崖等结构则需要特别处理。例如当区域内有一个坑洞时需要确保这个空洞部分不会被地面覆盖而是应该保持透明Alpha 0以便显示出下面的部分。生成地面时可以先填充整个区域的地面然后再根据空洞的位置将其清除从而实现挖空区域的效果。
这种方式的关键在于通过填充整个区域并识别空洞来处理地面的生成。生成的地面可以覆盖整个区域而空洞部分则通过透明处理去除。这样地面生成的主要工作就是“雕刻”空洞区域而不是重新填充整个区域。
黑板空地物体将会切割出类似的区域
在处理地面生成时考虑到空洞和悬崖的存在可以采用一个合理的思路先将空地区域划分为多个深度层比如地面、下方区域等然后根据不同的层次进行划分和处理。对于每个深度层空地实体即空洞区域会根据其最小值的位置被划分到相应的层级中。这意味着当存在重叠的深度层时可以根据层次划分来“切割”区域确保地面和空洞能够正确地显示。
在处理深度剥离depth peeling时当前的做法是通过将实体与相应的深度层进行匹配来决定它们的位置而不是为每个实体单独生成复杂的几何结构。这避免了使用计算复杂度较高的构造性固体几何CSG技术从而节省了大量不必要的计算工作。这样虽然实现上有些临时性和简化但在这种情况下考虑到操作主要是在几个分层平面上进行的这种方法仍然是可行的。
因此考虑到实际需要的复杂度和工作量将地面区域和深度层进行固定划分并采用简单的处理方式似乎是一个合理的选择这种方法能够满足大多数场景的需求并避免了过于复杂的计算和渲染处理。
黑板该区域的 splats 是什么
在生成地面区域时可以采用一种简化的方法即基于世界坐标生成随机数来决定每个区域的分布。具体来说可以通过设置一个基于当前位置的随机种子来为每个区域生成“涂抹”效果而不是存储每个涂抹的具体数据。
例如在填充一个区域时可以先定义一个基础分辨率然后对于每个区域使用该区域的中心点作为随机种子来生成涂抹效果。接下来类似于瓦片块系统的工作方式检查所有可能重叠的区域生成需要的涂抹效果。这样涂抹效果只是根据空间位置实时生成而不需要事先存储所有涂抹的具体信息这样的方式相对安全且高效。
尝试使地面平面在所有方向上无限滚动
接下来的目标是让地面在所有方向上无限滚动。也就是说当角色移动时地面会持续生成并且始终保持新鲜且不重复的状态。这意味着地面会实时生成而不是重复使用预先存储的纹理。首先将通过修改现有的地面生成机制来实现这一目标并尝试使地面在角色移动时不断生成以确保无论角色走到哪里都能有新的地面。
扩大 GroundBuffer介绍 MaximumZScale 和 GroundOverscan 变量
为了实现地面在所有方向上的无限滚动首先需要调整现有的地面缓冲区使其足够大以便在角色走动时地面能够扩展并覆盖新的区域。当角色沿着楼梯上升时地面需要逐渐退到远处但仍然能够覆盖当前视野区域。因此地面缓冲区需要有足够的空间以便地面在深度层次变化时仍能覆盖整个屏幕。
具体实现时首先通过平台层获得屏幕的宽度和高度并以此为基础计算缓冲区的大小。接着考虑到Z轴缩放当地面随着角色的移动逐渐消失在远处时地面缓冲区的宽度和高度需要相应增大以保证能够填充整个屏幕。虽然目前还不确定具体的Z轴缩放因子但可以通过预设一个缩放比例来为未来的实现做好准备。
此外为了提高性能决定引入“过扫描”技术即在缓冲区的大小上额外增加一些空间从而减少每一帧更新的次数。这样做有助于在地面滚动时减少计算量尤其是在后台线程处理中可以避免每帧都进行完全更新。
最终地面缓冲区的宽度和高度将根据屏幕尺寸和过扫描比例进行调整从而确保有足够的空间用于生成新地面并支持角色的移动。 将 GroundBuffer 分区以便我们可以在其中滚动
在这个过程中首先需要为地面区域提供足够的空间以便能够实现滚动。为了达到这一目标可以通过增加额外的空间来使地面区域能够有效地滚动。接下来需要将这一区域划分为一个可以更方便使用的结构以便可以按需进行滚动。此时必须确保地面区域能够随摄像机一起移动这是非常重要的功能。
为此第一步是让地面区域能够随摄像机的运动进行移动。为了实现这一点摄像机需要以一种合理的方式进行移动。这样可以确保当视角改变时地面区域的相对位置保持一致创造出一个连贯的视觉效果。
黑板当前如何定位 GroundBuffer
在这个过程中当摄像机移动时屏幕和缓冲区之间的关系需要特别处理。屏幕展示的是当前视野中的内容而缓冲区则存储了显示的图像数据。当玩家在某个方向上继续移动时可能会遇到缓冲区的边界这时屏幕上显示的内容就无法继续向该方向滚动。
为了应对这一情况需要将缓冲区重新居中。具体来说当玩家继续向某个方向移动并到达缓冲区的边缘时缓冲区会将已经显示的内容复制到它的起始位置模拟一个“回弹”的效果。这意味着当前屏幕上显示的区域将被“传送”到缓冲区的开始位置同时缓冲区中的其他内容也会相应地向后移动。这样就为接下来的地面数据填充腾出了空间玩家可以继续朝着原来方向前进。
这种操作虽然有效但在实现时会出现一定的延迟因为当前的处理过程没有多线程优化每次重新居中和填充缓冲区时都会出现短暂的卡顿。这种问题暂时不是优先解决的问题关键是先让核心功能正常运作至于如何加快这一过程并通过多线程来优化计划在后续进行处理。在此之前尽管会有一定的性能问题但这是可以接受的并且会随着开发的推进逐步解决。
确定 GroundBufferP 相对于 CameraP 的位置
为了让地面缓冲区随着摄像机移动首先需要知道地面缓冲区相对于摄像机的位置。因此地面缓冲区的初始位置将与摄像机位置重合然后允许摄像机移动。当摄像机移动到一定距离后需要将地面缓冲区重新定位使其与摄像机保持同步。
具体实现时可以通过屏幕的中心坐标来确定地面缓冲区的位置结合地面缓冲区的大小进行偏移处理使得地面缓冲区从屏幕的左上角开始绘制。接着需要计算摄像机与地面缓冲区的相对位置差异以某种方式表达为向量并根据这个差值来调整地面缓冲区的位置。
在此基础上还需要处理坐标系的转换问题。屏幕坐标是以像素为单位而地面缓冲区的坐标是以米为单位。因此必须将米转换为像素以便正确渲染。
此外在计算时还会遇到坐标方向上的问题。例如Y轴的方向在世界坐标系中是向上的但在屏幕坐标系中可能是相反的。这种问题需要在渲染时进行适当调整。
在实现过程中可以先将地面缓冲区的位置初始化为摄像机的位置。之后当摄像机移动时地面缓冲区的位置会根据摄像机的变化而更新从而实现地面缓冲区随摄像机的运动同步。 计划在 GroundBuffer 用完像素覆盖时将其朝摄像机的方向快速移动
当地面缓冲区即将无法覆盖像素时需要做的是将其位置调整到靠近摄像机的方向。具体来说当地面缓冲区即将超出屏幕范围时需要将其位置“吸附”到摄像机的方向确保它总是能够有效地显示。为此需要执行一个复制操作改变地面缓冲区的位置以便保持其与摄像机视角的对齐。
关闭树木
首先目标是摆脱当前被树木所限制的情况。因此暂时关闭生成树木的功能以便进行测试。接下来需要清除当前的树木和其他相关物体以便可以更自由地进行移动和测试。此时地面测试区域的空间可能不足因此需要增加空旷区域的大小确保测试能够顺利进行。可以通过调整“空旷空间添加器”来实现这个目标。为了确保足够的空间可以将空旷区域做得更大进一步确保测试的有效性。
关闭 Z 门
通过回到旧的方法限制生成的内容确保生成的区域不会出现Z型门。这样在随机选择时通过指定只生成平坦区域避免了不必要的复杂性。这使得可以实现之前设想的行走系统确保了功能的实现大家都能满意。
另外之前有一个功能只会生成一个房间经过调整停止了这种限制重新启用了实际的房间生成。这样房间的生成不再被局限于一个单一房间而是恢复了更灵活的生成方式。 打开树木
现在可以恢复之前的功能让生成更多的房间并确保房间中有更多内容。这样重新生成的房间变得更加丰富玩家可以顺利地穿行其中。
接下来目标是确保这些房间能够填充地面。在进入房间时必须确保地面始终存在并且被填充。这意味着每当走进一个房间时都需要确保该区域有稳定的地面支持保持持续的地面存在。
使地面不断地生成
为了生成填充地面的效果首先需要智能地生成屏幕内容。在生成这些内容时不需要复杂的瓦片化处理操作相对直接。通过使用 DrawTestGround 方法可以确保填充整个缓冲区。在执行 DrawTestGround 时关键是要避免使用半径方法而是要生成一种随机性能够扩展到缓冲区的边缘。
为了确保生成的地面足够大并且能够覆盖整个区域必须在瓦片边界上正确地重新生成种子。这样就能确保每次生成的内容都符合预期不会出现空白或不连贯的地面区域。
黑板平铺考虑
在生成地面时遇到的挑战是当玩家移动到屏幕一侧时需要复制缓冲区的一部分并将其填充到新的区域。然而由于不是使用简单的重复瓦片而是随机生成地面内容这个过程变得复杂。如果地面内容是重复的瓦片直接填充就能解决问题但随机生成的内容涉及更多因素比如区域内可能有不同的地形特征生成过程也需要考虑这些因素。
为了保证每次填充相同的区域时能生成一致的内容必须避免受随机因素的影响。一种解决方案是将地面分割成多个“块”每个块可以根据固定的参数来生成内容而不是依赖于动态的随机因素。这样生成的内容在每次填充时都能保持一致确保整个地面填充过程的连贯性和稳定性。
将 DrawTestGround 改为 DrawGroundChunk
为了生成地面块需要通过一个“DrawGroundChunk”绘制方法将其与缓冲区进行交互。在绘制时首先需要知道每个块的位置并确保生成的内容基于相同的初始位置以确保随机生成的内容每次一致。通过使用块的位置坐标如块的X、Y、Z值可以生成一个随机种子这个种子决定了该区域的内容。
接下来生成的地面块需要填充指定区域而不是依赖固定的半径或像素大小。在绘制时使用随机因素来确定偏移量确保地面内容覆盖整个区域。通过这种方式可以摆脱传统的固定尺寸和半径计算使用整个位图的尺寸作为偏移量来生成地面。最终生成的地面块会精确覆盖区域并使用随机值来调整偏移量以便每次填充的结果都能保持一致。
这些步骤确保了地面生成的灵活性和一致性但目前的实现还相对简化代码未完全优化仍然有改进空间。 问为什么不填满整个游戏窗口而是留那么多黑色空间
在填充整个缓冲区时尽管目前已经填充了大部分区域但细节层面尚未达到预期。因此需要提高填充的细节度可能需要增加参数值以获得更精细的覆盖。然而这个问题可以在后续阶段进一步解决。
至于在开发过程中不使用全屏显示这是为了避免出现绘制错误因为全屏可能会让问题隐藏在屏幕边缘。开发时通常会以窗口模式显示游戏内容而不是全屏这样更容易检测到潜在的绘制问题。在未来的调试过程中可能会采用一种居中显示的方式并且会标出安全区域确保开发人员能够看到更多的游戏区域尤其是屏幕之外的部分。
这种显示方式帮助开发者更好地定位和修复问题而不仅仅是展示玩家视角。全屏显示主要用于最终测试以确保游戏在实际玩家体验中正常运行。
问处理多个层级显示时的一些问题是否源于没有一个 Z 坐标来让摄像机直接进行线性插值
在处理多层显示时并不主要由于缺少相机的Z坐标进行插值lerp引起问题因为相机的Z坐标是有的问题更多是由于没有完整的3D几何体。如果游戏完全采用3D构建这些问题就不会存在。然而使用2D游戏时艺术创作会变得相对简单单个艺术家就能完成整个2D游戏的制作而3D游戏则需要更多的人员和资源。
2D游戏虽然在艺术质量上可能有所提升但程序复杂性相对较低因为不需要处理复杂的资产管道、预处理和着色器等3D开发中的问题。尽管2D游戏在一些方面简化了开发但如果要做一些有趣的、复杂的功能开发仍然会变得更加复杂。
如果想避免解决复杂的编程问题也可以选择使用单一Z轴水平或者不做平滑的楼梯上升这也是可以接受的做法。但如果追求更多复杂的编程挑战采取这些方式就会限制开发的灵活性。通过这个编程流目的是展示如何超越简单的工具推动代码开发的边界做一些在现成工具中无法轻易实现的事情。例如程序化生成的地面就是一个典型的例子这种功能可能无法通过简单的现成工具实现因此展示如何进行这类创新是重点。
问如果没有人问相关问题能否大致估算一下添加字体和文本渲染系统何时会变得有用或必要
添加字体和文本渲染系统的时间框架已经在开发计划中预计不会太久。虽然目前的工作重点是解决一些更为复杂的问题这些问题并不直接需要字体显示但在处理诸如资产流式传输之类的任务时字体系统将变得非常重要尤其是在调试时需要显示调试信息这时就需要字体系统来支持显示调试文本。此时可以使用临时的调试字体而不需要最终的字体设计。
讨论学习 C
关于学习C或OpenGL等编程问题推荐的学习资料并不多且目前市场上充斥着许多质量不高的教程。尽管如此还是可以找到一些有用的教程。例如OpenGL方面之前有一个名为Arc Synthesis的教程系列虽然它被认为是一个不错的学习资源但目前似乎已经无法找到这些教程了。如果这些教程确实消失了就需要另寻其他合适的学习资源。目前考虑到开发进度可能会在将来的直播中涉及一些图形API的内容若幸运的话未来也许会用到Vulkan图形API。因此尽管目前没有明确推荐的OpenGL教程但Arc Synthesis教程曾经是一个不错的选择。
问你提到将地面绘制工作转移到单独的线程以防止卡顿。是否有可能将绘制工作分配到多个帧中并且这比任何一种方法有益吗
计划将地面绘制的工作分配到单独的线程上以防止主线程出现卡顿。这种做法的目的是为了利用CPU上的空闲资源尤其是在2D游戏中一旦开始使用GPU进行渲染通常CPU上会有多个核心处于空闲状态。因此希望将一些生成性工作完全异步地从主线程中分离出来比如生成或加载数据等。可能会有一个专门用于后台加载和解压的CPU线程以及另一个用于生成工作的线程这些线程之间不需要直接关联而是通过队列进行通信。这种方法将能有效提高性能尽管目前无法保证最终一定会这样实现但这是一种可能的优化方案。
问你的游戏目前使用了多少内存占用当然它不会很大但我更想了解有多少不同的容器
游戏的内存占用目前不会很大但问题是关于使用了多少种不同的容器。如果能更具体地说明“容器”指的是什么可以更好地回答这个问题。
问2D 图形的程序生成是否有一些主流的数学方法
程序生成2D图形并没有明确的主流数学公式。虽然其中有一些数学元素比如噪声模式等但更多的是一种黑魔法。程序生成2D图形是一个需要不断学习和实践的过程。例如将会进行更好的地面生成这将是一个探索这类技术的实际案例。
问目前已经使用了多少不同的类
在编程中并不使用传统的类而是采用了系统化的方式。例如使用“模拟区域”Sim Region来处理游戏区域的模拟使用“世界表示”World Representation来将世界划分为多个块并允许快速访问。这些“系统”通过结构体来定义数据布局而不是传统的面向对象的类。系统之间的结构较为宽泛通常更侧重于整体的系统设计而非按类划分。
问有没有一种简单的方式来解释 C 中的指针和引用
在C中指针和引用之间的差异实际上并不复杂它们只是语法上的不同。指针使用*符号来表示一个指向某个变量的地址而引用则是某个变量的别名。 指针通过声明一个指针如int* x我们实际上是在声明一个指向整数的内存地址。这意味着指针存储的是另一个变量的地址通过解引用*x可以访问该地址存储的值。指针允许访问和修改它所指向的内存位置。 引用引用则是某个变量的别名。例如int x y;表示x是y的引用意味着x和y实际上指向相同的内存位置。引用无需解引用操作符*直接当作原变量来使用。引用在语法上看起来更像是直接访问变量但底层仍然是通过指针来实现的。
在实际使用中指针和引用在大多数情况下有相同的效果。在函数调用中无论是通过指针还是引用传递参数最终都能够修改原始数据。差异在于引用更简洁语法上更易于理解而指针则提供了更灵活的操作例如指针可以为空而引用则不能。
实际上指针和引用的实现方式相同都是指向内存地址区别在于它们的语法和用法。除非有特定的C特性要求使用引用否则指针可以提供更多灵活性引用则更多用于简化代码。