游戏引擎学习第193天
仓库:https://gitee.com/mrxiao_com/2d_game_4
回顾
我们昨天做了一些非常有趣的实验。在实验中,我们的目标是实现一个能够在运行时改变的编译时常量的概念。最开始,这个想法纯粹是出于一时的兴趣,觉得这应该是个很有意思的尝试。于是我们进行了实验,看看是否能够做到这一点,结果出乎意料地非常顺利,几乎没有遇到什么困难。
这次实验的成功让我们产生了新的兴趣,觉得应该继续在这个方向上探索。我们决定继续沿着这条路走下去,看看它能带我们去哪里。整体来说,这个过程让我们意识到,很多看似复杂的想法其实在技术上是可以很容易实现的,甚至能带来新的思路和灵感。
我们现在计划进一步开发这个思路,尝试更多的可能性,看看它能为我们带来哪些新颖的解决方案和技术进步。
今天的计划
目前的目标是尝试将现有的调试代码系统转化为一个更通用的系统。这个系统的设计目的是能够轻松地在运行时开启或关闭所有的调试代码,而不需要在游戏编译时将这些代码包含进去,也不需要因此带来任何额外的性能开销。此前从未尝试过这种做法,只是认为它应该是可行的,因此进行了尝试,结果效果不错。接下来,计划进一步探索是否能够将这个系统扩展得更为完善。
之前回顾
昨天所做的工作非常有趣。我们实现了一种方式,可以通过用户界面的操作来重新组合所有内容。具体来说,这个操作会触发游戏重新编译,并使用不同的宏定义,这些宏定义会完全改变游戏的代码。在这种情况下,它控制了调试相机是否开启的切换功能。也就是说,通过这个操作,可以轻松地开关调试相机,而不需要手动更改代码,整个过程变得非常灵活和方便。
我们将扩展调试系统,以便更轻松地编译进出调试功能
现在我们需要做的是,找到一种方法,能够在各种地方轻松地实现这种动态切换的功能。我们已经建立了可以进行更改的基础设施,接下来要思考的是,如何能以最小的成本将这种功能扩展到代码的各个地方。
首先,我们认为最简单的方式就是直接尝试去做。我们可以查找代码中那些需要调试的地方,尤其是那些需要开关切换的地方,然后思考如何让这些地方更容易被更改为可切换的功能。通过这样的方法,我们不仅能够实现动态切换,还能提高效率。
同时,我们也希望能够改进和整理界面。当前的界面比较简陋,只有一个测试用的单选菜单,里面文字重叠,看起来很不美观,也无法实现我们真正需要的功能。因此,在进行这些更改时,界面的改善也应该成为一个重要目标。我们希望通过这次更新,能让界面更加简洁、清晰和实用。
当我们整理出一系列真正需要设置或切换的功能时,这将是一个很好的时机,去重新设计和调整界面的外观和交互方式。最终,我们希望能通过这种方式,实现既能满足需求,又能提供更好用户体验的界面。
可选编译地面块轮廓
我们现在的目标是进入代码,看看如何在现有的结构中实现这一功能。首先,我们已经有一些代码可以进行类似的操作,例如我们已经有了用于显示地面瓦片边界的代码。这是一个很好的例子,说明了我们可能希望能够动态开启或关闭的功能。
根据目前的代码示例,我们可以借鉴现有的做法。比如,在“game_config.h”这个文件中,我们可以新增一个选项,比如“DEBUGUI_GroundChunkOutlines”之类的东西。然后,我们将相关代码放到这个选项中。这样,我们就可以利用相同的方式轻松地切换这个功能的开关。
接下来,我计划继续以类似的方式处理其他部分的代码。比如,我会查找类似的地方,看看是否能发现更多类似的功能需要切换。对于一些我们认为不重要的代码,我可能会忽略掉,而对于重要的部分,我们就根据之前的方法进行相应的调整,确保可以方便地打开或关闭这些功能。
可选编译粒子喷泉
这是另一个例子,我们之前有一个粒子喷泉的功能。这个粒子喷泉在代码中运行着,但我们不清楚它究竟在做什么,或者为什么它会发生、或者它是否没有按预期发生。总之,这也是我们可能希望能够动态开启或关闭的一个功能。
现在有个问题,我们似乎没有看到这个粒子喷泉的效果,我不确定是否因为某种原因我们把它关闭了。接下来,我们需要进一步确认这个粒子喷泉的状态,看看它是否被禁用了,或者是否存在其他配置导致它没有正常显示。
为什么粒子系统不起作用?
我们发现粒子喷泉没有正常渲染,似乎有一些问题。首先,粒子确实在生成和创建过程中没有问题,看起来我们已经通过粒子生成索引来创建了它们。然而,问题在于我们似乎从来没有从粒子中获取到位图,导致这些粒子无法显示。
接下来,我们检查了粒子系统是否正常运行。通过查看代码,发现粒子确实在创建,但它们没有正确显示。我们推测可能是我们在调用位图推送(push bitmap)时出现了问题,这个调用没有按预期工作。可能的原因之一是相关的字体或其他资源缺失,导致粒子无法渲染。
具体来说,粒子的效果是生成了,但是我们无法看到它们的渲染效果,可能是因为位图的推送过程出了问题。也有可能是字体资源或某些设置没有正确加载,导致粒子无法正确显示。
喷泉依赖于过时的字体代码
原来是这个问题,实际上我们需要加载一个特定的字体位图,但是目前我们并没有做到这一点。现在的代码中并没有正确地加载该位图,这导致了粒子效果无法正常显示。
game.cpp: 回到喷泉α
原来问题就出在这里,解决方法就是回到之前的做法,回到“头部喷泉”的实现。这样一来,问题就能得到解决。现在喷泉效果已经恢复正常,粒子效果也能够显示了。
接下来,可以继续按照原计划进行其他操作,不断完善并展示功能。其实,这也启发了我们更多的思路,说明了一些有趣的事情。这些操作让我们更清楚地了解了如何处理类似的情况,并在过程中发现了一些新的有趣点。
游戏覆盖了我们对game config文件的更改。让我们防止这种情况再次发生
问题出在系统会重写某个文件,这样就可能会覆盖我们已经添加的内容。因此,我们需要确保每次修改文件时,都能尊重已经添加的内容,否则就会发生覆盖的情况。
为了避免这种情况,我们需要在修改文件时格外小心,确保不会出现“走偏”或覆盖已有内容的情况。虽然有一些方法可以避免这种问题,甚至可能不需要修改该文件,但我还是决定按照预定的步骤来操作,这样能更清楚地看到整个过程,避免跳到结论。毕竟,我并不确定最正确的解决方法是什么,所以我只是猜测并继续操作,看能否从中找到有效的方案。
在这个过程中,我会进行一些测试,比如粒子测试等,以确保一切能够正常进行。
可选编译粒子网格
在进行调试时,我添加了一个调试选项,用于查看粒子网格。这样就可以清楚地看到粒子效果的状态。接着,我继续检查其他的功能,看看是否还有其他需要处理的部分,确保所有内容都能正常运行,并解决可能出现的问题。
可选编译房间轮廓
我们有很多的调试代码,比如矩形轮廓和空间边界的代码。可以看到,这里有大量的代码,很多调试功能其实已经被关闭了。通过仔细查看,会发现有许多调试代码。大部分这些调试代码之前只有在特定的条件下才能访问,比如通过特定的“if zero”判断。这些代码很容易被遗忘,但它们实际上对我们寻找 bug 或者进行其他操作是非常有用的。
修复过时的DrawRectangle调用
我不确定这段代码现在是否还能正常工作。很可能已经不行了,但具体情况还不清楚。我们来看一下这段代码。首先,绘制矩形的函数似乎不接受四个参数,我不确定它究竟接受多少个参数。可能是这个问题导致代码无法正常工作。
在仔细检查之后,发现我们没有一个函数是直接传递标准矩形的。我们有一些涉及裁剪(clipped)的代码,使用了不同的方式,比如传递蓝色或其他颜色。我们曾经尝试过偶数和奇数处理,但实际上从来没有真的在代码中实现过这些功能。对于超线程的处理,也没有做过明确的实现,可能这些部分已经不再需要了。
另外,我们可能需要移除那些关于偶数和奇数处理的部分。虽然这些部分的存在是为了某些特定的功能,但目前来看并没有实际使用过,可能可以清理掉。
至于矩形裁剪的部分,我们可能应该直接传递裁剪的矩形信息,比如最小值和最大值来确定矩形的范围。看起来这种方法是可以正常工作的,但需要确认代码是否还能运行。代码的运行速度非常慢,可能是因为绘制的位置不对。这个问题可能与我们没有更新投影代码有关,投影代码负责调整坐标系统,确保正确的显示。
所以,我打算暂时关闭这个投影的部分,然后回到光照相关的代码,解决这个问题。接下来,我会进行一些调试,确保一切能正常进行。
可选编译地面块棋盘图案
这一部分的代码是用来让我们能够看到交替的区块,而不会在它们之间绘制额外的分隔线。实际上,它的作用是创建一个棋盘格的模式,这样可以帮助我们更直观地观察不同的区域。
如果我们希望将这个功能集成到配置文件中,我们可以定义一个调试选项,例如 DEBUGUI_GroundChunkCheckerboards
,然后用它来控制棋盘格的显示。这样一来,我们就可以清楚地看到棋盘格模式的效果,这对于调试来说可能会很有帮助。
接着,我们回到裁剪网格的部分,继续检查代码的其他部分。这里还有一部分代码是用于某种行处理(row generation),但目前看来这部分内容并不是我们关心的,因此暂时忽略它,专注于我们需要的功能。
可选编译地面块在DLL重载时重置
这部分代码的调整是完全合理的,事实上,我们之前移除它可能是因为当时认为它的执行速度太慢。但现在的性能已经足够快,因此应该可以重新启用这个功能。
在重新加载时,我们需要确保 make config
也被正确保存。为了暂时避免问题,我决定让游戏的调试代码不再读取 game_config.h
,这样可以更方便地进行调整。
目前来看,重新启用这个功能并不会带来问题,比如在地块加载后,数据能够正常返回。因此,我暂时决定让它保持开启状态。如果以后发现需要额外的控制,可以再添加一个调试开关。不过,考虑到现在的目标是尽可能增加调试功能,我们可以直接在调试界面中加入一个选项,比如 DEBUGGUI_RecomputeGroundChunkOnEXEChange
,用于控制地面声音的重新计算。
接下来,我们继续检查其他部分,回到图形渲染的部分,看看是否还有 #if 0
之类的未启用代码需要调整。
可选编译奇怪的渲染器缓冲区大小
这部分内容主要涉及渲染错误中的缓冲区大小问题。起初,我们认为缓冲区大小是平台层的一部分,无法直接更新。但经过检查后,发现它实际上可以被覆盖,因此可以在调试界面中添加一个选项,例如 DEBUGUI_TestWeirdRrawBufferSize
,用于测试不同的缓冲区大小对渲染的影响。
除此之外,我们还发现了一个关于 “Familiar”(跟随主角的辅助角色) 的功能,它本应跟随主角移动,但目前被关闭了,不清楚具体原因。可能是之前出于某种考虑禁用了它,但现在我们可以重新启用并测试它的行为是否符合预期。
在此过程中,我们主要进行了以下调整:
- 允许覆盖渲染缓冲区大小,并添加调试开关
DEBUGUI_TestWeirdRrawBufferSize
。 - 重新启用 “Familiar” 的跟随功能,并检查其行为是否正常。
接下来,我们将继续检查 #if 0
相关的调试代码,看看是否还有其他功能可以恢复或优化。
可选编译使熟悉的角色跟随英雄的行为
在调试 UI
相关代码时,我们发现了一些未启用或未使用的功能。其中一个是 DEBUGUI_FamiliarFollowsHero
,这是用于让某个角色或对象跟随主角的功能,但目前并未启用,可能是因为它已失效或被移除。
此外,在性能分析器(profiler
)中,还有一部分代码已经不再使用,这些代码并未被调用,因此可以忽略。另一个被发现的功能是 chart_boundary
,这个功能旨在显示某种边界,但目前尚未真正实现,因此在当前阶段它并无实际作用。
我们还注意到 marks
相关代码,可能是用于某种标记或调试信息的显示。这部分功能需要单独处理,可能涉及 UI 显示或者某种逻辑调整。因此,在后续优化时,需要决定是否重新启用、修改或彻底移除这些未使用的功能,以保持代码整洁并提高可维护性。
可选编译双线性光照采样
在调试 UI
过程中,我们检查了 lighting_samples
相关的代码,这部分代码用于在地图中查看光照采样的位置,这个功能很可能是需要的,因此应该保留并启用。
此外,我们还发现了 ssc_clamping
相关的代码,检查后确认这部分代码已不再需要,因此可以忽略。我们还发现了一些函数,它们似乎已经不再被使用,比如 ben_developed_at_foot
及其他相关函数。这些代码与当前的需求无关,因此可以直接移除或忽略。
总的来说,我们正在清理代码库,确保只保留必要的调试 UI 选项,并移除那些已经过时或不再使用的功能,以提高代码的可读性和维护性。
可选编译基于房间的相机运动
我们检查了 摄像机跟随行为 的相关代码,但不确定该路径是否仍然有效,因此需要进一步确认其实际效果。随后,我们查找了 基于规则的摄像机(rule-based camera) 代码,以确定它是否仍然在使用或者是否需要调整。
当前的工作重点是清理和优化代码,确保仅保留必要的功能,并确认所有仍在使用的系统是否正常运行,以防止遗留代码影响整体性能或引发不必要的错误。
基于房间的相机坏了。让我们修复它
我们正在检查摄像机跟随行为的代码,发现之前没有使用它的原因可能是因为缺少必要的信息,比如当前摄像机跟随的实体。不过,我们确实有一个索引可以确定当前的实体,因此理论上应该能够获取该实体的相关数据,比如 px
和 dx
的位置参数。
然而,当前的摄像机系统并没有 abs_tile_x
这样的属性,这可能会带来一定的问题。由于当前系统已经不再使用**瓦片(tile)**的概念,因此我们需要调整摄像机计算方式,使其不依赖于瓦片单位。我们暂时假设房间大小为 9米 x 5米,并在代码中测试这一数值是否合理。
接下来,我们尝试调整摄像机的位置偏移。我们回顾了代码结构,发现世界数据结构提供了一些方法,比如 offset_by
或 MapIntoChunkSpace
,可以用于在世界坐标中进行偏移计算。因此,我们使用 MapIntoChunkSpace
方法来更新摄像机位置,确保新的摄像机位置能够正确计算。
然后,我们在 update_camera
函数中实现了这一步调整,并确保 NewCameraP
通过 MapIntoChunkSpace
计算得到。世界数据 (world
) 可以从 game_state
访问,而偏移量 (offset
) 则由房间宽度来决定。理论上,这样的计算应该可以正确更新摄像机位置。
我们在测试过程中发现摄像机并没有正确移动,经过检查后,发现是因为计算结果没有正确存储,导致摄像机位置没有被更新。修正代码后,我们再次尝试,确保摄像机能够正确响应房间变化。
现在它工作了
我们成功实现了基于房间的摄像机移动,而且**跟随实体(familiar)**的功能也恢复了正常。这意味着摄像机现在能够根据房间的位置进行调整,并且跟随系统也能够正确响应。
接下来,我们继续检查代码,确保所有相关部分都被正确处理。我们再次使用搜索工具来查找未检查的部分,并逐一确认它们的作用。
- **关于“投射方向”和“绘制位图”**的代码,我们不需要关注,因为它们与当前问题无关。
- “投射碰撞检测(speculative collide)” 代码未完成,因此我们暂时不会修改它。
asset_builder
相关的代码 只是之前用于演示如何使用外部库的代码,并未真正应用于当前项目,因此无需处理。
总的来说,我们已经筛选并确认了所有相关代码,确保没有遗漏重要部分。
目前我们已经有足够的项目
我们已经清理并整理了所有的**调试(debug)**相关代码,并确保它们能够被轻松找到。虽然可能还有一些零散的调试代码没有明确标记,比如缺少 #if 0
这样的标注,但目前这个列表已经相当全面。
为了便于管理,我们给所有的调试功能都添加了**DEBUGUI_
**前缀,这样在需要查找时,可以快速定位它们。例如,我们可以直接搜索 DEBUGUI_
,立刻看到它们在所有 Java 类中的位置,特别是在 game_hero
这类核心文件中。
这样做的主要目的是:
- 提高可维护性,让所有调试功能集中管理,避免混乱。
- 快速定位调试代码,当需要调整或删除时,能够立刻找到所有相关代码。
- 确保调试功能的可控性,可以随时启用或禁用,不会影响正式版本的代码。
现在,我们已经对所有的 DEBUGUI_
代码做了一轮检查,并确保它们的存在是有意义的。如果以后需要调整调试功能,可以很方便地修改或扩展。
#define DEBUGUI_UseDebugCamera 1 // bool32
#define DEBUGUI_GroundChunkOutlines 1 // bool32
#define DEBUGUI_ParticleTest 1 // bool32
#define DEBUGUI_ParticleGrid 1 // bool32
#define DEBUGUI_UseSpacesOutlines 1 // bool32
#define DEBUGUI_GroundChunkCheckerboards 1 // bool32
#define DEBUGGUI_RecomputeGroundChunkOnEXEChange 1 // bool32
#define DEBUGUI_TestWeirdRrawBufferSize 1 // bool32
#define DEBUGUI_FamiliarFollowsHero 1 // bool32
#define DEBUGUI_ShowLightingSamples 1 // bool32
#define DEBUGUI_UseRoomBaseCamera 1 // bool32
我们希望知道编译开关的值并将其写入game_config.h
有几个事情可以做。首先,显而易见的是,我们需要了解所有这些值,以便能够在用户界面中展示它们。其次,我们还需要能够将这些值写入文件。
作为第一步,我们进入到 game debug 进行处理。我们可以设想列出所有这些值,并通过我们已经做过的类似方式,很容易将它们展示出来,例如使用单选菜单(radio menu)。
接下来,我们需要保存这些值。为了避免在代码出现错误时丢失它们,我们可以将这些值先保存到一个注释中。然后,写入这些值时,实际的问题是,我们之前只写了一个值,但现在我们需要把所有这些值都写入文件。
这意味着,我们不再仅仅处理一个单一的值,而是需要确保把所有相关的值都按需要的方式保存和输出。
debug_variable结构体将保存开关的名称、值和类型
为了使所有刚才列出的调试变量能够正常工作,首先需要做一个非常简单的步骤,即创建一个列表,列出所有调试变量。
这个列表中的每个条目应该包含几个关键信息。首先,列出每个变量的名称,这样我们可以在后续过程中将其写入文件。其次,需要列出变量的值,以便能够查看当前变量的状态。
目前,我们只需要这些信息,因为这些变量都是基本类型(如整数、浮动值等)。但将来,可能还需要更多信息,例如变量的类型。这样一来,就可以更方便地处理不同类型的变量,如整数、浮动值等。
使用DEBUG_VARIABLE_LISTING宏定义它们
为了方便定义所有调试变量,可以使用宏来简化这个过程。可以定义一个类似于“#define”这样的宏,它的作用是创建一个调试变量列表,并为每个调试变量指定名称和对应的值。
通过使用这个宏,能够快速地将调试变量添加到列表中。例如,可以创建一个宏 DEBUG_VARIABLE_LISTING
,在每次调用时,只需要传递变量的名称,就可以自动处理该变量的名称和对应值。这个宏会将变量名称转化为字符串,并且能够获取到变量的实际值。
实现这个过程的关键是通过宏将调试变量名称和其值硬编码进去,这样每次变量的值变化时,可以直接获取并更新对应的输出。只需将这些调试变量转换成对应格式的列表,然后利用宏快速生成需要的代码。
此外,可以通过搜索所有以 #define
开头的部分,将其修改为调用宏的方式,只需要处理好宏后面的内容即可,从而得到一个干净整齐的调试变量列表,准备好进一步使用。
将变量写入配置文件
现在,如果我们想要将调试变量写入文件,可以通过列表的方式来实现。我们可以想象一个循环,遍历调试变量列表,并将每个变量的名称和值输出到文件中。
首先,在循环中,定义一个索引变量,然后通过该索引从调试变量列表中获取每个变量。每个变量的名称和值都已经存储在列表中,我们可以直接使用它们,而不需要猜测。
具体实现时,首先遍历整个列表,取出每个调试变量的名称和对应的值。然后,我们可以将变量的值写入文件。在输出时,如果需要控制输出的格式,可以使用 size_t
来确定变量的长度,调整输出内容。
当完成变量写入后,可以调整输出的大小,确保写入文件的内容完整。如果需要计算剩余空间,可以通过减去已写入的大小来确定还剩多少空间可以写入。
在操作过程中,要确保正确处理变量的大小并调整输出缓冲区的位置。这意味着在每次写入后,更新写入的位置,确保输出不超过预定的缓冲区大小。
最后,在进行调试时,确保代码逻辑正确,比如计算剩余空间的公式和更新文件写入的位置。如果遇到错误信息,可以根据提示进行相应的修正。
_snprintf_s需要什么参数?
在这个过程中,出现了关于函数参数类型转换的问题,尤其是在处理第三个参数时。看起来第三个参数应该是一个字符串,但出现了类型转换错误,提示无法将一个常量字符指针转换为 size_t
类型。问题的关键在于,printf
函数要求的是一个缓冲区指针和它的大小,而这里出现了类型不匹配的问题。
具体来说,代码中的 temp
是缓冲区的基础指针,at
则是当前写入位置的指针。通过 temp
指针和 at
之间的差值,可以计算剩余空间的大小。但为什么有些地方需要将其转换为 size_t
类型,而有些地方不需要,实际上是因为在某些情况下,缓冲区和大小已经通过函数签名被明确地定义,而在其他地方,它可能是隐式处理的。
问题在于,某些地方可能期望 printf
函数接收的是 size_t
类型而不是字符指针。这是因为 printf
会要求输入的缓冲区大小为 size_t
类型,而不只是单纯的字符指针。这解释了为什么某些代码段中传入的是字符指针,而其他地方却要求类型转换。
为了确保函数正常工作,可以尝试将缓冲区大小明确地转换为 size_t
类型。这是因为 printf
可能需要明确的缓冲区大小,而不是默认的字符指针类型。
总结起来,问题的根本原因可能在于 printf
等库函数在处理缓冲区时,对参数类型的要求不同。虽然一开始没有问题,但当遇到不同类型的数据传递时,便会触发类型不匹配的错误。因此,解决这个问题的方法就是明确传递正确的参数类型,或者进行适当的类型转换。
步骤代码,构建配置文件内容
在这个过程中,首先初始化了一个缓冲区 temp
,并开始向其中写入数据。写入的第一个数据是关于“调试相机”的信息,这表明代码正确地写入了第一个变量。接着,在循环中继续写入其他变量,每次都正确地写入了预期的内容。
接下来,代码将继续循环,直到将所有变量写入缓冲区。完成写入后,程序检查输出结果,确保所有的变量都已经正确写入了数据。然后,它将这些数据保存到一个文件中。
最后,加载该文件时,检查文件的内容,确认它与当前写入的数据一致,没有发生任何变化。经过这一系列操作后,整个过程达到了预期的效果,数据成功地保存并格式正确。
用vs调试 直接打开可执行文件打开对应的代码调试就行
可以不用选择打断点的文件,直接设置函数断点
写入文件成功
现在我们已经能够正确地重写所有的配置变量,这意味着如果需要进行调试,我们也可以轻松地做到。与之前在代码中硬编码变量不同,现在我们可以更灵活地处理这些配置。通过这种方式,不再需要像以前那样手动在代码中添加项目,而是可以更加结构化和简洁地管理这些配置项。这样可以提高代码的可维护性,同时为后续的开发和调试提供更多的便利。
打印变量列表,而不是旧的菜单项
我们可以不再使用菜单项来处理这些变量,而是改用调试变量列表。具体来说,调试变量列表的计数将取代原本的菜单项。这意味着,菜单中的每一项将不再是硬编码的,而是通过从调试变量列表中提取每个变量的名称来动态生成。
这样做是合理的,因为我们将根据调试变量的数量来创建对应的菜单项。当我们右键点击时,应该能够看到大量的调试变量项,每个项都代表了一个调试变量。
这意味着,所有这些变量现在都可以直接从调试变量列表中获取,并且每当点击某个选项时,都会触发相应的操作。这样,通过这种动态生成菜单项的方法,管理和切换调试选项变得更加灵活和高效。
切换调试变量
我们的目标是让每次点击时,选中的选项能够真正被切换。这个实现其实非常简单。基本思路是,当我们查看当前选中的菜单项(hot menu index)时,只需要确保这个索引值小于调试变量列表的数量,表示这是一个有效的选项。
具体步骤是,当鼠标按钮被释放时,就可以知道这个菜单项已经被选中了。然后,我们只需要根据热菜单索引,访问调试变量列表中的对应项,并将该项的值进行切换(即切换它的布尔值)。
这样,调试变量的值就会被成功切换,且下一次重新写入时,会带着新的值。整体过程非常简单,完全是基础操作,并没有什么复杂的地方。
通过这种方式,径向菜单(radio menu)就会被正确连接起来,在理论上,它应该能够按照预期工作,能够在运行时切换这些调试选项。
测试。它有效
现在,通过点击调试使用的相机选项并重新编译,应该能恢复到正常的相机视角。如果切换到例如测试缓冲区大小或者其他特定的选项,也可以恢复到全屏模式。这意味着,现在可以通过直接切换这些选项来动态更改任何变量。
如果不再需要使用基于房间的相机,也可以直接切换掉它。每次切换都会触发重新编译,并且相应的设置会更新。这使得在开发过程中,能够灵活地调整和切换各种调试选项,非常方便且高效。
运行时排除调试代码的一些优点…
我们现在的实现方式相比于直接在程序中使用变量,虽然需要重新编译,但功能更加强大。因为我们可以插入非常昂贵的计算操作,并且可以随时启用或禁用它们,而不会影响性能,也不会引入可能影响程序执行效率的分支判断。同时,我们还能在编译时切换掉整个函数调用,几乎不会有额外的开销。
任何可能影响程序整体结构的部分,比如内联函数,都可以通过这种方式进行灵活调整。例如,我们可以动态地更改使用哪一个版本的内联函数,而这一切都不会产生额外的成本。即使在发布模式(Release Mode)下,程序仍然能够获得正确的性能表现,这无疑是非常令人惊喜的功能。
此外,我们可以随时关闭或启用这些特性。例如,现在粒子系统(可能是粒子喷泉)已经变得有些夸张,因此至少需要关闭网格显示(Grid),因为网格的存在会影响可视化效果。关闭网格后,一切都变得清晰可见,整个系统就可以顺利运行了。这无疑是一个显而易见的优化手段。
说起Release模式好像得重新改
写配置了为什么release没生效呢
打开cmd窗口看看
release模式为什么不去build game.dll
#ifdef NDEBUG //release
char CommandLine[] = “/c cmake --build .\…\out\build\x64-release”;
#else //debug
char CommandLine[] = “/c cmake --build .\…\out\build\x64-debug”;
#endif
加一个依赖防止win32_game 编译失败不去编译game.dll,这个依赖会先编译game.dll 再编译win32_game
…唯一的小问题是,添加一个新开关仍然需要太多步骤
我们面临一个小问题,虽然它很小,但还是有些困扰。具体来说,就是每次我们需要将某些东西与 UI 连接时,都需要经过一定的步骤。这种情况变得有些繁琐,尤其是当我们想要添加新的元素时。如果在游戏中出现类似的需求,举个例子,可能是需要停止绘制某些元素,像是停止绘制所有的“召唤物”之类的东西。
每次要实现这些,我们就得手动添加代码来进行设置。比方说,想要新增一个功能,可能就需要手动加上一段逻辑,去做某些判断和处理。这个过程虽然看起来不复杂,但由于每次都需要重复这些步骤,所以有点令人觉得麻烦。这也是我们想要考虑如何优化这个流程的原因。
我们希望在添加新变量后,列表能够自动升级,但单纯为此解析代码可能过于繁琐
我们希望能够简化调试过程,尤其是当我们需要调整某些 UI 设置时,比如禁用“召唤物”的绘制。理想情况下,我们只希望通过修改一个变量就能完成,而不必每次都进入代码手动添加调试变量的监听功能。虽然这个过程本身并不复杂,也没有造成太大的麻烦,但它还是有点繁琐。
如果要彻底解决这个问题,我们可能会考虑开发一个自动化工具,能够扫描文件并自动更新调试相关的配置,而不是每次手动进行修改。通过这种方式,所有的调试变量会自动更新,避免每次都重复操作。尽管这样做可以节省时间,但这也可能有点过头,感觉像是做了多余的工作。因此,这种自动化的做法虽然能提高效率,但可能还是有些过于复杂了。
让我们把变量列表保存在一个单独的文件中
我考虑到一个比较简便的解决方案,那就是将调试变量放在一个容易找到的位置,这样就不需要每次都在代码中手动添加调试监听。我可能会将这些变量移到一个专门的文件里,比如一个 debug_variables.h
文件,然后在主代码中引入这个文件。这样做不仅能保持代码的整洁,而且也很方便,任何时候需要添加新的调试变量时,只需更新这个文件就好。
这个方法感觉比较简单直观,也不会太麻烦。所以,我觉得这样做是可以接受的。接下来,我打算用几分钟时间处理一些小问题,尤其是一些与收入相关的问题,可能有些细节需要修复。
另外,我也知道接下来需要开始处理一些新的 UI 元素,尤其是要完成我们的无线电菜单和一些新的 UI 屏幕。虽然这些工作很重要,但我决定先集中精力修复当前的几个小问题,等有了更多时间再开始新的 UI 开发。
我们的径向菜单应该允许我们在某项活动激活后不再选择它
目前,在调试菜单中有两个让人烦恼的问题。第一个问题是没有办法避免某些选择,原因是没有类似于内环的概念,导致用户始终会触发选择操作。理想情况下,想要做的改进是,通过调整鼠标位置和菜单中心之间的距离来控制是否触发选择。
具体的做法是,我打算不再使用目前设置热菜单索引的结果,而是将其重置为一个新的变量。然后,我会根据鼠标的位置来判断,如果鼠标位置和菜单中心的距离的平方小于菜单的半径,那么就允许触发选择。如果鼠标位置超出了菜单的半径范围,就不触发选择操作。这样可以避免用户误触发菜单,特别是当鼠标还在菜单的有效区域内时。
换句话说,只有当鼠标靠近菜单中心并且距离在菜单半径范围内时,才会允许选择操作。这样做的目的是为了避免用户在菜单区域外无意中选择了某个选项。
根据值为菜单项着色
我打算首先实现之前提到的功能,并且希望能够指示某些项是否已经设置好了,这样会更加直观。为了实现这一点,可以做一个简单的调整,比如设置一个项目的颜色为灰色,表示它当前没有被激活或设置。
因为我们已经知道调试变量的所有信息,不仅知道它的名字,还知道它的值,所以不仅可以获取它的文本,还可以根据它的当前值来判断是否需要高亮显示。如果变量的值满足某些条件,就可以决定是否高亮显示它。这会帮助更好地可视化哪些选项已经设置,哪些没有设置。
当然,在实现之前,我需要先清理掉一些临时的代码示例,然后重新测试这个功能,确保它能够正常工作并且按预期显示。
测试。菜单在我们停留在中心时应该不再选择任何操作
现在可以看到,调试菜单的功能已经开始正常工作了。刚开始时,我发现设置的逻辑有点反了,应该是检查鼠标是否移动到了菜单半径之外,而不是判断鼠标是否处于菜单内。这个问题我已经修正过来了,现在可以确保只有当鼠标移出菜单半径时,才会触发选择。
现在,用户可以从菜单中选择不同的选项,并且可以看到哪些选项是开启的,哪些是关闭的。例如,如果不希望“Grand Chancery”计算功能运行,只需要将其关闭,这样它就不会再被计算。同样,如果不希望“召唤物”继续跟随,可以将“召唤物跟随”关闭,之后它就不会再跟随了。
现在一切都按预期工作,可以顺利地选择、调节设置,调试代码也变得更加方便,甚至可以缩放视角等操作。总的来说,功能都已正常运行,达到了预期效果。
编译过程有点慢,但我们可以跳过资产构建器的编译
唯一不太满意的地方是编译时间有点慢,尤其是每次编译后的等待时间比较长。为了加快编译速度,我们可以采取一些措施。比如,资产处理器(asset processor)并不需要每次都重新编译,因此可以考虑在构建过程中禁用它,这样可以稍微加快编译过程。
在构建的批处理文件(cmake file)中,我们可以关闭资产处理器,这样编译会更快一些。此外,我们还可以关闭一些其他功能,比如重新编译不必要的部分,这样也能缩短编译时间。不过,虽然这些方法可以加速编译,但它们并不能显著提高刷新时间。
关闭资产处理器可能是一个值得尝试的优化,虽然它可能并不会对编译时间的提升有很大的影响,但至少我们可以看看这样调整后,编译时间会有多少改善。
总体来说,虽然编译速度并没有达到理想的速度,但相比以前,已经有了明显的改善,并且现在的速度也还算可以接受,不算太慢。
去掉影响也不大
我不明白为什么一个单独的if语句在运行时会很昂贵,你能给个例子吗?
我们讨论了在运行时插入调试代码可能带来的性能开销。通过一个具体的例子来演示,最初游戏的渲染非常流畅,帧率表现良好。但是,当开始加入条件语句时,例如一个if
语句来进行调试变量的切换时,帧率明显下降。我们通过不同的方式插入了多个if
语句,用来模拟在运行时执行不同的操作,结果发现,尽管帧率下降,但并不像预期的那样严重。加入更多的条件判断并没有显著影响性能。
我们还进一步测试了将这些调试代码封装在不同的静态变量中,以便在运行时开启或关闭这些判断。测试表明,在这种情况下,性能影响依然不是特别显著,尽管会有一些微小的下降。我们尝试了在代码中插入更复杂的逻辑,例如使用更高代价的操作,但结果也并未引起显著的性能问题。
在讨论了调试代码对性能的影响后,测试表明,在发布模式下,性能比调试模式下更好,运行时的性能更为稳定。即使启用了条件判断,性能的下降也并没有达到一个明显的程度,因此并不需要过度担心。关键是要确保在进行性能测试时,测试方法需要更加精准和严格,避免因代码对齐等因素带来的误差。
最后,虽然加入调试代码可能会稍微影响性能,但它对于调试工作非常重要,尤其是在开发过程中,能够通过这些调试工具确保代码的正确性。在性能优化时,可以通过合理安排调试代码的插入和关闭,来平衡调试与性能之间的关系。
为什么在配置文件中添加“// b32”注释?
我们之前遇到的冲突问题是由于最初考虑到需要某个功能来处理无限运动(infinite motion),因此在文件中加入了一些必要的标记。但是后来决定不再需要这个功能,因此可以去掉相关的b32
。如果以后发现这个功能确实重要,仍然可以重新添加一个工厂方法来处理。所以现在,去掉这些不再需要的部分是完全可以接受的,暂时没有问题。
你能在循环时切换调试选项吗?
可以在循环过程中切换调试选项。为了实现这一点,需要确保在每次循环中输入的鼠标事件能够通过。虽然鼠标输入和其他输入是分开的,但我们需要确保在输入处理过程中,鼠标输入的相关信息能够正常传递。
具体来说,鼠标输入会在一个单独的处理过程中进行处理,但在之后的输入回放时,这些鼠标输入信息可能会被覆盖。所以,如果想在循环中动态地访问这些调试功能,就需要确保鼠标输入能够正确地传递,避免在输入回放时被忽略或覆盖。
将鼠标处理与记录输入分离
为了确保调试编辑在循环中不被记录,需要让鼠标输入在调试过程中直接通过,而不是在回放时被记录或覆盖。为了实现这一点,可以采用如下方式:
首先,需要确保在每次循环中,鼠标输入事件能够通过处理逻辑。这意味着需要创建一个新的输入事件结构,将鼠标按钮和其他输入信息传递到游戏中。在这个过程中,可以考虑使用类似 newinput->mousebuttons
的逻辑来处理输入数据。
然后,需要复制相关的输入数据结构,将这些鼠标事件进行更新。通过复制这些结构,确保鼠标输入在调试过程中实时生效,而不是在之后的输入回放中被记录或覆盖。
但是,在实际操作中,可能会遇到一些限制,导致复制这些输入数据时变得困难。例如,有些情况下不能直接复制某些数据结构,可能需要额外的操作或者对输入的处理方式进行调整。
最终,通过这种方式,可以确保在调试过程中,鼠标输入可以正常通过,允许动态编辑,而不会受到回放机制的干扰。
录制之后播放鼠标菜单可以用
准备在循环时操作调试UI
现在,理论上这种方式应该可以让鼠标输入顺利通过处理逻辑,从而在调试过程中允许鼠标事件实时生效。这样一来,输入事件就可以在调试时被正常处理,而不会被回放机制覆盖或干扰。这意味着调试编辑的过程可以顺利进行,而不会受到录制回放的影响。
增加DrawDebugMainMenu()中的调试菜单半径
计划是在调试菜单中调整一个更明显的颜色,比如粉色,并且增加半径为400,这样能够更清晰地展示菜单的大小和位置。此外,比较时需要使用平方的值来进行长度的比较,以确保它与菜单半径的平方值进行匹配。这部分的细节会留到明天再处理。
尝试在循环时使用调试UI
现在调试菜单的UI部分已经完成。当开始循环时,调试菜单的UI也会显示在上方,可以进行交互。可以改变一些设置,例如更改地面棋盘的样式,调整其他元素。比如,可以让小伙伴跟随角色移动,也可以改变其他视觉效果。这些功能都能正常工作,能够实现预期的效果。
你应该在某个时候为UI添加一个优化开关
可以考虑在UI中添加一个优化开关,这是一个非常好的建议。为了实现这个功能,可以采用#pragma
指令来开关优化,这样可以在需要调试时关闭某些代码部分的优化。当调试时,可以方便地关闭特定部分的优化,而不影响其他部分的性能。这种方式让调试更加灵活,可以帮助更好地排查问题。
难道-O2不会把这些死分支优化掉吗?
为了优化死代码的去除,通常需要确保编译器能够识别出哪些代码是死的。然而,静态变量的存在可能会导致编译器无法正确识别这些分支是否为死代码,因为这些变量可能在其他地方被修改。为了解决这个问题,可以将这些变量声明为volatile
,这样编译器就会知道这些变量的值可能会在运行时改变,从而避免优化掉可能会被使用的代码。
你能有一个选项,允许你重新编译或简单地切换“if”吗?似乎大多数时候你会使用常规的“if”,所以变化是即时的,但在极端情况下你可以轻松地使用重新编译选项
为了实现一个在编译时可以选择切换优化或调试模式的选项,需要解决一个问题:如何在不重新编译的情况下切换这些选项。通常的做法是通过常规的if
语句,确保在大多数情况下切换是即时的,但在极端情况下需要重新编译来实现切换。
然而,问题在于,如果想要在运行时切换这些选项,可能会遇到宏和条件编译的问题。因为在C语言中,#if
不能包含在另一个宏内部,所以需要想办法在代码中实现这一点。为了做到这一点,可能需要使用一些复杂的宏组合,这种方法虽然可行,但编写起来会相对复杂,也可能不太优雅。如果C语言的宏处理器能够更强大一些,或许可以更方便地实现这一功能,但由于宏处理器的限制,这种方法可能不太理想。
相关文章:
游戏引擎学习第193天
仓库:https://gitee.com/mrxiao_com/2d_game_4 回顾 我们昨天做了一些非常有趣的实验。在实验中,我们的目标是实现一个能够在运行时改变的编译时常量的概念。最开始,这个想法纯粹是出于一时的兴趣,觉得这应该是个很有意思的尝试。于是我们进…...
数据结构每日一题day7(顺序表)★★★★★
题目描述:从顺序表中删除其值在给定值s与t之间(包含s和 t,要求 s<t)的所有元素,若s或t不合理或顺序表为空,则返回 false,若执行成功则返回 true。 算法思想: 输入检查:若顺序表为空、指针为…...
ACM模式常用方法总结(Java篇)
文章目录 一、ACM输入输出模式二、重要语法2.1、导包2.2、读取数据2.3、判断是否有下一个数据2.4、输出2.5、关闭scanner2.6、易踩坑点 一、ACM输入输出模式 在力扣上编写代码时使用的是核心代码模式,如果在面试中遇到ACM模式就会比较迷茫?ACM模式要求你…...
SpringCould微服务架构之Docker(6)
容器的基本命令: 1. docker exec :进入容器执行命令 2. docker logs: -f 持续查看容器的运行日志 3. docker ps:查看所有运行的容器和状态 案例:创建运行一个容Nginx容器 docker run--name myNginx -p 80:80 -d nginx 命…...
脑疾病分类的疑惑【7】一般FMRI数据都存储为什么格式?能不能给我用数据简单的描述一下FMRI是如何存储的?
fMRI 数据通常以 NIfTI(Neuroimaging Informatics Technology Initiative) 格式存储,这是一种专为神经影像设计的开放标准格式。以下是简化说明和示例: 1. 常见fMRI数据格式 格式扩展名特点NIfTI.nii 或 .nii.gz最常用࿰…...
DOM 加载函数
DOM 加载函数 在Web开发中,DOM(文档对象模型)加载函数是一个核心概念。它指的是在页面加载过程中,浏览器如何处理和解析HTML文档,并创建相应的DOM树。本文将深入探讨DOM加载函数的作用、原理及其在Web开发中的应用。 引言 随着互联网的飞速发展,Web技术日新月异。DOM作…...
[特殊字符]《Curve DAO 系统学习目录》
本教程旨在系统学习 Curve DAO 项目的整体架构、核心机制、合约设计、治理逻辑与代币经济等内容,帮助开发者全面理解其设计理念及运作方式。 目录总览: 1. Curve 项目概览 • 1.1 Curve 是什么?主要解决什么问题? • 1.2 与其他…...
webpack和vite之间的区别
Webpack 和 Vite 都是现代前端开发中非常流行的构建工具,但它们的设计理念、工作原理以及适用场景都有所不同。以下是两者之间详细的对比说明: 1. 构建机制与速度 Webpack: Webpack 是一个通用的模块打包工具,它通过分析项目中的依赖关系图来…...
《Operating System Concepts》阅读笔记:p495-p511
《Operating System Concepts》学习第 44 天,p495-p511 总结,总计 17 页。 一、技术总结 1.cache (1)定义 A cache is a region of fast memory that holds copies of data. (2)cache 和 buffer 的区别 The difference between a buffer and a cac…...
Java进阶——位运算
位运算直接操作二进制位,在处理底层数据、加密算法、图像处理等领域具有高效性能和效率。本文将深入探讨Java中的位运算。 本文目录 一、位运算简介1. 与运算2. 或运算异或运算取反运算左移运算右移运算无符号右移运算 二、位运算的实际应用1. 权限管理2. 交换两个变…...
特征增强金字塔FPN
特征增强金字塔FPN 利用 ConvNet 特征层次结构的金字塔形状,构建一个在所有尺度上都具有强大语义的特征金字塔 总结:特征金字塔是检测不同尺度物体的识别系统中的基本组成部分。 1.利用深度卷积网络固有的多尺度、金字塔层次结构,以边际额…...
Java课程设计(双人对战游戏)持续更新......
少废话,当然借助了ai,就这么个实力,后续会逐渐完善...... 考虑添加以下功能: 选将,选图,技能,天赋,道具,防反,反重力,物理反弹,击落…...
c++第三课(基础c)
1.前文 2.break 3.continue 4.return 0 1.前文 上次写文章到现在,有足足这么多天(我也不知道,自己去数吧) 开始吧 2.break break是结束循环的意思 举个栗子 #include<bits/stdc.h> using namespace std; int main(…...
Windows 图形显示驱动开发-WDDM 2.4功能-GPU 半虚拟化(十一)
注册表设置 GPU虚拟化标志 GpuVirtualizationFlags 注册表项用于设置半虚拟化 GPU 的行为。 密钥位于: DWORD HKLM\System\CurrentControlSet\Control\GraphicsDrivers\GpuVirtualizationFlags 定义了以下位: 位描述0x1 为所有硬件适配器强制设置…...
Android在KSP中简单使用Room
Android在KSP中简单使用Room 最近下载了最新版Studio,好多依赖和配置都需要升级,之前使用过room封装数据库工具类,最近在整理ksp相关,于是把room也升级了,简单记录一下升级过程,直接上代码。 1.添加KSP依…...
Maven 构建配置文件详解
Maven 构建配置文件详解 引言 Maven 是一个强大的项目管理和构建自动化工具,广泛应用于 Java 开发领域。在 Maven 项目中,配置文件扮演着至关重要的角色。本文将详细介绍 Maven 构建配置文件的相关知识,包括配置文件的作用、结构、配置方法等,帮助读者更好地理解和应用 M…...
精确截图工具:基于 Tkinter 和 PyAutoGUI 的实现
在日常工作中,截图是一个非常常见的需求。虽然 Windows 自带截图工具,但有时我们需要更精确的截图方式,比如选取特定区域、快速保存截图并进行预览。本篇博客将介绍一个使用 Python 结合 Tkinter 和 PyAutoGUI 开发的精确截图工具。 C:\pytho…...
Linux练习——有关硬盘、联网、软件包的管理
1、将你的虚拟机的网卡模式设置为nat模式,给虚拟机网卡配置三个主机位分别为100、200、168的ip地址 #使用nmtui打开文本图形界面配置网络 [rootrhcsa0306 ~]# nmtui #使用命令激活名为 ens160 的 NetworkManager 网络连接 [rootrhcsa0306 ~]# nmcli c up ens160 #通…...
【C++】 —— 笔试刷题day_12
一、删除公共字符 题目解析 题目给了两个字符串(其中包含空格),让我们在第一个字符串中删除第二个字符串中的字符。 我们要输出删除后的字符串。 算法思路 这道题,如果直接按照题目中的要求去第一个字符串中删除字符,…...
家乡旅游景点小程序(源码+部署教程)
运行环境 家乡旅游景点小程序运行环境如下: • 前端:小程序 • 后端:无 • IDE工具:微信开发者工具 • 技术栈:小程序 注意:此项目为纯静态项目,无后端 主要功能 家乡旅游景点微信小程序主…...
SQL Server:当在删除数据库时因为存在触发器而无法删除
当在删除数据库时因为存在触发器而无法删除,你可以通过禁用触发器来解决这个问题。下面为你介绍在 SQL Server 里禁用和启用触发器的方法。 禁用数据库中所有表的触发器 你可以使用系统视图 sys.triggers 来查询数据库里所有的触发器,然后生成禁用这些…...
多人协同进行qt应用程序开发应该注意什么2?
在多人协同开发Qt应用程序时,为了确保高效协作、代码一致性和项目可维护性,需要特别注意以下关键点: 1. 版本控制与协作流程 统一版本控制工具:使用Git并规范分支策略(如Git Flow),通过.gitign…...
js关于for of 与for in
for…of for-of循环用于遍历可迭代对象,如数组、字符串、Map、Set等。它直接访问每个元素的值,而不是键名。 const arr [3,5,6,7,0] for(let item of arr){console.log(item); } // 3 // 5 // 6 // 7 // 0只有部署了Iterator接口的数据结构才能使用fo…...
Python Excel
一、Python读Excel——xlrd -*- coding: utf-8 -*- import xlrddef read_excel():打开文件workbook xlrd.open_workbook(rD:\demo1.xlsx)获取所有sheetprint(workbook.sheet_names()) 列表形式返回sheet1_name workbook.sheet_names()[0]根据sheet索引或者名称获取sheet内容…...
前端全局编程和模块化编程
1. 全局编程 <!DOCTYPE html> <html> <head><title>OpenLayers 示例</title><style>.map {width: 100%;height: 400px;}</style><script src"https://cdn.jsdelivr.net/npm/olv7.4.0/dist/ol.js"></script>&…...
随机2级域名引导页HTML源码
源码介绍 随机2级域名引导页HTML源码,每次点进去都随机一个域名前缀。 修改跳转域名在 350 行代码,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行 效果预览 源码免费获取 随机2级域名引导页…...
Latex的各种数学公式
Latex的各种数学公式 简介公式1、 A 、 A ‾ \neg A\text{、}\overline{A} A、A2、 、 \text{、} 、3、 ⋅ 、 ∙ \cdot \text{、} \bullet ⋅、∙ 4、表格 简介 这里会随时更新我需要用到的数学公式,以csdn中写作格式为主,可能过时了,不适合…...
稻壳模板下载器(Windows):免费获取WPS稻壳模板的利器
稻壳模板下载器(Win) 稻壳模板下载器是一款功能强大的工具,能够帮助用户免费下载WPS稻壳儿中的各种模板,无需开通VIP会员。它支持多种模板类型,包括PPT、Word、Excel等,极大地提升了用户的办公效率。 依托…...
BeanDefinition和Beanfactory实现一个简单的bean容器
目录 什么是 Springbean 容器 设计思路 图解 参考文章 开源地址 BeanDefinition 类 BeanFactory 类 测试类 什么是 Springbean 容器 Spring 包含并管理应用对象的配置和生命周期,在这个意义上它是一种用于承载对象的容器,你可以配置你的每个 Bea…...
Mybatis的resultMap标签介绍
说明:在Mybatis中,resultMap 标签可以用于SQL查询后的封装数据,本文用两个场景介绍 resultMap 标签的使用。 搭建环境 先搭一个Demo,pom如下: <?xml version"1.0" encoding"UTF-8"?> &…...
jarvisoj API调用 [JSON格式变XXE]
http://web.jarvisoj.com:9882/ 题目要求:请设法获得目标机器 /home/ctf/flag.txt 中的flag值 抓包得到: POST /api/v1.0/try HTTP/1.1 Host: web.jarvisoj.com:9882 Content-Length: 36 Accept-Language: zh-CN,zh;q0.9 User-Agent: Mozilla/5.0 (W…...
论坛系统的测试
项目背景 论坛系统采用前后端分离的方式来实现,同时使用数据库 来处理相关的数据,同时将其部署到服务器上。前端主要有7个页面组成:登录页,列表页,论坛详情页,编辑页,个人信息页,我…...
RK3588使用笔记:纯linux系统下基础功能配置(不定期更新)
一、前言 用于记录使用RK3588这个平台在纯linux系统下的一些功能配置,RK3588只是一个芯片,linux只是一个系统,但是linux系统可以运行在无数的芯片上,也都大同小异,本编文章主要记录linux系统环境的一些常用的基础功能…...
yum install 报错(CentOS换源):
yum instally yum utils device mapper persistent-data lvm2 报错: 排查错误原因:centos7 系统停止维护了 解决方案:换源(更换操作系统) //1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-…...
HTTP常见状态码分析
当浏览者访问一个网页时,浏览者的浏览器会想网页所在的服务器发出请求,当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含 HTTP 状态码的信息头(server header)用以响应浏览器的请求。 常见的状态码…...
Python与Web 3.0支付系统:技术融合与未来展望
Python与Web 3.0支付系统:技术融合与未来展望 随着区块链技术的不断发展,Web 3.0支付系统正逐步成为数字经济的重要组成部分。Python作为一种高效、易用的编程语言,在Web 3.0支付系统的开发中扮演着不可或缺的角色。本文将从技术背景、Python的应用、代码示例以及未来发展趋…...
Linux命令-sed指令
sed命令参数: 基本参数 -n:抑制默认输出,只显示匹配的行。 -e:指定 sed 脚本。 -i:直接修改文件内容。 -f:指定包含 sed 脚本的文件。 -r:启用扩展正则表达式。 常用操作 s:替换字符…...
Unbantu24.04配置-软件安装
Ubantu24.04配置—环境安装 最近在笔记本安装了双系统,这次在这里回顾一下,本章节主要是一些软件的注意点,大多数都是在网上有一定的教程的 1.搜狗输入法 1.1 删除其他框架 sudo apt purge ibus sudo apt remove fcitx5* sudo apt pur…...
八股总结(Java)实时更新!
八股总结(java) ArrayList和LinkedList有什么区别 ArrayList底层是动态数组,LinkedList底层是双向链表;前者利于随机访问,后者利于头尾插入;前者内存连续分配,后者通过指针连接多块不连续的内存…...
NVIDIA TensorRT 10 [TAR]安装教程
平台信息 操作系统:Ubuntu 20.04.6 LTSCPU架构:x86_64GPU:Tesla T4 x 2驱动信息: NVIDIA-SMI:535.104.05Driver Version: 535.104.05CUDA Version: 12.2 步骤 预备步骤 安装驱动和CUDA 假设已经成功安装好驱动&a…...
深入探索 iOS 卡顿优化
认识卡顿 一些概念 FPS:Frames Per Second,表示每秒渲染的帧数,通过用于衡量画面的流畅度,数值越高则表示画面越流畅。CPU:负责对象的创建和销毁、对象属性的调整、布局计算、文本的计算和排版、图片的格式转换和解码…...
【C/C++算法】从浅到深学习---分治算法之快排思想(图文兼备 + 源码详解)
绪论:冲击蓝桥杯一起加油!! 每日激励:“不设限和自我肯定的心态:I can do all things。 — Stephen Curry” 绪论:本章是针对快速排序进行的优化和再次理解快排思想,将会通过4道题目带你再次…...
精通React JS中的API调用:示例指南
精通React JS中的API调用:示例指南 推荐超级课程: 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战目录 精通React JS中的API调用:示例指南为什么在React JS中进行API调用?在React JS中制作API调用:…...
浅谈Thread类及常见方法与线程的状态(多线程编程篇2)
目录 前言 1.Thread类及常见方法 Thread类中常见的属性 1. getId() 2. getName() 3. getState() 4. getPriority() 5. isDaemon() 6. isAlive() 7. isInterrupted() 2.Thread类中常见的方法 Thread.interrupt() (中断线程) Thread.start()(启动线程) 1. 覆写 run…...
算法刷题记录——LeetCode篇(1.2) [第11~20题](持续更新)
更新时间:2025-03-29 LeetCode题解专栏:实战算法解题 (专栏)技术博客总目录:计算机技术系列目录页 优先整理热门100及面试150,不定期持续更新,欢迎关注! 17. 电话号码的字母组合 给定一个仅包含数字 2-9…...
基于HTML5和CSS3实现3D旋转相册效果
基于HTML5和CSS3实现3D旋转相册效果 这里写目录标题 基于HTML5和CSS3实现3D旋转相册效果项目介绍技术栈核心功能实现原理1. HTML结构2. CSS样式设计2.1 基础样式设置2.2 容器样式2.3 图片样式 3. JavaScript实现4. 交互功能实现4.1 触摸和鼠标拖拽4.2 播放控制 项目亮点技术难点…...
unity中Xcharts图表鼠标悬浮表现异常
鼠标悬浮在面板附近,只显示单独的一个项目 而且无论鼠标如何移动,根本没有效果。 解决方案: 需要在对应的Canvas上绑定主相机才可以 鼠标移动到项目上就有信息展示了...
Unity程序嵌入Qt后点击UI按钮Button没有反应
一、前言 在一次项目中,需要将Unity程序嵌入qt中,并在主界面显示,根据网络资料与相关代码,成功将unity程序嵌入,但是在点击Unity的Button按钮时却没有响应,在查找相关资料后,解决问题ÿ…...
Linux安装Cmake (Centos 7.9)
cmake安装 这个虽然已经更新到了4.0.0版本了,但是我们要用3.5版本的,因为这个比较稳定 官方地址:https://github.com/Kitware/CMake/releases/tag/v3.5.0,选择那个cmake-3.5.0-Linux-x86_64.tar.gz下载, 首先解压文…...
31天Python入门——第14天:异常处理
你好,我是安然无虞。 文章目录 异常处理1. Python异常2. 异常捕获try-except语句捕获所有的异常信息获取异常对象finally块 3. raise语句4. 自定义异常5. 函数调用里面产生的异常补充练习 异常处理 1. Python异常 Python异常指的是在程序执行过程中发生的错误或异…...