今天没有计划。我们将整合调试UI代码,但我们仍然不知道如何操作。
在这里我们实时编写完整的游戏。今天的具体计划还不确定,通常在开发过程中,我们会有多个可以改进的方向,特别是在一个系统的多个维度都可以进行优化时,很难立即确定应该优先处理哪一部分。
昨天已经实现了一些基本的调试 UI 处理,因此今天最合适的任务可能是进一步完善它,但具体如何实施还不确定。因此,我们将直接进入代码,查看当前的进展,并判断如何让调试系统的 UI 整体更加实用,使其能够满足我们的需求。
当前的调试 UI 具备了一些基本的功能,比如调整变量、查看日志和性能分析数据等,因此今天的目标是尝试将这些功能整合到一个更为统一的界面中,使其更易用。虽然目前尚不清楚具体的实现方式,但我们将根据代码的现状,选择最合适的步骤进行改进,并逐步推进。
当前调试UI的状态。
目前的代码状态基本正常,我们之前的工作大部分都已经实现了。但仍然有一些部分尚未完成,例如 V 结构体(向量类型等)还未实现。不过,标量值的调整功能已经完成,比如调试摄像机的参数现在可以根据需要进行修改,同时布尔值的调整也已经实现了。
从界面上可以看到这些功能已经在运行,我们可以在调试 UI 中操作这些变量。接下来的目标是继续完善调试 UI,使其更加统一和易用,同时填补尚未完成的部分,例如向量类型的支持等。这将使调试工具更加完整,满足未来的开发需求。
我们希望将调试系统完成,并修改它,使将来使用起来更加方便。
目前已经完成了一部分调试系统的工作,现在的重点是将这些零散的部分整合起来,使调试系统更加完整和易用。当前的目标是让已有的调试功能能够协同工作,并且在未来需要新增调试功能时,可以方便地扩展和集成到现有系统中。
理想的结果是建立一个清晰、可扩展的调试框架,使其能够随着项目的推进不断优化和增强。例如,在开发过程中如果发现需要新的调试工具,应该可以方便地将其添加到现有系统中,而不需要大幅度修改已有代码。
此外,在测试过程中,注意到可以在房间视角摄像机和滚动摄像机之间切换,这一功能的实现效果相当有趣。这也说明了调试系统的灵活性和实用性,能够帮助更好地观察和调整游戏内部的各种状态。
“哦,游戏,真是古怪又奇妙。”
游戏的设计和调试过程中常常会遇到各种有趣和奇怪的情况。接下来,将继续推进调试系统的整合工作,使其更加完善和易用。目标是让调试工具能够高效协同工作,并且在未来需要新增功能时,可以轻松扩展和集成到现有系统中。这样可以确保在开发过程中遇到新的调试需求时,不需要大幅度修改已有代码,而是能够顺畅地添加和调整功能。
目前的调试系统已经具备了一些基本功能,例如调整调试摄像机、修改布尔变量等。接下来的任务是继续完善这些功能,并开始将不同的调试工具整合到一个统一的框架中,使其在未来的开发过程中更加高效和便捷。
我们将尝试统一调试UI和配置视图。
接下来,将尝试将调试视图与日志分析系统(profile log)进行整合,目标是让两者能够统一交互,使调试工具更加直观和高效。目前,这两个系统是相互独立的,但希望通过调整,使它们能够在同一个界面中协同工作,以便更方便地查看和操作调试数据。
具体而言,将探索如何在调试系统的层级结构中加入性能分析的相关信息,并确保它们可以像其他调试变量一样被访问和调整。这将使调试工具更加灵活,便于未来扩展和优化整个调试流程。
我们可以将配置显示作为调试变量层级的一部分进行集成。
一种可能的整合方式是将性能分析(profile log)系统嵌入现有的调试层级结构,使其成为一个可以展开和折叠的部分,从而在需要时查看,而不影响整体界面布局。这样可以在不干扰主要调试工作的前提下,使性能数据更加直观易用。
此外,还希望实现变量的“分离”功能,即允许用户将某些调试变量单独拖出,以便与其他信息并排显示。这种交互方式将提高调试的灵活性,使开发者能够根据需求调整调试界面。
目前,正在查看编译目录并检查调试代码的状态,以确定下一步的整合方案。具体实现过程中,将探索如何优化调试系统的架构,以确保性能分析功能能够无缝融入调试工具,同时提供良好的可视化和交互体验。
为配置系统引入新的debug_variable_type枚举。
当前的调试系统尚未支持将性能分析(profile group)集成到调试层级结构中。然而,由于已经定义了一些调试变量类型,因此可以扩展这些类型,使其支持调试层级的概念。这一改动应该相对直接,可以通过添加一个新的 debug_variable_type
来实现,例如 DebugVariableType_Counter
或类似的名称。
在实现过程中,需要查看调试变量的定义方式以及绘制逻辑,以确保新的层级概念能够正确融入现有的调试系统。理论上,这种整合方式应该可以让性能分析功能像其他调试变量一样,在层级结构中展开和折叠,使其更易于管理和查看。
下一步,将深入研究当前的调试变量绘制方式,并进行必要的调整,以支持新的调试层级结构,使其能够无缝地包含性能分析数据。
审查配置显示代码的结构,思考如何将其集成。
当前的调试系统中,已经有了一些用于绘制调试信息的基础框架,例如绘制草地的方法。观察现有的绘制方式,可以发现其基本结构由时间跨度(regions)和线程(lanes)组成,每个线程对应于一个计算任务或 CPU 线程。
在思考如何将性能分析(profile)数据整合进调试层级时,需要考虑层级结构的灵活性。目前的调试变量采用严格的层级组织方式,每个调试组(debug group)都有固定的 first_child
和 last_child
指针。但对于性能分析数据而言,更希望能够以多种方式查看这些信息,而不是受到固定的层级约束。
因此,需要一种机制,使某些调试项可以是临时性的,而非永久存储的。例如,在不同的视图模式下,可能需要以不同方式显示时间跨度数据——可以按线程展开,也可以按函数调用展开。因此,希望能够设计一个更即时(immediate mode)的 UI 机制,使得调试系统可以根据当前需求动态地显示不同的层级结构,而不必在初始化时就预先创建所有的数据项。
基于这些考虑,下一步的目标是研究如何调整当前的调试层级系统,使其能够更灵活地处理这些数据,同时保持现有 UI 结构的可用性。
重新思考配置枚举。
在编写调试系统时,当前的实现方式是使用 counter
类型的调试变量来记录数据。但如果要改进系统,使其能够更灵活地组织和展示调试信息,可以考虑引入更高层级的迭代器结构,而不是单纯的 counter
。
新的想法是,将调试变量类型(debug variable type)扩展,使其支持更复杂的层级结构。例如,可以新增一种 lane list
(线程列表)类型,用于存储不同的执行线程(lanes)。此外,还可以添加类似 parentage
(父子层级)概念,使调试系统能够以更灵活的方式组织数据,而不是严格按照原有的层级结构。
具体实现上,首先会定义 lane list
,然后再考虑其他类型,例如 function list
(按函数组织的调用栈数据)或 counter lane list
(按计数器整理的数据)。但目前先从 lane list
开始,看看是否能够成功整合进调试系统,然后再根据需求扩展其他的层级结构。
在创建变量的过程中,在 debug create variables
之后,可以尝试调整调试系统的组织方式,使其更加通用,能够适应不同的数据展示需求。
通过明确debug_variable_definition_context,将配置显示添加到层级中。
当前的改进目标是将不同的调试变量组织起来,使它们能够按照更有层次的方式进行显示。例如,可以通过线程(thread)来对性能分析数据进行分组,而不是仅仅使用计数器(counter)作为调试变量的主要组织方式。因此,计划添加一个 DebugVariableType_CounterThreadList
(计数器线程列表),用于按线程分类展示性能分析数据。
具体实现步骤:
调整变量创建流程:
- 在
DEBUGAddVariable
之后,将新的DebugVariableType_CounterThreadList
变量附加到调试变量组中,使其成为调试系统的一部分。 - 这样可以确保在创建变量时,自动将这些新的调试结构体纳入到调试系统的层级结构中。
- 在
修改变量上下文:
- 由于需要在
DEBUGAddVariable
之外再添加一些调试变量,因此将变量上下文的初始化移出DEBUGAddVariable
,改为在外部先创建上下文对象,再将其传入DEBUGAddVariable
进行操作。 - 这样可以允许在
DEBUGAddVariable
之外手动向上下文对象中添加额外的调试变量,例如DebugVariableType_CounterThreadList
。
- 由于需要在
简化
debug create variables
的参数:- 由于
debug create variables
现在只需要上下文对象,而不再直接依赖debug state
,因此可以去掉debug state
作为参数,使接口更加清晰。
- 由于
添加
DebugVariableType_CounterThreadList
并挂载到调试系统:- 通过
DEBUGAddVariable
,创建DebugVariableType_CounterThreadList
并添加到上下文中。 - 由于
DebugVariableType_CounterThreadList
只是一个用于展示的结构,不需要存储额外的变量,因此初步实现时不为其添加任何额外的字段。
- 通过
修复
debug menu
相关的问题:- 之前删除了一些用于设置
debug state
的代码,导致debug menu
可能无法正确显示。 - 需要重新设置
debug state
的根组(root group),确保debug menu
仍然能够正确访问调试层级结构。
- 之前删除了一些用于设置
预期效果:
- 代码运行后,调试菜单中应该会多出一个
DebugVariableType_CounterThreadList
选项,可以用于按线程查看性能分析数据。 - 未来可以继续扩展,使
DebugVariableType_CounterThreadList
具备更强的组织和筛选功能,例如按函数、按模块等进行分层。
我们不会将这些新变量转化为文本。
在创建调试变量时,存在一个问题,即当执行“将调试变量转为文本”(debug variable to text
)时,某些调试变量可能无法被正确转换成文本格式。此外,当执行“生成手动配置文件”(handmade config)时,也可能遇到类似问题,因为在生成配置文件时,程序会尝试将调试变量转化为文本。然而,有些调试变量(如某些临时或辅助类型的变量)并不需要被转化为文本,也不应该被保存到配置文件中。
因此,需要考虑以下几个方面:
- 避免将某些调试变量转换为文本:对于不需要保存的调试变量,应该避免将其转化为文本输出,以免将无关或临时变量写入配置文件。
- 手动配置生成时的处理:在生成配置文件时,应确保这些不需要的调试变量不会被错误地加入到配置文件中。可以通过添加条件判断来过滤掉这些变量,避免它们出现在最终的配置文件里。
总体来说,调试变量的转化和保存需要细致处理,确保只有必要的调试信息被输出和保存。
过滤掉配置计数器变量,使其不写入手工配置头文件。
在处理调试变量时,需要引入一种机制来判断哪些变量应该被保存或打印。这种机制通过一个简单的“谓词”来实现,谓词的作用是判断每个变量是否应该被处理或保存。在具体实现中,程序会遍历所有的调试变量,并检查每个变量的类型。如果变量类型是某种不需要保存的类型(例如“计数线程列表”类型),则该变量不会被保存。相反,其他类型的变量会被保存。
这个机制的初步实现非常简单,主要是判断特定类型的变量是否需要保存。随着需求的变化,可以逐步扩展这一机制,添加更多的变量类型和处理规则。这样,可以灵活控制哪些调试信息应该被记录和输出,哪些则应该被忽略,从而避免不必要的数据被保存或显示。
我们需要将UI元素的渲染通用化,以考虑配置显示。
在处理调试变量的显示和渲染时,首先需要考虑如何将这些变量转换为文本格式或进行自定义的渲染。由于没有复杂的面向对象的类层次结构,系统可以非常灵活地处理这些需求。具体来说,系统可以根据不同的调试变量类型决定是将其转换为文本,还是根据特定需求进行定制化渲染。
对于文本转换,系统可以根据变量的边界(bounds)来生成文本表示。这意味着在处理每个调试变量时,可以确定其显示区域,并基于这个区域生成相应的文本输出。如果系统无法识别某些变量的显示方式,则会尝试将它们转换为文本形式。
但是,对于一些特定的调试变量类型(例如“计数线程列表”类型),可能需要进行更复杂的渲染。这时,系统需要根据已有的绘制代码来生成相应的渲染结果。通过借用已有的代码逻辑,例如绘制配置文件的代码,系统可以将这些调试变量按照预定的样式显示出来,而不只是简单的文本输出。这样,可以确保系统在处理各种调试信息时,既灵活又高效。
将配置显示插入到层级中。
我们可以轻松地将该配置文件插入到我们的层级结构中。因此,我们将整个部分提取出来,按照计划将其移动到适当的位置。调整过程中,我们逐步整理内容,确保其结构合理,并在适当的位置插入所需的配置文件。这个文件可能是“DrawProfileIn”或类似的内容。接下来,我们会将其整合进系统,以保证其正确运行。
定义配置显示的边界。
我们可以让分析器在指定的框内进行绘制,因此我们需要明确边界的定义。首先,我们不想沿用已有的边界构造方式,而是希望直接使用一个概念,即确定起始位置,这个位置默认是基准线。然而,由于基准线的存在,我们可能需要进行一定的偏移。当前状态下,这个位置作为左上角点是合理的,但由于基准线的关系,我们可能需要根据下降高度(descender height)进行调整。
接下来,我们需要定义最小角(min corner)和最大角(max corner)。最小角的位置已经确定,而最大角应该对应屏幕的右边缘。不过,目前右边缘尚未明确,因此我们需要在这里定义一个具体的右边界。这样一来,矩形将从左侧延伸到屏幕右侧,并且高度可以根据需求进行设定。
关于矩形的大小,目前尚未确定合适的尺寸,因此需要引入一个参数来控制其高度。暂时设定矩形的高度为 100 像素,虽然这个数值是任意的,但可以作为初步的设定。
现在,我们已经确定了矩形的最小角和最大角,因此可以轻松创建一个矩形框。在这一过程中,不需要额外的复杂逻辑,只需计算最大角并调用绘制函数即可。最终,我们需要传递必要的参数,例如调试状态(debug state)以及矩形的边界信息,从而完成绘制过程。
在这些边界内绘制配置显示。
这个函数需要执行调试状态(debug state)相关的操作,并且需要定义边界(bounds)。当前的 ProfileRect
直接被传入,因此可以移除之前在其他部分定义的 ProfileRect
,因为现在它已经被整合到 UI 中,使得代码更加清晰整洁。因此,我们可以删除所有旧的相关代码,因为如果没有需要显示的内容,就不会调用相关函数。
我们检查了一下是否存在其他正交投影(orthographic)调用,发现它确实存在,但没有必要保留它,因此也可以删除。这样,我们就成功地获取了 ProfileRect
,并且可以继续向下推进开发流程。目前,我们暂时不会处理其他部分,虽然理论上可以立即实现,但是暂时先保持现状。
接下来,我们检查 ProfileRect
的使用情况,并发现其被多次调用,因此需要确保 RightEdge
被正确添加。此外,调试状态(debug state)需要正确写入,矩形的类型实际上是 rectangle2
,而 RenderGroup
可能属于 DebugState->RenderGroup
。此外,鼠标坐标 MouseP
也需要用于命中检测(hit detection),这完全可以在现有框架下实现。
关于 RobProfileIn
,它需要与鼠标交互功能结合使用,因此必须调整代码以适配 UI 逻辑。为此,我们决定移除 HotRecord
相关代码,并重新设计这部分 UI 逻辑,因为目前尚未完全确定其最终实现方式。
RightEdge
的计算将基于 debug state
进行处理。同时,我们发现 text_p
变量是不必要的,因此应该将其移除。此外,由于文本在 UI 中按行进行排列,因此 y
轴的调整可能需要作为 bounds
计算的一部分,以确保文本的正确对齐和间距。
当获取文本大小时,我们需要考虑 AtY
是否应该在外部根据边界计算,而不是直接在内部调整。目前,我们暂时保持现状,但感觉这种方式不是很理想。或许更好的方式是让 AtY
直接受边界影响,而不是依赖其他计算逻辑。
因此,我们可以调整 DEBUGGetTextSize
相关的处理方式,例如确保文本大小始终一致,以避免元素堆叠时产生不一致的情况。不过,我们暂时不关注这些细节,而是更倾向于保持代码的可靠性,使其在任何路径下都能稳定执行,特别是在调试代码中。
为了实现这一点,我们决定摒弃现有逻辑,采用更直接的方法。具体来说,在绘制完一个元素后,我们会检查当前 AtY
位置,并直接根据边界进行推进。例如,我们可以取当前边界的最小 Y
值,并将其作为下一行的起始位置。这种方式可以保证 AtY
始终按照边界推进,而不会受到其他因素影响。
在 DebugState->Hierarchy.UIP
相关逻辑中,我们会从 Y
位置开始,并逐步推进,可以看到这个方法的作用。因此,这种调整不仅简化了 AtY
的处理方式,同时也增强了代码的可预测性,使其在所有路径下都能保持一致的行为。
AtY现在将表示元素的左上角,而不是文本的基线。
我们正在调整 AtY
的概念,以适应新的需求。由于现在绘制的内容不仅仅是文本,因此不应再按照基准线(baseline)推进,而是应该基于矩形元素的左上角进行布局。
首先,我们检查了 uip
相关的逻辑,并发现 AtY
之前是通过 0.5 * type
计算屏幕顶部位置,然后再根据 font_scale
和 GetStartingBaselineY
进行偏移。我们决定移除这部分逻辑,使 AtY
直接对应矩形元素的左上角,而不是依赖字体的基准线。
接下来,我们在绘制文本时,确保偏移逻辑被内置到文本绘制函数中。这意味着,我们在提供 AtY
时直接使用矩形的左上角位置,而文本本身会自动向下偏移,以对齐其基准线。这样,所有矩形元素的绘制都不需要再考虑字体基准线的问题,使得整体结构更加清晰和统一。
为此,我们引入 GetMinCorner
方法,以获取当前元素的最小边界框(bounding box),并在计算 AtY
时,减去一个 SpacingY
值,该值用于定义元素之间的间距。例如,我们可以设定 SpacingY = 4
像素,确保每个元素之间有固定的间隔。当然,也可以基于 FontScale
进行动态调整,以适应不同的 UI 需求。
在实现过程中,我们遇到了一些类型问题,例如 GetMinCorner
返回的值需要正确解析,以确保 dot y
访问的是正确的数据结构。这部分需要进一步检查,确保返回值符合预期,并且能够正确计算 AtY
的推进方式。
调试UI项的摆放位置。
我们发现矩形的绘制存在问题,主要是 AtX
和 AtY
的计算不正确,导致矩形的位置偏移异常。经过分析,我们发现需要在偏移之前正确记录 MinCorner
,确保它表示的是矩形的左上角。同时,我们在绘制文本时需要考虑基线偏移,以确保文本对齐正确。
关键调整点:
正确记录
MinCorner
在偏移AtX
和AtY
之前,我们需要记录MinCorner
,因为它表示的是矩形的左上角,而不是文本的基线位置。之前的逻辑导致MinCorner
计算错误,影响了后续的偏移计算。修正
AtY
计算方式
由于我们现在不仅绘制文本,还绘制矩形,因此AtY
不能简单按照基线推进,而应该基于矩形的左上角进行计算。我们去掉了GetStartingBaselineY
相关的偏移,使AtY
直接指向矩形的顶部,同时在绘制文本时内部处理基线偏移。修正
MinCorner
和max_corner
计算
我们发现MinCorner
和max_corner
的计算存在问题,导致矩形的位置计算错误。我们调整了逻辑,使MinCorner
表示矩形的左下角,而max_corner
表示矩形的右上角,这样计算矩形高度时不会出错。调整
bounds
计算
计算bounds
时,我们需要确保:MinCorner.x
仍然是left_px
,表示矩形左侧对齐的位置。MinCorner.y
需要减去bounds
的高度,以确保MinCorner
仍然表示左下角,而不是左上角。max_corner
仍然表示矩形的右上角,确保矩形正确绘制。
确保
debug_text_out
颜色正确
我们发现debug_text_out
并没有正确设置颜色,导致文本未正确显示。调整逻辑,在绘制前正确设置item_color
,确保文本渲染正确。修正死循环问题
我们发现代码进入了无限循环,原因是VAR
未正确更新,导致while
循环无法退出。修正逻辑后,确保VAR
正确推进,避免陷入死循环。
目前的状态:
调整后,矩形的位置和文本对齐已经基本正确,颜色渲染正常,死循环问题也已修复。虽然仍然存在一些小问题,但整体逻辑已经更加清晰,继续调整即可完善最终效果。
DebugVariableType_CounterThreadList断点进不来,应该是DebugVariableType_CounterThreadList 没有插进去
修改让从DEBUGCreateVariables函数调用的外面插进去
交互时没显示颜色
它们的定位仍然有点问题。
我们目前的矩形和文本定位已经有所改善,但仍然存在一些细微的偏移问题。从观察结果来看,主要的问题在于矩形的高度计算依赖于是否存在 descender(下降部)。如果文本包含下降部,矩形的大小和对齐方式可能会受到影响。这意味着我们的矩形边界计算需要进一步优化,以确保无论文本是否包含下降部,矩形的大小和对齐都能保持一致。
关键问题分析:
矩形高度受下降部影响
- 当前计算矩形高度时,如果文本包含下降部,矩形可能会偏移,导致对齐不一致。
- 需要考虑 统一矩形的高度计算,避免因不同字符的基线不同而产生不对齐的问题。
可能的解决方案
- 固定矩形高度:不管文本内容如何,确保矩形的高度是一个稳定的值,比如基于字体行高(line height)而不是文本的具体内容计算。
- 基于最大下降部计算:如果需要适配不同字体,获取最大
descender
值,并在所有文本渲染时使用相同的descender
计算。 - 调整基线对齐逻辑:确保基线偏移计算时,能够正确处理带有
descender
的文本,而不会影响整体矩形对齐。
观察新的问题点
- 当前
min_corner
和max_corner
的计算是否需要调整,以适应新的基线逻辑? - 现有的
debug_text_out
方法是否需要额外的偏移修正,以确保文本对齐到正确的矩形位置? - 需要检查 多行文本 和 不同字号 是否会影响矩形的计算方式?
- 当前
下一步改进方向:
- 调整矩形的高度计算,确保无论文本内容如何变化,矩形的大小和对齐方式保持一致。
- 优化基线偏移逻辑,让文本正确对齐到矩形内部,而不是依赖
descender
变化。 - 测试不同字体和文本长度,检查是否仍然存在偏移问题,并进行微调。
整体来看,目前的改进方向是正确的,只需要进一步优化矩形高度和基线对齐逻辑,即可解决剩余的偏移问题。
折叠配置视图。
我们已经完成了第一部分的目标,即在实际界面中内联包含一个性能分析(Profile)视图,并使其能够与其他 UI 元素协同工作。接下来,如果我们想让它具备可展开和折叠的功能,只需要为其创建一个 分组(Group),这样它就可以随着分组的展开和折叠而显示或隐藏。
关键实现步骤:
创建分组结构
- 目前,Profile 视图并没有独立的分组管理,因此无法单独展开或折叠。
- 需要在
thread list
内部创建一个分组,使得 Profile 视图能够成为其中的一部分,并随着该分组的展开或折叠而改变可见性。
集成到现有 UI 逻辑
- 在
Hamidou
变量管理部分,我们已经实现了 UI 组件的 分组管理(即打开和关闭组)。 - 只需在 Profile 视图外部包裹一个新的分组,使其成为 UI 结构的一部分,并赋予它一个名称,如 “Profile By Thread”,这样它就可以和
thread list
其他部分一起管理。
- 在
验证交互效果
- 通过添加分组,现在可以在 UI 界面中展开和折叠 Profile 视图。
- 目前已经能够与 Profile 视图进行一定程度的交互,不过 UI 交互逻辑仍需优化。
- 需要进一步思考如何改进 UI,使其更直观、更易用,可能包括:
- 增加折叠/展开的视觉指示(如箭头图标)。
- 调整交互逻辑,确保 Profile 视图的折叠状态不会影响其他 UI 组件的正常功能。
下一步优化方向:
- 优化 UI 设计:增强 Profile 视图的可视化表现,使其更易于理解和操作。
- 改进交互体验:增加折叠/展开的指示符,确保操作直观流畅。
- 测试多线程情况:确保 Profile 视图能够正确地在不同线程的分组中展开或折叠,不影响整体 UI 结构的稳定性。
目前的实现已经达到了基本功能目标,接下来需要进一步打磨 UI 细节,使其更加符合实际使用需求。
完成文本的定位。
目前,我们还需要修复 Debug Text 相关的问题,特别是底部的 DebugTextLine 不能正确对齐的问题。
问题分析
- 主要问题是 Debug Text 在绘制时没有正确考虑
offset
(偏移量),导致它们的对齐方式不符合预期。 - 在
menu draw
(菜单绘制)逻辑中,AtY
的计算方式可能存在问题,导致文本输出位置与 UI 其他元素对不齐。 - 可能的原因包括:
min_corner
计算有误,导致bounds
设置不正确。DebugTextLine
绘制时 未包含offset
调整,所以文本位置错乱。debug_state.AtY
没有正确应用baseline
偏移量,因此 Debug Text 的位置计算存在偏差。
解决方案
修正
DebugTextLine
的偏移逻辑- 确保
DebugTextLine
的 Y 位置计算 考虑到baseline
偏移,而不是直接使用debug_state.AtY
。 - 使所有 Debug Text 绘制都基于
min_corner
,以保证统一的坐标系。
- 确保
调整
menu draw
逻辑- 在 文本绘制之前,计算正确的
offset
,然后传递给debug_text_out
。 - 确保
AtY
更新时正确 基于baseline
计算,而不是直接使用debug_state.AtY
。
- 在 文本绘制之前,计算正确的
测试和验证
- 检查底部 Debug Text 是否对齐,确保它们不会偏移或重叠。
- 确保 UI 其他部分不受影响,即 Profile 视图和 Debug 文字可以正确共存,不会相互错位。
- 不同字体和缩放测试,以验证
baseline
计算方式的适配性,防止字体大小变化时影响对齐。
后续优化方向
- 提供对齐基准设置,确保所有 Debug Text 在同一基线上输出,而不是依赖不同的计算路径。
- 统一
bounds
管理,让min_corner
和offset
在所有 Debug UI 组件中保持一致。 - 优化
DebugTextLine
API,让其默认考虑baseline
计算,减少手动调整的复杂度。
修复这些问题后,Debug Text 的显示应该会更清晰,避免错位,并且能更好地适配 UI 结构。
现在文本字符串对齐正确了。
现在整体的 UI 结构 终于基本对齐了,Debug Text 也能正确排列,一切看起来都相对合理。
目前的进展
- 调试信息的对齐问题已经解决,所有 Debug Text 现在能正确显示,不会出现错位或重叠的情况。
- Profile 信息可以嵌入 UI 结构中,并且能够在需要时展开或折叠,交互性增强。
- 代码结构更加清晰,
bounds
计算方式和offset
逻辑更加合理,减少了手动调整的复杂度。
下一步优化方向
清理代码
- 优化 Debug 相关的代码逻辑,确保
DebugTextLine
、DebugTextOut
等 API 使用统一的baseline
计算。 - 减少重复代码,将常见的 UI 计算逻辑抽取成 独立函数,避免每次手动计算
offset
和bounds
。
- 优化 Debug 相关的代码逻辑,确保
提升 UI 交互性
- 改进
profile
UI 组件的可用性,确保展开/折叠功能更直观。 - 支持多个
profile
同时存在,比如让thread list
(线程列表)可以管理多个profile
,而不是仅支持单个。
- 改进
优化
Group
逻辑- 确保
group
结构合理,begin_group
和end_group
需要能够正确管理profile
组件,以便可以灵活折叠和展开。 - 调整
group
交互方式,如果profile
过多,可以提供 筛选、排序等 UI 控件,提升可用性。
- 确保
总结
目前 基础 UI 结构已完成,但仍需优化细节以提升可用性。
下一步主要关注 代码清理、交互优化、UI 结构完善,让 profile
管理更灵活,确保 UI 更易用、更直观。
添加第二个配置显示,用于按功能显示计数器。
现在的 UI 结构 进展较好,接下来的工作主要是 组织和优化组件,以便处理 多个功能块 和 不同类型的视图。以下是当前的进展与计划:
目前进展
- 增加了多个组结构,包括 函数列表 和 变量列表。这些列表用来管理和显示不同类型的数据,使得 UI 可以承载更多内容。
- 每个组都有一个可展开/折叠的功能,允许用户根据需求查看不同的内容块(例如变量、函数等)。
- 代码的可维护性提升,通过为不同的内容块(如函数、变量)定义不同的组,使得 UI 变得更加模块化。
存在的问题
编译速度较慢:目前在使用 MSVC 编译器时,仍然面临着编译速度较慢的问题,尤其是在包含多个功能块的情况下。虽然现在可以正常工作,但如果依赖于频繁编译进行调试,效率较低。
代码结构过于冗长:当前的代码虽然实现了多种功能,但是 结构上还是显得有些杂乱,尤其是涉及多个组件时,可能会导致某些功能之间的耦合度过高,造成维护上的难度。
未来计划
继续优化 UI 结构:
- 使得 功能块更加灵活,比如支持 多个函数列表和变量列表,避免当前的单一实现方式。
- 可以考虑通过 功能分组 的方式,进一步细化界面,比如按功能分类显示不同的变量或函数。
解决编译问题:
- 尽量避免频繁的编译,考虑优化构建流程,减少冗余的编译过程。
- 可能需要 调整编译配置 或者使用其他工具来加速编译,避免在开发过程中频繁停顿。
增强交互性:
- 在组结构中实现更多的 交互功能,如 动态加载/卸载 内容、根据需求展示不同的组件等,提升用户体验。
总结
UI 结构已逐步完善,现在的主要挑战是 代码的优化 和 编译效率提升,为了支持更加灵活的组件显示,下一步将集中在提升 性能 和 交互性,使得整体系统更加高效和易于使用。
我们希望能够调整配置视图的大小。
当前的目标是使 个人资料视图 在 UI 中更具 灵活性,尤其是在 调整大小 和 用户自定义 设置方面。以下是这部分工作的总结:
现有进展
支持动态调整大小:为了让用户能够改变 个人资料视图 的大小,已经实现了一个可以存储附加信息的地方,特别是与 调试变量组 相关的设置。这些设置可以包括 尺寸 信息(例如,宽度和高度),并且这些信息可以被用户动态编辑。
调整显示区域:为了调整个人资料视图的大小,视图的 最小角点 和 最大角点 会根据 用户设置 的尺寸进行计算。通过改变这些角点的位置,可以灵活地控制视图的显示大小。具体来说,最小角点 的位置会根据 高度 调整,而 最大角点 的位置会根据 宽度 进行移动。
具体操作
添加个人资料设置:为每个 调试变量组 增加一个 调试个人资料设置,该设置包括 尺寸(例如,宽度和高度)。用户可以在界面中直接调整这些尺寸,进而影响显示的 个人资料视图 大小。
动态修改视图大小:
- 通过设定
profile dimension
,调整视图的 宽度和高度。 - 示例:一个 高度为 1024 的个人资料和一个 高度为 200 的个人资料,通过不同的尺寸设置展示不同的效果。
- 通过设定
支持多样化的尺寸:每个个人资料视图的尺寸可以独立设置,使得在打开多个视图时,不同的视图可以显示 不同的大小,提升 UI 的灵活性和可定制性。
潜在的进一步优化
剪裁功能:目前 渲染器 已经支持 剪裁,但还没有明确的设置来处理不同视图的 剪裁逻辑。未来可以考虑添加相关的逻辑,使得当视图尺寸超出预设范围时能够进行 自动裁剪。
用户交互:随着用户对界面需求的增加,可能还需要实现一些 拖动调整 的功能,允许用户通过 拖拽 操作调整视图的大小。
总结
通过允许 调整个人资料视图的尺寸,并提供灵活的设置选项,整体界面变得更加 定制化,能够适应不同的用户需求。当前的设置已经实现了 动态大小调整,未来需要考虑进一步完善 剪裁功能 和 交互逻辑,提升界面的 可操作性 和 表现效果。
我们将引入一个小的控件,使用户可以调整其大小。
为了使界面更具互动性,可以考虑为 个人资料视图 添加一个 调整大小的手柄,以便用户能够通过拖动该手柄来调整视图的大小。以下是这部分功能的实现思路和步骤:
实现步骤和思路
添加调整大小的手柄:
- 在 绘制个人资料视图 时,绘制完成后,可以在视图的 右下角(通常用户调整大小的地方)添加一个可拖动的小 手柄。这个手柄是一个可交互的控件,用户可以通过 拖动 来调整视图的大小。
- 具体实现时,可以使用一个小的矩形(例如 2x2 或 4x4 大小),绘制在视图的 右下角。这个小矩形将作为手柄,供用户点击和拖动。
设置手柄的绘制区域:
- 在绘制这个手柄时,需要计算其 位置,这可以通过视图的 最小角点(min corner)和 最大角点(max corner)来推算。视图的右下角通常就是用户调整大小的起始点,因此可以根据 视图的尺寸 计算出 大小点(size point),并将手柄绘制在这个点附近。
处理交互逻辑:
- 用户点击并拖动手柄时,应该有一个机制来检测用户的拖动行为。当前,已经有一个 交互模型,它通过
debug begin interact
函数来检测用户正在与哪个控件或元素交互。 - 需要确保,拖动手柄时,系统能够 识别 到用户的操作,并且能够根据拖动的方向更新视图的大小。手柄的拖动行为会影响视图的 最大角点 和 最小角点,从而调整整个视图的尺寸。
- 用户点击并拖动手柄时,应该有一个机制来检测用户的拖动行为。当前,已经有一个 交互模型,它通过
进一步完善交互体验:
- 目前,系统的模型主要关注 调试变量,但随着用户交互的复杂性增加,可能需要在 UI 中增加更多的交互元素,例如可以让手柄不仅仅调整 数值,还能够调整其他类型的控件或元素的属性。这样可以进一步扩展当前的交互模型。
关键挑战与解决方案
手柄的交互性:添加手柄后,最重要的是确保它能够与界面其他元素良好互动,例如拖动时更新尺寸、限制拖动的范围等。需要确保 拖动操作 能够顺利地调整视图的大小,并且可以正确地更新其 坐标和尺寸。
UI扩展:随着更多交互功能的加入,需要考虑 UI 的扩展性。例如,如果未来需要处理多个交互元素,如何让这些元素有序地进行交互而不干扰其他功能。
总结
通过为个人资料视图添加 调整大小的手柄,可以使界面变得更加 动态 和 互动。用户能够通过 拖动 手柄调整视图的大小,提供了更好的 自定义能力。接下来,需要进一步完善手柄的 交互行为 和 视图调整,确保用户在使用过程中能够顺利地调整大小并获得良好的体验。
有几种方法可以处理调整大小的控件。我们将让调用者建议应执行的交互方式。
为了让 调整大小的手柄 具备更强的交互能力,可以考虑实现两种不同的方式来处理交互:
方法一:使用合成的调试变量
这种方法的思路是引入一个合成的 调试变量,该变量代表调整大小手柄的 尺寸信息。具体来说,可以创建一个合成的调试变量,如 v2
,这个变量表示该视图框的尺寸。通过这种方式,虽然在程序内部所有变量仍然保持为 v2
类型,但这个合成变量可以专门用于处理视图尺寸的调整。具体步骤如下:
- 合成调试变量:将一个新的调试变量(例如
v2
)作为视图尺寸的表示。 - 调整尺寸:在用户进行交互时,调整该合成变量来改变视图的尺寸。
这种方式的优点是实现简单,可以直接在现有的调试框架中添加一个新变量,控制手柄的尺寸。但是,这也意味着它依赖于固定的 v2
变量,并且可能无法轻松扩展到更复杂的交互场景中。
方法二:扩展交互模型
另一种方法是通过扩展现有的交互模型,使其能够动态识别和处理不同类型的交互行为。具体来说,修改当前的 交互类型 定义,让它不仅仅依赖于调试变量,而是根据不同的交互目的来确定具体的操作。操作步骤如下:
定义交互类型:添加一个新的交互类型,例如
debug interaction hot interaction
,用来处理特殊的交互需求。例如,当用户鼠标悬停在一个可调整大小的手柄上时,可以通过这种交互类型告知系统:“这是一个可调整大小的操作”,而不是传统的仅根据调试变量进行的操作。交互处理流程:每当有新的交互发生时,首先检查当前的交互类型是否有效。如果有效,系统会根据该类型进行相应的操作。例如,如果用户正在调整视图的大小,系统就会识别这个交互并允许调整。
处理尺寸调整:当用户进行调整时,可以通过 矩形框 来表示当前视图的尺寸。每次交互时,系统会根据手柄的拖动行为更新视图的尺寸。具体实现时,可能需要通过计算 矩形的最小角点 和 最大角点 来确定新的视图尺寸。
具体实现
- 在 交互开始 时,首先判断当前是否是 尺寸调整 操作。如果是,则激活
resize profile
交互,并根据 尺寸框 来重新绘制调整后的视图。 - 交互过程中,会实时更新视图的 最小角点 和 最大角点,从而改变视图的尺寸。
通过这种方法,系统不仅能够处理传统的调试变量交互,还能够扩展支持 不同类型的交互,例如调整视图大小、拖动元素等。
总结
这两种方法分别有其优势和适用场景:
- 方法一 简单直接,适合用来处理简单的尺寸调整,容易实现,但扩展性差。
- 方法二 更灵活,可以支持多种不同的交互行为,适合复杂的交互需求,但实现起来会稍微复杂一些。
在实际应用中,可以根据具体需求选择最合适的方法,或者结合两者的优点,来提高交互的丰富度和灵活性。
如果点击发生在调整大小矩形内部,我们设置HotInteraction来调整配置视图的大小。
为了实现更精确的交互行为,可以通过 设置热区检测 来判断是否在特定的 尺寸框 内进行操作。具体来说,下面是实现思路:
交互行为的定义与热区测试
尺寸框交互检测:当进行交互时,首先要 确定当前交互的目标区域,即尺寸框。我们希望根据用户是否在尺寸框内进行不同的操作。如果鼠标位置处于尺寸框内,就执行特定的操作;否则,执行其他操作。
设置热交互类型:通过设置 热交互类型 来表示当前是否正在与一个 可调整大小的区域 交互。具体而言,当鼠标位于尺寸框内时,将当前的交互类型设置为
resize profile
,否则执行默认的交互操作。热交互的测试:在进行操作时,需要检测当前的 热交互状态,即检查鼠标是否悬停在目标区域。如果是调整尺寸的操作,系统就会标记该交互为
resize profile
。如果当前交互状态与目标交互匹配,就执行相应的动作,比如改变颜色或者触发特定的行为。颜色变化的反馈:通过
item color
来反馈当前交互是否处于热区。如果热区被激活,则采用 黄色 作为高亮显示颜色,表示当前正在与可调整尺寸的区域交互;如果不在热区,则采用默认的 白色 颜色。
具体实现步骤
设置下一个热交互:当检测到鼠标位置时,首先检查是否在尺寸框内,如果在尺寸框内,则设置
NextHotInteraction
为resize profile
,否则设置为默认的交互。颜色与状态切换:在交互处理中,根据当前交互是否是
resize profile
来决定item color
的显示颜色。如果交互有效且正在进行尺寸调整,显示为黄色;否则,显示为白色。热交互判断:通过检查是否为
resize profile
并判断是否处于热区,来决定当前的交互行为。具体操作时,执行热交互状态的切换,同时根据交互结果更新 UI。
通过这种方式,交互检测不仅限于一个简单的区域点击,而是考虑了更具体的区域判断和响应,从而实现更精准的交互反馈和操作。
当鼠标悬停时,突出显示调整大小控件。
为了实现交互功能,可以通过以下步骤来处理鼠标悬停和实际的交互行为:
实现思路
高亮显示与热区检测:
- 当鼠标悬停在目标区域(比如尺寸框)时,需要将该区域的状态标记为“热交互区域”。
- 具体来说,通过检查当前鼠标是否悬停在尺寸框内,如果悬停,就设置该区域的热交互状态为“高亮”,并将该区域的颜色改变为黄色,表示当前正与该区域进行交互。
交互行为的编写:
- 当前,通过 热交互状态 可以知道鼠标是否在目标区域内,但如果没有编写实际的交互行为代码,那么虽然鼠标悬停时能高亮显示目标区域,但实际操作时并不会产生任何效果。
- 为了使交互生效,必须编写 交互逻辑,例如在用户点击或者拖动时,应该触发相应的操作,比如调整尺寸、改变属性等。
交互逻辑实现:
- 在鼠标交互过程中,当检测到鼠标处于 热交互区域 并且符合相应的交互条件时(比如点击或拖动),需要触发实际的交互操作。
- 例如,可以在代码中加入检查条件:如果鼠标位于热区内并且交互类型为
resize profile
,则执行相应的调整操作。
实现的目标:
- 高亮效果:鼠标悬停时目标区域变为黄色,表示热区激活。
- 实际操作:鼠标点击或拖动时,根据预设的交互逻辑触发实际操作,如调整尺寸或其他属性。
通过上述方法,能够在交互时提供视觉反馈,并且通过代码实现实际的交互功能。
与调整大小控件交互。
为了实现调整尺寸的交互功能,可以按照以下步骤进行操作:
调整尺寸逻辑
尺寸改变:
- 当交互类型是 调整尺寸 时,首先需要通过鼠标的位移量 (
d mouse
) 来调整目标区域的尺寸。 - 根据鼠标的移动,可以将该值加到当前的 配置文件尺寸 上,直接修改宽度和高度。
- 当交互类型是 调整尺寸 时,首先需要通过鼠标的位移量 (
设置最小尺寸限制:
- 为了避免尺寸过小,可以在调整尺寸时设置一个最小值限制。
- 比如,可以设定宽度和高度不能小于 10x10 的大小。通过条件判断,如果当前尺寸小于最小尺寸值,就强制将其设置为最小尺寸。
实现代码示例:
- 在调整尺寸时,增加如下代码来确保最小值的限制:
这里,profileDimensionX = max(profileDimensionX, 10); profileDimensionY = max(profileDimensionY, 10);
profileDimensionX
和profileDimensionY
分别表示目标区域的宽度和高度,10
是最小尺寸限制。
- 在调整尺寸时,增加如下代码来确保最小值的限制:
总结
通过这种方式,在改变目标区域的尺寸时,不仅能根据鼠标的拖动调整尺寸,还能保证尺寸不会小于预设的最小值(例如 10x10)。
一直按住拖动鼠标交互
调试新代码。
在实现调整尺寸功能时,出现了以下问题和解决方案:
问题 1:使用错误的函数
- 在调整尺寸时,发现使用了
min
函数来限制尺寸的最小值,但实际上应该使用max
函数。- 由于
min
会返回两个值中的最小值,导致尺寸的限制不符合预期。 - 应该使用
max
来确保尺寸不会小于预定的最小值。
- 由于
问题 2:鼠标坐标反转
- 由于坐标系问题,鼠标的 Y 坐标出现了反向变化。
- 在屏幕坐标中,通常是
Y
坐标随着鼠标向下移动而增大,而这里却是反的。 - 解决方案是对
Y
值进行取反处理。即当进行尺寸调整时,需要将Y
坐标的值取反,使得向上移动鼠标时,尺寸变小,向下移动时,尺寸变大。
- 在屏幕坐标中,通常是
总结
- 在调整尺寸时,要确保使用
max
函数来限制最小尺寸。 - 在处理屏幕坐标时,需要注意坐标系的方向问题,可能需要对
Y
坐标值进行取反,以使得鼠标向上时尺寸减小,向下时尺寸增大。
它工作了!
为了实现调整尺寸功能,以下是总结的简化过程:
实现概要
- 通过引入一些配置,可以方便地添加和调整“配置文件”视图的尺寸。这使得能够轻松管理这些配置文件的显示和交互。
- 添加功能的过程非常简便,只需按照现有的框架扩展功能即可。
设计理念
- 尽管尺寸调整功能能够很容易地实现,但在实际使用中,并不总是推荐频繁使用此类功能,因为它可能影响用户界面的清晰性和可操作性。
- 这种尺寸调整功能更多的是为了灵活性和用户交互的自定义,允许调整“配置文件”显示区域的大小,以适应不同的需求和显示效果。
总结
- 为了实现用户界面的可调节性,通过简单的修改代码,可以轻松为界面组件添加可调整大小的功能。这种功能提供了更多的自定义空间,让用户可以根据自己的需求调整视图展示的大小。
通常我们会通过测量从按下点击的点到当前位置的距离来设置显示大小,但这是内部调试代码。
为了实现更精细的尺寸调整,有以下几点改进建议:
改进方法
- 使用“Delta from point A”方法来计算尺寸调整,而不是直接加上Delta。这是因为直接添加Delta可能会导致调整后的鼠标位置不正确,特别是在尺寸被限制时(clamp)。使用Delta方法可以更加准确地调整尺寸,避免不必要的偏差。
- 另外,为了更精确地控制调整过程,最好在开始调整时记录鼠标点击的起始位置。虽然对于调试用途,这不是必须的,但这是一种更为精准的做法。
易于扩展
- 通过这种方式,添加尺寸调整功能变得非常简单,这也是我们期望的效果。希望能通过简单的操作扩展UI功能,减少复杂的代码操作。
- 为了让添加功能变得更容易,应该精简一些冗余代码。虽然目前的代码是直接写的,但可以通过进一步整理,使得扩展更加简洁和清晰。
未来展望
- 对于未来的改进,考虑到目前已经实现了基础功能,可以进一步优化UI界面的绘制,确保所有配置文件视图都能够在同一个系统中管理和显示。虽然仍有一些细节不确定,比如如何绘制配置文件的UI,但总体结构已经理顺,后续可以逐步完善。
总结
- 本次的调整和改进,已经使得UI功能更加灵活和易于扩展。虽然还存在一些细节需要完善,但核心功能已经完成,后续可以通过优化和扩展进一步提高用户体验。
引入根组。
可以通过简化代码结构,将“配置文件”和“调试”功能整合成一个更加清晰的体系。具体来说,可以考虑在代码中引入一个根组(root group),这个根组一开始是不可见的,只有在需要时,才会从中提取相关内容来使用。这种方式能够让代码更简洁且不显得杂乱,且在开始实际操作时再显现出来,这样能有效避免干扰。
通过这种方式,可以将与调试和配置文件相关的所有操作组织在一起,使得代码更易于管理和扩展。所有的调试信息和配置文件的内容都能够被清晰地分隔和控制,提升了整体的可读性和维护性。
你认为这种结构UI代码的方式可以用来构建一个完整的应用程序吗,还是仅仅对调试UI有用?为了使其适用于完整的应用程序UI,你认为还需要添加什么东西?
这种结构化的代码方式是可以用于构建完整应用程序的,但问题在于目前实现的只是应用程序开发的初步阶段,远未完成一个完整的应用。虽然目前的代码框架可以用来开始构建应用的UI,但还需要更多的优化和完善才能适应复杂的应用需求。
具体来说,当前的结构主要处理了调试系统的交互和变量,但随着开发的推进,系统需要更多的功能。例如,可能需要实现一个更加复杂的“交互存储结构”,用于跟踪用户点击和交互的状态。这样的方法可以使得交互更具灵活性和可操作性,而不仅仅是简单的“调试交互”。
此外,交互单元(如UI控件)将有状态,这意味着每个单元的状态需要被持续追踪和管理。随着项目的发展,除了调试系统,还会涉及更多的组件和状态管理工具。虽然目前的代码只是初步实现,但它为构建一个完整的应用程序奠定了基础。总的来说,从调试到完整应用的过程需要逐步过渡,随着需求的增加,代码也需要进行逐步的优化和扩展。
第一次直播时你紧张吗?
第一次进行游戏直播时,完全没有感到紧张。其实,直播和公众演讲的最大不同就在于,你虽然知道有很多人观看,但你并不能看到他们的实际面孔。公众演讲中,看到面前有大量的观众,这会引起人们的紧张,因为这种直观的互动和感受是非常真实的。而直播时,即使有成千上万的人观看,感受到的却只是镜头前的自己,就像与一个没有情感反应的设备互动。因此,这种感觉并不像面对面公众演讲那样令人紧张。
你怎么看待GCC及其调试功能?
对于GCC及其调试工具,我并不特别喜欢在这些系统上调试。GDB虽然能够提供大部分所需的功能,但它的调试体验并不理想。尤其是控制台的界面和头部显示部分,它并没有提供一个非常高效的调试环境,使得调试过程不够直观和便捷。虽然在紧急情况下GDB能够派上用场,但作为日常使用的调试工具,它并不合适。
通常情况下,我使用GDB的场景是当我在进行移植工作时,这时我已经编写了99%的代码,剩下的只是处理一些移植相关的工作。因此,调试效率不是我的首要关注点。在这种情况下,GDB足够用,但如果是在日常的开发和调试过程中,我更倾向于寻找其他更高效的工具。
你考虑过在Valve工作吗?你对他们的看法是什么,他们的组织结构如何?
曾经在1998年面试过Valve,但最终没有选择加入,因为当时他们正在开发《半条命》《半衰期》 (Half-Life),而自己对第一人称射击游戏并不感兴趣,最后选择了加入Gas Powered Games,并且认为他们的游戏更具吸引力。对于Valve的结构,有优点也有缺点,和任何其他公司一样,更多的是看自己能否对他们的项目感兴趣。Valve的项目大多数并不符合个人的兴趣,尤其是像《Dota》之类的游戏,不太可能激发工作热情。
虽然Valve提供很好的薪酬,且有很多朋友在那里工作,但工作在那里并不被认为是第一选择。可能更感兴趣的是像VR系统这样的新技术,或者Steam平台相关的工作,因为这些方面可能有更多想要去改变和尝试的地方。总体而言,虽然Valve的工作机会并不令人排斥,但个人对于他们的某些项目并不激动,可能不太容易找到激励自己继续工作的动力。
游戏在25集后会是什么样子?
在讨论游戏开发的进度时,提到未来25集的内容,游戏的外观预计不会有太大变化。当前仍有一些引擎方面的工作需要完成,因此,预计在接下来的过程中,可能会开始进行艺术上的变更,比如加入实际的内容和资源。然而,这些变化的具体时间尚不确定,可能会在第250集或240集左右发生,但这些都只是大概的估计,因为开发进度和质量总是优先于速度。
开发的目标不是急于完成,而是确保能够给观众提供教育性的内容。重点在于展示如何编程和理解系统的工作原理,而不仅仅是快速制作一个游戏。如果只是为了迅速完成游戏,不关心质量或如何构建系统,那么使用诸如GameMaker这样的工具快速生成游戏可能是更合适的选择。
至于开发的时间安排,最初的预估是需要200集来完成引擎部分的内容,其中大约20集将集中在引擎的细节上。虽然有可能跳过一些调试代码,集中精力完成灯光和Z轴的部分,从而提前达到目标,但并不希望采取这种做法。目标是让每个环节都尽可能细致,尽管一些步骤看似不完全必要,但依然希望能够展示如何创建UI,帮助观众理解这些开发技巧。
总的来说,开发的节奏注重质量与教育性,而不是仅仅追求快速完成。
你会使用性能分析工具(如gperf)来找出代码中的热点,还是仅依赖你自己的调试系统?
在讨论开发过程中使用的工具时,提到了当前已经有了相当不错的性能分析(profiling)工具,因此不太需要依赖像gdb这样的工具来检测代码中的热点问题。虽然不太需要使用gdb,但也提到会使用其他工具(如IACA)来转储汇编代码,这是之前在直播中使用过的工具,未来也会继续使用它来查看指令的执行次数。
关于时间的估算,提到“197小时”其实并不算多,按每周20小时的工作量计算,大约需要10周时间,而这在游戏开发中是相对较少的时间。虽然听起来像是很多小时,但实际上并没有花费太多时间,因此感觉开发进度相当快。如果不考虑时间限制,甚至可以选择更慢的节奏,以便有更多的时间来详细探讨每个环节或探索更多的选项,这样可以更好地向观众展示不同的开发过程和技巧。
虽然一些观众可能希望看到更快的进展,或者只是想看到特定的内容,但开发者强调了开发过程不会被仓促推进,不管观众的期待如何。目标是保持教学的质量,不会为了满足一些快速结果的需求而降低节奏。
最后,尽管花费的时间相对较少,但仍然感到进展相当快,并不急于加速开发过程。
你见过Michael Abrash或Carmack本人吗?
提到曾经与 John Carmack 和 Michael Abrash 见过面,并且在多个会议和展会上与 Carmack 有过几次接触。而与 Michael Abrash 的关系更加紧密,因为在某段时间里,两人的办公室仅相距两间,并且共事了三到四年,因此对 Michael Abrash 非常熟悉。
你会去看《火星救援》吗?
对于是否去观看电影《火星救援》还没有确定,因为尚未阅读原著。不过,身边有人已经读过这本书,并且认为它很好,同时也计划去看电影。因此,考虑是否在观看电影之前先阅读原著,或者直接去影院观看。可能会在对方看完电影后,询问是否值得先读书再看电影。
你谈过自己喜欢编程的项目。我们现在看到很多太空游戏,之前一段时间没有好游戏。你对太空游戏感兴趣吗?
对太空游戏是感兴趣的,但具体要看游戏的质量。如果要玩太空游戏,希望能有一款高质量的飞行摇杆,像以前的比例式飞行摇杆那样精准。此外,希望游戏能像《X-Wing》那样,不仅仅是简单的飞行和射击,而是包含更多战术性和智能化的要素,比如管理护盾、能量分配、武器发射模式等,而不仅仅是无脑飞行绕圈射击。
对《Wing Commander》那种简单的空战模式并不感兴趣,认为那样的战斗缺乏深度。如果要玩太空游戏,希望它具备更丰富的战术选择和更强的沉浸感。目前还没有去专门寻找或者尝试新出的太空游戏,也没有购买摇杆。
对《EVE: Valkyrie》和《Elite Dangerous》的系统设计并不了解,不确定它们是否具备期望的战术复杂度。之前曾尝试玩过《Enemy Starfighter》,但当时游戏还处于早期阶段,感觉缺乏战术层面的细节和沉浸感。此外,还未尝试过《Limit Theory》,但从目前来看,它仍然处于开发初期,因此对它的游戏体验也没有确切的判断。
Kerbal Space Program?
玩过《坎巴拉太空计划》(Kerbal Space Program),但感觉物理引擎并没有达到应有的水准,无法准确模拟太空任务的真实物理效果。在建造航天器时,感觉系统的反馈有些随意,比如像一个质量较差的弹簧-质量模型,导致整体体验不够精准和可信。
如果要让《坎巴拉太空计划》真正做到完美,物理引擎应该达到极高的精度,足以让人用它来测试 NASA 级别的火箭,并且能得到与现实一致的计算结果。这样,才能真正发挥这类模拟游戏的潜力,提供严谨且有深度的航天探索体验。
Star Citizen正在崩溃。
从未关注过《星际公民》(Star Citizen),但听起来这个项目像是一场巨大的灾难。他们筹集了大量资金,却似乎没有相应的组织架构或团队来支撑如此庞大的开发计划,因此对这个项目的未来感到担忧。
这种情况可能会变成一个资金黑洞,上亿美元投入后却无法交付预期成果。如果最终失败,不仅对玩家和支持者来说是一个巨大损失,还可能影响未来的众筹环境。人们如果因为这种失败案例变得不愿再支持众筹项目,那会对整个行业产生负面影响。
希望《星际公民》最终不会彻底崩盘,因为它的失败会对众筹的信誉造成极大的打击。相比之下,《精英:危险》(Elite Dangerous)就表现得更好。他们通过众筹获得了合理的资金,并按时推出了游戏。虽然游戏最终品质可能因人而异,但至少他们兑现了承诺,按照计划完成了开发并交付给玩家,这是值得认可的。
你是如何开始参与《见证者》的工作,以及作为“自由职业者”如何找到工作?
参与《见证者》(The Witness)的工作是因为与核心团队成员关系密切,了解到他们可能需要额外的帮助,因此最终加入了项目。这主要是基于朋友之间的联系,而不是通过正式的招聘流程。
至于自由职业者如何找到工作,并没有太多经验可以分享。过去的工作大多是通过已有的朋友关系进行的,而不是主动寻找或申请职位。因此,对于那些没有现成的行业人脉或熟悉的团队可以接洽的自由职业者来说,如何寻找项目机会并不太清楚。
如果Star Citizen最终交付,你认为它有可能改变当前的发行商AAA模式,还是认为它无论成功与否都是一次性事件?
如果该项目最终成功交付,是否会改变当前的发行商 AAA 模式?还是无论成功与否,它都只是一个特例?
实际上,即使该项目成功,也不一定能够复制相同的模式。至于对 AAA 发行模式的影响,可能并不会太大。因为从某种程度上来说,它本质上与现有的 AAA 发行模式并无太大区别。
当前的 AAA 发行模式主要依赖于高额售价,例如 60 美元一款游戏,同时通过各种额外内容进行增值销售,比如游戏内购、预购奖励、特殊版本、赛季通行证等。而该项目采用的模式实际上也类似,只是资金来源不同。传统发行商本身有足够的资金,因此无需提前向玩家筹资,而该项目则依赖玩家预付款来支持开发。
因此,从整体来看,这种模式并不会对 AAA 发行模式带来颠覆性的变化,而只是换了一种资金筹集方式。