游戏引擎学习第61天

embedded/2024/12/28 9:05:16/

回顾并计划接下来的事情

我们现在的目标是通过创建一个占位符版本的游戏来展示我们所做的工作。这个版本的游戏包含了许多基本要素,目的是快速构建一些东西,进行测试,并观察代码结构的形成。这些代码的实施是为了理解系统如何工作,并为真正的系统打下基础。我们正在避免一些常见错误,特别是在没有充分理解系统需要如何工作的情况下就开始编写系统。

目前的任务包括为游戏中的怪物添加活动,例如让怪物跟随玩家并进行攻击,同时还需要为怪物和英雄分别添加生命值,允许两者之间交换伤害。这样可以帮助我们逐步构建对这些操作的理解,并为最终的游戏系统做准备。

我们已经实现了跳跃功能,现在考虑将其映射到空格键,并绑定箭头键进行攻击。攻击的实现将允许玩家在特定方向上进行攻击,并对在该方向上的怪物造成伤害。当攻击命中怪物时,我们会减少怪物的生命值。

为了使怪物能够拥有生命值并进行伤害交换,我们为怪物添加了生命点。此时所有实体的数据都集中在一个地方,这样可以方便管理和操作。虽然目前的实现并不完美,但它为游戏功能的测试和调试提供了基础。

最终目标是将代码结构整理清晰,并为更复杂的系统实现打下良好的基础。

game.cpp: 提取出绘制生命值的代码

为了绘制怪物的生命值,我们决定使用与英雄相同的代码绘制生命点。首先,我们确保每个实体都有生命点,并且在代码中为每个怪物初始化这些生命点。这样,怪物和英雄都可以拥有生命点,并且能够通过相同的方式进行绘制。

为了实现这一点,我们将绘制生命点的代码抽取出来,并确保它可以在怪物的对象中调用。当我们给怪物添加生命点时,代码会检查并初始化它们,以确保每个怪物在场景中都有自己的生命值显示。

接下来,我们将继续完善这一功能,确保怪物在场景中能够正确显示它们的生命点,并通过适当的位置来进行绘制。通过这种方式,我们为后续的功能实现奠定了基础,同时也保持代码的简洁性和统一性。

在这里插入图片描述

game.cpp: InitHitPoints

为了初始化和管理怪物的命中点,首先我们定义了一个命中点计数,并在代码中设置了这一值。对于每个实体,尤其是怪物,我们需要初始化命中点,并确保它们的数量正确。命中点的初始化是通过设置一个合理的填充量来实现的,每个点都可以独立储存信息。我们还确保每个点在初始化时都具有一定的属性,比如标记状态和填充量。

在怪物和英雄都有了命中点后,我们的目标是能够攻击这些实体并最终击败它们。为了实现这一点,我们需要一种攻击机制,并且考虑到可能会有新的实体或功能出现,我们的系统设计保持一定的灵活性。

在准备好这些功能之后,接下来我们将继续实现攻击和怪物的死亡机制。虽然目前缺少精灵图像和显示效果,但我们已经具备了基本的命中点管理和初始化功能,为后续的游戏进程做了准备。

在这里插入图片描述

使用精灵 “rock03” 作为英雄的攻击区域

我们讨论了攻击区域的设计,决定使用类似《塞尔达》东风风格的系统。在这个系统中,攻击区域的形态类似于剑的挥动。具体来说,攻击区域是一个短暂存在的区域,位于玩家旁边,任何被该区域触及的敌人都会被认为是命中并受到伤害。

目前有两种方法来实现这一机制。第一种方法是将其作为一种特殊状态,当玩家攻击时触发。第二种方法是将其作为一个“剑实体”来实现,这个剑实体只会在攻击期间存在,如果与其他实体发生碰撞,就可以确定命中并执行伤害处理。

目标是使攻击机制更加清晰和可控,以便能够准确判断和处理命中的目标。

Blackboard: 讨论如果把剑当做实体来处理时会遇到的困难

我们讨论了游戏中剑击机制的实现,特别是在处理碰撞和击中检测时的挑战。首先,剑击区域通常在几帧内持续,我们希望确保剑击只对目标造成一次伤害,而不是每一帧都造成伤害。为了实现这一点,我们需要跟踪每次碰撞的状态,避免重复计算。例如,如果剑与怪物碰撞多次,应该只计算第一次碰撞为有效击中。

一种方法是通过在剑击时创建一个实体,并通过碰撞检测程序判断是否有其他实体与之接触。这个过程相对简单,但问题出现在当剑在移动时。移动的剑可能与怪物发生多次重叠,导致多个伤害计算。为了避免这种情况,我们考虑使用"新碰撞"的概念,即仅处理第一次碰撞。

然而,处理动态剑击的情况更加复杂。如果剑与怪物同时移动,可能会因为数值不精确而出现重复伤害。为了解决这个问题,我们需要更精确地跟踪剑击的起始和结束时间,确保每个目标只在第一次碰撞时受到伤害。

通过这种方式,我们可以避免多次伤害的情况,并确保游戏的公平性和准确性。

Blackboard: “想象一下”α

内容讨论了游戏中碰撞检测和剑击机制的一些概念。以下是详细总结:

  1. 碰撞检测与剑击

    • 游戏中的剑击只能对目标造成一次伤害,假设剑与怪物发生多次接触,但不希望每次接触都记录为有效攻击。
    • 为了避免这种重复记录,考虑实现一个“击中表”来记录每次实体之间的接触,确保每次接触仅计入一次。
    • 通过这种方式,避免了对实体结构的冗余数据存储,同时提高了效率。
  2. 剑击与时间管理

    • 剑在游戏中并不移动,而是由“攻击状态”来决定是否进行伤害,因此需要记录每个攻击事件的发生。
    • 若剑击结束,相关的击中数据应从表格中移除,避免存储不必要的信息。
    • 在碰撞检测中,考虑到屏幕上可能有多个攻击和接触事件,需要优化存储结构,以免影响性能。
  3. 处理复杂情况

    • 讨论了在多个攻击事件同时发生的情况下如何合理处理记录和碰撞检测。即使是复杂的交互,利用“击中表”仍能有效避免不必要的资源浪费,并简化逻辑处理。
  4. 优化与方案选择

    • 比较了不同的解决方案,考虑了在多次攻击或快速事件发生时,如何保持游戏机制的公平性和合理性。
    • 强调在设计时避免采取“捷径”(如通过使攻击不可战胜来绕过问题),而是尝试实现一个更智能、可靠的方案。通过合理的设计,确保击中表不会导致内存溢出或其他性能问题。

总之,通过击中表的管理,可以更加高效地处理碰撞检测和攻击事件,避免资源浪费并保证游戏的稳定性。这种方法既能确保逻辑的清晰,也能为未来可能扩展的功能提供便利。

实现剑

在游戏开发中,我们设计了一把剑,重点不在于其位置,而是剑的行为和交互。首先,剑作为一种"EntityType_Sword"的实体,不需要在一个具体的地点上存在,而是通过一个"AddSword"的调用来激活它。剑的存在可以被视为一种"空实体",这有助于避免不必要的位置管理,使得系统更加灵活。

我们探索了如何让剑在游戏世界中进行碰撞测试,而不仅仅是处于某个位置。当剑被投掷或使用时,可能会涉及时间限制或距离限制,即剑的活动范围是有限的,过长的存在时间或距离可能会导致剑消失或停止活动。

对于剑的绘制,我们决定使用一个简单的位图,并通过调整其中心点来确保其正确显示。同时,我们考虑到剑可能会投掷出去,因此需要为其设置一个z轴高度,确保其在游戏世界中的位置合适,并有可能添加阴影效果。

此外,剑与其他实体的互动也需要通过一个"低频实体"和"高频实体"的系统来进行区分。特别是,当剑被激活或投掷时,我们需要确保它处于相机可视区域内,并且存在于游戏世界的正确位置。这个过程需要根据实体的位置更新其状态,以保证游戏逻辑的连贯性。

最后,我们还考虑了代码编译的顺利执行,确保所有的函数和变量能够正确地被编译器识别,避免出现任何错误。

在这里插入图片描述

在这里插入图片描述

将 “开始按钮” 绑定为跳跃,箭头键绑定为不同方向的攻击

上面的内容描述了游戏中关于控制和动作按钮的设计。主要涉及到以下几个方面:

  1. 控制和按键绑定:游戏中有多个按钮被绑定到不同的动作上。虽然这些按键的绑定看起来没有太多逻辑关系,但这是暂时的设计。最初有考虑使用跳跃按钮,但最终决定不在游戏中实现跳跃功能,而是将一些动作保留,比如角色在游戏中跳跃的动作。

  2. 动作和按钮功能:某些按钮绑定了特定的动作,例如启动按钮被设置为跳跃按钮。游戏中设计了多种按钮,但最终决定将它们和动作绑定,这可能是暂时的设计选择。

  3. 剑的方向:在游戏中,剑的发射方向由按键控制。不同的方向键会导致剑在特定方向上发射。虽然剑的发射机制尚未完全实现,但目标是能够让剑在特定方向上发射并产生效果。

  4. 简化设计和基本功能:设计中没有加入复杂的功能,而是以基础的、简化的方式处理按键和动作绑定。重点是能够快速实现剑的发射,并观察其效果。

  5. 功能实现的计划:当方向键被按下时,剑将按照相应的方向发射。开发中假设剑会在不动的情况下发射,接着处理它的方向,并计划通过这种方式来进行测试和调整。

这些内容描述了当前的设计选择,以及如何通过简单的控制和按键绑定来实现游戏中的基本功能。
在这里插入图片描述

确保我们拿起剑并发射它

为了确保剑的发射能够在指定方向上成功启动,我们首先需要确认是否有一个剑的实体,并且该实体是否处于有效状态。如果方向的 xy 分量不为零,我们就认为剑应该向该方向发射。因此,在检查后,我们需要启动剑的发射。

首先,检查是否已经有一把剑。如果没有剑实体,我们通过检查剑的低索引(SwordLowIndex)是否为零来验证。如果剑实体不存在,这将返回空指针。若剑存在,我们会将该实体强制放入“高频实体”集合中,确保它能够正确处理并进行移动。

接下来,如果有一把剑,我们需要将它的位置调整到合适的位置,并将其设定为“高频实体”,以便能够在游戏中有效地进行控制。这个操作的核心是确保剑能够被正确地映射到合适的实体集合,并且在移动过程中得到正确的处理。

整个过程涉及将剑实体强制定位到预定位置,然后将它强制推入高频集合,确保剑能够按预期执行动作。在这个过程中,我们不断检查并更新剑的位置以及它是否处于正确的频率集合中。

对于效率问题,我们可能希望在一个操作中同时完成这些步骤,而不是分别进行。这样可以避免多次检查和调整,提升游戏的效率。
在这里插入图片描述

将剑当做低频实体处理,整个过程中让摄像机系统强制它进入高频

我们正在讨论一种处理低频实体的方法,尤其是关于如何将某个实体提升为高频实体。主要思想如下:

  1. 获取低频实体:
    通过调用某种方法获取低频实体,例如“剑”,并检查是否存在对应的低频实体。
  2. 位置变更:
    在某种情况下,可以改变低频实体的位置。
  3. 无需强制提升:
    考虑到某些情况下,我们可能不需要强制将低频实体提升为高频实体,而是可以让摄像机相关的系统或逻辑来处理这些细节。
  4. 让系统自动完成:
    最终选择可能是信任现有的系统,让其按照既定的逻辑处理低频实体,而非人为干预过多。
    在这里插入图片描述

考虑如果 ChangeEntityLocation 将实体移动到摄像机视野内,则将实体映射到高频集合

我们讨论了关于实体位置变化时的处理逻辑,尤其是涉及相机范围和高频实体集合的内容,主要思路如下:

  1. 位置变化的影响:
    每当实体的位置发生变化时,需要仔细考虑其可能的影响。当前逻辑下,任何位置的变化似乎应该触发将实体映射到高频集合的操作,特别是在实体进入相机范围的情况下。

  2. 自动提升的机制:
    需要探讨是否应该在实体进入相机范围后立即将其提升到高频集合。这样可以确保实体在帧的剩余部分内被正确处理,而不是等待到下一帧由相机的检查逻辑来完成提升。

  3. 帧间处理的优先级:
    在帧结束时,由相机逻辑检查实体是否需要提升到高频集合是一种默认机制,但是否需要在实体被创建后,直接提升到高频集合以确保当前帧中的其他逻辑能够及时处理,是一个值得考虑的优化点。

  4. 待办事项的提示:
    这表明在涉及位置变化和相机范围交互时,应在相关逻辑中添加明确的待办事项(TODO),以确保未来对这一机制的处理更加清晰和完善。

  5. 即时性与性能权衡:
    在帧内立即提升实体至高频集合可能带来额外的复杂性或性能开销,但同时也能确保逻辑一致性,需要进一步权衡和设计。

总结,这一部分内容强调了对实体状态的实时管理,以及如何在框架内优化相机范围和实体集合之间的交互逻辑。
在这里插入图片描述

返回到实现发射剑的代码

讨论的内容涉及实体位置的调整、控制实体的行为以及验证实体状态的逻辑,主要总结如下:

  1. 调整实体位置:
    在处理某个实体时,首先会检查其当前状态,并根据需要将其位置设置为玩家所在的位置。这一步确保实体的位置与玩家相关联,方便后续的逻辑处理。

  2. 控制实体行为:
    任何实体的行为都由其控制逻辑决定。当前的目标是根据实体的初始状态设置其位置,为后续可能的修改打下基础。

  3. 设置成功的基础:
    在调整实体的位置时,同时为其未来的扩展留出空间,例如可能会对其 Z 轴或其他属性进行进一步调整。这种方法为长远设计提供了灵活性。

  4. 实体位置变更:
    修改实体的位置后,需要进一步跟踪其在世界中的表现。为了确保逻辑一致性,可能需要对实体的状态进行多次验证。

  5. 验证实体是否已经存在:
    为了避免重复插入实体,需要验证目标实体是否已经存在于当前世界中。然而,目前系统中似乎缺乏一个明确的机制来表示实体是否已经被插入,这可能需要改进。

  6. 实体结构中的缺陷:
    当前的实体结构中缺乏对世界中实体有效性的追踪,无法确认某个实体是否在世界中具有有效的位置。这个缺陷可能会导致逻辑上的漏洞,需要通过引入新的标志或属性来解决。

总结,这部分讨论强调了在处理实体状态时的周密性,同时指出了当前系统在验证实体状态和位置有效性方面的不足,建议通过改进实体结构来提升整体逻辑的可靠性和一致性。

在这里插入图片描述

引入表示 world_position 是否有效的概念

这段内容主要讨论了在系统中引入一种机制,以标记实体位置的有效性,并通过验证和更新位置逻辑来确保实体状态的正确性。以下是总结:

  1. 引入位置有效性标志:
    提议在系统中引入一个机制,用于标记某些位置为无效。例如,可以设置某些超出特定范围的数值(如非常大的值)表示无效偏移。这将有助于快速判断实体是否在有效范围内。

  2. 处理低实体位置:
    在添加低实体时,如果实体没有明确的位置,可以将其位置标记为“无效位置”。通过这种方法,可以在系统中追踪实体是否存在于世界中。

  3. 定义无效位置:
    无效位置可以通过特定的返回值或标志来定义,例如一个特殊的“世界位置”。这类位置明确表明实体尚未插入到世界中,并且可以随时返回这一标志值。

  4. 断言位置状态:
    在更新实体位置的逻辑中,需要对旧位置进行断言,确保它要么是无效位置,要么是有效位置。这样可以防止无效位置被用于不合规的状态更新。

  5. 验证和更新逻辑:
    提议在位置更新中添加额外的检查,确保任何实体在被更新位置时,其新的位置必须是有效的。例如,当一个剑实体没有有效的位置时,可以将其移动到一个有效的位置以使其生效。

  6. 修改存储结构:
    通过引入无效位置的概念,可以优化实体的存储结构,甚至不再需要使用指针操作,而是直接判断位置的有效性。这种方法可以简化代码逻辑,同时提升整体运行效率。

  7. 处理场景实例化问题:
    在特定的场景中,如游戏竞技场或世界场景中,当对实体进行位置变更时,需要确保变更逻辑与场景实例化机制兼容,避免因初始化错误导致的逻辑问题。

  8. 确保实体状态正确性:
    在完成位置变更后,还需验证新的位置是否有效,例如确认一个剑实体已经出现在正确的集合中并可被正常使用。这种验证机制可以防止意外的状态错误。

总结,这段内容强调了在系统中管理实体位置时的严谨性,通过引入无效位置的概念、断言机制和验证逻辑,可以更好地管理实体的有效性和状态更新,确保系统的可靠性和一致性。

在这里插入图片描述

运行游戏,发现剑没有显示出来

通过代码调试,我们需要设置断点来实际查看刚刚的实现是否正常工作。以下是详细分析和总结:


设置断点和调试流程

我们首先在程序中设置了断点,以观察新实现的行为。重点是检查新增逻辑的实际效果,以及这些更改是否按照预期运行。

  1. 启动程序
    在程序启动阶段,我们设置了相关环境并准备好执行调试。启动程序后,我们定位到具体的测试场景。

  2. 查看状态

    • 初步观察发现,剑的位置被设置在 (0, 0, 0) 块中。这表明该位置可能与玩家的位置一致。
    • 虽然尚不能完全确认,但推测这应是符合逻辑的初始状态。
  3. 检查循环迭代

    • 在循环的当前迭代中,剑的位置被成功初始化。
    • 下一次循环迭代时,我们期望逻辑能够继续执行,进入绘制或更新实体的流程。
  4. 绘制与更新

    • 剑的绘制过程需要等待下一轮循环迭代才能触发。初步验证显示,逻辑在当前阶段运行正常。
  5. 结果验证

    • 通过设置断点、运行程序,以及观察相关变量和位置状态,初步确认了新代码的逻辑可以正常工作。

结论

  1. 初步验证显示,剑的位置初始化与玩家位置一致,这符合预期。
  2. 循环中的更新流程正常运行,绘制过程将在后续迭代中触发。
  3. 调试过程未发现明显错误,下一步需进一步验证整体逻辑在更复杂场景中的适用性。

这种调试方法为进一步完善功能提供了清晰的验证路径,同时也为后续扩展和优化打下了基础。
在这里插入图片描述

在这里插入图片描述

开始调试

在调试过程中,首先我们发现剑的位置没有正确更新。期望是将剑的实体移动到世界中,但它没有进入空间分区,也没有被正确的处理。虽然我们有一个设置摄像机的调用,它应该能触发对该实体的操作,但这并没有发生。为了进一步调试,我们尝试在代码中添加断点,以便检查具体问题。

我们开始验证实体的索引,发现剑的实体索引为 92005。此时发现游戏中已经创建了很多实体。我们继续检查,并意识到问题可能出在空间分区的实现上,尤其是在把剑的实体移到正确的空间分区时,发生了错误。

为了进一步调试,我们尝试设置断点,检查所有低频实体是否正确添加到空间分区中。结果显示,某些实体没有被正确地添加,尽管空间分区的块中有 10 个员工,看起来很合理。我们也检查了实体的块和计数,发现这些实体并没有按预期出现在目标位置。

最终,我们考虑到空间分区的调试仍然存在问题,因此我们需要仔细检查每个步骤,以确保剑的实体能够在正确的位置移动,触发正确的摄像机调用,并加入到空间分区的活动集中。这可能是由于编译器或代码逻辑的问题,导致实体没有被正确识别和处理。因此,进一步的检查和验证是必要的,以确保游戏中的所有实体都能按预期行为正常运行。

在这里插入图片描述

在这里插入图片描述

上面的貌似没发现什么问题

在这里插入图片描述

发现剑的 CameraSpaceP 完全是垃圾

在进行代码调试时,我们观察到一些不一致的行为,特别是在实体处理和集合更新方面。具体而言,当尝试将实体从低频集合移至高频集合时,某些块未被正确迭代,导致预期的实体未被添加到高频集合中。我们通过调试代码,检查了相关的块和实体,并发现实体的位置更新没有被正确设置。

在调试过程中,虽然块的值已经按预期更新,但在某些情况下,相机空间的偏移量没有正确应用,导致实体的空间位置没有更新。进一步分析发现,这个问题源于新的位置变化并未被正确反映,而只是对实体的状态进行了更新。

为了解决这个问题,建议确保代码能够正确地更新每个实体的位置,避免类似的错误发生。此外,可能需要调整代码逻辑,使其在更新实体位置时更加可靠,以确保集合的准确性和实体在不同状态下的正确处理。

在这里插入图片描述

让 ChangeEntityLocation 正确更新新的 world_position

我们在处理代码时发现,问题并不在于存在多个bug,而是空间分区的逻辑在某些情况下没有正确地更新位置。为了确保代码能够正常运行,需要在改变位置时进行更新,并确保实体的位置和集合保持一致。具体而言,在代码函数结束后,如果有新的位置被分配给实体,应该立即更新其位置,并确保其被正确地分配到相应的集合。

为了简化代码,进一步的调整使得函数能够接收更多的信息,从而便于在更新位置时更加精准。这个调整确保了实体的位置会被准确更新,并且能处理空间分区中的变化。当所有的实体在同一块时,代码会根据条件继续执行,而不再依赖多余的逻辑。最终,这种处理方式有效解决了我们遇到的问题,并确保了空间分区的正确性。

通过这些调整,代码更加简洁且高效,避免了不必要的复杂性,同时确保了实体的正确位置和集合更新,从而使得整个系统能够顺利运行。

在这里插入图片描述

运行游戏以验证是否修复了 bug

经过一系列的调试和代码修改,问题似乎已经得到了解决。接下来,继续优化代码库并关注其他任务,如处理命中点(hit points)等内容。在修复了这次的bug后,重点是确保错误不再重现。通过将代码转移到更好的结构中,可以避免这些bug的发生,并且在以后的开发中,逐步减少出现新的bug的可能性。

对于任何一个bug,都不应留下不处理的情况,及时修复是非常重要的。虽然追踪每个小bug可能花费不多时间,但如果有bug不断重复出现,最终会带来更多麻烦。因此,保持代码库的清洁、避免遗留bug是开发中的关键目标之一。

在这里插入图片描述

你说过 Visual Studio 在显示变量时很糟糕,那你是怎么在 Emacs 中编程并在 Visual Studio 中运行的?

在调试过程中,遇到了Visual Studio的变量显示问题。尝试查看变量时,发现Visual Studio展示的是过时的信息,而不是当前的值。这种情况令人困惑,尤其是在变量的值没有更新时。尽管刷新尝试过,但Visual Studio依然未能正确展示当前指针位置的值,甚至无法单独刷新特定变量的值。

这种问题在Visual Studio的多个版本中都有出现,尤其是随着每次更新,调试功能变得越来越差。升级到新版本的Visual Studio通常是为了支持新的编译器和指令集,但调试功能的质量却没有得到改进,反而每次更新后调试工具变得更加糟糕。这种情况导致开发者在调试时不断遇到困难。

在进行探索性/实验性编程时,我发现很难决定是继续当前的路径,还是转换为不同的方法。很多时候,我开始时一切顺利,但最终因为一些预料之外的问题停滞不前。我常常会花费大量时间思考如何解决或绕过这个问题,即使是以简单的方式。是不是分析瘫痪呢?有什么建议吗?真的只是继续编写代码,无论它看起来多么愚蠢?

在进行探索性实验编程时,常常会面临决定是继续执行当前路径,还是转换到其他方法的困难。即便一开始一切顺利,随着时间的推移,难以预见的问题可能会导致停滞。常常我们花费大量时间思考如何解决这些问题,尤其是即使是简单的解决方法也会变得复杂,从而导致分析瘫痪。

解决这一问题的关键是保持编程的持续性。就像赛跑者追求极限速度一样,编程也需要实践与不断尝试。在学习如何编写代码的过程中,过多的抽象分析往往无法帮助加速进程,实际的编程经验才是提升能力的关键。只要不断编写代码,通过解决小问题逐步积累经验,就能够在面对复杂问题时做出更好的决策。

此外,编程中的成功不仅依赖于掌握正确的理论和方法,还需要通过大量实践来建立直觉与经验。这些直觉通常无法通过理论学习获得,必须通过不断的编码实践、错误修正以及反思才能积累起来。通过实践,不仅能解决实际问题,还能避免重复犯同样的错误,从而提升编程能力。

你会处理剑和怪物互相碰撞时的情况吗?如果它们朝着彼此快速移动,可能会在一个帧内穿过对方而没有碰撞。

在处理剑与怪物之间的碰撞时,问题可能出现在它们以非常高的速度相向移动,以至于在某一帧内它们不会发生碰撞,甚至相互穿过。为了解决这个问题,已经在移动代码中实现了处理方式。该代码能够确保即使物体的移动速度非常快,也能有效检测并处理碰撞,不会出现穿透现象(隧道效应)。这是通过在系统中进行必要的碰撞检测和重铸技术来避免的,因此系统能够正确处理这一情况,确保物体不会在坐标系中发生穿透。

你认为“cheesing”(让敌人在被击中后 10 帧内无敌)是游戏设计的罪恶,还是只是你想避免的东西?

在游戏设计中,是否使用“作弊”技术(例如让敌人无敌几帧)是一种有争议的选择。某些设计决策可能为了节省时间或提高产品进度而做出调整,这并不一定是错误的,前提是这些决策不会对整体质量产生负面影响。游戏开发的目标之一是做出高质量的工作,但在实际开发中,时间是一个有限的资源。因此,设计者可能会在某些情况下选择使用“作弊”技巧,以加速开发进程,或者简化某些复杂的算法。

这种做法的关键在于做出明智的决策。设计者需要权衡每个决策对最终产品的影响,确保这些决策不会损害产品的长期质量。使用“作弊”技巧并不意味着游戏质量一定会降低,而是应该根据具体情况做出判断。最终,开发者需要根据项目的需求和资源做出合理选择,既不盲目追求完美,也不放弃质量。每个决策都应基于其对产品的整体影响,而不是出于教条主义。

在开发过程中,可能会出现一些设计决定,比如为了快速完成某些功能而采取妥协,这时候就需要开发者具备足够的经验和知识,能够做出适合的决策,而不是机械地避免一切妥协。

为什么不直接使用自动窗口?

使用自动窗口(Auto Window)虽然能够节省输入时间,但并不能解决一些特定的问题。比如,当开发者需要查看特定信息时,自动窗口可能不如手动设置的窗口那样灵活。自动窗口根据其设定来展示信息,但它无法确保在动态变化时,窗口内容不会移动或者改变位置。相反,手动设置的窗口可以固定显示所需的信息,使得内容不会因为变化而消失或者重新排列。

此外,尽管自动窗口有时可以提供一些便捷的功能,但它并没有解决更复杂的问题,比如跨过某个特定的代码块后,窗口内容会突然消失,这可能导致调试时的信息丢失。因此,尽管自动窗口在某些情况下可以节省时间并提供帮助,但它并不总是能提供理想的解决方案。对于某些开发者来说,手动控制窗口内容的位置和展示方式仍然是更合适的选择。

VC++ 仍然比开源替代品更好吗?

目前,尽管开源替代品在某些方面逐渐追赶,但在许多开发领域,Visual Studio 和它的编译器仍然被认为是最好的选择,尤其是在稳定性和可靠性方面。尽管 Visual Studio 的质量在每次发布时似乎有所下降,但在编译器方面,尤其是对于 Windows 平台,Visual Studio 依然占据主导地位。

然而,开源替代品也在不断进步,尤其是 Clang 编译器,已经在多个方面超越了 Visual Studio 的编译器,尤其在性能和效率上。Clang 被认为是更为优秀的选择,尤其是对于跨平台开发者而言。虽然 Visual Studio 在某些优化和功能上可能更好,但 Clang 在大多数编译任务中表现更为出色。

尽管如此,Visual Studio 仍然是一个不可忽视的工具,在许多开发工作中,尤其是 Windows 相关的开发,它仍然是最佳的选择。虽然开源工具逐渐发展,但在编译器和某些开发工具的成熟度上,Visual Studio 仍占据优势。

你认为改变艺术风格以便更容易实现如何?比如,对于早期提到的剑的碰撞,如果你做这样的事情:好吧,剑将会瞬间沿着路径瞬移,类似于动漫中的红线,并且在几帧内持续显示。基本上可能会从根本上改变艺术风格,以便让它运行得更好。你有没有听说过类似的例子?

在开发中,改变艺术风格或游戏设计是解决技术问题的一个常见方法。通过改变艺术风格,可以使得某些功能更容易实现。例如,调整剑的碰撞方式,让它在一帧内瞬间传送,而不是逐帧显示,可以简化处理,避免复杂的碰撞检测和动画运算。类似地,某些游戏设计决策可以通过修改艺术风格来优化性能,减少开发上的难题。

然而,在某些项目中,尤其是展示编程和技术实现时,目标是尽可能保持现有设计,解决技术问题而不依赖于改变艺术风格或设计。即使如此,在自己的项目中,开发者需要根据项目的具体情况做出选择,判断哪些调整最有利于项目的完成。

总的来说,艺术风格和游戏设计的调整可以是提高开发效率的一种有效方式,但是否采用这种策略需要根据每个项目的需求和目标来决定。

你总是谈论编程的方式,尤其是在编程巅峰时期。作为一个 18 岁的人,我怎么知道那是什么样的,或者怎么获得你关于编程的知识?有没有书籍、语言或任何我可以做的事情来学习编程的“老方法”?

讨论中提到编程的学习方法和方式,从传统的编程风格到现代的技术演变,反映了如何从过去的编程经验中获得启发。传统的编程方法,比如使用汇编语言编写程序,要求开发者面对更复杂的技术限制和挑战。相较之下,现代的编程环境提供了更多的资源和技术支持,令编程变得更为简单。然而,仍有一些核心的传统编程理念值得传承,比如从低层开始编写代码并逐步构建高层功能。

对于想要学习这些“旧式”编程方法的人,有些经典的书籍可能有帮助。例如,关于图形和动画的编程,有一些书籍提供了早期编程的实践案例,如飞行模拟器的实现过程,这些例子展示了如何在资源有限的环境下进行编程优化。此外,还有一些书籍探讨图形编程的哲学,帮助读者理解旧时开发者如何在硬件限制下进行创作。

尽管现代技术使得编程变得更加高效,但学习传统编程方法的核心价值在于了解如何在资源受限的情况下进行创新。这不仅仅是对过去的回顾,更是对未来编程方式的启发,帮助开发者在技术演变的过程中保持对底层操作的理解和掌控。

为什么你选择了 C++ 作为编程语言?

选择C++作为编程语言主要是因为其高性能的特点。几乎所有游戏的编程都是用C++进行的,这是因为C++提供了对硬件的低级控制以及高效的执行性能,适合需要处理大量数据和复杂计算的游戏引擎开发。在游戏开发的历史中,C++和C语言一直是最常用的编程语言,直到最近才出现了像C#、Java等较高层次的语言,用于某些没有很高性能需求的游戏开发。

C++不仅适用于性能要求极高的游戏引擎开发,还广泛用于大型游戏引擎的底层部分。例如,Unity游戏引擎虽然在脚本部分使用C#编写,但底层依然是使用C++来实现。对那些希望写出高性能引擎的开发者来说,C++仍然是最合适的选择,除非选择更低级别的语言如汇编语言。对于游戏开发者而言,C++不是一个奇怪的选择,反而是最常见且有效的选择。

总的来说,C++的选择不仅仅是基于技术需求,也是基于历史和行业惯例。对于大多数游戏项目而言,C++仍然是最符合需求的编程语言。

有没有比 C++ 更容易的语言来编写这款游戏?

如果不打算编写游戏引擎,使用更简单的语言编写游戏是可行的。例如,可以使用XML或Python等语言来编写类似《塞尔达传说》的简单游戏,因为这些语言拥有大量现成的库,可以帮助开发者完成许多工作,使得开发过程更加容易。

实际上,选择简易语言的一个主要原因是有强大的库支持。通过使用现成的库,可以避免自己编写底层代码,从而更专注于游戏设计。这种方式通常适用于性能要求不高的游戏,且不需要进行复杂的引擎开发。在这种情况下,开发者可以选择Unity等现有的游戏引擎,利用其强大的功能和工具进行游戏开发。

总体而言,游戏开发的难易程度不仅仅取决于语言本身,更取决于所选择的库和引擎。如果不需要自己编写引擎或处理复杂的游戏设计问题,使用简单的语言和现有的工具会更加高效和方便。例如,对于第一人称射击游戏,选择像Unreal Engine这样的专业引擎可以大大简化开发过程。

要想超越 C++ 成为默认的游戏编程语言,作为一门语言需要具备什么特点才能超越 C++?

要想有一门编程语言能够超越C++,成为编写游戏的实际语言,需要做的就是创造一种比C++更具优势的语言。虽然C++在过去的三十年中没有显著进步,但它依然是编写游戏的主流语言。然而,C语言虽然曾是很好的选择,但现在的C++在很多方面并没有提供太多新的价值。

因此,要超越C++,需要创造一种语言,能够为游戏编程提供更多有价值的特性。这种语言不仅要解决C++的局限,还要在语法和功能上具备更高的效率和易用性。通过对现有语言的改进,可以创造出一种更加适用于现代游戏开发的语言,这样的语言能够提供更好的性能、可读性和可维护性,从而超越C++成为游戏编程的主流选择。

仓库: https://gitee.com/mrxiao_com/2d_game


http://www.ppmy.cn/embedded/149403.html

相关文章

华为 IPD,究竟有什么特点?(二)

关注作者 (四)华为版 IPD 特点四:一定要把差异化竞争力持 续建立在平台上 平台不仅带来研发效率的提升,更重要的是,它是技术竞争力的载体,是研发质 量的重要保证。 1)为什么很多企业摆脱不了同…

外网访问 Docker 容器的可视化管理工具 DockerUI

DockerUI 是一个 docker 容器镜像的可视化图形化管理工具,DockerUI 可以用来轻松构建、管理和维护 docker 环境。让用户维护起来更方便。 本文就介绍如何安装使用 DockerUI 并结合路由侠内网穿透来访问 DockerUI。 第一步,安装 DockerUI 1,…

Seatunnel2.3.8 JDBC连接器开发

JDBC连接器开发 说明必要知识Seatunnel基础开发流程拉取项目编译构建运行工程样例打包发布 JDBC连接器开发包目录介绍食用技巧catalog中的类介绍dialect中的类介绍 说明 该文档旨在帮助开发人员,快速了解熟悉seatunnel2.3.8程序框架,并能够进行JDBC连接器…

大数据的尽头是数据中台吗?

大数据的尽头是数据中台吗? 2018年末开始,原市场上各种关于大数据平台的招标突然不见,取而代之的是数据中台项目,建设数据中台俨然成为传统企业数字化转型首选,甚至不少大数据领域的专家都认为,数据中台是…

ChatGPT 搜索工具被曝存在安全漏洞

据报道,OpenAI 的 ChatGPT 搜索存在安全问题,其反馈结果可以被页面的隐藏内容操纵,甚至可能反馈恶意代码。 英国卫报重点测试了 ChatGPT 搜索工具对包含隐藏内容的网页处理情况,此类隐藏内容可能包含来自第三方、可以更改 ChatGPT…

Day55 图论part05

并查集理论基础 并查集理论基础很重要,明确并查集解决什么问题,代码如何写,对后面做并查集类题目很有帮助。 并查集理论基础 | 代码随想录 总结 1.并查集主要有两个功能:主要就是集合问题 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个将两个节点接…

RabbitMQ工作模式(详解 工作模式:简单队列、工作队列、公平分发以及消息应答和消息持久化)

文章目录 十.RabbitMQ10.1 简单队列实现10.2 Work 模式(工作队列)10.3 公平分发10.4 RabbitMQ 消息应答与消息持久化消息应答概念配置 消息持久化概念配置 十.RabbitMQ 10.1 简单队列实现 简单队列通常指的是一个基本的消息队列,它可以用于…

自学记录HarmonyOS Next的HMS AI API 13:语音合成与语音识别

在完成图像处理项目后,我打算研究一下API 13的AI其中的——语音技术。HarmonyOS Next的最新API 13中,HMS AI Text-to-Speech和HMS AI Speech Recognizer提供了语音合成与语音识别的强大能力。 语音技术是现代智能设备的重要组成部分,从语音助…