游戏引擎学习第199天

回顾并发现我们可能破坏了某些东西

目前,我们的调试 UI 运行得相对顺利,可以创建可修改的调试变量,也可以插入分析器(profiler)等特殊视图组件,并进行一些交互操作。然而,在上一次结束时,我们似乎遇到了一个问题。

当前的问题出现在 ResizeProfile 这个功能上,它在某些情况下无法正确提供变量值。具体原因尚不清楚,因此我们需要检查代码,找出问题所在。

修改大小会触发段错误

调试器:逐步调试 DEBUGInteract

当前的问题出现在 DEBUGInteract 代码部分,它正在与 VAR profile 交互。在检查 VAR 变量时,发现它的值为空(null)。这意味着我们在执行 ResizeProfile 时,可能并没有正确地设置 VAR,或者 VAR 在某个过程中被清除了。

回顾之前的开发流程,问题可能出现在上一次直播的最后修改中。当时做了一些调整,很可能在这个过程中破坏了 VAR 的正常赋值。不过,这样的错误其实也是有积极意义的。之前已经提到过,这部分代码在清理方面需要做一些改进,而这个问题正好暴露了现有实现中的管理不足。通过改进清理逻辑,不仅可以避免类似的错误,还可以让状态管理变得更清晰,防止代码变得难以维护。

不过,在修复这个错误之前,首先需要确认它的真正成因。尽管直接修改某些代码可能会解决当前的问题,但如果不清楚根本原因,就有可能只是掩盖了错误,而不是彻底修复它。这样,潜在的问题仍然存在,只是暂时没有暴露出来。因此,在修复之前,需要进一步检查,确保真正理解了问题所在。

game_debug.cpp:识别问题并在不同的位置设置 DebugState->InteractingWith

当前的目标是检查 ResizeProfile 相关的代码,找出导致 NextHot 没有正确设置的问题。通过查看代码逻辑,发现 ResizeProfile 只有在 NextHot 被设置为 VAR 时才会触发。因此,需要弄清楚 NextHot 为什么没有被正确赋值。

在分析过程中,首先检查了 debug_state.Hot 以及 HotInteraction 的相关代码。观察发现,代码逻辑确实在某些情况下正确地设置了 hot 变量,但在某些情况下却没有正确地接受并传递 VAR 变量。换句话说,当 begin_interaction 发生时,可能存在某些逻辑分支没有正确地处理 VAR,导致它没有被正确传递。

进一步检查代码后,发现问题的根本原因是:在修改代码时,某些交互逻辑被调整,但没有确保 VAR 变量在所有情况下都能正确地被接受。在某些特定情况下,即使 interaction 被设置了,VAR 变量仍然可能未被正确更新。

为了解决这个问题,可以在相关代码中增加一个检查,即在交互发生时,无论如何都确保 VAR 变量被正确设置。通过这种方式,能够保证 ResizeProfile 逻辑正常运行,而不会因为 VAR 变量未正确赋值而导致异常行为。

这一错误的根本原因是修改代码时不够严谨,导致遗漏了一些必要的赋值逻辑。不过,这种错误并不严重,只需要稍作调整即可修复。

运行游戏,发现一切正常

现在代码应该已经修复,可以正确拖动元素,并且可以实现拖拽操作。但目前整体仍然比较粗糙,界面也显得有些简陋,功能虽然初步具备,但还没有经过足够的优化和完善,使其真正变得易用。

当前的实现只是一个基础框架,虽然核心功能已经建立起来,但仍然缺乏必要的细节打磨。因此,接下来的目标是深入优化代码,使其更加整洁,并改进用户交互体验,使整个调试 UI 更加流畅和实用。

game_debug.h:引入新的 debug_interaction 并将旧的重命名为 debug_interaction_type

我们目前的概念较为松散,涉及到交互的类型以及交互对象,但这些信息基本上是隐含的。我们现有的体系包括交互的类型、当前的热点交互(hot interaction)以及交互对象,但"热点"变量承载了大量的信息。我们希望重新审视这个体系,使其更加规范和逻辑化,从而更清晰地表达交互的内容。

本质上,我们的体系中存在一定的耦合关系。具体来说,调试交互(debug interaction)必然是针对某个对象进行的,因此交互本身和交互的参数是紧密相关的。我们需要构建一个结构,将这些内容封装起来,使其更加清晰易懂。这个结构应当包括交互的类型(interaction type)以及交互对象(interaction target),并且允许不同类型的交互根据需要传递不同的参数,以适应多种交互场景。

为此,我们可以创建一个类似"调试交互参数"(debug interaction params)的结构,用于存储交互的具体内容。例如,我们可以在其中指定交互的类型,以及交互作用的变量(interaction target)。此外,该结构应当具备足够的灵活性,使其能够与不同类型的交互对象进行交互,无论这些对象是什么类型,都可以作为交互的目标。

不同的交互类型可能需要不同的交互参数,因此我们的结构需要支持这些不同的需求。例如,我们可以将交互类型定义为"调试交互类型"(debug interaction type),并将整个交互过程抽象为"调试交互"(debug interaction)。前者仅仅表示交互的类别,而后者则包含了交互的具体参数信息。通过这种方式,我们能够更好地组织交互的逻辑,使其更具可读性和可扩展性。

game_debug.h:简化 debug_state

当前的结构中,存在多个关于交互状态的变量,包括普通交互(interaction)热点交互(hot interaction)以及下一个热点交互(next hot interaction)。这些变量的管理方式较为混乱,导致逻辑复杂且不易维护。因此,需要对其进行整理和简化,使得整体结构更加清晰、直观。

整理交互状态的目标

  1. 减少多余的变量:原本存在多个不同层级的交互状态,使得代码的可读性降低。通过调整结构,可以去掉冗余的部分,使代码更加整洁。
  2. 定义清晰的交互层级 :将交互状态明确划分为三层,使其命名更加直观,便于理解:
    • 交互目标(interaction):当前交互对象。
    • 热点交互(hotinteraction):鼠标悬停或其他方式标记的高优先级交互对象。
    • 下一步热点交互(nexthotinteraction):即将成为热点的交互对象。
  3. 改善逻辑清晰度:通过重新组织变量,使得交互的判断和执行流程更加清楚,避免混乱的状态更新逻辑。

优化后的交互层级

优化后的交互管理方式如下:

  • 第一层:基础交互(interaction)
    • 这是所有交互的基础,表示当前正在发生的交互行为。
  • 第二层:热点交互(hotinteraction)
    • 在命中测试(hit testing pass)过程中,如果发现鼠标悬停在某个交互对象上,该对象将被标记为"热点"。
    • 这个状态用于指示用户当前可能要与哪个对象进行交互。
  • 第三层:下一步热点交互(next hot interaction)
    • 这个变量用于存储下一次可能的热点交互对象。
    • 在下一个渲染周期或交互循环中,热点交互状态会被更新为这个值。
    • 这样可以确保交互状态的平滑过渡,而不会出现状态混乱的问题。

优化后的好处

  • 减少变量,提高可读性 :原先存在多个不清晰的变量,现在只有三个明确的层级,使代码更易于维护。
  • 逻辑更加直观:每个层级的交互状态都有明确的作用,避免了多个变量之间的相互影响。
  • 更易于调试和优化:当出现交互问题时,只需要检查这三个变量的状态变化,而不需要处理多个不确定的变量。

下一步计划

在完成这一结构调整后,代码中原有的变量可能会导致编译错误,因为一些变量名称和引用已经被调整。下一步的任务是:

  1. 修复编译错误:按照新的结构逐步调整所有相关代码,使其兼容新的交互管理方式。
  2. 验证交互逻辑:确保新的交互层级能够正确响应用户操作,并且状态转换符合预期。
  3. 优化相关模块:根据新的结构,优化交互相关的其他功能,使整个系统更加流畅和高效。

这一优化过程能够大幅提高代码的可维护性,并使交互逻辑更加清晰合理。

game_debug.cpp:使 DEBUGDrawMainMenu 在新结构下正常工作

在**绘制调试菜单(draw debug menu)**的过程中,需要更清晰地管理交互状态,并优化"热点交互(hot interaction)"的判断逻辑。

优化"热点交互"逻辑

在现有实现中,"热点交互"用于判断某个变量是否处于悬停状态。然而,当前的实现较为零散,涉及多个临时变量和手动比较的逻辑,不够直观。优化的目标是:

  1. 利用"调试交互(debug interaction)"的概念,使"热点交互"的判断更加清晰和通用。
  2. 引入标准化的交互比较机制,替代手动判断的方式,使代码更加模块化和易维护。

调整后的实现思路

1. 确定当前项的交互状态
  • 任何交互对象都可以抽象成一个交互实例(item interaction) ,它包括:
    • 交互类型(例如鼠标悬停、点击等)。
    • 关联变量(即当前交互涉及的具体数据对象)。
  • 通过构造一个标准化的交互实例,可以确保所有交互的判定逻辑一致,不需要在不同代码块中手动检查变量状态。
2. 交互状态的初始化
  • 在计算交互状态时,首先创建当前项的交互实例
  • 交互实例的内容由该项在正常情况下的行为决定,例如:
    • 若没有特定交互,则仅记录其关联的变量。
    • 若有特定交互,则记录具体的交互类型和变量信息。
  • 这样可以确保每个交互项都有标准的结构,避免手写大量判断逻辑。
3. 统一交互状态的比较
  • 过去,热点交互的判定依赖于手动比较多个变量,现在可以直接进行标准化的交互实例比较

    • 如果当前项的交互实例匹配"热点交互"实例,则该项处于热点状态(is hot)。
    • 这种方式减少了手动管理多个变量的复杂度,使代码更清晰。
  • 具体实现可以通过一个通用的比较函数 来处理,例如:

    cpp 复制代码
    bool isHotInteraction(const Interaction& current, const Interaction& hot) {
        return current == hot;
    }
    • 这样,热点交互的判断可以直接调用此函数,而不需要在不同代码块中反复写手动比较逻辑。

优化后的好处

逻辑更加直观

  • 过去,热点交互需要手动检查多个变量,现在直接比较标准化的交互实例,使逻辑更清晰。
    减少重复代码
  • 通过统一的比较函数,避免在多个地方写类似的判断逻辑,提高可维护性。
    增强扩展性
  • 未来如果要增加更多交互类型(如拖拽、双击等),只需要修改交互实例的定义,而不需要大范围调整判断逻辑。

下一步计划

  1. 实现标准化交互实例的构造,确保所有交互项都能用统一的格式表示。
  2. 替换手动变量判断逻辑,改为基于交互实例的直接比较。
  3. 测试新逻辑的稳定性,确保热点交互判定准确,不会出现误判或遗漏的情况。

通过这一优化,交互状态的管理更加清晰,减少了手动判断的复杂度,使调试界面的逻辑更加稳定和易维护。

game_debug.cpp:引入 InteractionsAreEqual

计数器线程列表(counter thread list)的实现过程中,首先会编写一个简单版本的比较函数,用于判断两个对象是否相等。

实现的基本逻辑

  1. 定义比较函数 ,接收两个对象作为输入,假设它们分别为 AB
  2. 比较对象类型 ,如果 AB 的类型相同,则进入下一步。
  3. 检查对象内容是否相等,目前假设所有对象都是指针,因此可以直接比较指向的内容,而无需进一步解析结构。
  4. 执行测试值比较 ,如果 A.test 等于 B.test,则判定两个对象相等。
  5. 返回最终比较结果,用于后续逻辑处理。

代码逻辑示例

cpp 复制代码
bool areEqual(const Object* A, const Object* B) {
    if (A->type == B->type) {
        return A->test == B->test;
    }
    return false;
}
  • 检查对象类型是否相等A->type == B->type
  • 比较关键字段 testA->test == B->test

进一步优化的方向

提升健壮性 :目前的实现假设所有对象都是指针,但在更严谨的实现中,应该首先检查 AB 是否为 nullptr,以防止解引用空指针导致的错误。

扩展比较逻辑 :未来可能需要支持更多字段的比较,比如 ID状态 等,可以通过扩展条件来增强判断的准确性。

优化性能 :在某些情况下,可能可以用哈希值唯一标识符来加速比较,避免字段级别的直接比较。

下一步计划

  1. 完善空指针检查 ,确保 AB 不是 nullptr
  2. 优化比较逻辑 ,允许扩展到更多字段,而不仅仅是 test 值。
  3. 测试代码可靠性,确保函数能正确比较各种不同类型的对象,并在边界情况下仍然能正常工作。

通过这一实现,基本的对象比较功能已经具备,可以作为后续计数器线程列表管理的基础。

game_debug.cpp:继续处理 DEBUGDrawMainMenu

在当前的状态管理中,存在一些冗余的测试和设置逻辑 。过去的方式是先进行零散的测试(ad hoc testing),然后**独立地设置(ad hoc setting)**相关状态,这种做法容易导致逻辑分散、重复代码以及潜在的状态冲突。因此,需要优化这部分代码,使测试和设置的逻辑更加紧密结合,从而提高可读性和维护性。


优化思路

1. 统一测试和设置逻辑

  • 过去的逻辑是先测试,然后再独立设置状态,这导致了代码冗余。
  • 现在优化为测试的结果直接决定状态的设置 ,从而避免额外的赋值操作。例如:
    • 优化前 (原始逻辑):

      cpp 复制代码
      if (isInsideRectangle(x, y)) {
          // 测试通过后,再手动设置
          nextHotInteraction = itemInteraction;
      }
    • 这样,只有当 isInsideRectangle(x, y)true 时,nextHotInteraction 才会被更新,否则保持原有值,减少了冗余判断。

2. 消除多余的交互判断

  • 在代码中,存在多个地方分别进行不同的交互测试 ,然后再独立地设置相应的交互变量,这种做法容易导致状态管理混乱。
  • 现在的改进方法是:
    • 定义一个通用的交互判断逻辑 ,确保所有交互都经过同一层测试,然后根据测试结果统一设置交互状态
    • 消除多个地方手动设置 nextHotInteraction 的情况,确保所有交互项的赋值逻辑都遵循一致的规则。

3. 适用于不同交互类型

  • 目前的优化不仅适用于一般交互,还适用于大小调整(resize)交互
  • 例如,过去大小调整的交互逻辑需要单独定义,但现在可以使用相同的方法:
    • 这样,无论是普通交互还是调整大小交互,它们的状态设置都遵循同样的逻辑,减少了代码重复。

优化后的好处

减少冗余代码

  • 过去的代码需要在多个地方分别进行测试和赋值,现在合并后避免了重复操作。
    逻辑更清晰
  • 交互状态的测试和赋值合并后,交互的触发逻辑变得更加直观。
    避免状态冲突
  • 过去可能存在多个地方修改 nextHotInteraction,导致不同逻辑互相覆盖,现在统一由一个逻辑控制 ,减少冲突的可能性。
    便于扩展
  • 未来如果要增加更多的交互类型,如拖拽、双击等,只需要修改统一的交互测试逻辑,而不需要在多个地方分别修改代码。

下一步计划

  1. 应用优化逻辑到所有交互判断代码,确保测试和赋值逻辑统一化。
  2. 测试优化后的交互管理方式,确保不同交互类型仍然能够正确响应用户操作。
  3. 观察代码可读性和性能,如果仍然存在冗余代码或逻辑不够清晰的地方,进一步调整优化。

这次优化后,交互状态的管理更加直观、简洁,提高了代码的可维护性,并避免了状态混乱的问题。

game_debug.cpp:引入 InteractionIsHot

在优化**交互状态(interaction state)的过程中,需要改进热点交互(hot interaction)**的判定逻辑,以减少冗余代码,并提高可维护性。


优化目标

  1. interactionsAreEqual 替代手动判断是否为热点交互(hot interaction),避免重复逻辑。
  2. 新增 interactionIsHot 方法,简化热点交互的判断,使其更加直观。
  3. 使 interactionIsHot 直接处理 debugState ,让调用方无需关心 hotInteraction 变量的具体来源,减少额外的状态管理逻辑。

优化思路

1. 过去的热点交互判断方式

原本的逻辑是:

cpp 复制代码
bool isHot = (itemInteraction == debugState.hotInteraction);

这种方式有几个问题:

  • 代码重复 :每次需要判断是否为热点交互时,都要手动写 itemInteraction == debugState.hotInteraction
  • 耦合性高 :调用方必须知道 debugState 的具体实现,才能访问 hotInteraction 变量。

2. 使用 interactionsAreEqual 统一判断逻辑

可以用 interactionsAreEqual 来封装判断逻辑:

cpp 复制代码
bool isHot = interactionsAreEqual(itemInteraction, debugState.hotInteraction);

这样可以避免手写 == 逻辑,使代码更整洁,并且后续如果交互比较逻辑需要调整,只需要修改 interactionsAreEqual,而不需要改所有调用点。

3. 引入 interactionIsHot 方法

为了进一步解耦 debugState,可以定义一个新的 interactionIsHot 方法,让它负责判断交互是否为热点:

cpp 复制代码
bool interactionIsHot(const DebugState& state, const Interaction& itemInteraction) {
    return interactionsAreEqual(itemInteraction, state.hotInteraction);
}

这样,调用方就可以直接写:

cpp 复制代码
if (interactionIsHot(debugState, itemInteraction)) {
    // 处理热点交互
}

相比原始写法,这种方式有以下好处:

  • 调用更直观 :不需要直接访问 hotInteraction,降低了 debugState 的内部耦合度。
  • 逻辑更加集中 :所有交互判断逻辑都集中在 interactionIsHot 方法内,便于维护和修改。
  • 增强可读性:方法名清楚地表达了语义,使代码更易读。

最终优化的交互判定逻辑

cpp 复制代码
bool interactionsAreEqual(const Interaction& a, const Interaction& b) {
    return (a.type == b.type) && (a.test == b.test);
}

bool interactionIsHot(const DebugState& state, const Interaction& itemInteraction) {
    return interactionsAreEqual(itemInteraction, state.hotInteraction);
}

调用示例:

cpp 复制代码
if (interactionIsHot(debugState, itemInteraction)) {
    // 该交互项处于热点状态
}

下一步优化方向

  1. 检查所有热点交互的调用点 ,确保它们都使用 interactionIsHot 方法,而不是直接比较 hotInteraction
  2. 扩展 interactionsAreEqual 逻辑,支持更复杂的交互判定,例如不同类型的交互对象可能有不同的匹配规则。
  3. 优化 interactionIsHot 的性能,如果交互项数量较多,可以考虑缓存热点交互信息,减少重复计算。

通过这一优化,交互状态的判断逻辑更加清晰,热点交互的管理更加高效,为后续扩展和维护提供了良好的基础。

game_debug.cpp:继续清理 DEBUGDrawMainMenu

在优化交互状态管理的过程中,重点是**简化热点交互(hot interaction)**的判断逻辑,使代码更加清晰、可维护,并减少重复逻辑。


优化目标

  1. 统一使用 interactionIsHot 方法 ,避免直接比较 hotInteraction,提升代码可读性。
  2. 优化 nextHotInteraction 的管理,确保所有交互操作遵循统一逻辑,减少状态管理的复杂性。
  3. 提高交互逻辑的模块化 ,使 moveInteractionsizeInteraction 等交互类型的处理更加一致,便于扩展。

优化过程

1. 过去的热点交互判断方式

原本的代码中,每次检查某个交互是否为热点时,都需要手动进行比较:

cpp 复制代码
bool isHot = (sizeInteraction == debugState.hotInteraction);

或:

cpp 复制代码
if (moveInteraction == debugState.hotInteraction) { 
    // 进行某些操作
}

这种方式的缺点:

  • 代码重复 :每个交互类型(如 sizeInteractionmoveInteraction)都要重复写相似的判断逻辑。
  • 维护成本高 :如果 hotInteraction 的判断逻辑改变,需要修改所有调用点。
  • 可读性差 :调用者必须了解 hotInteraction 变量的来源及如何比较,增加了代码理解的难度。

2. 统一使用 interactionIsHot

  • 调用更直观 ,不再需要直接访问 hotInteraction
  • 减少代码重复 ,所有交互都通过 interactionIsHot 进行判断,后续修改更加简单。
  • 提升可读性 ,逻辑更加明确:调用 interactionIsHot 就是在检查某个交互是否是当前热点交互。
    这样,通过优化 interactionIsHotnextHotInteraction 逻辑,不仅减少了冗余代码,还使交互状态管理更加清晰,便于扩展和维护。
    image-1625.png

game_debug.cpp:使 DEBUGBeginInteract 在新结构下正常工作

我们现在需要对交互逻辑进行一些调整,使其能够更合理地处理不同类型的交互状态。目前,我们有一个"热交互"(hot interaction)系统,并且处于调试(debug)状态。在这个系统中,交互类型(interaction type)与具体的交互对象已经被绑定在一起,这正是我们想要的效果。因此,我们可以省去之前为了匹配交互对象而编写的一些额外逻辑,使整体代码更加简洁。

如果存在"热交互类型"(hot interaction type),那么一切正常。如果"热交互类型"不存在,但仍然有一个具体的交互对象,那么我们需要对其进行一些处理。实际上,我们可以让逻辑变得更智能一些,从而省略掉大部分原有的复杂逻辑。在查看代码的过程中,可以发现之前实现的一些"切换值"(toggle value)和"拖动值"(drag value)等逻辑实际上并不必要。我们只需要确保,如果存在某种交互,我们能够正确处理它,而不需要手动管理这些额外的值。

我们可以简化逻辑,假设如果存在某种"热交互",那么就进行相应的处理。首先,需要移除部分无用代码。然后,如果"热交互类型"存在,则继续处理;否则,将其设为一个空操作(no-op)。这样做可以分阶段优化代码,使其更加清晰和易读。

进一步优化后,我们可以引入一个更有层次的处理方式。例如,如果调试状态下的"热交互类型"是某种特殊类型,比如"自动修改变量"(Auto Modify Variable),那么可以基于"热交互变量类型"(hot interaction variable type)进行不同的处理。在这种情况下,可以直接将"热交互类型"设置为对应的交互类型,从而实现更清晰的逻辑。

此外,如果交互类型是"自动修改变量",那么可以让备用 UI(alt UI)自动生效,以便在该状态下更新相关的变量值。最后,不管如何,始终接受当前的"热交互",确保交互逻辑的完整性。这样处理之后,整体逻辑更加合理,交互也更加直观。

在设置交互状态时,之前的代码会将其设为"无交互"(None),但现在应该改为"自动修改变量"(Auto Modify Variable)。这样可以更准确地表达其交互状态,使其符合新的交互机制。最后,还需要调整 debug end interact 的逻辑,使其能够正确处理新的交互方式。这样,整个交互系统的逻辑就更加清晰、简洁,并且易于维护。

game_debug.cpp:使 DEBUGEndInteract 在新结构下正常工作

假设 end Interaction.Type 不是 NOP,那么我们需要检查当前实际发生的情况。从逻辑上来说,这里应该使用 switch 语句来处理不同的交互类型,因为这段代码基本上是 UI 交互的核心部分,负责处理所有交互操作。目前主要涉及的功能包括布尔值(Bool)切换和组展开(expand group)。因此,我们需要实现一个逻辑来区分这些交互,并根据 interaction type 进行处理。

目前交互类型相对较少,实际上只有一个主要关心的类型,但未来可能会增加更多类型,因此需要留出扩展空间。在处理交互时,我们可以从交互对象中提取变量(VAR),然后针对该变量执行相应的逻辑操作。这样可以确保交互能够正确生效,并且代码保持清晰和可扩展。

switch 语句的 default 分支中,我们暂时不需要处理所有的情况,因为大多数情况下可能不需要额外操作。不过,这一点并不完全确定,因此先保持当前逻辑,之后如果有需要再进行调整。

此外,交互部分的 generic 交互处理完成后,需要清理不再使用的交互状态。例如,之前的 dragging hierarchy 逻辑已经被移除,因此不再需要保留相关代码。这部分调整完成后,代码逻辑会更加清晰,交互处理也更加直观。

game_debug.cpp:使 DEBUGInteract 在新结构下正常工作

debug interact 逻辑中,我们的处理方式与之前相同。如果交互类型(Interaction.Type)不是空值,我们就会对其进行处理。即使我们不确定是否存在变量(VAR),仍然可以尝试提取变量,因为使用它的人会知道如何正确使用,而不使用它的人也会知道忽略它。

move hierarchy 交互为例,现在不再需要依赖某个额外的全局函数来处理,而是可以直接在当前逻辑中提取 DebugState->Interaction.Var 以及 DebugState->Interaction.Hierarchy。这样可以确保交互逻辑更加清晰,变量管理更加直观。具体来说,我们可以先检查 variable Hierarchy 是否已经存在,如果还不存在,就创建一个新的 Hierarchy = DebugState->Interaction.Hierarchy = AddHierarchy(DebugState, RootGroup, v2{0, 0}); 并赋值。随后,所有相关逻辑都可以基于该层级(hierarchy)进行操作。

同样的处理方式适用于其他交互。如果 hierarchy 仍未定义,就创建一个新的层级,并确保 DebugState->Interaction.Hierarchy 指向这个新创建的层级。这样可以避免不必要的全局变量,使得交互管理更加模块化。

在变量引用(variable reference)处理时,我们将交互的 VAR 转换为与层级本身的交互。这种方式实际上更具结构性,使交互更加直观。这意味着原本的 VAR 只是一个变量,而在这个转换过程中,它演变成了层级交互的一部分,这样的设计更加清晰合理。

对于 debug state,其作用只是将 HotInteraction 赋值为 NextHotInteraction,也就是说,新交互会替换旧交互。因此,不再需要额外的处理逻辑,之前的一些状态变量也不再需要,例如 dragging hierarchy 已经被移除,不再参与交互逻辑。这部分优化后,代码更加简洁,交互逻辑更加明确。

game_debug.cpp:使 DEBUGEnd 在新结构下正常工作

当前逻辑的处理方式类似于一次清理(clear)。NextHotInteraction 在每次执行时都会被清除,而所有相关的交互状态现在都通过这个统一的清理操作来管理,不再需要额外的处理步骤。

这样做的好处是,所有的交互状态重置逻辑都被集中到一个地方,避免了分散的清理代码,提高了代码的可维护性。通过这种方式,我们可以确保 NextHotInteraction 在每个交互周期结束后都被正确清除,不会残留无效状态。同时,之前可能需要单独清理的其他交互状态现在也都由这个清理逻辑统一处理,使整个交互系统更加简洁高效。

这意味着不再需要手动清理每个具体的交互对象,而是让整个系统在交互结束时自动清理相关状态,从而减少潜在的错误和不一致性。这样一来,交互管理更加直观,逻辑更加清晰,整个流程也更加顺畅。

没生效

点击goup 没反应

debug 跟踪一下

goup 进来了 交互类型Toggle

发现不能拆分group

加上一个断言

运行游戏并遇到断言错误

拆分的时候发生断言错误

在当前的调整完成后,需要检查整个交互逻辑是否仍然能够正常运行。在经过所有的修改和优化后,整体看起来运行良好,但仍然存在一个问题:系统尝试打印一个尚未存在的变量。这显然是不合理的,说明在某个环节,变量的管理存在漏洞。

初步分析,该问题出现在 DEBUGAddVariable 过程中。在执行变量添加操作时,某些变量可能尚未正确初始化或赋值,导致后续的打印操作无法正常执行。因此,需要进一步检查 DEBUGAddVariable 的执行过程,找出具体的错误点。

可能的原因包括:

  1. 变量在 DEBUGAddVariable 过程中没有被正确创建,导致后续访问时出现错误。
  2. 变量在被引用之前,尚未经过正确的赋值操作,导致访问到一个未定义的值。
  3. 变量的作用域问题,可能在某些条件下,变量未能正确传递或存储。

接下来,需要深入检查 DEBUGAddVariable 的具体执行过程,确定变量何时被创建、如何被赋值,并确保变量在被使用之前已经存在并且具有正确的值。同时,可能需要增加一些异常处理逻辑,以避免类似问题的发生,并提供更友好的错误提示。

game_debug.cpp:在 DEBUGBeginInteract 中设置这些变量

在交互变量的引用过程中,执行 AddHierarchy 可能导致了某些异常。尽管具体原因尚不明确,但问题可能出现在层级添加 (DEBUGAddRootGroup) 之后的操作阶段。

经过分析,原有的实现方式存在一些问题,特别是在 TearValue 变量的处理上。当前的逻辑实际上是错误的,因为 TearValue 需要在 mouse down 事件发生时执行相关操作,否则交互系统不会知道该如何处理。这是因为 TearValue 变量只是一个影子变量,它与 Union 结构中的变量相同,之前采用的方式实际上是一个临时的、不可靠的解决方案,无法正确工作。

正确的处理方式应该是在 begin interaction 过程中执行 TearValue 相关的逻辑,而不是依赖之前的懒加载方法。因此,需要调整逻辑,使 begin interaction 在检测到特定交互类型时执行相应的操作。

具体实现上:

  1. 先按照 switch 语句确定交互类型。
  2. 在交互类型确定之后,再执行 TearValue 相关逻辑,而不是在变量定义时懒加载。
  3. 如果交互类型匹配 TearValue,则创建一个新的组(group),并将其添加到层级结构中。
  4. 之后,在交互系统中添加对该新组的引用,确保它能够正确生效。

关于 hot interaction 的处理方式,初步考虑是在 hot 交互状态下执行,但最终决定还是保持 hot 方式,因为这种方式在当前交互逻辑下更加清晰,也能更好地管理交互状态。

最终的调整使得整个交互逻辑更加合理,不再依赖不稳定的变量影子机制,而是直接在交互开始时执行必要的操作。这样不仅优化了代码结构,也避免了潜在的交互逻辑错误,使系统更加稳定和可维护。

运行游戏,发现情况有所改善

当前已经成功将 renderer 组件提取出来,并且可以自由拖动它,同时其他相关功能也可以正常交互。例如,profile 组件现在可以正确显示,并且其拖动操作也能够顺利进行。整体来看,系统的交互体验已经得到了明显的改善。

尽管目前的状态比之前更好,但仍然有一些可以进一步优化的地方。例如,代码结构虽然已经有所清理,但还没有达到完全精简和高度优化的状态。仍然存在一些可以进一步压缩、精炼的部分,以使代码更加清晰、简洁,并提升整体的维护性。

总体而言,当前的优化方向是正确的,系统正在逐步趋向稳定,并且交互逻辑变得更加清晰。接下来的优化目标可能是:

  1. 继续清理冗余代码,去除不必要的中间变量或重复逻辑,使代码更加精炼。
  2. 进一步优化 rendererprofile 组件的交互体验,确保拖动、缩放等操作更加流畅。
  3. 进行更深入的结构优化,使不同功能模块的职责更加清晰,减少耦合,提高可维护性。

尽管还未达到完美状态,但系统的交互管理已经明显变得更为合理,整体代码结构也在向更清晰、更高效的方向发展。

game_debug.h:在 debug_interaction 中添加 v2 *P

目前已经实现了 renderer 组件的拖动功能,并且 profile 组件的交互也正常运行。然而,关于交互系统的优化仍有进一步改进的空间,特别是在尺寸调整(sizing interaction)方面。

现有的尺寸调整交互可能过于专门化,仅适用于某些特定场景。因此,考虑将尺寸调整逻辑设计得更加通用,使其能够适用于多个组件,而不仅仅是当前 profile 相关的元素。这样可以增强系统的灵活性,使不同的 UI 组件都能够利用相同的尺寸调整机制。

一个潜在的改进思路是:

  1. 提取通用的尺寸调整交互逻辑

    • 目前的 resize 交互应当被拆分出来,形成一个通用的 resize interaction 机制。
    • 该机制应当允许不同的组件(如 profilerenderer 等)都能应用同样的尺寸调整逻辑,而不是每个组件独立实现自己的尺寸调整方式。
  2. 创建一个通用的 resize 组件或方法

    • 设计一个可以被任何 UI 组件复用的 resize 处理逻辑。
    • 这个逻辑应当能检测鼠标拖动,并根据拖动方向调整组件大小。
    • 允许不同组件根据自己的需求调整 resize 方式,例如横向调整、纵向调整、自由缩放等。
  3. 确保交互的流畅性

    • resize 交互应当响应迅速,并具有流畅的用户体验。
    • 需要避免尺寸调整时的闪烁、跳跃或者不连贯的问题。
  4. 考虑约束条件

    • 设置最小和最大尺寸,以防止组件过度缩小或扩大到不合理的大小。
    • 可能还需要支持一些对齐或网格吸附功能,以便组件能更有规律地调整尺寸。

总体而言,通过将 resize 交互设计成更通用的机制,可以提高系统的扩展性,并使不同的 UI 组件都能共享相同的尺寸调整逻辑。这将使交互系统更加一致,同时减少代码重复,提高整体可维护性。

game_debug.cpp:在 DebugInteraction_Resize 和 DebugInteraction_Move 中使用该 *P

目前正在对 resize profile 进行重构,以使其更加通用,最终目标是将其简化为 resize,使其不再依赖于特定的变量,而是直接基于 interaction 中的 V2 位置进行调整。这意味着 resize 交互不再关心具体调整的是什么,而是对任意位置进行操作,从而增强其通用性。

优化方案

  1. 使 resize 更加通用

    • 目前 resize profile 依赖于特定的 VAR 变量,而实际上,它完全可以作用于 interaction 结构中的 V2 位置,使其对任何交互目标都适用。
    • 这样 resize 逻辑可以独立于 profile,使不同组件都能使用相同的调整逻辑,而不需要为每个组件创建单独的 resize 方法。
  2. 统一 move hierarchyresize 的逻辑

    • move hierarchy 目前的逻辑也可以进行类似的改进,即将其简化为一个通用的 move 方法,使其不再依赖于特定的层级,而是基于 V2 位置进行移动。
    • 这样可以让 move 直接作用于 interaction 结构中的 V2,减少对层级结构的特殊处理。
  3. 删除 ter value,简化交互

    • 由于 resizemove 都可以基于 V2 进行操作,因此可以完全去除 tear value,从而减少额外的变量,使代码更加精简。
    • 这样 resizemove 变得更模块化,任何组件都可以基于相同的逻辑进行调整,而不需要额外的特殊处理。

优化后的优势

  • 代码复用率提高 :通用的 resizemove 逻辑适用于多个交互场景,避免重复代码。
  • 降低耦合性 :不再依赖特定的变量或层级结构,使 resizemove 适用于不同的 UI 组件。
  • 易于扩展 :未来如果需要添加更多交互类型,只需扩展 resizemove 逻辑,而无需修改多个不同的组件。
  • 更清晰的交互逻辑 :去除 tear value 之后,交互逻辑更加直观,不会有不必要的变量干扰操作。

整体来看,这次调整有助于提升系统的模块化和扩展性,使 UI 组件的交互更加统一,同时减少冗余代码,提高整体的维护性。

game_debug.h:将 DebugInteraction_Resize 和 DebugInteraction_Move 添加到 debug_interaction_type

目前正在优化 resizemove 这两个操作,使其成为更通用的交互操作。这些操作现在被设计为通用运算符,可以作用于任何能够提供其位置的对象,而不再局限于特定的 UI 组件。

优化调整

  1. resizemove 作为通用运算符

    • resizemove 现在可以适用于任何对象,而不仅仅是特定的 profilehierarchy
    • 任何对象只需提供自身的位置信息,这两个操作就可以自动调整其位置或大小。
    • 这样能够提高代码的复用性,避免为不同的 UI 组件单独编写调整逻辑。
  2. 交互逻辑简化

    • 现在,我们只需要检查对象是否支持 resizemove,而不需要关心具体的对象类型或结构。
    • 这意味着交互代码更加清晰,减少了不必要的条件判断。
  3. 更加模块化

    • resizemove 现在变成了独立的操作模块,任何需要这些功能的 UI 组件都可以直接调用它们。
    • 这让代码的扩展变得更容易,未来如果需要新增交互操作,只需添加新的运算符,而不需要修改现有的交互逻辑。

最终效果

  • 减少冗余代码 :所有涉及 resizemove 的组件都可以复用相同的逻辑,而不需要重复实现调整功能。
  • 提高可维护性:交互逻辑更加直观,每个操作模块都有明确的职责,方便后续维护和修改。
  • 增强可扩展性:未来可以更方便地增加新的交互类型,而不会影响已有的逻辑。

通过这次优化,resizemove 变得更加通用,不再局限于特定组件,使得整个交互系统更加灵活和易维护。

game_debug.cpp:继续添加 P

目前正在调整 resizemove 交互,使其直接操作目标对象的 position,以提高代码的通用性和可维护性。

调整内容

  1. resize 操作

    • 现在 resize 直接作用于 profile.Dimension,即目标对象的尺寸属性。
    • 代码优化时,发现 Dimension 变量的命名方式与其他部分不一致,因此进行了统一调整。
    • 交互方式调整为直接使用该属性的地址,确保操作能够正确修改对象的尺寸。
  2. move 操作

    • move 交互不再局限于 hierarchy,而是可以适用于任何对象。
    • 代码调整为直接操作 hierarchyui.p 属性,以实现移动功能。
    • 这样 move 变得更通用,可以复用于所有需要拖动的 UI 组件。
  3. 指针优化

    • 由于 resizemove 现在操作的是目标对象的属性,而不是独立变量,因此改用指针传递数据。
    • 这样可以确保交互操作直接修改原对象,而不是修改临时变量,避免了数据同步问题。

最终效果

  • 代码通用性增强
    resizemove 现在可以适用于各种 UI 组件,而不仅仅是 profilehierarchy

  • 减少冗余代码

    通过统一 resizemove 的实现方式,去除了对特定组件的依赖,使得交互逻辑更加清晰。

  • 提高代码可维护性

    交互逻辑基于目标对象的属性,而不是创建额外的变量,这样在修改 UI 逻辑时,调整更少,风险更低。

通过这些调整,resizemove 变成了通用的 UI 交互操作,使整个系统更加灵活和可扩展。

运行游戏并尝试与菜单互动

当前的调整旨在使 resizemove 交互更具通用性,并修正了部分错误,确保交互能够正确执行。

调整内容

  1. 通用交互设计

    • resizemove 交互现在可以适用于任何对象,而不仅限于 profilehierarchy
    • 代码被优化为接受通用的 position 变量,使得 resizemove 可以作用于任何 UI 组件。
  2. 错误修正

    • 之前误将 DmouseP 变量修改为错误的计算方式,导致 move 操作失效。
    • 通过恢复 DmouseP 的正确用法,使 move 交互可以正确计算目标对象的位置偏移量。
    • 避免了对象在计算过程中引用自身,从而防止无效或错误的更新。
  3. 交互逻辑优化

    • move 现在可以正确计算目标对象的位置偏移量,使得拖动交互更加流畅。
    • resize 现在基于 profile.Dimension 进行调整,确保用户调整尺寸时的计算逻辑正确。
    • 由于 resizemove 现在都是基于指针操作,它们可以直接影响目标对象,而不需要额外的变量存储计算结果。

最终效果

  • 交互操作更加通用

    现在可以轻松应用 resizemove 到任意 UI 组件,提高了代码的扩展性。

  • 错误修正,交互正常运行

    修复了 DmouseP 计算错误,使得 move 交互能够正确计算位置变化。

  • 代码更加精简

    由于 resizemove 现在基于指针传递数据,不需要额外的变量存储临时数据,使代码更加简洁、高效。

随着这些调整,resizemove 交互功能已经变得更加稳定,并且可以用于各种 UI 组件,使整体系统更加灵活和易于维护。

game_debug.cpp:给 DebugInteraction_TearValue 添加一个交互

优化 Tear Value 交互并转换为 Move 交互

当前的调整主要针对 tear value 交互,使其更加直观和高效,并且在 tear value 交互开始后,自动转换为 move 交互,确保拖拽操作顺畅。


调整内容

  1. 移除 tear value 交互的单独处理

    • 之前 tear value 交互需要单独的交互逻辑,现在我们不再单独处理它,而是直接在 move 交互中完成相关操作。
    • tear value 交互一旦触发,就会转换成 move 交互,使得 UI 交互逻辑更加统一。
  2. 优化拖拽初始化

    • tear value 开始时,目标层级 (hierarchy) 的 uip 会被设置为当前鼠标位置 (mouse position)。
    • 这样,在 move 交互开始后,对象就已经处于正确的位置,并且可以被正确拖拽。
  3. 交互逻辑调整

    • 交互初始化时,debug variable hierarchy 仅用于获取当前 hierarchy,不再作为 tear value 的独立存储。
    • hot interaction hierarchytear value 交互时,直接初始化 uip,随后 tear value 交互变为 move 交互。
    • move 交互直接作用于 hierarchyuip,保证拖拽操作的连续性。
  4. 代码优化

    • 之前的 tear value 交互代码冗余,主要是为了处理 uip 变化,现在通过 move 交互统一逻辑,代码更加清晰。
    • move 交互不再依赖 tear value 交互进行初始化,而是直接使用 uip 进行位置变更。

最终效果

  • tear value 交互逻辑简化

    • tear value 交互不再独立存在,而是转换为 move 交互,逻辑更加流畅。
  • 拖拽行为优化

    • move 交互从 tear value 交互无缝衔接,确保被拖拽对象始终处于正确位置,避免了跳跃或错位。
  • 代码更加精简

    • 由于 tear value 交互不再需要额外的 interaction 变量,减少了不必要的状态存储,提高了代码可维护性。

经过这些优化,tear value 交互已经成为 move 交互的一部分,使得 UI 拖拽功能更加直观,减少了不必要的复杂度,同时提高了交互的响应速度和稳定性。

运行游戏并测试这个通用移动

优化交互系统:通用化移动与缩放

此次优化的重点是将 move(移动)和 resize(缩放)交互从特定对象(如 hierarchy)抽象为通用交互,使得未来可以轻松扩展到其他 UI 组件,而不需要单独为每种组件编写交互逻辑。


主要调整

  1. 通用化 move 交互

    • 之前 move 交互是专门为 hierarchy 设计的,现在已经扩展为适用于任何对象的通用 move 交互。
    • 这样一来,未来如果有新的 UI 组件需要支持拖拽,只需要设置 uip(用户交互位置)即可,不需要额外修改逻辑。
  2. 通用化 resize 交互

    • resize 交互原本绑定到 profile 组件,现在改为通用 resize 交互。
    • 未来如果有其他组件需要支持大小调整,只需要提供相应的 dimension(尺寸变量),就能自动适配缩放功能。
  3. 提升代码扩展性

    • 现在 moveresize 交互不再依赖特定的数据结构,而是作用于 V2(二维向量),使得它们可以适用于任何可移动或可调整尺寸的 UI 元素。
    • 未来如果有新的 UI 组件(例如 windowpanel 等),可以直接复用 moveresize 逻辑,而无需重写交互代码。
  4. 移除 tear value 交互

    • 之前 tear value 交互主要是用于拆分层级并移动,现在已经整合到 move 交互逻辑中,不再需要单独处理 tear value
    • 这一改动减少了不必要的状态管理,提高了交互的简洁性。

最终效果

  • 交互更加通用

    • moveresize 现在适用于所有支持拖拽和缩放的 UI 组件,无需为每个组件单独编写交互逻辑。
  • 代码结构更清晰

    • 通过统一 moveresize 逻辑,减少了重复代码,提高了可读性和维护性。
  • 易于扩展

    • 未来如果要为新的 UI 组件(如窗口、控件、面板等)添加移动或缩放功能,只需将 V2 绑定到 moveresize 交互,无需修改底层逻辑。

这次改动使得 UI 交互系统更具灵活性和可扩展性,减少了代码耦合,提高了整体架构的简洁性。

game_debug.h:将这种通用移动的概念扩展到另一个 debug_variable_type

扩展交互系统:处理新类型数据

为了进一步扩展交互系统,考虑将一个新的调试变量类型引入,比如"位图"类型(bitmap)。这一扩展的目的是展示如何让系统能够处理不同类型的交互对象,尤其是那些新的或复杂的类型。


扩展目标:位图类型处理

  1. 引入位图类型

    • 在原有的变量类型中,添加一个新的变量类型 bitmap ID,用于表示位图数据。
    • 这样一来,系统能够处理包括位图在内的更多数据类型,提供更灵活的交互选项。
  2. 调试变量扩展

    • 调试变量的处理方式可以扩展为支持显示位图的调试信息。例如,可以通过位图 ID 来展示图像内容或其他与位图相关的信息。
    • 这种扩展不仅可以用于调试显示,还可以用于将位图类型与其他交互元素关联,从而使得用户可以通过拖拽、缩放等方式对位图进行交互。

实现步骤

  1. 位图类型的定义

    • 在系统中引入位图 ID 类型。这可以是一个指向具体图像数据的引用,允许系统在交互过程中动态加载和显示不同的图像。
  2. 调试变量的展示

    • 在调试时,系统可以根据新的位图 ID 类型,加载相应的位图,并将其显示在 UI 中。
    • 例如,使用 debug variable 时,如果变量类型为位图,系统将渲染该图像并允许用户对其进行交互。
  3. 交互性增强

    • 类似于之前的 moveresize 功能,位图交互也可以进行缩放或拖拽操作,使得用户能够以图形化方式与图像进行互动。
    • 这种交互方式的引入,使得 UI 不仅限于文本、按钮等基本元素,还能处理更复杂的内容,如图片和图形。

效果和意义

  • 更丰富的调试信息

    • 系统能够处理位图类型,使得调试过程中可以直接显示图像信息,帮助开发人员更直观地查看和调试 UI 元素。
  • 扩展交互能力

    • 位图交互的引入不仅提高了系统的灵活性,还为未来处理更多复杂数据类型提供了基础,尤其是在需要图像或多媒体支持的情况下。
  • 易于扩展

    • 这种扩展方法能够支持更多类型的数据,未来只需增加新的类型和相应的处理方式,即可扩展交互系统的能力。

总的来说,这次扩展提升了交互系统的适应性,使其能够处理更复杂的数据类型和交互需求,为未来的功能添加奠定了基础。

game_debug.h:引入 debug_bitmap_display

为了增强位图类型的交互和调试展示,目标是使得 bitmap ID 变得更加富有表现力。具体来说,可以通过定义一个新的调试变量类型 bitmap display 来提高其功能性和扩展性。

扩展目标:位图显示类型

  1. 定义新的调试变量类型:

    • 引入一个新的调试变量类型 bitmap display,它不仅包含一个 bitmap ID,还应当具备其他属性,比如尺寸、大小、透明度等,以便能够更灵活地控制图像显示。
  2. 属性设计:

    • bitmap ID:表示位图资源的标识符。
    • V2 size:表示位图的尺寸,可能用一个二维向量来表示,包含宽度和高度。
    • R32 size:可以选择用浮点数表示位图的尺寸或其他相关的度量方式。
    • alpha:表示是否使用位图的 alpha 通道,即透明度。可以通过一个布尔值来决定是否启用透明度的处理。
  3. 位图显示的实现:

    • 定义一个新的位图显示结构体,包含上述属性,这样在调试或交互时,可以清晰地显示位图的相关信息并进行交互。
    • 该结构体可以让系统在 UI 中动态加载位图,并支持如透明度控制等附加功能。

实现方式

  • 位图显示的交互性:

    • 通过为 bitmap display 添加新的属性,用户可以不仅仅看到位图本身,还可以对图像的尺寸、透明度等进行交互修改。
    • 例如,用户可以在调试过程中查看位图的具体尺寸,调整图像的显示效果,甚至控制图像的透明度,以便测试不同的显示效果。
  • 更加灵活的调试展示:

    • 通过扩展位图类型,能够在调试界面中展示更多信息,帮助开发者更清晰地了解当前显示的图像数据状态。
    • 除了常规的显示功能,还可以添加一些特殊的调试功能,如显示位图的 alpha 通道或其他图像处理信息。

意义

  • 提升交互性

    • 通过使得位图显示支持更多可调参数,增强了系统与图像数据的互动性。开发人员可以通过这些控制参数来精细调节图像显示,满足不同的需求。
  • 提高灵活性

    • 这种扩展不仅增强了位图显示的功能性,还使得系统能够处理更多类型的图像数据和交互需求。未来可以轻松加入其他类型的数据或效果。
  • 更高效的调试过程

    • 使用 bitmap display 类型,可以更清楚地展示和调试图像数据,使得开发者可以更快速地发现和解决与图像显示相关的问题。

总结

通过引入一个更加丰富的 bitmap display 类型,增强了位图的表现力和交互性,使得系统能够更加灵活地处理图像数据。在开发和调试过程中,开发者能够轻松地调整图像的各个显示参数,从而提升了系统的功能性和可调性。

game_debug.cpp:实现 DebugVariableType_BitmapDisplay

在处理位图显示的过程中,首先需要在调试界面中添加一个新的调试变量类型------位图显示。这个新的类型可以让我们更方便地展示和处理位图信息。

步骤与实现过程:

  1. 定义调试变量类型:

    • 需要创建一个新的变量类型 bitmap display,并将其纳入到调试显示中。在这个新的类型中,包含了位图的ID以及相关的尺寸信息(如 dimension)。这些信息将会在调试过程中进行展示。
  2. 初始化与设置:

    • 在界面上展示位图时,首先会通过 bitmap display 这个类型来进行调试显示,注意此时没有交互功能,因为位图目前没有交互功能。先将其保持简单,避免过早实现不必要的交互。
  3. 绘制位图:

    • 代替先前的 profile 绘制,我们现在使用 bitmap display 进行绘制。使用之前定义的变量来存储和访问位图的信息,并确保尺寸正确应用(dimension)。
  4. 处理绘制时的推送位图操作:

    • 绘制位图时,首先调用 push bitmap 函数,这个函数需要一些必要的参数:
      • 渲染组:用于确定位图的绘制位置。
      • 位图ID:指向特定位图资源。
      • 高度:基于位图的尺寸设置,通常使用位图的 Y 维度来确定。
      • 偏移量:用于调整位图的绘制位置,通常将位图放置在某个区域的中心。
  5. 位置和尺寸调整:

    • 对于位图的显示,计算其绘制位置时,需要将其置于区域的中心。可以通过获取区域的中心点来调整位图的绘制位置,以确保位图正确显示。
  6. 渲染与显示:

    • 位图的颜色设置可以选择默认或者不进行修改。如果不需要特殊的颜色设置,可以跳过这一步。之后,将位图推送到渲染系统进行显示。
  7. 总结:

    • 通过这一系列的操作,位图可以成功显示在调试界面中,且尺寸和位置可以根据需要进行调整。虽然此时位图的交互功能尚未实现,但已经具备了基础的显示功能,未来可以扩展为更复杂的交互操作。

优化与扩展:

  • 当前的实现方式主要集中在位图的显示和定位上,后续可以进一步扩展其功能,例如支持位图的交互(如缩放、拖动等),以及调整透明度、颜色等属性。
  • 此外,如果未来有更多的位图处理需求,还可以进一步完善 bitmap display 类型,加入更多功能。

通过这样的实现,调试过程中的位图显示变得更加灵活和高效,为后续的交互和功能扩展打下了基础。

game_debug_variables.h:为 bitmap_id 引入 DEBUGAddVariable

在实现位图显示时,接下来需要做的是确保能够正确地添加调试变量以及实际显示位图。这涉及到几个关键步骤,包括正确地将位图数据与调试变量关联起来,并确保能够通过调试界面显示位图。

实现步骤:

  1. 添加位图显示变量:

    • 需要通过 DEBUGAddVariable 函数来将一个新的位图显示变量添加到调试变量列表中。这时,首先需要指定位图的 ID,然后为其设置相关的尺寸(如 100x100 或者 25x25 等)。同时,设置 alpha 值,即使当前未使用该值,也应设置为 true,以便未来可以扩展使用。
  2. 定义调试变量类型:

    • 为了处理位图显示,定义一个 bitmap display 类型的调试变量,它包含位图的 IDdimension,这些信息将会在调试过程中用来显示位图。
  3. 获取位图资源:

    • 由于当前还不确定使用哪个位图,需要通过 GetBestMatchBitmapFrom 或类似的函数从资产系统中获取合适的位图资源。这时,需要查找或加载一个合适的位图ID,然后将其传递给调试变量。
  4. 处理变量添加:

    • 在调试过程中,位图的ID和其他参数会被传入 DEBUGAddVariable 函数中。这个操作会将位图信息与调试界面相关联,使得调试过程中的变量能够正确显示相应的位图。
  5. 测试与验证:

    • 一旦完成位图ID的配置,可以通过 DEBUG_VARIABLE_LISTING 来查看调试变量的添加效果。这个操作可以在调试界面中列出当前所有添加的调试变量,验证是否成功将位图变量添加到调试列表中。
  6. 调整资产访问:

    • 在实现中,访问资产的部分需要保证我们已经创建了适当的资源,并将其正确关联到调试界面。如果资产尚未创建或没有正确加载,则可能导致无法成功获取位图ID。在这种情况下,可能需要调整或补充代码来确保正确的资源访问。
  7. 处理错误与修复:

    • 在添加调试变量时,如果发生参数类型不匹配或调用失败的错误(如 overload 异常),需要仔细检查调用方式和参数类型,确保函数能够正确处理传入的参数类型。

总结:

通过上述步骤,位图能够被成功地添加到调试界面并进行显示。整个过程主要涉及调试变量的添加、资产资源的正确获取、以及确保显示功能正常工作。在调试界面中添加位图显示后,未来可以通过更复杂的交互操作来进一步扩展位图的功能,例如支持缩放、拖动等操作。

运行游戏并遇到 InvalidDefaultCase

当前的实现过程中,仍然存在一些不确定性,尤其是在位图显示是否能够正常工作的部分。由于配置文件的写入机制以及调试变量的处理方式,可能会导致某些类型的变量在未明确写入时触发断言(assert)。这一行为可能会带来一定的不便,特别是在添加新类型时,即使并不需要将其写入配置文件,也会触发断言。

当前面临的问题与分析:

  1. 断言(assert)处理:

    • 在当前的实现方式下,每当添加新类型的调试变量时,都会触发断言。这是因为某些类型的变量默认不会被写入配置文件,而断言的作用是确保所有变量类型都得到处理。但在很多情况下,我们并不希望将某些类型写入文件,因此这可能导致额外的干扰。
  2. 位图显示变量的处理:

    • 新增的 bitmap display 变量已经正确添加,并且能够在 debug variable listing 中显示。但目前仍然需要确认它是否能够正确地与调试系统交互,并最终在界面上正确绘制位图。
  3. 调试变量的存储方式:

    • debug 相关的代码中,位图的调试变量处理方式与 profile 相关的调试数据可能有所不同。因此,需要检查 profile 变量的存储和读取方式,确保 bitmap display 变量也能够遵循正确的存储和访问流程。
  4. 配置文件的写入机制:

    • debug 系统似乎有一套机制来决定哪些变量应当被写入配置文件,而哪些不需要。这一机制需要与位图变量相匹配,以避免不必要的错误或断言失败。

可能的解决方案:

  1. 调整断言逻辑:

    • 如果断言主要用于检测哪些变量未被写入文件,可以在代码中添加例外情况,允许某些特定类型的变量(如 bitmap display)跳过这一检查。
    • 例如,在 assert 之前,先检查变量类型,如果是 bitmap display,则直接跳过断言。
  2. 确认 debug 变量存储方式:

    • 检查 debug 变量存储的相关代码,确保 bitmap display 类型的变量可以正确存储,并且不会影响其他类型的变量。
  3. 优化 bitmap display 的加载和显示逻辑:

    • 确保 bitmap display 变量的 ID 正确映射到实际的位图资源,并在 debug 界面中能够正常显示。
    • debug 界面的绘制部分,检查 bitmap display 变量是否正确地调用了 push bitmap 进行渲染。
  4. 调试 profile 数据的处理逻辑:

    • 检查 profile 数据的存储和显示方式,以确保 bitmap display 变量的处理方式与 profile 变量的逻辑保持一致。

总结:

当前的实现已经基本完成了 bitmap display 变量的添加和管理,但仍然需要解决 assert 触发的问题,并确认 bitmap display 变量在 debug 界面中的正确显示。通过调整断言逻辑、优化变量存储方式以及确保位图正确渲染,可以进一步完善 bitmap display 变量的调试功能。

添加 DebugVariableType_BitmapDisplay 到 DEBUGShouldBeWritten

当前的 debug 变量管理方式是通过 DEBUGShouldBeWritten 进行控制,因此可以按照这个方式处理。当前有一部分变量是需要写入的,而另一部分则不需要。未来可以进一步优化,将这些变量分离成两个集合,一个用于存储需要写入的变量,另一个用于存储不需要写入的变量。这样的话,就可以通过范围检查 (range check) 来快速判断某个变量是否应该被写入。例如,可以设定一个值的范围,表示这个范围内的变量都需要写入,而超出范围的变量则不需要写入。

这种优化方式的好处在于:

  1. 提高判断效率:通过范围检查,而不是对每个变量进行单独判断,可以减少条件判断的复杂度,提高执行效率。
  2. 更清晰的逻辑管理:将变量分类存储,使代码逻辑更加直观,便于维护和扩展。
  3. 减少错误可能性:避免因个别变量的特殊情况而导致错误,比如遗漏了某个应该被写入的变量。

在当前实现中,这些 debug 变量的管理方式还是比较基础的,主要是通过 DEBUGShouldBeWritten 进行单独判断,未来可以根据实际需求引入更加高效的方式,比如通过哈希表、位标记或直接使用结构体中的标志位来优化管理。

显示的不对得check一下

之前的DrawProfileIn(DebugState, Bounds, MouseP)没有注释掉

运行游戏并尝试调整大小交互

当前的实现方式使得我们可以非常轻松地创建一个可调整大小的交互对象,并复用相同的 resize interaction 逻辑来调整其尺寸。目前已经成功地让位图(bitmap)作为交互对象,但仍然存在一个问题:

在渲染器 (renderer) 内部,位图的偏移 (offsets) 和对齐 (alignment offsets) 仍然会被使用,因为它们的计算方式依赖于渲染器的定义方式。因此,在当前的实现下,位图的显示位置和缩放可能会受到这些内部计算规则的影响,而不是完全由 resize interaction 直接控制。

查看渲染器的实现时可以发现:

  • 偏移和对齐规则仍然被应用,可能导致位图位置不符合预期。
  • 需要找到合适的方法来调整渲染逻辑,以确保 resize interaction 控制的尺寸变化能正确反映到最终的渲染结果上。
  • 可能需要额外的逻辑来处理这些偏移,确保在调整大小时不会影响到其他渲染元素的对齐方式。

总的来说,当前的方式已经实现了基本的调整大小功能,但仍需要进一步优化,使位图的交互行为更加直观并符合预期。

考虑如何在不使用对齐偏移量的情况下直接调整位图大小

当前的 push bitmap 调用仍然会执行对齐计算 (alignment),这意味着:

  • 位图在渲染时会经过 get bitmap dim 之类的转换处理,使其位置和尺寸受到额外的对齐计算影响。
  • 现有的 push bitmap 函数默认执行一系列变换,导致无法直接控制位图的渲染方式。

解决方案的思考:

为了绕过这些默认的对齐计算,理想的方式是直接推送位图,而不进行额外的变换。然而,如何在现有的 push bitmap 逻辑上实现这一点而不破坏原有功能是一个问题:

  1. 增加一个标志位(flag)

    • push bitmap 里添加一个额外参数,比如 bypass_alignment,用于控制是否跳过默认的对齐计算。
    • 但这样会让 push bitmap 函数变得更加复杂,并引入额外的分支逻辑。
  2. 创建一个新的专用函数

    • 新建一个 push bitmap rawpush bitmap unaligned 这样的函数,专门用于直接推送位图,不做对齐计算。
    • 这样可以复用 push bitmap 的大部分逻辑,但去掉对齐的 hadamard 计算,使得位图能按照提供的参数直接绘制。
  3. 调整现有 push bitmap 逻辑

    • 研究 push bitmap 内部调用链,看看能否通过调整 get bitmap dim 之类的调用,使其能接受不同的对齐方式,而不需要完全绕过对齐计算。

选择的方案:

目前看起来,最佳的解决方案是 创建一个新的专用函数 ,以避免破坏现有的 push bitmap 逻辑。

  • 该函数应当接受 明确的位置和尺寸 ,不经过 get bitmap dim 计算,而是直接使用传入的数据进行渲染。
  • 这样可以保证调试功能 (debug function) 具有足够的灵活性,同时不会影响原有的 push bitmap 逻辑。

结论:

为了实现更精准的位图渲染,需要避免 push bitmap 内部的对齐计算,可以通过创建一个新的 push bitmap raw 函数来实现,这样能确保位图按预期位置和尺寸渲染,而不会受到默认对齐计算的干扰。

game_render_group.cpp:实现关闭对齐功能

目前的问题是 push bitmap 默认会执行对齐变换(alignment transform),导致位图的偏移量 (offset) 会受到 get bitmap dim 计算的影响。这使得直接控制位图位置变得困难。

优化方案

为了绕过这种自动对齐,我们可以引入 一个可调的对齐系数(alignment coefficient),让用户可以选择是否应用对齐变换:

  1. 新增对齐系数参数

    • push bitmap 中新增一个 alignment multiplier,用于控制对齐计算的影响程度。
    • 例如,默认值为 1.0(完全应用对齐),如果设为 0.0,则可以完全禁用对齐计算,从而使位图按给定参数直接渲染。
  2. 修改 push bitmap 逻辑

    • alignment multiplier 影响 offset 计算,如果用户希望禁用对齐,就将该参数设为 0.0
    • 这样,get bitmap dim 仍然可以返回尺寸,但不会影响最终的 offset
  3. debug 代码中禁用对齐

    • bitmap display 相关代码中调用 push bitmap 时,显式传入 0.0 作为对齐系数,以确保调试渲染不受对齐计算影响。
    • 由于默认 push bitmap 可能会基于 中心点 进行偏移,因此需要额外调整,使其基于 左下角 进行绘制。

具体实现步骤

  1. push bitmap 添加 alignment_multiplier 参数

    cpp 复制代码
    void PushBitmap(RenderGroup *group, BitmapID id, V2 position, V2 size, float alignment_multiplier = 1.0f);
    • 默认情况下,alignment_multiplier = 1.0f,位图仍然按照标准对齐方式处理。
    • alignment_multiplier = 0.0f 时,跳过所有对齐计算,直接绘制。
  2. 修改 push bitmap 内部逻辑

    cpp 复制代码
    V2 offset = alignment_multiplier * ComputeAlignmentOffset(id);
    V2 final_position = position + offset;
    • 如果 alignment_multiplier == 0.0f,则 offset == 0.0f,直接按照 position 绘制位图。
  3. bitmap display 代码中禁用对齐

    cpp 复制代码
    PushBitmap(render_group, bitmap_id, GetBoundsMin(bounds), dim, 0.0f);
    • 这里 GetBoundsMin(bounds) 取的是 左下角 作为起点,以确保禁用对齐后仍然正确放置位图。

结论

  • 引入 alignment_multiplier 使 push bitmap 更灵活,可用于普通渲染和调试渲染。
  • debug 代码可直接调用 push bitmap 并传 0.0f,从而绕过对齐计算,实现精准的位图显示。
  • 避免创建额外 push bitmap raw 之类的函数,减少代码重复,保持 push bitmap 逻辑一致性。

运行游戏,发现它正确地调整了大小

目前的位图渲染已经达到了预期效果,尺寸也是正确的。

确认尺寸正确的原因

  1. 位图导出时未裁剪

    • 由于导出时没有对位图进行裁剪,因此即使部分区域为空白,整体尺寸仍然是完整的原始大小。
    • 这样可以保证位图的大小不会因为透明区域被误缩小,避免了额外的调整需求。
  2. 渲染时尺寸匹配

    • 由于 push bitmap 传入的尺寸与未裁剪的原始尺寸一致,因此最终显示的内容与期望一致。

结果

  • 位图显示正确,未出现额外偏移或缩放问题
  • 尺寸与导出时保持一致,确保完整呈现
  • 即使部分区域为空,也不会影响整体渲染

最终,我们达到了希望的调试显示效果。

game_debug.cpp:绘制人物的边界

为了增强位图的可视化效果,我们可以在其后方绘制一个矩形边界,使其更容易辨认。

实现方式

  1. 绘制矩形边界

    • 通过 rect 在位图的背景上绘制一个矩形,该矩形的大小与位图的 bounds 相匹配。
    • 这样可以清楚地显示出位图的实际范围,尤其是在某些部分可能为空的情况下。
  2. 矩形样式

    • 颜色 :黑色 (black),提供良好的对比度,使位图边界更加明显。
    • 透明度:可调整,使其不会干扰位图本身的显示。
  3. 无交互影响

    • 由于矩形仅用于显示,不需要交互逻辑,因此不设置交互 (hot)。
    • 这样可以保证调试过程中不会影响位图的其他行为。

最终效果

  • 位图的边界清晰可见,方便调试和调整。
  • 背景黑色矩形确保即使位图部分透明或颜色接近背景,也能清楚显示其轮廓。
  • 保持无交互状态,避免对其他渲染逻辑产生影响。

去掉对齐

为了增强位图的可视化效果,我们可以在其后方绘制一个矩形边界,使其更容易辨认。

实现方式

  1. 绘制矩形边界

    • 通过 rect 在位图的背景上绘制一个矩形,该矩形的大小与位图的 bounds 相匹配。
    • 这样可以清楚地显示出位图的实际范围,尤其是在某些部分可能为空的情况下。
  2. 矩形样式

    • 颜色 :黑色 (black),提供良好的对比度,使位图边界更加明显。
    • 透明度:可调整,使其不会干扰位图本身的显示。
  3. 无交互影响

    • 由于矩形仅用于显示,不需要交互逻辑,因此不设置交互 (hot)。
    • 这样可以保证调试过程中不会影响位图的其他行为。

最终效果

  • 位图的边界清晰可见,方便调试和调整。
  • 背景黑色矩形确保即使位图部分透明或颜色接近背景,也能清楚显示其轮廓。
  • 保持无交互状态,避免对其他渲染逻辑产生影响。

运行游戏并考虑纵横比

在位图显示过程中,我们遇到了一个问题:如何在拖动调整大小时保持位图的宽高比(Aspect Ratio)?

问题分析

  • 当前情况

    • 如果仅根据宽度或高度调整大小,位图可能会被拉伸或压缩,导致比例失真。
    • 需要确保无论如何调整,位图的纵横比始终保持不变。
  • 理想方案

    • 设定一个固定的宽高比,当用户调整大小时,根据其中一个维度自动计算另一个维度。

实现思路

  1. 获取位图的原始尺寸

    • 使用 used_bitmap_dim 获取位图的原始宽高。
  2. 计算新的尺寸

    • 当用户拖动时,优先调整 高度宽度 ,然后根据 aspect_ratio = width / height 计算另一维度。
    • 例如:
      • 如果调整宽度 :新高度 = 新宽度 / 原始宽高比
      • 如果调整高度 :新宽度 = 新高度 * 原始宽高比
  3. 实时更新 UI

    • 在拖动过程中,每次更新尺寸时,都重新计算 宽度或高度 以保持比例。

优势

防止图像变形 ,确保位图显示正常

提升用户体验 ,让拖拽更加直观

兼容不同大小的位图,适用于各种分辨率

最终,我们可以在调整位图大小时自动维持其原始比例,使其始终以正确的方式呈现。

game_debug.cpp:对位图实现与字体相同的调整大小功能

实现位图显示的宽高比自适应

在位图显示中,为了确保位图不会因缩放而变形,我们调整了计算方式,使其能够根据原始尺寸比例进行缩放。


1. 方案分析

问题

  • 目前位图显示的缩放方式可能会导致图像拉伸或压缩,影响视觉效果。
  • 需要一种方法在调整尺寸时保持原始宽高比(Aspect Ratio)。

解决方案

  • bitmap_display 过程中,使用 get_bitmap_dim 获取位图的原始宽高(dimensions)。
  • 基于 size_y 计算 size_x ,确保 size_x = size_y * (原始宽 / 原始高),这样能保持比例不变。

2. 具体实现

2.1 获取位图的尺寸信息

bitmap_display 过程中,我们首先获取当前位图的 ID,并通过 get_bitmap_dim 获取它的尺寸。

cpp 复制代码
bitmap_dim = get_bitmap_dim(bitmap_id);

此时,我们可以拿到 bitmap_dim.xbitmap_dim.y,分别代表位图的原始宽度和高度。


2.2 计算新的宽度(size_x)

由于我们在调整时 优先改变高度(size_y) ,所以需要根据比例计算新的 size_x

cpp 复制代码
size_x = size_y * (bitmap_dim.x / bitmap_dim.y);

这样,不管 size_y 如何变化,size_x 都会自动调整,保证宽高比不变。


3. 代码优化

PushBitmap 过程中,我们提取了 bitmap_scalebitmap_offset 变量,使其在 bitmap_display 中可以直接使用:

cpp 复制代码
bitmap_scale = whatever_scale_value;  
bitmap_offset = whatever_offset_value;

这样可以减少冗余代码,使逻辑更加清晰。

同时,优化了 MinCorner 的计算方式,直接使用:

cpp 复制代码
MinCorner = MinCornerValue;

避免了重复计算 bounds,提高了代码的可读性和执行效率。


4. 结果与测试

  • 通过 PushBitmap 进行渲染后,发现位图能够 保持原始比例 进行缩放,且不受拖动方式的影响。
  • 代码结构更加清晰,并减少了重复计算,提高了执行效率。

5. 总结

解决了位图缩放时的形变问题 ,确保图像始终按照正确比例显示。

优化代码结构 ,减少不必要的计算,提高可读性和执行效率。

适用于所有位图类型 ,不管尺寸如何变化,都能保持正确显示比例。

image-1672.png

运行游戏,发现调整大小效果好多了

总结与实现过程

通过对UI交互的优化,完成了位图显示的尺寸保持和缩放功能,并且通过简单的代码改动实现了更多的灵活性和可扩展性。


1. 主要改动和成果

  • 显示位图及缩放功能优化:通过调整位图的缩放比例,确保位图显示时保持宽高比,避免拉伸或压缩。
  • UI交互的灵活性:利用现有代码,轻松实现了UI元素的调整,保持了代码的简洁性和灵活性。在UI的设计中,快速添加和修改调试功能变得更加高效。

2. UI设计的简便性

  • 由于UI代码的设计本身就注重灵活性和扩展性,因此即使需要做一些较小的调整,例如限制显示时的宽高比,也只需要在相关的显示代码中进行简单的修改,不需要修改大量复杂的代码或结构。
  • 这样的设计使得在调试过程中可以快速进行调整和展示,节省了开发时间,提高了工作效率。

3. 存在的问题和待改进的地方

尽管位图的显示和交互已经改进,但依然存在一些需要解决的问题:

  • 界面布局混乱:目前的UI元素布局仍然不够规范,部分元素位置不理想。
  • 手动处理尺寸问题:虽然位图的显示功能已优化,但某些方面仍需要手动管理尺寸、边界等,缺乏更自动化的处理方式。
  • 缺乏裁剪功能:当前没有实现裁剪功能,导致一些位图可能会被显示到不应显示的区域,虽然这种情况在当前的调试中可以容忍,但在正式版本中可能需要处理。

4. 未来的改进方向

  • 进一步整理和优化UI布局:计划优化UI的整体布局,使其更加整洁有序。
  • 实现自动裁剪功能:需要加入裁剪功能,防止显示过大的位图占用不必要的区域。
  • 参数化视图大小:目前视图大小和变量绑定在一起,可能导致调试过程中无法灵活调整。未来可以将视图的大小与变量分开,使其具有更多的自定义空间。

5. 总结

通过这次优化,成功地实现了位图的高效显示和缩放,确保了显示效果不变形,并且增强了调试过程中的灵活性。然而,UI布局和某些功能(如裁剪和尺寸管理)仍有待改进。在接下来的开发中,将继续优化界面结构和增加新的功能,以提升整体的用户体验。

也许我误解了,但"tear"功能是否应拆除所有其下的组,即使它们在层级中处于相同的级别?我认为你应该只拆除当前组及其子组,而不是其他同级的组。例如,你不希望在拆除"particles"组时,"profile"组也被拆除

当前的行为存在一个问题,即当执行"tear"功能时,所有子组都会被一起撕裂,而不仅仅是当前组及其子组。这种情况可能不符合预期,尤其是在层级结构中,不同层级的组应该独立管理。举个例子,在执行"tear"操作时,如果对"particles"组进行撕裂,可能会意外地导致与其同层级的"profile"组也被撕裂,这是不希望发生的。


问题根源分析:

  • 引用问题:目前在处理"tear"操作时,实际上只是引用了目标对象,并没有复制该对象。因此,任何被撕裂的对象会影响到其子组,甚至同层级的其他组。这是因为引用本身不会创建对象的独立副本。

  • 结构性改进需求:为了防止这种问题,需要对当前的"tear"操作逻辑进行结构性修复。理想情况下,当执行"tear"时,应该克隆(复制)组的引用,而不是直接引用,这样可以避免对其他同层级的组产生不必要的影响。


解决方案:

  1. 克隆引用:在执行"tear"操作时,应该首先创建当前对象的副本,而不是直接操作引用。通过这种方式,可以避免对子组和同层级其他组产生意外的影响。

  2. 修复展开行为:此外,当前存在一个问题,即展开行为也没有处理好。我们希望能够独立控制每个组的展开和收起状态,而不是全部同步操作,这也需要进行相应的修复。


未来工作方向:

  • 结构优化:需要从根本上重构组的引用方式,确保每个组都是独立的,避免不必要的级联效果。
  • 克隆与扩展功能:引入克隆机制,并优化展开/收起的控制逻辑,以便对每个组进行独立的管理。

通过这些改进,可以使得"tear"操作更加符合预期,并有效避免出现不希望的层级影响。

新的位图显示是否也可以被拆除?

  • 拆卸功能:目前无法拆卸的原因是没有为其设置相应的交互功能。虽然拆卸的功能理论上是可行的,但因为缺少交互支持,所以暂时不能实现。

game_debug.cpp:允许位图有一个 ItemInteraction

  • 拆卸功能实现:为了启用拆卸功能,需要为项目设置一个交互项,以便系统能够识别并执行拆卸操作。如果没有设置交互项,就无法进行拆卸。

  • 调试交互:可以通过设置调试交互类型(例如"tear"交互)来实现拆卸功能。为此,需要确保为项目设置了正确的交互类型和条件。

  • 拆卸交互的默认设置 :目前,位图的默认交互类型设置为拆卸,这样它就能执行拆卸操作。

点击之后自动拆分

如果游戏没有太多 UI,做这么多 UI 工作值得吗?

  • 关于UI工作是否值得投入: 如果是在开发一个游戏并考虑UI的工作量,答案是肯定的,特别是如果涉及到调试UI。尽管游戏本身可能不会有太多UI,但为调试UI投入一定的时间是值得的。通常,调试UI需要花费几周的时间,可能是2到3周,约90小时的编程工作。虽然目前的工作量比较少,但最终目标是让UI达到相对不错的水平。
  • 对于项目: 这个项目的重点是进行有趣的编程探索,因此在UI方面投入时间也是值得的,尤其是当它涉及到值得学习的编程技巧。最终的UI系统可能不会是世界上最好的,但目标是建立一个相对合理且有效的系统。
  • 对于UI系统的开发进展: 当前的UI系统还没有完全完成,但预计再过几天就能达到一个比较理想的状态,满足项目需求。

能否添加变量来改变匹配向量?

关于如何更改匹配向量的讨论,主要有以下几个要点:

  1. 修改匹配变量的可变性: 如果希望将匹配变量设为可变的,可以通过查询它们每次绘制时的值来实现。这样就不再存储位图ID,而是存储一个类型和一个向量。这虽然可能增加一些复杂度,但并不一定是坏事。

  2. 存储与查询: 不需要每次都在绘制时查询,而是当匹配变量发生变化时才进行查询和更新。这样可以避免每次绘制时都进行查询。

  3. 考虑事项: 这个方案虽然可行,但需要仔细思考实现细节,确保每次变化时都能正确地更新相关的匹配变量和向量。

会有像塞尔达中按开始键来切换物品的菜单系统吗?没有什么花哨的功能,只是简单的功能,帮助我们入门,了解如何做这件事

关于是否会有类似《塞尔达》那样的菜单系统(例如按下开始键切换物品),答复是否定的。主要原因如下:

  1. 对传统菜单的不喜欢: 传统的菜单系统,尤其是像《塞尔达》那种需要暂停游戏并进入菜单来更换物品的设计,令人感到很不喜欢。认为这种设计会让玩家从游戏体验中脱离,打破游戏的沉浸感。

  2. 偏好游戏内UI: 对于游戏内UI(例如《死空间》那样的设计)比较认可,这种方式可以让玩家在不脱离游戏的情况下完成操作,不会破坏游戏的流畅性和沉浸感。

  3. 整体体验: 强烈的偏好是避免传统的暂停菜单,这种方式不符合自己的游戏设计理念,认为游戏的互动应该更自然、更直接地融入到游戏过程中,而不是通过打断玩家的沉浸感来进行物品管理或其他操作。

相关推荐
云上艺旅11 小时前
K8S学习之基础七十四:部署在线书店bookinfo
学习·云原生·容器·kubernetes
你觉得20512 小时前
哈尔滨工业大学DeepSeek公开课:探索大模型原理、技术与应用从GPT到DeepSeek|附视频与讲义下载方法
大数据·人工智能·python·gpt·学习·机器学习·aigc
A旧城以西13 小时前
数据结构(JAVA)单向,双向链表
java·开发语言·数据结构·学习·链表·intellij-idea·idea
无所谓จุ๊บ13 小时前
VTK知识学习(50)- 交互与Widget(一)
学习·vtk
FAREWELL0007513 小时前
C#核心学习(七)面向对象--封装(6)C#中的拓展方法与运算符重载: 让代码更“聪明”的魔法
学习·c#·面向对象·运算符重载·oop·拓展方法
吴梓穆13 小时前
UE5学习笔记 FPS游戏制作38 继承标准UI
笔记·学习·ue5
Three~stone14 小时前
MySQL学习集--DDL
数据库·sql·学习
齐尹秦14 小时前
HTML 音频(Audio)学习笔记
学习
瞌睡不来14 小时前
(学习总结32)Linux 基础 IO
linux·学习·io
Moonnnn.14 小时前
运算放大器(四)滤波电路(滤波器)
笔记·学习·硬件工程