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

网站域名dnsgoogle推广教程

网站域名dns,google推广教程,建站宝盒小程序,空间网站打不开仓库: https://gitee.com/mrxiao_com/2d_game_7(已满) 新仓库: https://gitee.com/mrxiao_com/2d_game_8 回顾并为今天的内容定下基调 我们接下来要继续完成之前开始的工作#xff0c;上周五开始的部分内容#xff0c;虽然当时对最终效果还不太确定#xff0c;但现在主要任…仓库: https://gitee.com/mrxiao_com/2d_game_7(已满) 新仓库: https://gitee.com/mrxiao_com/2d_game_8 回顾并为今天的内容定下基调 我们接下来要继续完成之前开始的工作上周五开始的部分内容虽然当时对最终效果还不太确定但现在主要任务是让渲染器的前端能够正常工作确保我们想要实现的所有Z轴处理效果能够正确呈现。 目前我们已经实现了排序算法精灵的排序基本上是正常工作的但还没有实现我们想要的分层切片机制。我们打算把精灵分到不同的堆栈里这些堆栈是基于图层的并且希望这些图层能够相对独立地发生变化不受屏幕上其他内容的影响。因此现在必须回到之前想完成的工作——确保Z轴排序从头到脚都正确。 下一步要搞清楚这种分层切片的具体表现形式。因为现在我们有真正的游戏内容比如怪物行为和渲染逻辑我们希望这些代码能够说同一种“语言”也就是说让实体能够简单明了地表达自己想要渲染什么、渲染在哪里不希望有太多零碎的代码引起问题。 虽然听起来不算大事但这实际上是大量的工作。我们需要对代码进行组织和调整把内容合理划分成切片。第一步是确定怎么划分这些切片第二步是确定切片如何经过渲染系统和排序阶段最后是这些切片怎么通过后端渲染器软件渲染或者OpenGL输出。 这里面涉及很多复杂的决策而且有很多相互竞争的需求。举个简单例子现在排序主要是在渲染流程的最后完成但我们可能需要把排序往上移一点提前到游戏逻辑层处理。原因是我们在游戏代码中已经知道每个切片包含的内容没必要把所有这些细节都暴露给渲染层。渲染层本身需要在软件渲染和OpenGL两套系统中都实现并且在底层要保证简洁高效避免复杂难控的代码。 此外我们还要传递和存储排序键sort keys这可能会造成资源浪费或者效率低下也需要仔细权衡。 总的来说这是一件非常复杂的事情需要我们深入思考制定合理的设计方案才能正确地实现这些目标。接下来会花不少时间在这方面的工作上。 计划实现一个功能对精灵集合进行排序 接下来可能会从明天开始着手处理这个问题。今天的计划是回到上周五查看的那段代码继续实验和探索如何实现这样一个功能让一个角色或对象拥有一组已经预先排序好的精灵集合然后让这个集合整体参与排序而不是把集合中的每个精灵单独拿出来通过各自的排序键逐个排序。 针对这个问题我们有几种不同的实现方式但目前还不确定哪种方式最简单可行。上次我们慢慢地开始探索这条思路。这里还涉及之前一次讨论中的一些观点所以需要结合之前的想法一起考虑。总体来说就是尝试设计一个系统使得预先排序的精灵组可以作为一个整体被排序从而简化排序流程和提高效率。 黑板讨论我们可以使用哪些方法来对精灵集合排序 我们在讨论手动排序覆盖的问题考虑了几种不同的处理方式。首先有一种方案是将一组相关的精灵合并成一个整体的“盒子”这样排序器就可以简单地把它们当成一个单元来处理这样做看起来挺简单。但问题是这样合并的盒子可能会包含过多重叠区域导致排序时出现不必要的复杂情况和错误因为把多个元素合成一个大盒子会让排序区域变得很宽泛包含了很多本不应该被包含的部分。 因此更安全的做法可能是保持每个精灵都有自己的盒子同时提供一种机制来告诉排序器它们应该被视为一组一起排序。也就是说不是物理合并它们的空间区域而是逻辑上把它们关联起来。 另一种相对简单的方式是依赖排序键SortKey机制。如果我们有一组精灵需要按预定顺序排列这些精灵可以赋予相同的排序键。比如精灵A、B、C都给出完全相同的排序键这样排序系统在排序时会根据它们在缓冲区中出现的顺序来决定绘制顺序。因为排序过程通常是稳定排序顺序相同的键值时会保持它们原来的排列顺序。 这种方法相对简单且已有部分实现。不同的精灵虽然有各自的屏幕区域但排序键相同就能保证它们保持在预期顺序里。具体排序键的数值该怎么确定呢如果是Y轴精灵Y-sprite排序键可以用其最大Z值和某个固定的Y值可能是平均Y或者第一个Y坐标这些数值可以由用户指定。如果是Z轴精灵Z-sprite则可能需要更复杂的Y最小值和最大值区间来确定排序这部分还不完全确定。 相较于之前考虑的“串联链表daisy chaining”的复杂方案这种统一排序键的方案看起来更简单更易于实现。把“串联链表”功能移除后可以让这些相关的精灵按照正常顺序依次加入排序器再让排序器依据排序键自动处理。 简而言之尽量减少系统中的复杂特殊处理逻辑保持排序系统尽可能简单是有利于整体效率和可维护性的。即使这种方法在某些情况下可能略微降低效率但减少复杂性带来的整体优化和代码简洁性会带来更大的好处。 总体来说希望尝试这种用相同排序键通过缓冲区顺序实现多精灵有序绘制的方式简化整个排序系统的设计使它既满足需求又不增加不必要的复杂度。 运行游戏观察当前的排序效果 当前运行的是一个标准的游戏版本。我们进行了测试加载并运行了最新版本后观察游戏中角色的表现情况。现在关注的重点是主角的Sprite渲染顺序。 当前的Sprite渲染逻辑中角色在Y轴向后移动时会被排序系统判断为应该“更靠后”渲染导致角色头部被衣服遮挡。虽然这种Y轴深度排序在大多数情况下是正确的但这并不适用于主角的头部和身体之间的关系。 我们希望无论主角在Y轴上的位置如何变化头部始终渲染在衣服之上避免出现视觉上的遮挡错误。换句话说我们要调整渲染层级让头部始终显示在最上层而不是被自动排序逻辑所影响。 当前的测试目的就是验证是否能够实现这个目标。我们计划通过调整渲染优先级、分层逻辑等方式确保主角的头部在任何时候都不会被衣服遮挡从而提升游戏的视觉一致性与表现力。 修改 game_render_group.cpp移除 PushRenderElement_() 中的 NewElement引入“写回”机制允许使用新的信息覆盖已有的 SortKey 我们正在优化游戏渲染系统中的排序机制目标是更好地控制不同Sprite精灵之间的渲染顺序特别是主角Sprite的部分遮挡问题。 目前在render group中我们开始初步设计新的排序方法。以往的逻辑是每个元素在渲染时都会生成一个新的排序元素sort field这在大多数情况下是有效的但现在我们需要一种更加灵活的机制以支持多个Sprite按照特定规则进行整体排序。 我们不再希望保留原有的通用排序逻辑而是要引入“排序回写write-back”的概念也就是说在将多个Sprite渲染后我们需要用一个“聚合后的排序键aggregate sort key”来覆盖原始的排序键。这就需要我们记录下多个Sprite组合后的边界信息形成一个“聚合边界aggregate bound”供后续使用。 为此我们计划在render group中新增一个字段例如SpriteBound或类似的变量用来存储聚合边界信息。这个字段会在每次添加新Sprite时通过一系列min和max操作来不断更新确保包含所有相关Sprite的完整范围。 值得注意的是我们不打算更改每个Sprite自身的屏幕区域screen area信息这部分仍然保持独立确保它们各自的绘制区域正确分离。我们只聚合边界信息用来影响排序逻辑。 通过这种方式在render group中我们就能为多个Sprite提供统一的排序依据使它们作为一个整体进行渲染排序。接下来我们可能还会设计一个小型API供调用者使用方便地将Sprite打包为一个排序单元从而提升整体的渲染控制能力和视觉一致性。 继续在 game_render_group.cpp 中考虑是否让 PushBitmap() 返回一个值以供 PushRenderElement_() 修改 我们正在进一步改进渲染排序机制重点在于处理 push_bitmap 操作的行为变化。 以往在调用 push_bitmap推送一个Sprite贴图时并不会返回任何值。但现在由于新的排序策略引入我们需要让它返回某些信息。原因在于我们需要在推送完一系列Sprite之后重新写入overwrite它们的排序键sort key。这是因为直到我们完成多个Sprite的处理之后我们才知道它们真正的聚合排序信息进而能确定应该使用的最终排序键。 因此我们必须引入一种机制使调用者能够在事后回头修改这些已推送Sprite的排序信息。这也意味着我们要为每个 push_bitmap 操作返回某种可追踪的数据结构这样在之后可以使用新的排序信息覆盖已有内容。 解决这个问题的一种思路是在开始推送Sprite之前显式调用一个“重置聚合边界reset sort bound”的函数。这样就能确保我们记录的是这批Sprite的统一边界。随后在完成这些Sprite的所有 push_bitmap 操作之后我们便拥有一个聚合边界aggregate bound其中包含我们想要用来计算最终排序键的数据。 核心问题就变成了如何获取之前已经推送过的Sprite的排序键因为只有拿到这些键我们才能将新的聚合排序键写回去。 所以下一步的设计方向是 修改 push_bitmap 接口返回可以被追踪和访问的结构比如一个记录了该Sprite在渲染队列中的索引或句柄。支持排序键覆盖引入一个机制允许我们在事后使用新的排序键覆盖这些记录中对应的Sprite。提供聚合边界API通过 reset_sort_bound 开始记录一个新的聚合过程结束后使用聚合结果统一更新一组Sprite的排序键。 这种设计将使得多个相关的Sprite能够被当作一个整体进行排序同时又不会破坏它们各自独立的屏幕区域信息。整体目标是实现更精确的视觉层级控制特别是在角色头部与身体等部位之间保持正确的渲染前后关系。 修改 game_entity.cpp在 UpdateAndRenderEntities() 中加入 BeginAggregateSortKey() 和 EndAggregateSortKey()标记哪些实体共享一个排序键 我们正在继续完善渲染排序系统的结构当前的重点是解决多个Sprite例如一个角色的身体部位之间如何共享统一的排序键sort key的问题。 以往每次调用 push_bitmap推送一个Sprite时并不会返回任何数据也不追踪这些调用的位置。但在当前的设计中我们需要将这些Sprite当作一个整体来处理因此必须追踪这些操作以便在最后用一个统一的排序键来覆盖它们。也就是说我们需要一种机制来记录在某段时间内推送了哪些Sprite并在它们全部被推送后统一更新它们的排序信息。 在查看push_bitmap调用的位置时我们注意到Sprite的推送逻辑已经被移到entity系统中。在遍历piece index并进行Bitmap推送的地方是一个合适的切入点来标记这些Sprite将共享同一个排序键。 但问题在于如何标记和覆盖这些排序键这是当前遇到的主要挑战。 我们不希望引入太多复杂的内存复制或指针操作因此在考虑如何以简单清晰的方式实现这一功能。设想如下 开始和结束一个聚合排序阶段通过调用类似 begin_aggregate_sort_key() 和 end_aggregate_sort_key() 的函数标志着接下来的一批 push_bitmap 调用将属于同一个聚合排序单元。在这个阶段内推送的所有Sprite会记录索引位置例如在渲染缓冲区中的位置而不是返回复杂的结构或指针。在 end_aggregate_sort_key() 被调用时我们将计算出一个聚合的排序边界aggregate bounds并统一将该排序键写入到之前记录的Sprite中。 这一思路的好处是 不需要外部干预用户只需明确开始和结束聚合区域即可内部结构高度有序可以轻松基于索引范围更新排序键不依赖额外指针避免复杂的内存管理。 目前还有一个技术上的难点就是聚合排序键的类型推断。例如 如果推入的是Y轴排序类型的Spritey-sprite那么聚合后也应该保留为y-sprite但使用简单的min-max方式进行聚合可能意外将其“扩展”为Z轴类型从而改变渲染逻辑 因此需要决定 是否允许用户在 end_aggregate_sort_key() 中手动提供排序类型信息或者是否从某个代表性Sprite比如第一个中提取排序类型作为基准又或者直接在内部通过某种策略来保持最初的排序类型。 为简化初期实现我们将先做一个完全自动化版本即用户无需传递任何信息系统会自动追踪聚合边界并更新排序键。后续如果发现自动推断带来问题再考虑添加更细化的用户控制接口。 总体而言当前的设计逐渐清晰将支持更强大而灵活的排序控制能力尤其适用于多个Sprite需要共同排序但又要保持各自独立屏幕区域的复杂渲染场景。 在 game_render_group.cpp 中实现 BeginAggregateSortKey() 和 EndAggregateSortKey() 我们目前正在实现一套聚合排序键Aggregate Sort Key机制用于在渲染流程中统一管理一批被推入的 Sprite使它们拥有一致的排序行为。核心目标是确保在调用 begin_aggregate_sort_key() 到 end_aggregate_sort_key() 之间的所有 Sprite 都共享一个统一的排序边界Sort Bound。 以下是详细设计与实现逻辑 初始化聚合边界Aggregate Bound 在 begin_aggregate_sort_key() 被调用时我们首先需要初始化聚合边界数据 最小值设为最大可能值最大值设为最小可能值。这样可以确保后续任何一个 Sprite 推入时它的边界信息都会“扩展”当前聚合边界保证边界最终包含所有 Sprite 的范围。这种初始化策略是通用技巧可以确保聚合边界在遍历过程中被正确更新。 记录 Sprite 推入的位置 我们在每次调用 push_bitmap 时都会生成一条排序命令并推入渲染命令缓冲区。为了在 end_aggregate_sort_key() 时能够回头修改这些命令的排序键我们必须知道它们在缓冲区中的确切位置。 解决方案 在调用 begin_aggregate_sort_key() 时记录当前缓冲区的起始位置命名为 first_aggregate_at。随后每推入一个 Sprite就自增一个聚合计数器 aggregate_count。在 end_aggregate_sort_key() 中我们使用 first_aggregate_at 和 aggregate_count 计算出所有参与聚合的命令位置然后统一修改它们的排序键为聚合边界所生成的排序键。 结束聚合并覆盖排序键 在 end_aggregate_sort_key() 中 遍历从 first_aggregate_at 开始的所有 aggregate_count 条渲染命令。每一条命令的排序键字段被替换为聚合边界生成的统一排序键。 这个操作确保所有聚合内的 Sprite 都按照这个统一的排序逻辑参与最终渲染。 排序键计算中的注意事项 我们还需要考虑排序类型的保持例如 若起始 Sprite 是一个 Y-Sprite则不希望聚合后变成 Z-Sprite。使用边界 Min/Max 来自动生成排序键时可能会误将 Y-Sprite 变为 Z-Sprite因为边界扩大了。 为此我们考虑两种方案 完全自动推断在聚合过程中自动提取最初 Sprite 的排序类型并在结束时应用到统一排序键上用户手动指定允许 end_aggregate_sort_key() 接收一个明确的排序类型参数避免误推断。 当前阶段我们先采用全自动模式在必要时再引入手动控制的选项。 技术实现细节 使用 push buffer 的索引计算 Sprite 的实际位置渲染命令结构通过已有字段如 SortEntryAt与渲染组内的 Sprite 数组结构对齐因此只需要计算偏移量即可精准访问所有聚合 Sprite 的排序键都通过统一聚合边界生成避免了冗余数据复制或不必要的内存操作编译时也需调整 include 顺序确保相关的结构体如 render_group 和 render_doh 在使用前已正确定义。 这一机制的设计简洁、直接避免了复杂的内存管理或返回值处理同时具备高扩展性为后续更高级的渲染排序策略例如动态层级分组打下了坚实基础。我们下一步要处理的问题是如何在结束聚合时确保类型标识的一致性。 让 PushRenderElement_() 能够正确设置 Y/Z 精灵的聚合边界AggregateBound 我们正在解决的问题是在执行聚合排序Aggregate Sort Key操作的过程中如何根据 Sprite 的类型Y Sprite 或 Z Sprite合理地处理它们的排序边界尤其是在多次 push_bitmap 的情况下正确扩展或设置聚合边界信息。 基本逻辑流程 每当 push_bitmap 被调用我们都会做以下几件事 递增聚合计数器 aggregate_count。 判断当前是否为聚合的第一个 Sprite 如果是第一个aggregate_count 0则将其排序边界直接复制给聚合边界。如果不是第一个则进入边界合并逻辑。 关键判断Y Sprite vs Z Sprite 在第一个 Sprite 被推入后后续的每一个都要判断是否应该合并进同一个聚合边界而这个判断的核心在于 Sprite 类型 Y Sprite 通常根据 Y 坐标进行排序。Z Sprite 通常根据 Z 坐标进行排序。 我们必须确保所有被聚合的 Sprite 类型保持一致否则排序逻辑会出错。 我们引入一个辅助条件判断机制来处理这个 if (is_y_sprite) {// 聚合逻辑更新 Y 边界 } else {// 聚合逻辑更新 Z 边界 }判断是否是 Y Sprite 或 Z Sprite 的方法我们已有代码逻辑可用例如通过 Sprite 的排序键中的某个位来判断是否为 Y Sprite。 聚合边界的处理策略 第一个 Sprite 聚合边界直接等于当前 Sprite 的排序边界 后续 Sprite 如果是 Z Sprite通常对 Z 方向的 min/max 值做合并扩展范围如果是 Y Sprite则可能只对 YMin/YMax 做扩展且不能改变 Sprite 类型仍需标记为 Y Sprite类型一致的情况下我们只需对边界进行标准 min/max 扩展。 这个机制确保了聚合排序键能保持一致性并且不意外改变原始的排序逻辑。 总结当前策略的优势 自动处理逻辑简洁明确 使用 aggregate_count 0 判定首个 Sprite后续扩展边界类型判断严谨 根据 Sprite 类型Y/Z决定如何合并边界数据结构利用高效 不需要引入额外的复杂数据结构或指针操作行为可扩展 未来可添加如平均边界值等策略仅需在此逻辑中扩展分支判断即可。 下一步要继续完善的是聚合结束时是否允许外部指定排序类型或者完全依赖首个 Sprite 类型作为基准并自动传播这还需要进一步验证更复杂使用场景中的表现。 修改 game_render.cpp新增 IsYSprite() 函数用于判断是否为 Y 向精灵 我们正在实现一个聚合排序系统并进一步完善其中的逻辑处理尤其是针对 Y Sprite 和 Z Sprite 的处理方式。 目标与背景 我们希望支持在一段时间内连续推送多个 Sprite比如多个 tile、物体或图层片段在逻辑上把它们作为一个整体进行排序。因此需要构建一个聚合边界Aggregate Bound这个边界能够代表所有 Sprite 的联合排序信息。 但由于不同类型的 SpriteY Sprite 与 Z Sprite在排序方式上是完全不同的我们必须确保一个聚合内部的所有元素类型是统一的否则无法正确排序。 主要处理逻辑细化 1. 判断 Sprite 类型 我们通过排序键Sort Key中的某些字段是否相等来判断 Sprite 的类型 如果某两个特定字段 不相等那么这是一个 Z Sprite否则就是一个 Y Sprite。 于是我们实现了一个函数 is_z_sprite() 来封装这个判断逻辑。 2. 对聚合中的 Sprite 做类型一致性检查 我们加入断言逻辑 若聚合中第一个 Sprite 是 Z Sprite后续所有必须也是 Z Sprite若聚合中第一个 Sprite 是 Y Sprite后续也必须是 Y Sprite否则立即触发断言阻止继续聚合不同类型的 Sprite。 这保证了聚合排序的合法性和行为一致性。 3. 聚合边界更新方式的差异 Z Sprite 的聚合 需要不断扩展聚合边界的 Z 值区间例如 zMin/zMax以涵盖所有 Z Sprite 的实际可见排序范围。 Y Sprite 的聚合 当前策略下我们选择不更新边界即保持第一个 Sprite 的 Y 值作为聚合边界。这是因为 Y Sprite 的排序往往固定在起始值即可。 若后续需求复杂可以考虑改为扩展 YMin/YMax。 聚合状态的控制机制 为避免错误地在非聚合期间执行聚合逻辑我们增加了一个标志变量 bool aggregating;在 Render Group 内部使用该变量表示当前是否处于聚合状态。 控制逻辑 调用 begin_aggregate_sort_key() 时 aggregating 必须为 false设置为 true初始化聚合状态断言防止重复 begin 调用 end_aggregate_sort_key() 时 aggregating 必须为 true设置为 false写入聚合键断言防止漏掉 begin 或嵌套聚合 这样可以有效防止多次 begin 或 end 调用造成的状态混乱也防止在非聚合状态下执行聚合边界扩展逻辑。 当前实现的优势 强一致性保证 类型判断断言确保不会错误聚合 Y 和 Z Sprite。 逻辑清晰且可扩展 分支结构处理不同 Sprite 类型聚合行为后续可扩展更多行为策略如平均值聚合、特殊 Y 扩展等。 状态机制明确可靠 使用 aggregating 标志位严格限制聚合边界的执行范围避免误操作。 调试友好性高 合理使用断言让调试过程中的逻辑错误快速暴露减少潜在 bug。 下一步计划 检查调用聚合 API 的地方确保 begin 和 end 成对出现验证所有 Y/Z Sprite 的聚合逻辑在实际渲染流程中的正确性如有必要进一步引入聚合类型枚举或配置以便支持更复杂的排序需求。 再次运行游戏发现当前效果其实还不错 现在我们需要确认之前实现的聚合排序逻辑是否真的生效。虽然结果乍一看好像不太对但仔细观察之后发现可能其实是工作正常的只是视觉表现让我们误以为出了问题。 观察现象分析 我们看到屏幕上有三个元素顺序发生了变化本以为这是错误的表现。但之后发现这三个元素实际上并不是被作为一个聚合体传递的它们来自两个独立的实体entity所以目前还不能用它们的排序变化来判断聚合是否正确工作。 进一步检查后发现躯干torso和披风cape在排序中并未发生变化说明当前聚合机制可能已经部分起效只是头部head尚未被纳入同一聚合序列中。 当前阶段判断 因此在当前的测试中 躯干与披风作为一个实体没有显示出异常行为头部暂时未聚合表现正常暂无明显排序错误或断言触发。 所以可以推测虽然还没有正式完成全部聚合逻辑的使用但当前的聚合排序机制本身在底层已经能够正常运作。 现有方案的价值与意义 目前的方案不仅基本可行还有以下几个额外优势 1. 结构清晰 聚合逻辑通过明确的 begin_aggregate_sort_key() 与 end_aggregate_sort_key() 来界定使用范围便于维护与阅读。 2. 不强制依赖结构完整性 即便没有把所有相关 Sprite比如头部立即聚合进去现有逻辑仍然稳健不会导致渲染失败或逻辑崩坏。 3. 允许逐步集成 我们可以先把躯干、披风等部分纳入聚合确认其工作机制再逐步引入更多 Sprite比如头部。每一步都是可测试、可观察的降低了调试难度。 4. 支持动态可变组合 当我们在使用聚合机制时不需要所有 Sprite 都一开始就被静态组合可以根据实际情况动态加入聚合区域。只要确保聚合边界正确系统就能正确处理。 后续改进方向 添加头部 Sprite 到聚合结构中验证整个聚合单元能否被正确排序确保在所有需要聚合的地方都使用了 begin 和 end 包裹增加可视化调试机制比如调试打印聚合索引、Sprite 类型以确认实际聚合行为最终目标是整个人物头部、躯干、披风等作为一个聚合单元始终保持视觉与逻辑排序一致性。 总结来说目前的聚合排序系统已经基本具备了功能并且具备良好的可扩展性和测试分层能力虽然还未完全应用到所有部件但已有良好基础。接下来将逐步整合更多组件验证完整性。 修改 game_render_group.h移除 render_group_entry_header 结构中的链式指针daisy-chaining 我们在实现聚合机制的过程中发现了一种非常实用的“后门”方式。通过聚合排序键aggregate key我们不仅能够在一段连续的 Sprite 推送中完成聚合还可以保存这个聚合键并在稍后的时刻直接将其他元素加入同一聚合组只要它们使用相同的聚合键即可。这个设计思路让我们的系统更灵活不再依赖原来的顺序式推送增强了结构的可控性。 优化方向删除多余的链式结构 原先我们使用了一种“链式”的方式进行聚合管理通过 next 字段将多个 render_entry 串联起来以便构建聚合单元。但在新的聚合键机制下这种链式结构显得不再必要甚至变得多余与复杂。因此我们决定彻底移除这部分功能以简化系统。 具体修改操作 1. 移除 next 字段 在 render_entry_header 结构体中曾经存在一个 next_offset 字段用于链式链接。现在我们将其彻底删除。这样每个渲染条目只保存自己不再拥有对下一个条目的链接信息。 2. 修改相关逻辑 所有使用 next_offset 或链表逻辑的地方都需要进行调整 删除相关偏移量的处理移除遍历链表的循环确保每次只处理一个条目不再期望自动进入下一个条目。 3. 清理游戏渲染路径中的遗留代码 在游戏渲染函数中曾经存在一个基于 next_offset 的遍历循环这在链式结构下是合理的但在当前逻辑下则会导致死循环或错误渲染。我们识别出这段代码是个潜在的无限循环并及时清除避免运行错误。 当前优化的好处 简化数据结构去除了不再必要的字段让 render_entry 更轻量提升逻辑清晰度每个条目独立存在通过聚合键统一识别归类逻辑更直接提高灵活性可以在不同时间、不同位置将元素归入相同聚合组避免错误或复杂度膨胀减少出错点降低维护成本。 后续可行方向 增加聚合键注册和回收机制避免重复或错误使用键值增强对聚合键渲染区域的可视化调试验证“延迟加入聚合组”的实际使用效果确认渲染输出符合预期。 最终我们通过删除链式聚合结构、引入更灵活的聚合键机制使聚合渲染系统变得更简洁、高效、易维护同时也更符合现代实时渲染系统对灵活性与稳定性的要求。 再次运行游戏开始思考主角精灵的绘制顺序问题 我们现在面临的问题是到底以什么顺序来处理这些渲染对象。对此我们采取了一个非常实际的策略按照最利于渲染系统当前实现的顺序来处理也就是说我们不会去强行定义某种理想顺序而是直接顺从现有逻辑。 顺序处理策略 我们决定采用和对象被推入的顺序相反的绘制顺序。也就是说 如果某个对象最后一个被加入到渲染队列中它就会第一个被绘制最先加入的则最后绘制这种策略可以简化当前的渲染逻辑减少对排序机制的额外负担。 这种做法实际上在很多渲染队列中非常常见特别是在基于栈式结构的处理方式里后入先出LIFO非常自然。 对当前结构的适配 在具体代码逻辑中我们查看了 world 相关的渲染部分确认了当前渲染顺序的处理模式。因此决定不打乱已有顺序只要反向读取就能满足渲染需求 不需要对聚合组内部再做额外排序渲染系统只需按原顺序反向处理渲染指令保证聚合组整体的渲染顺序依旧合理且性能不会受影响。 好处总结 简洁清晰直接复用已有的推入顺序省去了额外排序逻辑性能友好避免在渲染阶段增加计算负担行为可控由于是固定规则开发者对对象的渲染顺序拥有明确的预期易于调试出问题时能根据对象推入顺序快速定位渲染顺序问题。 后续优化可能 虽然目前我们使用的是反向顺序策略但未来如果渲染需求变化比如加入了深度层级控制、多层视差背景、半透明图层等复杂情况可能需要引入 显式排序字段按需自定义渲染层级动态优先级调整机制。 但在当前架构下这种“推入顺序反向渲染”的方案既高效又简单足以满足我们现阶段的所有需求。我们可以基于这个规则继续推进聚合渲染系统的其他部分构建与测试。 修改 game_world_mode.cpp调整 AddPlayer() 中 AddPiece() 的调用顺序 我们接下来查看了角色hero创建的部分逻辑尤其是在添加身体部件piece的时候的顺序安排。通过检查与处理代码我们确认了一件事情 角色部件添加顺序的控制 我们在构造角色时对各个渲染片段如头部、躯干、披风等的添加顺序进行了检查和整理 每一个角色的部件都是按特定顺序进行添加的例如先添加躯干再添加披风最后添加头部这个顺序是有意设定的以确保在渲染阶段绘制顺序也是合理的后添加者先绘制 通过当前渲染系统中采用的“推入顺序反向绘制”策略这种添加顺序就直接转化为了视觉上的前后关系 最后添加的头部先绘制 → 显示在最上层最先添加的躯干最后绘制 → 显示在最底层。 这一点在我们实际测试时也得到了验证绘制出来的角色结构清晰遮挡关系正确。 渲染结构与添加逻辑对齐 我们通过这种策略达成了一个非常重要的目标 添加逻辑和渲染结构完全一致不需要额外的“排序”过程来处理遮挡顺序简化了代码逻辑也降低了维护成本。 效果验证 从现有的运行效果来看 渲染顺序完全符合我们的预期部件之间的覆盖和叠加关系是正确的没有出现错乱或者不一致的问题 因此可以认为这部分逻辑目前是稳定并且可靠的。 下一步方向 在角色的部件渲染顺序确认无误之后我们就可以继续推进 实现更多角色、物体或场景的聚合渲染将这个逻辑通用于所有类似需要排序控制的渲染元素开始进一步测试聚合与非聚合对象之间的排序关系是否稳定 我们当前的基础框架已经奠定后续就是逐步扩展与稳固整体的渲染系统结构。 修改 AddPiece() 调用的数值参数不再使用难以理解的偏移值 我们接下来的问题更多是实体系统层面的问题而不仅仅是渲染排序本身。问题在于如何表达一种非标准但又非常关键的规则比如“如果头部和身体同时存在那么头部始终应该绘制在身体之上”。 问题背景与症状 我们发现了一个渲染问题 当角色头部在 Z 值上“进入”身体的后方时会出现一种视觉闪烁的伪影这是一种由于 Z 值排序引起的不一致视觉现象用户看到的就是角色部件突然在前后之间“跳动”非常不自然 这个问题并不是简单地靠现有排序逻辑可以解决的因为 我们的排序是通用性的而这个需求是特例化的逻辑关系头部必须盖在身体上不管 Z 值如何。 潜在的解决方向 我们需要在实体系统中找到一种方式来表达这类“特殊部件关系” 一种可能是添加一个渲染顺序的附加规则表 比如当某个实体中包含“头部”和“躯干”时强制让“头部”渲染在“躯干”之上 这种规则要能够在 render group API 中传递下去并影响最终的渲染排序逻辑 这需要我们在设计 API 时就考虑到这类语义性的关系排序需求。 虽然目前我们主要在处理排序系统的核心逻辑但这类附加规则对 API 设计有重要影响所以我们提前考虑是有必要的。 清理临时 hack 和冗余代码 同时我们也注意到以前为了临时解决排序问题添加的一些“乱七八糟”的 tweak 有些实体被硬编码了不合理的 Z 值仅仅是为了让排序“看起来”对现在由于我们有了更合理、语义化的排序方式这些 hack 就变得多余了我们可以清除这些值避免系统逻辑混乱或后续维护困难。 这样整个渲染系统就能更加“干净”不再依赖硬编码技巧而是真正基于逻辑语义来驱动绘制顺序。 下一步计划 回到实体系统探索在哪一层可以表达这种“部件优先级”的规则确保这些规则能够通过 API 向渲染层传递清理掉不再需要的临时代码保证排序系统的核心逻辑和特殊规则都能良好共存。 这不仅让渲染行为更可控也为后续扩展复杂角色更多可组合部件提供了基础。 探讨如何明确表达一个 sprite比如头部始终要绘制在另一个 sprite比如身体之上的意图 我们现在面临的问题是如何表达一种部件之间的前后绘制关系约束尤其是像“头部必须始终绘制在身体前面”这种需求。这个问题的复杂之处在于头部和身体作为独立实体存在它们在渲染时并不知道彼此的存在也无法预知彼此的渲染顺序。 问题分析 实体之间相互独立 头部和身体是两个不同的实体渲染顺序依赖于它们被推入渲染队列的时间顺序我们当前没有机制可以让一个实体提前声明“后续还会有另一个需要与我有关联排序的实体”。 无法前向引用 如果身体先被推入渲染队列它无法告知渲染器“等一下还会来一个头部那个要画在我前面”如果头部先进入渲染队列也无法修改身体的渲染顺序渲染器的排序是“事后统一进行”的但缺少跨实体排序依赖关系的输入。 不希望强制规定推送顺序 虽然可以通过让调用方严格规定“先推身体再推头”来解决部分问题但这会让系统变得脆弱、不通用稍有疏漏就出错属于不可靠设计。 可能的解决方向 引入“排序依赖边”机制 可以在渲染系统内部构建一个图结构表示实体之间的“绘制先后依赖关系”每个渲染实体可以显式指定“我必须绘制在另一个实体之后或之前”在最终排序阶段基于这些依赖边执行拓扑排序生成最终绘制顺序这种方式不依赖实体被推入渲染队列的顺序允许前向或后向引用。 在 render group 中添加接口 我们可以在 render group 中增加一个方法比如 PushRenderOrderingDependency(entityA, entityB); // 表示 A 应该绘制在 B 之后每个实体在推送时或脑系统中可以检查自身是否有关联的依赖 如果有就把该关系推送到渲染系统内部的依赖图中。 在脑系统中分析依赖 比如在 Hero 的脑模块中我们知道头部和身体是成对存在的可以在这里收集渲染顺序关系把这些逻辑从渲染系统中剥离出来保持渲染系统本身的“纯粹性”。 对已有系统的影响 渲染系统中的 Sprite 图构建阶段需要支持读取并处理这些依赖边排序逻辑要从纯 Z 值或层级排序转变为有向图排序清理掉原来依赖 Z 值的“排序 hack”和伪造位置数据所有这些操作应保持模块化避免在一般情况下影响性能。 当前策略总结 不建议强行规定推送顺序太脆弱 不建议使用临时 Z 值偏移做排序维护成本高 最佳方式是 实体系统中收集排序依赖在 render group 中注册这些关系渲染系统在排序阶段执行拓扑排序处理。 这种机制不仅能解决当前“头部-身体”问题也为未来扩展更复杂角色结构打下基础比如装备叠加、坐骑、多人动作交错等场景。最终我们可以获得一个语义清晰、易于维护的 2D 渲染排序系统。 黑板讨论手动指定排序边缘Manual Edge Specification 我们考虑采用手动边Manual Edge指定机制来解决某些实体之间的绘制顺序问题比如“头部必须绘制在身体之前”这种情况。以下是该策略的完整思路与分析 核心想法构建手动排序边 Sideband 在构造 Sprite 渲染图Edge Graph时额外附加一份手动边的列表每条边表示一个明确的“绘制优先关系”例如“Sprite A 应该在 Sprite B 前面绘制”这个“谁在谁前”是我们代码中明确知道的并且可由我们主动指定我们只需在前面那个 Sprite上指定即可因为渲染系统处理的是“前在后之上”的逻辑。 边的定义方式 使用的形式大致如下 is_in_front_of(SpriteA, SpriteB)表达的含义是SpriteA 应该在 SpriteB 上方渲染 因为边是从“前面那一位”发出的我们只需要关注那个前面的对象 所以我们可以在“头部”那一边记录说“我要在身体前面”。 标识目标对象如何找到要依附的对象 遇到的难点是我们不知道 SpriteB 是哪个对象因为它可能稍后才出现解决方案是为需要关联的对象打上标记Tag并记录 Tag 编号具体操作流程如下 每个需要被引用的 Sprite比如身体被赋予一个 tag 编号比如 tag 3在头部 Sprite 被推入渲染队列时附加一条边信息我在 tag 3 的前面渲染排序阶段遍历 Sprite 列表时将所有带 tag 的节点加入到对应 tag 的桶bin中随后根据手动边的描述从前者找到对应 tag 后者在图上添加边 总结该机制的优势 特性描述灵活可以处理前向或后向引用关系无需控制实体推送顺序精确明确指定“谁在谁前”不依赖 Z 值或偏移等临时手段通用不局限于头部-身体关系也可扩展到任意其他视觉层叠需求兼容原有机制不影响原有自动排序系统仅在有特殊关系时才使用手动边 实现细节建议 维护一个 manual_edges[] 列表包含{ front_tag, back_tag }每个 Sprite 允许指定一个 tag并注册到 tag_bin[] 中渲染排序图构建时先将所有节点加入图遍历 manual_edges[]根据 tag 在图中查找目标节点添加方向边执行拓扑排序完成最终绘制顺序计算。 这个机制设计虽然多了一些小的结构和步骤但逻辑清晰、结构稳定、可扩展性强是目前看来最合理、最通用的处理方式。我们决定采用这个方案并作为后续处理实体层级绘制关系的标准模式。
http://www.zqtcl.cn/news/545837/

相关文章:

  • 网站建设报价方案doc网站建设seo视频教程
  • 北京免费建站网络营销怎么做查询网站后台
  • 深圳外贸网站推广用html制作个人博客
  • 建设银行网站最近打不开吗wordpress c
  • 网站icp备案费用浅谈做网站的好处
  • 制作网站需要懂哪些在线设计平台的市场调研
  • 接计设做的网站河南网站建设华企祥云
  • 网站系统维护一般要多久企业网站推广工具
  • 如何诊断网站seo做个网站商场需要多少
  • 腾讯云做视频网站吗创业商机网加工项目
  • 网站建设论文文献郑州seo外包费用
  • 网站优化西安如何免费推广网站
  • 固原市建设局网站外贸网站建设方法
  • 做违规网站主页制作语言缩写
  • 汝南县网站建设怎么注册公司钉钉账号
  • 网站建设酷隆信通网站开发中心
  • 保定网站建设方案报价怎么做网站_
  • 做网站功能的框架结构图做网站用python好吗
  • 襄樊市网站建设模版网站建设企业
  • 网站换服务器php大流量网站开发规范
  • 网站备案主体域名平面设计线下培训班多少钱
  • 优秀网站专题wordpress 外部调用插件
  • 域名服务网站建设科技公司做棋子网站怎么提高浏览量
  • 用易语言做攻击网站软件下载彩页设计多少钱
  • 个人网站可以做淘宝推广手机版怎么用百度快照
  • 制作网站的公司叫什么外包软件
  • 廊坊企业建站模板邱县手机网站建设
  • 辽宁响应式网站费用建设银行官网app
  • 河北黄骅市网站建设网站外链的优化方法
  • 青岛城阳网站制作网站建设详细步骤