游戏引擎学习第227天

news2025/4/16 10:12:06

今天的计划

今天的工作重点是进行吸引模式(attract mode)的开发,主要是处理游戏的进出和其他一些小的细节问题,这些是之前想要整理和清理的部分。我做了一些工作,将游戏代码中的不同部分分离到逻辑上独立的区域,这样就可以更容易地管理和切换不同的游戏模式。

例如,我可以启动一个独立的过场动画,它是完全自包含的;同样,我也可以启动世界模式,它也是自包含的,这样就能方便地在它们之间切换并进行操作。这些就是我想要完成的主要目标,虽然昨天我们大部分做完了,但因为时间不够,没能完全完成。所以今天的任务就是把剩下的部分完成。

回顾昨天取得的进展

现在回头看看我们昨天留下的状态,基本上我们已经把所有需要的部分都提取出来了,但最后的一些内容还没有来得及完成。目前游戏已经无法正常启动了,因为我们把启动相关的那部分逻辑移除了。

现在的流程是,会先进入过场动画,这部分运行是正常的,也就是说,过场动画的启动已经被成功地独立出来,结构上也比较合理。然而,如果此时按下空格键,原本应该让角色进入游戏世界的功能却没有任何反应。同时,按下 ESC 键也不能退出游戏了。

也就是说,原本在游戏运行过程中用来处理界面交互的那一部分代码已经不在当前流程中了,导致无法响应用户输入。因此我们接下来需要修复这些问题,把这些逻辑重新接入进来。

此外,也开始思考为什么当前这个场景会出现这样的状况,以及可能的原因。这就是今天需要集中处理的部分。

临时调整以修复开场动画镜头的缩放问题

我们发现当前某一个镜头完全没有进行预期的缩放操作。昨天其实已经注意到了这个问题,当时还在想是否不小心把这个镜头的缩放逻辑删除了。查看代码后发现,这个镜头(比如镜头2)是有设置缩放的:从 (0,0,0) 缩放到 (5, -5, -1),按理说应该是有动态变化的。

但实际运行时却完全感觉不到镜头的缩放变化,非常奇怪。其他镜头的缩放操作都能正常工作,只有这个出现了异常。于是我们开始尝试定位问题。

首先确认各个图层的深度(Z 值)是不同的,比如角色、树、墙、窗户和冰柱等,它们都位于不同的深度层级上,所以从逻辑上讲,不应该出现画面静止不动的情况。

为了进一步验证问题,我们人为地把缩放的时间增量(dt)加大,使其缩放效果更加明显,这样可以观察是否有任何视觉上的缩放运动。结果显示确实有缩放,只不过幅度太小,肉眼几乎察觉不到。因此判断问题在于缩放太过微弱,导致看起来好像没有发生任何变化。

于是我们尝试将缩放速率加倍,测试是否能让运动更加明显。发现确实更容易看出镜头在运动了,但依旧显得很微妙。最终推测,等到之后要把配音或者背景音乐和镜头同步的时候,再回来调整这个镜头,让它看起来更有戏剧性一些。

此外,还有一个小问题:当前的角色和树似乎在画面中的位置太突出,导致整体视觉效果不够协调,缺少景深感。所以也考虑稍微把它们往后推一点,让它们更靠近背景,从而提升整体画面的层次感。

最后的结论是,当前需要继续思考在过场动画、吸引模式(Attract Mode)等不同阶段如何处理 UI 的显示与交互。对于过场动画这类内容,倾向于尽量不添加过多 UI 操作逻辑,让画面保持简洁专注。总体目标还是希望不同模式之间可以顺畅切换,同时让画面和交互都保持良好的用户体验。

在这里插入图片描述

重申模式切换的工作方式

我们目前在思考如何处理过场动画和吸引模式(Attract Mode)期间的 UI 问题。我们的想法是,在这两个阶段中,UI 应该尽量简化,保持干净整洁。因为在这些阶段中,唯一真正需要响应的交互行为,就是玩家试图开始游戏的操作——例如按下“开始”按钮。在这种情况下,系统应该立即切换到游戏模式。

除此之外,吸引模式和过场动画阶段不需要处理其他任何复杂的交互逻辑。一旦切换到了游戏模式,那些游戏内的功能,比如角色加入、多人参与等,都会由游戏模式本身来处理,这样流程也会更加清晰。

我们也考虑到了可能支持多位玩家的情况。虽然还没有最终决定是否在正式发布版本中开放多人模式,但我们希望从结构上预留这个可能性。为此,我们设想加入游戏的机制应该是随时都可用的,而不是某个特定状态下(比如在过场动画期间)才生效。换句话说,“加入游戏”的操作不能受限于当前是哪一种模式,它应该在任何时候都有效,这样才能支持流畅的多人游戏体验。

因此,我们的决定是:

  • 将所有与 UI 有关的处理逻辑集中放在游戏模式中;
  • 在吸引模式或过场动画中,仅实现一个非常基础的响应逻辑:只要有玩家触发“开始”操作,就立即切换到游戏世界;
  • 进入游戏世界后,由该模式负责处理所有后续的 UI 和交互流程。

这种方式既保持了结构的清晰,也避免了在非游戏阶段引入复杂的交互处理,从而保证了系统整体的健壮性和可扩展性。

对缩放效果进行最后调整

我们目前的过场动画视觉表现已经比之前好很多了,运动感变得更明显,看起来更加自然,不再显得那么生硬。虽然目前还不是最终效果,但已经接近可以接受的程度了。暂时先不继续优化这一部分,等以后再来处理。现在主要是确认了一下整体镜头的动态是否如预期那样逐渐推进,并验证了角色在镜头中是否合适。

我们稍微调整了角色的位置和大小,之前角色有点偏移和比例不对,现在进行了居中和比例微调,看起来更合理了。虽然这个优化细节不太重要,但为了后续剧情表现更自然,我们还是选择花点时间把这个视觉效果做好。

之后我们准备继续处理逻辑部分,本来计划进入“吸引模式(attract mode)”的相关文件,但发现根本不需要那个文件,所以将其删除。因为我们其实不是真的需要一个独立的吸引模式,而是通过过场动画(cutscene)来完成吸引模式的作用。也就是说,我们把“吸引模式”和“剧情开场”合并为一个系统,在进入游戏前就用同一个机制处理,避免逻辑重复。

所以现在的流程设计是:

  • 启动游戏后默认进入过场动画(同时作为吸引模式);
  • 玩家在任何时候按下“开始”键或其他输入,就直接跳转进入游戏模式;
  • 游戏模式内部负责处理玩家加入、交互界面等所有复杂功能;
  • 保证逻辑清晰分离:吸引/过场只负责展示,交互和控制只在游戏模式内处理;
  • 同时,我们也顺便在视觉细节上微调了人物位置与比例,使画面更平衡自然。

总之,我们现在的整体逻辑和美术层都在朝着模块清晰、表现自然的方向推进,打下了进一步开发的基础。
在这里插入图片描述

为开场动画和标题屏幕的游戏模式添加输入处理

我们现在正在处理游戏启动流程中与“标题画面”和“过场动画”相关的输入逻辑整合工作。目标是让玩家在这些阶段只要按下“开始”键,就可以无缝进入游戏世界,且这一行为逻辑保持一致。

目前的逻辑结构是这样的:

我们有两个初始界面:一个是“标题画面”,另一个是“过场动画”。这两个模块都需要响应玩家的输入,特别是“开始游戏”或“退出游戏”的操作。因为它们的行为几乎相同,所以我们决定将这段输入检测逻辑抽取出来,封装成一个统一的函数,例如叫做 check_for_start 或更广义的 check_for_meta_input

这个新函数的职责就是:

  1. 遍历所有的控制器;
  2. 检查是否有玩家按下了“开始”键或者“返回/退出”键;
  3. 如果按了“开始”,我们就立即切换到游戏世界模式;
  4. 如果按了“退出”,就设置一个退出标志,通知主程序进行游戏关闭操作;
  5. 一旦有任何输入发生(无论是开始还是退出),就终止进一步输入处理(比如跳出循环),避免重复处理。

为了实现切换到游戏世界,我们使用了一个叫 PlayWorld 的函数,它会启动游戏世界并初始化玩家数据。当玩家按下“开始”键后,我们调用 PlayWorld,并将当前游戏状态传进去用于初始化。之后,如果需要进一步控制,比如直接渲染第一帧游戏画面,也可以调用 UpdateAndRenderWorld

关于退出的处理,我们注意到之前的逻辑是通过访问 game_memory 来设置 QuitRequested 标志。不过考虑到代码结构和逻辑职责划分,我们现在倾向于把 QuitRequested 放在 game_input 中,这样可以避免到处传递 game_memory,逻辑也更加集中。因为退出本质上是一种输入行为,放在输入模块里更合适。

接下来,我们还有一些细节逻辑上的规划:

  • 如果在检查到“开始”按钮被按下之后要切换到游戏模式,我们可能不希望当前画面继续更新和渲染。相反,我们可能要“跳过”本帧的后续处理,让下一个模块(游戏模式)接手;
  • 因此,我们会在输入检查后判断是否有模式切换,如果有就直接返回,避免多余操作;
  • 我们可能还会设计一个更系统化的框架,例如统一管理模式切换、状态持有和切换后的初始化流程。

整体来说,我们正在朝着结构清晰、逻辑分离的方向重构启动阶段的逻辑,确保标题画面和过场动画都具备一致且稳定的输入响应行为,同时为之后的游戏世界模式提供清晰入口。最终目标是让整个游戏从启动到进入游戏的过渡流畅自然,不存在逻辑冲突或混乱。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在游戏模式调度中添加一个循环,允许在发生模式切换时立即重新运行更新/渲染

我们现在正在整理并优化游戏主循环中的模式切换逻辑,尤其是当游戏从标题画面或过场动画切换到实际游戏世界时的流程控制。目标是确保当输入发生导致模式发生切换时,系统能立即响应并跳过当前不再适用的逻辑,快速进入新的模式,同时结构上保持简洁、灵活、可维护。

核心思路如下:


我们在主循环(位于 handmade.cpp)中,通过判断当前的游戏模式(Game Mode)来调用相应的更新与渲染逻辑,例如调用 UpdateAndRenderCutsceneUpdateAndRenderTitleScreen。但在这种结构中,一旦模式发生改变,比如玩家按下开始键,导致从“标题画面”或“过场动画”进入游戏世界模式,原来的逻辑不会立即跳出,而是会继续执行剩余部分,可能导致逻辑混乱或画面撕裂。

为了解决这个问题,我们引入了一个标志变量,例如 rerun = false,表示是否需要“重新执行一次主循环判断”。具体做法如下:

  1. 在每帧主循环中增加一个 do-while 或等效结构,允许在模式切换后立即重新判断游戏当前模式;
  2. UpdateAndRenderCutsceneUpdateAndRenderTitleScreen 被调整为在处理完输入后返回一个布尔值;
    • 如果返回 true,表示模式已经改变,需要“重新执行”一次主循环流程;
    • 如果返回 false,表示没有变动,可以继续处理当前模式;
  3. 模式切换函数不需要直接跳出逻辑,而是通过设置返回值来通知主循环“我切换了模式”;
  4. 对于退出游戏的请求(QuitRequested),它不会触发 rerun,因为不会改变模式,仅仅设置一个退出标志即可。

示意逻辑如下:

bool rerun;
do {
    rerun = false;
    switch (GameMode) {
        case MODE_CUTSCENE:
            rerun = UpdateAndRenderCutscene(...);
            break;
        case MODE_TITLE:
            rerun = UpdateAndRenderTitleScreen(...);
            break;
        case MODE_GAME:
            UpdateAndRenderGame(...);
            break;
        // 其他模式...
    }
} while (rerun);

这种设计的好处是:

  • 结构清晰:每个模式只需关心自己的逻辑和是否需要切换,不需要直接控制全局跳转;
  • 响应迅速:模式切换立即生效,不会延迟到下一帧;
  • 易于扩展:未来添加新模式也可以用相同方式接入;
  • 逻辑解耦:输入处理、模式切换、渲染更新各自分离,通过清晰的信号传递进行配合。

目前的初步框架已经搭建完成,接下来可以逐步将现有模式模块化,确保它们都遵循这一约定方式,并统一返回是否需要“rerun”的结果,让主循环驱动整个状态流转。整体逻辑更加稳固且灵活。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

将原有的输入处理代码移动到世界游戏模式中

我们考虑将当前这部分内容移出,并将其放入 game world 模块 中。我们倾向于将其放在这个位置,因为感觉这是更合适的归属地,但目前还不能完全确定它到底属于哪里。也有可能它应该放在其他地方,比如某个相关模块中,但这还需要进一步探索。

对于 controlled heroes(受控英雄) 的归属问题,我们也进行了思考。尽管它与 game world 存在联系,但我们认为它不应该仅仅存在于 game world 中。因为 controlled heroes 可能会在不同的上下文之间持续存在,所以将它放在更广义的 game state(游戏状态) 中更为合理。这样可以确保它的生命周期和作用范围不会被限制在特定的 game world 中。

基于这一判断,我们决定将 game state 传入当前逻辑中,使其能够在使用过程中灵活地访问和操作整个游戏状态,从而实现更高层次的控制和数据管理。这个结构能更好地支持我们后续的功能扩展与模块解耦。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

修复导致的编译错误和头文件包含顺序问题

在这里插入图片描述

当没有英雄存在时,使世界游戏模式切换回开场动画模式

我们现在处理的是退出流程的逻辑。之前我们的做法是:如果没有英雄存在,就直接退出。因此我们设置了一个类似 “heroes exist” 的判断逻辑。现在我们想更进一步完善这个机制,也就是说——

在逻辑执行到末尾时,如果检测到英雄仍然存在,我们就什么都不做,继续保持当前状态;但如果 没有英雄存在,我们就需要切换游戏状态,比如 重新进入引导动画(cutscene) 的状态。因此我们调用 PlayIntroCutscene 来重新开始流程,同时切换游戏状态。

在这个切换状态过程中,我们意识到其实并不需要重新运行任何旧的逻辑,流程也不会受到影响,所以现阶段这个切换是安全的。

但当尝试调用 PlayIntroCutscene 时,发现编译器报错:标识符未找到。这个问题确实是之前提到过的 依赖管理 的真实案例。也就是说,PlayIntroCutscene 这个符号需要被暴露给当前模块,而它还没有被正确引入。因此我们要把这部分函数上移到更高的作用域(例如头文件),以便其他模块能够调用它。

随后我们检查 PlayIntroCutscene 依赖的所有内容,确保都被正确包含和传递。同时注意到另一个问题:UpdateAndRenderTitleScreen 函数必须返回一个值。编译器提示我们遗漏了 return 的部分,这一块我们已经做了修正,确保它能返回正确的状态。

此外,我们还意识到在处理标题画面时,需要同时检测 meta 输入,这是用户交互的重要一环,因此也一并加上了处理逻辑。

最后一个错误是:QuitRequested 并不是 game_memory 的成员。这是因为我们此前已经调整了结构,把与退出相关的逻辑从 game_memory 中移走了,可能现在属于另一个结构或者模块。因此需要同步更新调用部分,使其与最新的数据结构保持一致。

综上所述,这一系列工作主要围绕以下几个方面展开:

  • 基于英雄存在与否决定是否切换状态;
  • 将引导动画函数暴露给外部模块使用;
  • 补全返回值和输入判断逻辑;
  • 修复因结构调整导致的成员访问错误;
  • 进一步清理并理顺模块之间的依赖关系和调用路径。

在这里插入图片描述

在这里插入图片描述

调试新代码

我们现在的目标是让当前的这套流程真正运作起来,但这需要一些时间和调试。目前我们正在尝试初始化某个流程,不过此时传入的是一个完全无效的 world mode 指针,这显然是不对的。

我们在调用 fill_ground_chunk 时出现了问题,从现象来看,是传入了一个错误的 world mode。问题是——到底是谁负责提供这个 world mode 的?我们目前并不清楚这个指针的来源,也无法准确确认是哪个模块或函数生成了它。

进一步回顾整个结构时我们意识到,其实对 ground chunk 的处理我们可能根本不需要。发现这个功能在新的设计方向下很可能不会真正启用。虽然以前可能有用武之地,但现在它的必要性已经存疑。

尽管如此,我们仍然决定把它先 调试清楚,确保当前流程中不会因为它而出错。哪怕之后我们完全删除这部分逻辑,也必须先确认它不会影响其他流程的稳定性。

因此我们接下来要做的是:

  • 调查 world mode 的传入路径,找出错误的来源;
  • 明确 fill_ground_chunk 是否在当前或未来版本中还具备实际价值;
  • 即使未来可能移除,也先保证目前运行状态下不出错;
  • 整体上继续理顺资源传递链、数据初始化顺序等底层逻辑问题。

这部分的工作主要集中在调试、理清责任链、排查无效指针来源,以及决定某些功能是否值得保留的问题上。虽然有些模块未来可能会被删减或重构,但在现阶段依然必须保证整体系统的稳定性与可预测性。

在这里插入图片描述

在这里插入图片描述

思考新模式切换代码如何与多线程交互

我们目前在处理 mode 切换的问题时,面临一个比较棘手的点——当退出 world mode(或关闭一个 world 实例)时,必须考虑到 仍然可能有线程正在使用这个 world mode 的情况。这是一个线程安全性和资源管理的问题。

换句话说,world mode 相关的数据很可能还被其他线程在后台访问,尤其是在执行渲染任务或者是 ground chunk 的生成过程中。如果我们在这些线程仍然运行时就去销毁 world mode 使用的内存,那么这些线程一旦访问到被释放的内存,就会发生严重错误,甚至导致崩溃。这种场景非常危险,所以必须特别注意。

虽然这次的问题并不是因为我们真的尝试关闭了一个 world,但这是我们在整体设计中必须重视的隐患之一。

为了简化当前调试并避免 ground chunk 造成干扰,我们决定 暂时禁用所有 ground chunk 的生成逻辑。具体做法是,直接移除了 fill_ground_chunk 的调用,这样可以完全避免地面块渲染所带来的线程问题和错误行为。

禁用后重新运行程序,情况明显好转。我们现在可以更清楚地看到系统其他部分的实际运行状态,也能更容易追踪和定位其他潜在问题。这种分步调试的方式有助于理清当前混乱的状态,并逐步验证每个模块是否正常运作。

这段调整的核心内容包括:

  • 意识到退出 world mode 时需要确保没有线程仍在访问其资源;
  • 暂时禁用 ground chunk 的异步工作,避免访问非法内存;
  • 移除相关调用后重新运行系统,确认现阶段问题得到缓解;
  • 为后续的多线程安全管理与资源生命周期控制埋下设计基础。

整体策略是先停掉有潜在风险的部分,优先理顺主流程,再逐步引入并重新实现复杂模块,确保系统稳定性与可维护性。

更改世界初始化方式

我们发现当前代码存在一个非常明显的问题:在真正初始化 world(世界)之前,就尝试向它压入结构体(push struct),这是明显错误的。逻辑顺序上必须先进行 world 的初始化,否则后续的内存使用都是未定义的。

因此我们决定重新组织这一部分逻辑。现在的做法是:game_state 会负责分配 world 对象,然后再调用初始化函数来完成设定。但从设计角度来看,其实更合理的方式是:让初始化函数 initialize_world 自己完成 world 的内存分配和子 arena 的创建。因为在初始化过程中本身就需要一个独立的子 arena,所以由它自己分配内存、并初始化该 arena,会更加清晰、封装更好。

基于这个想法,我们重命名了初始化函数,从 initialize_world 改成 create_world,其职责不再是“配置一个传入的对象”,而是“构造并返回一个全新的 world 对象”。

具体流程变为:

  1. 在父 arena 上 push 一个新的 world;
  2. 初始化这个 world 的 arena;
  3. 返回这个新创建并完成配置的 world 实例。

这样做的好处是:

  • 更符合创建型函数的语义;
  • 减少外部调用者的负担,不再需要自己先手动分配结构体;
  • 避免未初始化就使用的潜在风险;
  • 逻辑上更清晰,内聚性更强。

在完成重构后,我们编译时遇到一个小问题:create_world 识别不了,发现是函数名修改后忘记同步调用处的名称,改正后一切恢复正常。

继续调试过程中,我们发现:在调用 create_world 后,内部子 arena 请求分配资源时提示 无法分配(can’t fit)。这提示我们:

  • 子 arena 可能容量不足;
  • 父 arena 剩余空间不够;
  • 或者分配逻辑出错。

下一步需要重点排查 arena 的容量分配逻辑以及实际分配的内存情况,确保 world 初始化的内存需求可以被满足,避免越界和分配失败。

总结当前进展:

  • 明确了初始化 world 前必须先分配;
  • 重构了 world 创建流程,封装为 create_world
  • 实现了更清晰的资源分配逻辑;
  • 开始排查 arena 内存不足的分配异常;
  • 进一步推进系统调试流程,朝稳定结构靠近。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

修复世界游戏模式立即退出并返回开场动画

我们现在进一步调试时发现,当前的运行逻辑仍然存在严重问题。比如在游戏中按下空格键后,屏幕上什么都没有,甚至还会错误地重新开始播放引导动画(cutscene),这显然是不符合预期的。我们意识到需要对其进行深入排查。

首先分析更新和渲染逻辑时发现:

  • 在调用 update_and_render 时,并没有如预期地创建英雄角色(hero),这是主要的问题之一;
  • 接着尝试查看 ground chunk 的更新是否恢复正常,结果仍然表现为混乱的内存状态
  • 怀疑是因为一进入世界模式(world mode)后马上就退出了,导致所有的 fill_ground_chunk 调用都访问了已释放的内存区域,于是程序崩溃;
  • 验证这一点时发现 heroes_exist 被错误地设为了 0,而不是 1;

继续调查后发现:

  • 这是因为输入检测逻辑存在不一致,was_pressed 的判断逻辑和动画那边用的 ended_down 不一致,导致根本就没有检测到玩家的按键动作;
  • 正确的输入检测应该用统一方式进行判断,两个逻辑应该一致,才能让输入被正确处理,进而创建英雄角色并进入世界模式;
  • 当前只有在某个具体代码路径中 heroes_exist 才被设为 1,但这个路径没有被触发,所以状态一直是错误的;
  • 简单的解决方法是将这一逻辑也覆盖到其他输入路径中,从而确保在任意输入有效时都能进入正确的流程;

总结当前的修复方向如下:

  1. 修复输入判断逻辑,统一使用 was_pressed 判断;
  2. 确保每次从 cutscene 切换到 world mode 时,英雄角色都被成功创建;
  3. 在内存分配逻辑中,防止访问已释放的 arena,避免 fill_ground_chunk 等线程继续运行;
  4. 梳理所有状态切换的输入路径,确保状态改变后不会被错误回退到引导动画;
  5. 确保在 world mode 中启动时,所有必要资源和数据都已初始化成功;

这样处理之后,系统就能够在玩家输入时正确进入游戏世界,不会反复跳回开场动画,且不会再触发访问空指针导致的奔溃。整体逻辑更加稳定,输入处理也更统一。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

运行游戏。现在可以进入游戏模式,但仍然有一些bug

目前系统终于恢复到一个相对合理的状态了,已经能够成功进入游戏、启动流程,也能够正常退出游戏并返回引导动画(cutscene),这正是我们期望的基本行为模式。虽然看似整体流程已经通了,但仍然存在两个明显的 bug


Bug 1:状态切换流程仍不稳定

  • 从初始动画进入游戏世界再返回,再次尝试进入时,似乎存在某些隐藏的状态错误
  • 当前仍可能在某些情况下导致状态机异常,比如重复切换时状态未完全重置;
  • 这个 bug 尚未完全定位,但从表现上看像是有未清理干净的残留状态或初始化遗漏;

Bug 2:进入游戏世界后,角色无法移动

  • 尽管时间是正常流逝的(可以通过阴影的抖动观察得出),但玩家无法控制角色移动
  • 说明渲染和更新循环正在运行,但输入并未被正确地传递或处理
  • 推测可能的原因包括:
    • 控制器输入并未绑定到正确的玩家对象;
    • 输入状态在切换状态过程中丢失或未初始化;
    • 玩家角色虽已生成,但未被赋予控制权或未注册进可控制实体列表;
  • 总之当前输入系统与实体控制系统之间未正确连接,需要排查创建角色后的绑定逻辑是否完整;

当前进度总结:

  • 游戏与引导动画之间可以来回切换;
  • 世界模式的基础逻辑逐步分离完成;
  • 状态切换仍然存在边界条件问题;
  • 玩家角色移动完全失效,说明输入链未打通;
  • 接下来应重点处理输入系统与控制系统的连接逻辑,并修复状态初始化一致性问题;

一旦这两个问题解决,基本的游戏循环就能稳定跑通,可以继续进入更深层的功能开发。整体看来,当前已经非常接近一个干净的、可控的状态管理架构。

通过重新启用昨天被注释掉的代码来修复无法移动的问题

目前正在解决玩家角色无法移动摄像机未跟随角色的问题。经过排查,定位和修复进展如下:


问题一:角色无法移动

  • 排查方式是直接搜索项目中使用了 #if 0 的地方,寻找被暂时禁用的代码;
  • 发现一段与角色控制逻辑相关的代码块被注释掉,导致玩家输入根本未传递到角色控制逻辑;
  • 这正符合之前的猜测,即为了临时测试某部分逻辑,将控制逻辑注释掉后忘记恢复
  • 将这段代码重新启用后,玩家角色可以正常移动,功能恢复。

问题二:摄像机未跟随角色

  • 移动恢复后,发现摄像机并未随着角色一起移动
  • 怀疑是设置摄像机跟随目标的逻辑失效;
  • 跟踪相关逻辑,确认摄像机是通过 camera_following_entity_index 来追踪目标;
  • 在添加玩家时,会设置该跟随索引,例如 camera_follow_to = LindseyLowIndex
  • 推测目前的问题可能是该索引值被设置错误或未被正确更新;
  • 尝试检查玩家创建流程中是否有遗漏设置该字段的逻辑;

初步结论:

  • 玩家移动问题已修复,原因是控制逻辑被注释导致输入未生效;
  • ❌ 摄像机不跟随角色问题尚在排查中,但基本逻辑链清晰,疑点集中在索引值设置或未更新;
  • 接下来应:
    • 核对添加玩家时摄像机跟随字段是否确实设置;
    • 确保玩家被添加后 camera_following_entity_index 正确指向玩家;
    • 检查是否有在其他地方将该值覆盖或清空;

总体进展:

  • 基本的游戏状态切换、输入响应、角色控制逻辑已逐步恢复;
  • 摄像机逻辑是当前的关键缺口;
  • 修复后,即可形成完整的“切换-控制-观察”基础系统框架,为后续功能扩展(如多人模式、状态保存等)打好基础。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

修复摄像机无法跟随的问题,确保区域被零初始化

目前我们正在修复初始化内存未清零导致的各种潜在错误,同时也在完善整体内存分配流程,以确保所有结构体或数据对象在首次使用时状态都是一致的、可预测的。当前的进展与思路如下:


问题现象与本质

  • 当前系统中有些对象的内存没有在分配时清零;
  • 而系统设计假设所有分配的内存默认是全零的,因此未初始化会导致不确定行为,例如摄像机未跟随角色、角色状态出错等;
  • 所以我们必须确保所有内存对象在分配时都被清零。

解决思路与实现策略

  1. 改进 PushStruct 宏/函数行为

    • 每次调用 PushStruct 分配新对象后,自动清零;
    • 实现方式是,在 PushSize 之后调用 ZeroSize
    • 只清零所申请的内存大小,而不是整个 Arena 剩余空间;
    • 这样可以确保每个结构体被创建时其字段都是干净的、符合预期的初始值。
  2. 可扩展性考虑

    • 为了应对某些特殊情况(比如:不需要初始化大块内存以提高性能),计划为 PushStructPushSize 添加一个标志位,用于控制是否清零;
    • 例如:可以通过传递一个参数来决定是否执行 ZeroSize
    • 目前系统中实际使用 PushStruct 的地方并不多,所以检查起来不复杂,可以一一确认是否需要初始化。
  3. 重用已有的 ZeroSize 工具函数

    • 系统中已有封装好的清零函数,因此只需在分配后调用它即可;
    • 避免重复造轮子,代码更加整洁。

后续步骤

  • 确认现有的 PushStruct 全部按需清零;
  • 针对大容量非结构体数据的分配,评估是否需要添加跳过清零的标志位;
  • Game.h 中调整 PushStructPushSize 的实现逻辑,将清零操作作为默认行为;
  • 测试各种对象的初始化状态是否符合预期,确保后续逻辑不再依赖未定义值。

总结

通过修改 PushStruct 的默认行为为“分配即清零”,我们大幅提升了程序初始化阶段的安全性和可预测性。同时考虑到了未来可能出现的性能优化需求,设计中预留了灵活性接口,为后续系统扩展打下了坚实基础。
在这里插入图片描述

再次运行游戏,修复所有bug后运行正常

目前为止,我们已经修复了一个核心问题:在内存分配时未自动清零,导致程序逻辑在初始化后的状态异常。现在我们已经确保内存分配时默认会被清零,系统行为恢复正常。以下是详细总结:


当前实现成果

  • 修复了未初始化内存的问题:
    系统期望所有新创建的数据结构在一开始就是零状态,这样逻辑判断才能可靠运行。之前由于未清零,导致如角色状态、摄像机追踪等逻辑出现混乱,现在已经解决。

  • 成功实现了游戏模式之间的切换:
    能够自由地在不同模式(如世界模式和元游戏模式)之间切换,包括:

    • 创建新世界;
    • 进入世界中运行;
    • 退出世界并返回元游戏界面。
  • 模式状态一致性良好:
    模式之间切换时的状态保存与恢复如预期工作,没有出现内存异常访问、线程冲突或资源未释放等问题。


当前剩余问题

  • 存在一个新问题需要处理,虽然具体细节未展开,但从上下文来看:
    • 可能与资源回收、状态保持或线程管理有关;
    • 也可能是切换过程中某些系统状态没有完全恢复或清理;
    • 具体问题需进一步排查并定位。

总结

当前系统的内存管理已经回归到预期的稳定状态。默认的内存清零机制保障了数据结构在创建时的正确初始状态,使得模式切换、角色控制、摄像机追踪等子系统恢复了正常功能。接下来,将针对最后发现的异常进一步调试,完成最终的修复闭环。整个架构正趋于稳定和可维护状态,推进整体开发进入下一个阶段。

在这里插入图片描述

在这里插入图片描述

评论之前提到的关于模式切换的潜在线程问题

目前我们面临的一个关键问题是多线程环境下“地面块填充(fill ground chunk)”任务的潜在崩溃风险,尽管它现在没有显性崩溃,但从架构角度来看,这是一个潜在的严重 Bug。以下是详细总结:


当前发现的问题:多线程任务未安全关闭

  • 多线程访问已释放内存风险
    地面块填充是一个在独立线程中运行的任务,而它所访问的数据结构(例如世界状态)在模式切换或重置后可能被释放或重分配。这将导致访问“悬空指针”,尽管当前没有崩溃,但实际是读取了无效或过时的内存。

  • 当前之所以没崩溃是巧合
    内存可能还没被其他内容覆盖,所以访问时没有立即崩溃,但这并不意味着安全 —— 在更复杂或内存更紧张的情况下,这种行为是极不稳定且不可预测的。


我们需要实现的机制:任务引用计数式的安全退出

  • 每个游戏模式在退出前,必须确保:

    • 自身所创建的后台任务(如填充地面块)全部完成或手动终止
    • 不再有任何任务访问该模式下的资源(如世界数据);
    • 模式才可以被安全销毁或替换。
  • 参考模型
    这类似于“引用计数机制”:

    • 模式启动任务时,相当于将引用计数 +1;
    • 任务完成或主动关闭时 -1;
    • 模式在引用计数归零前不能销毁;
    • 这是任务层面的引用计数,而非内存对象引用计数。

我们的临时处理:

  • 添加了一个重要的注释标记 // TODO AC IMPORTANT
    • 明确指出 fill_ground_chunk 在模式切换时可能会崩溃;
    • 标记这是一个必须在最终版本前解决的问题;
    • 为后续开发留有清晰的方向指引。

总结

目前虽然功能表面正常运行,但后台任务未管理好生命周期是一个明显的架构漏洞。我们未来需要添加一种机制来确保每个模式退出前所有相关任务已经停止,从而避免悬空内存访问,确保系统稳定性。这种机制在任何含有异步操作或多线程的系统中都是必须的基础保障措施。后续开发中需优先解决此问题。

实现标题屏幕的基础版本

目前我们开始着手处理标题画面(title screen)系统的构建,并计划如何使其在游戏流程中合理切换和显示。整个目标是建立一个基本的主循环模式:片头动画 -> 标题画面 -> 再次进入片头动画或游戏主流程。以下是详细过程和当前实现逻辑的总结:


当前目标:实现标题画面与过场动画之间的切换

过场动画完成后切换到标题画面
  • 原本判断 cutscene 是否完成的逻辑使用了错误的变量名(命名是 cutscene_complete,但含义却是 still_running),导致语义与实际含义相反,逻辑混乱。
  • 现已修正为 cutscene_still_running,使判断条件逻辑更清晰:如果动画仍在播放,就继续播放;否则,跳转到标题画面模式。
标题画面计时与跳转逻辑
  • 在标题画面模式中,使用一个变量 title_screen_t 累加每帧的 dt(delta time),也就是实际经过的时间。
  • 每帧会判断是否达到 10 秒时间:
    title_screen_t += input.dt_for_frame;
    if (title_screen_t > 10.0f) {
        // 切换回 intro cutscene
    }
    
  • 达到时,切换回 intro cutscene,从而形成循环。

可视化验证:调试用红屏清屏

  • 为验证标题画面确实被触发,在 update_and_render_title_screen 函数中添加了清屏操作:
    ClearScreenToColor(红色);
    
    用红色背景清屏作为视觉提示,确认此函数被正确调用。

启动顺序验证调整

  • 为便于测试标题画面逻辑,临时修改了初始流程,游戏启动时直接进入标题画面模式而不是原本的 intro cutscene,方便观察红屏是否生效,验证流程控制逻辑正确。

未来工作展望

  • 当前还剩下一个“重大问题”尚未处理,后续会在剩下的时间内进行展示与说明;
  • 不过就目前的阶段来看,我们已完成以下内容:
    • 片头动画与标题画面之间的自动切换;
    • 标题画面的超时跳转;
    • 标题画面基本渲染路径的验证。

小结

我们已经成功搭建起基础的流程控制框架,实现了 intro cutscene 与 title screen 之间的双向切换机制,并验证了标题画面渲染逻辑的正常执行。尽管还有关键问题未处理,但已经朝着模块化、流程明确的结构迈出了一大步。接下来的重点是进一步完善资源状态管理以及最后的问题排查与修复。
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

测试标题屏幕代码

发现没有title screen 红色
在这里插入图片描述

switch case 没进来
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

目前我们完成了标题画面的初步实现,并验证了其在逻辑流程中的正确切换。以下是这一阶段的具体内容和调试过程总结:


标题画面成功显示与自动切换

  • 我们现在已经实现了**“淡出 -> 标题画面 -> intro 片头动画”**的流程:
    • 在过场动画结束后,成功切换至标题画面;
    • 标题画面保持显示 10 秒;
    • 时间到后,自动切回片头动画;
    • 逻辑顺畅,流程衔接正确。

⏱加速测试逻辑

  • 为了验证逻辑的完整性,同时避免每次等待过长,我们尝试人为加速游戏内时间流逝,即调高 delta time 的值,使得 10 秒更快过去。
    • 查找了处理 dt(delta time)的相关代码位置;
    • 计划将 dt 人为增大,加速过渡;
    • 示例:可以将 input.dt_for_frame 乘以一个因子,如 4.0f,让模拟时间流逝变快。

遇到异常情况

  • 在加速时间之后,尝试运行发现画面表现异常(出现了 “whoa what happened there” 的情况):
    • 可能是加速后导致某些逻辑没有按预期运行;
    • 比如动画播放提前完成但资源未准备就绪、未正确复位状态等;
    • 有待进一步调试,排查在加速过程中具体出了什么问题。

阶段性成果

  • 成功实现了基础流程控制框架;
  • 标题画面与片头动画之间可以正常切换;
  • 时间控制机制工作正常;
  • 基本调试机制(例如视觉反馈、时间调控)生效;
  • 初步发现了加速逻辑下的一些潜在 bug,为后续优化提供方向。

这部分标志着我们完成了游戏模式切换机制的一个重要里程碑,下一步需要进一步排查快速切换下的异常,并逐步增加更多内容到标题画面中(比如实际图像、文字、菜单等)。目前来看,流程控制的架构已经趋于稳定。

快速调试并修复与模式切换相关的开场动画崩溃

在这里插入图片描述

目前我们意识到当前的游戏模式切换机制存在一个结构性问题,这个问题可能在一些特殊情况下引发错误或不稳定行为,下面是详细总结:


模式切换机制存在的根本问题

我们当前的实现中,每次只允许一个游戏模式(mode)存在。一旦切换模式,就会立刻销毁原来的模式结构(如 cutscene 的状态结构)。这会导致以下严重问题:

  • 如果我们在当前模式中处理逻辑时,中途切换到了新模式,那么当前模式的内存结构立即被清除;
  • 接下来代码中任何对旧模式状态(如 cutscene_t)的访问都会访问无效的内存区域,造成数据错乱程序崩溃难以定位的潜在 bug
  • 当前遇到的异常现象(如时间加速后画面混乱)其实已经提前暴露了这个问题。

正确做法:延迟模式切换 + 多模式并存支持

为了让模式切换更稳健、逻辑上更合理,我们决定引入以下机制:

多模式结构并存:
  • 即使我们只「激活」一个模式,其他模式的结构仍然保留在内存中
  • 切换模式时,不再立刻销毁旧模式结构,而是让其保持活跃直到本帧处理结束;
  • 这样即使新模式已经准备好,也可以等旧模式的处理完全完成后再切换。
延迟执行切换操作:
  • 将“模式切换”变成一种延迟操作,只有在逻辑流程真正结束之后再执行;
  • 例如设置一个 next_mode 变量,在主循环末尾检测其是否存在并进行切换;
  • 避免中途执行切换造成的状态混乱。

理解方式:任务/资源的引用计数模型

可以将其类比为引用计数管理:

  • 每一个游戏模式就像一个带引用计数的资源;
  • 只有当没有任何代码再访问它时,才可以安全释放;
  • 这类似于对「任务」或「线程」管理中确保退出前资源安全释放的做法。

总结现状

  • 当前实现是单一模式机制,存在访问已销毁数据的风险
  • 我们决定升级为支持多模式并存 + 延迟切换机制
  • 这样能提高系统健壮性、避免潜在 bug,同时也便于扩展复杂的游戏逻辑(如后台加载、过渡动画等)
  • 这也是下一阶段开发中的一个关键性目标。

接下来我们将实现这个改动,重构相关的模式切换逻辑,使其更加稳定、健壮和易于维护。
在这里插入图片描述

游戏运行正常,三个游戏模式都按预期工作

我们目前已经完成了模式切换的基本流程测试,并验证了之前的问题是否存在。以下是本阶段的详细总结:


验证模式切换与加速播放的稳定性

  • 10倍速运行过场动画(cutscene),用作测试加速模式下是否会引发潜在的逻辑错误;
  • 动画顺利播放完毕后,成功切换回标题画面,说明基本的状态管理与时间推进逻辑在高倍速下依然稳定;
  • 接着成功从标题画面进入游戏场景,然后又成功退出回元模式界面
  • 整个过程中,模式状态切换正确、流程流畅,没有崩溃或卡顿现象,初步验证之前的问题已经得到了控制。

标题画面尚未完成但已占位

  • 当前只是使用占位的红色背景作为临时标题界面
  • 后续需要正式设计和绘制标题画面,内容可能包括:
    • 游戏名称或 LOGO;
    • 背景动画或静态画;
    • 菜单选项(开始游戏 / 设置 / 退出等);
  • 一旦图像资源准备好,可以直接接入现有流程中,无需重构切换逻辑。

游戏流程基本架构已具雏形

目前已实现以下基本结构:

  1. 启动时播放过场动画;
  2. 动画结束后自动跳转到标题画面;
  3. 标题画面停留固定时间后,重新播放过场动画(循环演示模式);
  4. 支持从标题进入游戏,再退出回主界面;
  5. 支持退出程序。

这些逻辑构建了一个初步可交互的“完整体验流程”,为后续游戏正式内容的扩展打下了基础。


当前进度与阶段性成果

  • 已完成:多模式并存逻辑、延迟切换机制、状态保持与销毁管理;
  • 正在进行:标题画面设计、美术资源接入;
  • 已验证:高速运行下流程稳定性、模式切换正确性;
  • 下一步目标:完善标题画面后,进入游戏主体功能的构建阶段。

总的来说,我们已经从一个原始的启动动画过渡到了一个具备完整流程的基础游戏框架。虽然功能还不丰富,但骨架已基本成型,接下来就可以围绕这个流程不断丰富细节和内容了。

能否在尝试实时调整开场动画的值时利用调试代码,而不是重新编译?

我们其实可以在调试中直接利用调试工具来查找过场动画(cutscene)与实时运行(real time)之间合适的时间值,而不是每次都重新编译来测试。但目前我们还没有完全完成调试系统的开发,所以暂时还无法真正派上用场。

调试功能还需要继续完善,等到调试界面和参数可视化控制做好之后,就可以在运行时动态修改和观察数值变化,从而更高效地调整动画时长、速度等参数,而无需频繁地手动修改代码并重新编译。

总结如下:

  • 调试工具理论上可以用于快速调整参数,例如 cutscene 时长等;
  • 当前调试系统尚未完成,暂时不能实际使用;
  • 后续将继续开发调试模块,使其支持实时调节、数值追踪等;
  • 已有初步的片尾/title信息展示逻辑,可能用于标记阶段性完成或作为演示用途。

这个部分虽然简短,但也说明未来开发中会更多依赖调试工具,来提升开发效率与测试准确性。

如何在结束时终止或结束每个线程?

在结束每个线程时,是否指的是在整个程序执行完毕之后?即在游戏关闭时,所有的线程都需要被正确关闭吗?

这一问题涉及到程序在退出时如何正确清理资源和终止各个线程。通常,在游戏或者应用程序结束时,所有的后台线程和任务需要被终止,以防止在程序关闭后,仍然有线程在后台占用资源或发生错误。

我们会重新实现性能分析器吗?

会重新实现性能分析器吗?是的,当我们达到想要的调试状态时,可能不会太远,我们会完成调试代码部分,以便能够查看并实现性能监控功能。

可执行文件的结束

当可执行文件退出时,其实不需要手动关闭线程。当退出时,程序会跳出主循环,执行return 0,这时会进入C运行时库的外部代码,调用exit process,这会终止所有线程,包括我们的线程。所以不需要特别去关闭线程,它们会自动结束。

能否重新解释一下为什么在开场动画之后无法移动英雄?

之所以在过场动画之后无法移动角色,是因为相关的控制代码被注释掉了。原因是当时还没有完成相应的代码迁移,这导致了角色无法移动。

如果有人想以不同于原生分辨率的全屏模式运行游戏,应该怎么更改?你之前说过不喜欢菜单,那么会用启动器来提供这些选项吗?

关于如何在不同分辨率下全屏运行游戏,如果需要改变分辨率的设置,最好将这些选项放在游戏启动器里,而不是游戏内的菜单中。这是因为,游戏启动时如果分辨率设置不当,可能会导致画面无法显示,从而无法访问游戏内的设置菜单进行修改。因此,最理想的方式是将这些设置放在游戏启动前就可以调整的地方,比如 Steam 启动器中,用户可以通过右键点击游戏,设置命令行参数来修改分辨率。

这样做的好处是,普通用户不需要关注这些技术性设置,游戏可以自动选择最佳分辨率,确保大多数玩家无需手动调整,像看电影一样,用户只需点击播放,系统会自动选择最佳的画质。只有那些对技术比较精通的玩家,才会需要或者想要修改这些设置,而这些高级设置应该放在一个完全独立的技术性区域,普通用户在启动游戏时永远不需要看到这些内容。

启动时是否可以做一些分辨率检测,避免启动时出现破坏性分辨率?

关于分辨率检测和启动时避免使用不适合的分辨率,最安全的做法是始终使用桌面分辨率启动游戏。即使操作系统报告显示器支持当前分辨率,实际上可能存在显示器不兼容的情况,导致用户看不到任何画面。因此,为了确保游戏在启动时能够显示,最好根据用户当前的桌面分辨率启动游戏,因为用户必须已经能够正常使用该分辨率。

如果某些用户希望拥有更高的自定义控制权限,那么他们可以通过编辑配置文件来设置分辨率等参数,但需要明确告知用户编辑配置文件时要小心,游戏不会对因修改配置文件所带来的任何问题负责。这样的方式可以让那些有技术需求的用户自行调整,而普通用户则不需要担心这些设置,始终能够顺利启动游戏。

你说“普通人”,好像说技术人员是件很糟糕的事。

在讨论“普通人”时,并不是贬低那些懂技术的人,而是指那些不关心技术细节的用户。如今,很多人可能根本不知道自己的分辨率是多少,尤其是智能手机用户。以前,玩电脑游戏的人往往了解分辨率是什么,但现在很多人甚至不关心这个问题。当一个普通人玩游戏时,他们可能连分辨率都不清楚,特别是如果他们是手机用户,或者他们在购买电视时才知道分辨率的高低。因此,现代游戏的目标是让大多数人不需要了解技术细节,游戏应该能自动适应,尽量让一切都“正常工作”。

这意味着对于大多数用户来说,游戏应该自动选择合适的分辨率和设置,而不需要用户进行任何操作。然而,对于那些技术感兴趣、希望调整游戏设置的用户,可以通过启动文件或命令行参数来修改一些高级设置,如强制特定的分辨率或帧率等。这些设置不应该出现在普通用户看到的菜单中,因为大多数人并不关心这些内容,他们只希望游戏能顺利运行。

因此,理想的情况是,游戏能“自动工作”,不让普通用户担心技术细节。如果有技术需求的用户需要调整,他们应该能够在一个特定的配置文件或参数中修改,而不是通过游戏菜单进行操作。

进一步讨论分辨率/4K

如今,大多数人对分辨率的了解其实非常有限,通常只是知道“1080p”或者“4K”这些名词,而对具体的技术细节并不清楚。例如,很多人可能会问“这是1080p的显示器吗?”但他们并不真正理解1080p代表什么,而4K的概念也常常让人感到困惑。4K实际上并不是指某一个特定的分辨率,而是一个包含多个分辨率的范围,通常这些分辨率至少是1080p的两倍。更复杂的是,不同的显示器可能会被称为“4K”,但它们的分辨率其实不同,有些可能是多个1080p分辨率拼接在一起,或者是更高的分辨率,如5000×某个值,比4个1920×1080的屏幕还要高。

总的来说,大多数普通用户并不关心这些细节,他们只是知道“4K”是更高质量的显示标准,但并不理解不同的4K显示器之间的差异。

通常在开发游戏时,你会先做开场动画代码还是游戏玩法代码?

在开发游戏时,是否先做剧情动画代码还是先做游戏玩法代码并没有固定的规则。通常会根据项目的需求来决定。比如,如果剧情动画的艺术制作非常耗时,并且需要与游戏的开发有较大重叠,那么可能会提前编写剧情动画代码,以便艺术团队可以在开发过程中有所准备,避免出现意外情况。但如果剧情动画的制作不需要太多与游戏玩法的交互或影响,那就可以将它推迟到最后再做。

作为程序员,应该根据项目的依赖关系来安排开发时间,确保技术开发与艺术团队的工作能够尽可能顺利地衔接。这意味着有时候需要先做剧情动画的代码,有时则可以在游戏开发后期再做,这完全取决于项目的具体需求。

对于这个项目,剧情动画代码之所以提前做,是因为它可以有效利用渲染器,并且不会过多依赖游戏的其他部分。这样,艺术团队可以在不完全依赖游戏玩法的情况下,先行制作动画部分,而不必等到某些玩法元素完全确定后才开始。

在项目中,程序员的开发进度相对较慢,而艺术进度通常会更快。因此,开发顺序不仅取决于技术需求,还要考虑如何在直播过程中更高效地学习和展示。这个顺序可能会与传统的开发方式有所不同,因为直播的特点要求程序员调整开发顺序,以便观众能够更容易理解和跟随开发过程。

我们是否已经接近需要实现mixins的阶段?

目前,是否需要实现混合功能(mix-ins)取决于是否决定继续推进游戏玩法代码的开发。如果决定直接进入游戏玩法代码的实现,那么可能会涉及到混合功能的实现。然而,如果之后决定回过头来完成一些其他的工作,那么就不一定需要立刻实现混合功能。具体情况尚不明确。

C++17模块能解决#includes依赖问题吗?

C++17模块是否能解决包含依赖问题的问题没有明确的答案,因为即使是C++委员会的新特性也很少能有效解决实际问题。在过去的经验中,新增的特性常常会出现不符合预期的情况,即使看起来是简单的功能,通常也需要开发者付出很多额外的工作才能使其正常运作。这种现象在C++中已经变得很常见,尤其是当引入像“decltype”这样的新特性时,就发生了预期之外的问题。例如,在尝试使用“decltype”来获取某个类型的大小时,原本简单的任务变得异常复杂,甚至需要创建模板来强制映射类型,这显得非常不合理。

这种问题的出现源于C++委员会在设计语言特性时,往往没有考虑到开发者的实际需求和使用场景,导致新增的功能不仅不直观,而且使用起来非常繁琐。因此,尽管C++模块被提出来作为一种可能的解决方案,但对于其是否能真正解决包含依赖问题,仍然持怀疑态度。总的来说,C++的语言发展方向似乎经常导致开发者面对的是一系列复杂而不必要的解决方案,尤其是对于那些本来可以通过简单方法完成的任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一键直达:用n8n打造谷歌邮箱到Telegram的实时通知流

欢迎来到我的博客,代码的世界里,每一行都是一个故事 🎏:你只管努力,剩下的交给时间 🏠 :小破站 一键直达:用n8n打造谷歌邮箱到Telegram的实时通知流 前言n8n的强大之处实现简便性实战…

【QT】 QT定时器的使用

QT定时器的使用 1. QTimer介绍(1)QTimer的使用方法步骤示例代码1:定时器的启动和关闭现象:示例代码2:定时器每隔1s在标签上切换图片现象: (2)实际开发的作用 2.日期 QDate(1)主要方法 3.时间 QTime(1)主要方…

【自动化测试】如何获取cookie,跳过登录的简单操作

前言 🌟🌟本期讲解关于自动化测试函数相关知识介绍~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废话…

每天五分钟深度学习PyTorch:RNN CELL模型原理以及搭建

本文重点 RNN Cell(循环神经网络单元)是循环神经网络(RNN)的核心组成部分,用于处理序列数据中的每个时间步,并维护隐藏状态以捕获序列中的时间依赖关系。 RNN CELL的结构 RNN是一个循环结构,它可以看作是RNN CELL的循环,RNN CELL的结构如下图所示,RNN CELL不断进行…

【基于开源insightface的人脸检测,人脸识别初步测试】

简介 InsightFace是一个基于深度学习的开源人脸识别项目,由蚂蚁金服的深度学习团队开发。该项目提供了人脸检测、人脸特征提取、人脸识别等功能,支持多种操作系统和深度学习框架。本文将详细介绍如何在Ubuntu系统上安装和实战InsightFace项目。 目前github有非常多的人脸识…

进程(完)

今天我们就补充一个小的知识点,查看进程树命令,来结束我们对linux进程的学习,那么话不多说,来看. 查看进程树 pstree 基本语法: pstree [选项] 优点:可以更加直观的来查看进程信息 常用选项: -p:显示进程的pid -u&#xff…

【控制学】控制学分类

【控制学】控制学分类 文章目录 [TOC](文章目录) 前言一、工程控制论1. 经典控制理论2. 现代控制理论 二、生物控制论三、经济控制论总结 前言 控制学是物理、数学与工程的桥梁 提示:以下是本篇文章正文内容,下面案例可供参考 一、工程控制论 1. 经典…

软考中级-软件设计师 2022年上半年下午题真题解析:通关秘籍+避坑指南

📚 目录(快速跳转) 大题(下午题)(每题15分,共75分)一、结构化分析与设计🍔 试题一:外卖订餐系统 二、数据库应用分析与设计🚗 试题二:…

波束形成(BF)从算法仿真到工程源码实现-第十节-非线性波束形成

一、概述 本节我们基于webrtc的非线性波束形成进行代码仿真,并对仿真结果进行展示和分析总结。更多资料和代码可以进入https://t.zsxq.com/qgmoN ,同时欢迎大家提出宝贵的建议,以共同探讨学习。 二、仿真代码 2.1 常量参数 % *author : a…

《忘尘谷》音阶与调性解析

一、音高与音名的对应关系 根据搜索结果及音乐理论,结合《忘尘谷》的曲谱信息,其音阶与调性分析如下: 调性判定 原曲调性为 D调(原曲标注为D调),但曲谱编配时采用 C调指法,通过变调夹夹2品&…

App测试小工具

前言 最近app测试比较多,每次都得手动输入日志tag,手动安装,测完又去卸载,太麻烦。就搞了小工具使用。 效果预览 每次测试完成,点击退出本次测试,就直接卸载了,usb插下一个手机又可以继续测了…

数智读书笔记系列029 《代数大脑:揭秘智能背后的逻辑》

《代数大脑:揭秘智能背后的逻辑》书籍简介 作者简介 加里F. 马库斯(Gary F. Marcus)是纽约大学心理学荣休教授、人工智能企业家,曾创立Geometric Intelligence(后被Uber收购)和Robust.AI公司。他在神经科学、语言学和人工智能领域发表了大量论文,并著有《重启AI》等多部…

Apache Kafka UI :一款功能丰富且美观的 Kafka 开源管理平台!!

Apache Kafka UI 是一个免费的开源 Web UI,用于监控和管理 Apache Kafka 集群,可方便地查看 Kafka Brokers、Topics、消息、Consumer 等情况,支持多集群管理、性能监控、访问控制等功能。 1 特征 多集群管理: 在一个地方监控和管理…

临床协调简历模板

模板信息 简历范文名称:临床协调简历模板,所属行业:其他 | 职位,模板编号:C1S3WO 专业的个人简历模板,逻辑清晰,排版简洁美观,让你的个人简历显得更专业,找到好工作。希…

【第45节】windows程序的其他反调试手段上篇

目录 引言 一、通过窗口类名和窗口名判断 二、检测调试器进程 三、父进程是否是Explorer 四、RDTSC/GetTickCount时间敏感程序段 五、StartupInfo结构的使用 六、使用BeingDebugged字段 七、 PEB.NtGlobalFlag,Heap.HeapFlags,Heap.ForceFlags 八、DebugPort:CheckRem…

Linux常见指令介绍上(入门级)

1. ls指令 功能:显示出当前目录下的所有子目录与文件。 PS:注意显示的是当前文件下的子目录与文件。 以下这些是可以和ls配套使用的一些选项 -a 列出目录下的所有文件,包括以 . 开头的隐含文件。 -d 将目录象文件一样显示,而不是显示其下…

【版本控制】git命令使用大全

大家好,我是jstart千语。今天来总结一下git的使用命令,上文会先将git命令都列出来,便于快速寻找,然后还会对部分常用命令图文讲解,适合新手,让你快速地理解。最后还会总结在idea中使用git。如果有缺失的&am…

手阳明大肠经之合谷穴

个人主页:云纳星辰怀自在 座右铭:“所谓坚持,就是觉得还有希望!” 又名:1.《针灸甲乙经》:虎口。 所属经络:手阳明大肠经 定位 在手背,第1、2掌骨间,当第2掌骨桡侧的中点…

【VUE3】练习项目——大事件后台管理

目录 0 前言 1 准备工作 1.1 安装pnpm 1.2 创建vue项目 1.3 Eslint & Prettier的配置 1.4 husky 提交代码检查 1.5 目录调整 1.6 VueRouter4 1.6.1 基础配置 1.6.2 路由跳转 1.7 引入 Element Plus 组件库 1.8 Pinia 1.8.1 优化 1.9 封装请求工具 1.9.1 安…

万字长篇————C语言指针学习汇总

经过一段时间的学习,我们已经接触到了C语言的很多知识了。不过目前我们接下来我们要接触C语言中一个最大的“门槛”:指针。 什么是指针? 在介绍指针之前,我们首先要明白变量与地址之间的关系。 举一个生活中的案例:一…