当前位置: 首页 > article >正文

游戏引擎学习第29天

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

回顾目前完成的工作

在这段讨论中,首先提到了回顾之前的进度,之前做了一些矩形的移动,并且有一个简单的瓦片地图,这些都已经完成。

清屏并偏移可绘制区域

在这段讨论中,首先提到的是清理屏幕并设置一些操作,比如让屏幕的区域变为黑色。这是通过调用 Windows API 来实现的,可以在绘制内容之前先清空屏幕。通过设置一些偏移量,确保屏幕的显示区域保持清晰,避免视觉上的混乱。提到了偏移量主要是用来给屏幕留下一个小的空白区域,这样可以确保显示的区域和未显示的区域之间没有冲突。

接下来,讨论了一个名为“拉伸函数”的实现,该函数会将位图绘制到屏幕上,并通过设置偏移量来调整显示的位置。虽然这段代码还需要进一步的调整和验证,但整体思路是通过一些简单的操作来控制显示和碰撞的行为。

讨论还提到了调试代码的必要性,尤其是在验证帧率和动作的实现时。通过验证程序是否每秒钟能够获得30帧,可以确保程序没有卡顿并且能够正常运行。此外,还提到了调整和测试小黄色矩形的移动,确保它不会穿透墙壁,并且当矩形碰到地图的边缘时能够停止。

最后,提到要继续推进项目,完成一些基本的操作,比如处理碰撞和门的交互,使得矩形可以穿越门并进入下一个地图。整个过程中,目的是构建一个引擎,让它能够处理这些基本的操作,随着时间推移逐步构建更复杂的功能。
在这里插入图片描述

在这里插入图片描述

偏移

在这里插入图片描述

清除四边的颜色为黑色

在这里插入图片描述

将玩家初始位置移入地图内

内容描述了一个游戏开发中的调试过程,重点是如何解决角色移动和碰撞问题。首先,讨论了角色在地图上的位置初始化,角色最初被放置在地图外,需要调整其初始位置以确保它进入有效区域。接下来,讨论了如何在游戏初始化时设置玩家的位置,并指出该位置可能是随机选择的,且还需要进一步的验证。

在实际的开发过程中,碰撞检测出现了一些问题,玩家可以在地图上半途穿过某些无效区域,而没有被阻止。为了解决这个问题,提到需要检查角色的外缘,确保角色的外缘不会与地图上的障碍物发生碰撞。

在这里插入图片描述

在这里插入图片描述

玩家与瓦片地图的碰撞

  1. 目标与问题:
    在开发过程中,目的是确保玩家的移动是有效的,特别是当玩家试图移动到已经被占用的区域时,需要阻止这种无效移动。为了实现这一目标,开发者需要将玩家的屏幕坐标转换为瓦片地图中的坐标,并验证目标瓦片是否已被占用。

  2. 玩家坐标转换:
    玩家当前的位置是以像素为单位的屏幕坐标,但需要将这些像素坐标转换为瓦片地图的坐标。瓷砖地图中的每个瓦片可能包含多个像素,因此坐标转换涉及将玩家的位置除以瓦片的宽度和高度,从而得到玩家所在的瓦片坐标。具体操作是,通过计算玩家的x和y坐标相对于地图的最小值,得到玩家相对于地图的位置,然后通过除以瓦片的宽度和高度并截断值来确定玩家在瓦片地图中的具体位置。

  3. 坐标截断与边界检测:
    在进行坐标转换时,开发者提到会用到“截断”操作,而非四舍五入。这是因为截断能确保玩家位置始终落在一个具体的瓦片上,而不会出现不精确的浮动值。截断后,玩家的坐标将被转换为瓦片坐标,这样就可以进一步验证该瓦片是否有效。

  4. 瓦片的有效性检查:
    在得到玩家的瓦片坐标后,开发者还需要检查玩家是否处于有效的区域内。这需要通过对玩家的瓦片坐标进行边界检查,确保玩家的坐标在瓦片地图的有效范围内。如果玩家的坐标越界,那么此移动将被视为无效,玩家将不能移动到该位置。

  5. 地图验证:
    一旦玩家的瓦片坐标被确认有效,接下来需要通过查找地图数据来验证该瓦片是否被占用。假设地图中使用“1”表示被占用的瓦片,使用“0”表示空闲的瓦片,开发者会通过在地图中查找相应位置来检查瓦片是否被占用。如果目标位置为空闲,则玩家可以继续移动;如果被占用,则玩家的移动将被阻止。

  6. 后续优化:
    尽管当前的方法可以完成基本的玩家移动验证,开发者意识到还需要进行优化和修复,尤其是可能存在的bug和逻辑问题。此时的目标是确保代码正确无误,并在必要时进行调整,以便后续可以处理更复杂的交互和场景。

  7. 总结:
    整体而言,这段代码和思路的核心在于确保玩家的移动在游戏世界中是有效且合理的。通过坐标转换、边界检测以及地图数据验证,开发者能够准确判断玩家的移动是否合法,并采取适当的措施防止玩家进入不应去的区域。

在这里插入图片描述

修改一下Bug
在这里插入图片描述

检查点是否被占用的函数及瓦片地图结构

内容讨论了如何改进角色碰撞检测、地图渲染和函数设计等方面的工作。最初提出的目标是避免角色穿越墙壁或无效区域,并且在角色移动时进行有效的碰撞检查。在讨论过程中,提到了一些优化方法,比如通过检查多个位置点来决定角色是否可以移动,使用函数来判断某个点是否有效。这是为了避免重复编写相同的碰撞检测代码。

具体来说,通过创建一个函数来判断给定的点是否有效,可以简化代码逻辑,并避免冗余的代码。函数的设计包括检查每个点是否为空,若为空则返回“空”,否则返回其他值。这样可以提高碰撞检测的准确性,并减少代码的复杂性。

然而,开发过程中遇到了一些问题,比如如何获取并传递正确的地图数据。由于需要进行数学运算和坐标转换,所以传递正确的地图数据变得至关重要。在此基础上,还考虑到地图数据的有效性问题,明确指出了左上角坐标和相关数据的重要性,并强调了避免猜测数据的必要性。

此外,还讨论了如何在地图上处理不同的块和区域,确保游戏中的各种物体和角色能够正确交互。通过调整数据结构和代码逻辑,确保游戏中的功能能够顺畅运行,并且避免了不必要的重复代码。

总体来说,讨论的核心是通过细化函数和优化数据传递方式来解决碰撞检测和地图渲染中的一些问题,同时确保游戏逻辑更加简洁和高效。
在这里插入图片描述

将瓦片地图数据作为一维数组访问

要使瓦片地图更具灵活性并避免硬编码的城市地图大小,可以采用一种方式,使得地图的宽度和高度不再固定,而是动态计算。目的是让地图的访问和处理不依赖于预先定义的固定尺寸,而是能够适应不同尺寸的瓦片地图。以下是实现这一目标的思路和步骤。

思路总结:

  1. 不再硬编码地图大小

    • 通过使用指针代替固定的地图数组,使得地图的尺寸可以动态改变。这样,地图的尺寸和内容可以根据需求灵活调整。
  2. 采用二维到一维的映射

    • 原本的瓦片地图是二维的(X 和 Y 坐标),但为了简化内存管理,可以将其转换为一维数组,按行优先的顺序将每一行的瓦片放入连续的内存区域。
    • 每一行的瓦片在内存中按顺序排列,进入下一行时会在内存中跳到下一个位置。
  3. 如何访问瓦片

    • 当访问地图中的瓦片时,不再直接使用二维索引(如 TileMap[X][Y]),而是计算出对应的线性索引。
    • 计算线性索引的方法是:index = y * width + x,其中 width 是地图的列数,xy 是当前瓦片的坐标。
    • 这样,X 和 Y 的值被“压缩”成一个线性数组,使得可以通过简单的计算访问任意瓦片。
  4. 动态内存分配和管理

    • 使用动态分配的内存(如 mallocnew)来创建瓦片数组,确保可以在运行时调整地图的大小。这样做能够避免提前定义固定的地图大小,且能在不同的需求下创建不同尺寸的地图。
  5. 二维和一维之间的转换

    • 对于二维坐标(x, y),可以根据之前提到的公式将其映射到一维数组中。访问方式将类似于图像像素的访问:通过行列值计算出内存地址,从而访问该位置的瓦片。
  6. 实现细节

    • 通过公式 index = y * width + x 来进行二维坐标到一维数组的转换,其中 width 是瓦片地图的列数。
    • 对于每个 x 值,地图的访问会按照一行一行的顺序来处理,并且每次向上移动时,访问的偏移量会增加一整行的瓦片数量。

代码实现步骤:

  1. 定义瓦片地图结构体

    • tile_map 结构体中,不再预定义一个固定大小的瓦片数组,而是使用一个指针来存储瓦片数据,允许动态调整地图的大小。
  2. 动态分配瓦片数据

    • 使用 malloc 或类似方法为瓦片数组分配内存,可以根据地图的尺寸动态创建一个大的连续内存块来存储所有瓦片信息。
  3. 修改访问方式

    • 改变地图访问的方式,从直接通过二维坐标访问,改为通过线性计算来访问一维数组中的瓦片。

动态瓦片地图访问方式:

  • 假设瓦片地图的列数为 width,则对于每一个 y 坐标,访问相应的 x 坐标的瓦片位置时,通过公式计算线性索引:index = y * width + x
  • 这样,无论地图的行数和列数如何变化,都能够通过统一的方式访问瓦片数据。

通过上述方式,可以将瓦片地图的结构和访问方式从硬编码的固定尺寸改为灵活的动态结构,能够适应不同大小的地图,同时保持访问和操作的高效性。这种方法对于处理复杂的城市地图或其他大规模地图非常有效。
在这里插入图片描述

将玩家宽度加入碰撞检测

在进行瓦片地图相关操作时,首先需要替换掉先前的检查逻辑,改为调用新的函数来完成瓦片查询。接下来,去掉不再需要的代码,因为新函数已经可以完成所有相关操作。然后,可以开始测试,通过测试不同的点来验证功能是否正常。测试时,需要确保所有点都位于空白区域内,以便功能能够正确发挥。

接着,通过移动玩家的位置,检查玩家是否能够进入或停留在期望的区域。如果遇到障碍,玩家应该无法进入该区域,这样就能够检测到某些地方已被成功屏蔽。

随着这一过程的进行,逐步开始形成新的设计思路,尽管这些改动在表面上看似简单,实际上是在稳步推进游戏设计的整体进程。通过小步快跑的方式,代码变得更加容易理解,且每一步都能为最终的设计目标提供反馈。

最终,目标是让玩家能够从一个瓦片地图中移动到另一个新的地图类型。在实现这个目标时,需考虑如何有效地管理玩家在不同地图间的转移。这一过程中,测试和调试是非常重要的,通过反复验证功能,可以确保游戏行为符合预期。
在这里插入图片描述

在这里插入图片描述

修改玩家的坐标

在这里插入图片描述

在这里插入图片描述

让玩家走过门时切换地图

在开发过程中,首先考虑了如何实现多张可行走的平铺地图。为了达到这一目标,创建了一个包含多个平铺地图的系统,并进行了多次调整。在设计时,选择了使用多个平铺地图,而不仅仅是一个。初步设定了两个地图,并进行了配置,使得玩家能够在这些地图之间流畅过渡。

在这个过程中,定义了两个主要的平铺地图,并通过不同的配置确保它们之间的过渡是连贯的。为了更好地管理地图,设计了指向平铺地图的指针,并通过数组的方式进行组织。此外,还在地图的某些区域引入了“门”,使玩家可以从一个地图进入另一个地图。为了进一步简化操作,采用了指针来标记当前使用的地图,并根据需要进行更新。

在实现中,发现了一些细节问题,比如地图上的门消失了。解决方案是确保每次玩家走出一个区域时,能够正确地过渡到下一个屏幕。这不仅涉及到如何在多个地图间移动,还要确保在这些平铺地图之间切换时,玩家的动作流畅且合理。

通过在编程中添加必要的条件检查,保证了每次传递数据时,系统能够有效地判断地图的有效性,从而避免了潜在的错误。整个开发过程中,重点是灵活调整平铺地图的配置,确保玩家的移动和过渡逻辑得以顺利执行。

在这里插入图片描述

在这里插入图片描述

关于将所有瓦片地图存储在一个大结构中的讨论

上面讨论的内容主要集中在如何管理和存储大型游戏世界中的瓷砖地图,特别是处理稀疏存储和避免浪费内存的问题。以下是该讨论的详细总结:

  1. 稀疏存储的必要性:在游戏中,尤其是开放世界类的地图,我们往往不会有大量的瓷砖数据都被填充或者被使用。许多区域可能是空的,或者在某些特定的场景下才会激活。这时候,存储整个世界的所有瓷砖地图会浪费大量内存,因为很多地方没有内容。为了解决这个问题,我们可以采用稀疏存储策略,仅存储那些实际存在并且玩家可以访问的区域的瓷砖数据。

  2. 传统大规模地图的缺点:将整个游戏世界作为一个巨大的一维、二维或三维数组进行存储,虽然在技术上可行,但随着维度的增加,内存消耗呈指数级增长。例如,存储一个包含大量瓷砖的二维地图,可能会涉及到几百个瓷砖图层和几千个条目,甚至在空间上达到了数千兆字节。这种做法在面对庞大的世界时,尤其是当世界本身稀疏且不均匀时,会迅速变得不现实。

  3. 稀疏存储与密集存储的对比:在游戏中,瓷砖地图的密度决定了存储的效率。稠密地图意味着每个位置都有瓷砖数据,而稀疏地图则仅在有实际内容的位置存储数据。存储稠密地图需要更多的内存,因为每个位置都必须占据空间,而稀疏存储只关心那些有内容的区域,从而减少了内存浪费。

  4. 稀疏存储的优势:稀疏存储的关键优势是它能够减少对无效空间的内存消耗。假设游戏世界中存在一个塔楼,玩家只能在塔楼内向上移动一小段高度,传统的存储方式会要求为每个潜在的塔楼位置存储数据,而稀疏存储则只存储实际存在的塔楼部分。这样,玩家只需加载和存储游戏中实际存在的区域,而不需要浪费内存来存储空的、不需要的部分。

  5. 3D世界和多维度存储的挑战:随着游戏世界的维度增加,尤其是引入了高度(例如塔楼)或立体空间时,存储的复杂性也随之增加。如果不采取稀疏存储方式,存储空间会很快达到不可接受的程度,尤其是当世界非常庞大时。将整个世界存储在一个巨大的数组中可能导致内存消耗爆炸性增长,因为每个位置都必须保留数据,即使其中许多位置没有被使用。

  6. 适应性查询与存储:理想的存储方案应当能够有效查询和处理瓷砖地图数据,同时仅加载实际存在并被玩家访问的部分。通过这种方式,游戏不仅能节省内存,还能够确保在不同区域之间流畅地进行查询和交互,例如,当玩家移动到一个新的城市或区域时,游戏可以快速加载新的瓷砖地图,而不需要加载整个世界的所有地图数据。

  7. 稀疏存储的具体应用:实现稀疏存储时,可以按需加载瓷砖地图的片段,而不是存储整个大世界。这种方法能够帮助管理复杂的世界结构,如城市、塔楼和地下区域等,避免将这些区域填充成一个巨大的、占用大量内存的无用区域。每次玩家接近某个位置时,系统只加载该区域的数据,而非整个世界,优化了内存的使用。

总结来说,稀疏存储技术允许开发者将游戏世界划分为多个独立的瓷砖地图区域,只有在玩家实际访问的区域才会加载和存储数据,从而减少了内存浪费和提高了游戏的性能。这种方法可以有效管理大规模、复杂的开放世界游戏,避免了传统大地图存储方法中不可避免的内存开销问题。

开始存储和访问多个瓦片地图以及世界结构

这个讨论围绕的是如何处理多张瓷砖地图(tile maps)的问题。在处理这些地图时,关键点包括如何管理和访问不同的地图坐标,以及如何在一个更广泛的“世界”结构中进行地图的查找和操作。以下是详细的总结:

  1. 多个瓷砖地图的处理:目标是让系统能够处理多个瓷砖地图,而不仅仅是单一的地图。为了实现这一点,需要有一个能够访问和查询多个地图的函数,而不是仅仅依赖于单一地图。

  2. 坐标系统的改进:当前的系统可能只考虑一个地图的坐标,接下来需要引入更高层次的坐标系统,允许在多个地图之间进行查询。这个新的坐标系统应当可以跨越多个地图,类似于将“世界”空间引入到系统中。

  3. 地图查询的方式:提出了通过传递包含世界坐标的查询来访问特定瓷砖地图。每个瓷砖地图的位置和坐标需要精确管理,以确保查询能够正确地定位到目标地图。系统中的每个坐标应当指向正确的瓷砖地图,而不是简单的查询单个地图。

  4. 世界结构与地图存储:世界结构被设计用来包含所有的城镇地图(town maps),而每个城镇地图又包含具体的瓷砖地图。此结构可以帮助组织和管理地图数据,确保系统能够有效地进行地图之间的切换。

  5. 数学和坐标计算:系统使用一定的数学运算来计算各个地图之间的坐标关系,这需要确保每次查询都能正确地转换坐标,特别是在多张地图的情况下。这里的数学包括对坐标的“跨越”计算,以确保可以精确访问任何给定位置。

  6. 数据的返回和验证:通过这种方式查询地图时,系统还需要检查返回的数据是否有效。如果某个坐标位置的地图有效,那么返回该地图。如果无效,则需要根据预定义的逻辑进行处理。

  7. 未来的工作:尽管这个系统的基本框架已经搭建起来,但还有许多细节需要完善。特别是在稀疏性和效率方面,需要进一步优化如何管理大量的地图和坐标数据,以便在大型世界中流畅运行。

总的来说,核心目标是创建一个可以高效访问、管理多个瓷砖地图的系统,并确保在查询过程中能够精确地处理坐标转换和数据验证。

在这里插入图片描述
在这里插入图片描述

简短的进度回顾

本次的工作目标是扩展平铺地图的概念,从单一的地图扩展到多个地图。为了能够在不同的平铺地图之间进行移动,引入了第二层坐标系统,即x和y坐标。这允许从不同的地图中提取正确的tile map。

目前,虽然系统运作依然像处理单一地图一样,但目标是让它能够在不同的地图之间进行切换。因此,需要处理新的坐标系统,确保能够正确地识别和提取目标地图。在这个过程中,也注意到一些渲染坐标问题,特别是关于平铺地图的坐标与渲染坐标之间的关系,此外还需要考虑像素和这些坐标之间的转换。

目前的工作状态良好,尽管存在一些细节和技术难点,特别是在处理不同坐标和地图之间的关系上,但总体进展顺利。虽然这些问题还没有完全解决,但接下来的工作将专注于在多个城镇地图之间移动,这是一个更为复杂和有趣的任务。这一阶段结束后,将为接下来的更复杂的工作打下基础,为更大范围的开发做准备。

为什么玩家有时会在碰到墙壁前停留一个像素?

这个问题我貌似没遇到

当玩家在接近墙壁时,有时会停在离墙一个像素的地方,这个问题通常是由于玩家的移动逻辑和碰撞检测方式导致的。在游戏中,玩家通常会按照固定的步长(例如每次移动两个像素)来进行移动,但如果玩家正朝着墙壁移动并且目标位置会让玩家穿过墙壁,系统就会发现无法继续移动。因为玩家在移动时会根据一定的步长前进,而这个步长可能会导致玩家停在距离墙壁一个像素的地方,因为下一步会导致穿透墙壁。

解释原因:

  • 玩家每帧移动一定的像素(如2个像素),并且在进行碰撞检测时,系统检查玩家的目标位置是否与墙壁发生冲突。
  • 如果玩家试图前进时,下一步会让玩家进入墙内(如距离墙壁不足2个像素),那么系统就会阻止玩家移动。由于玩家每次移动的距离较大,玩家停下来的位置可能恰好是距离墙壁1个像素的位置,而不是停在墙壁前面。

解决方案:

为了解决这个问题,可以对玩家的移动逻辑进行优化。一个可能的解决办法是让玩家每次移动时,不是直接前进一个固定的步长,而是逐步调整步长。例如,在接近墙壁时,如果检测到无法完全移动,那么可以减少移动的距离,使玩家停在离墙壁合适的位置,而不是停在墙壁内部。

还可以采用更细粒度的碰撞检测,在每次尝试移动时,先检查是否有障碍物阻挡玩家的路径。如果有阻挡,可以尝试将玩家推回或调整移动路径,避免玩家被卡住。

总结:

  1. 问题:玩家在接近墙壁时,移动可能停在墙壁前1个像素的位置,因为固定步长的移动与碰撞检测的关系导致无法进一步移动。
  2. 解决方法:优化玩家的移动逻辑,减少步长或调整碰撞检测机制,以避免玩家停在不合适的位置。

这种情况通常出现在初期的简单碰撞检测系统中,当开发者准备加入更复杂的运动系统时,这个问题通常会被解决。

使用 bool32 而不是 8 位 bool 有什么优势?

在处理计算机系统中的数据时,选择合适的数据类型和大小对于性能至关重要。使用不适合处理器的值,尤其是那些处理器并不直接支持的值,会导致效率低下。因此,通常情况下,32位数据(而不是8位或其他不适合的值)是处理器最容易处理的值,这对于提升性能和优化计算效率很有帮助。

关键点:

  1. 选择合适的数值大小:对于处理器来说,32位值通常比8位值更容易处理,因此通常推荐使用32位值来进行计算和数据存储。8位值并不总是最方便的,因为它并不适应于处理器的计算边界,比如处理器通常倾向于处理3到5倍数的边界。

  2. 存储数据的方式:在存储数据时,通常建议将数据打包成位域,这样有助于优化空间和计算效率。这种方法将多个小数据合并成一个更大的单位,以减少存储和访问时间。

  3. 计算过程中的选择:在进行计算时,使用32位值通常会比使用8位值更高效,因为32位值与大多数现代处理器的工作方式更兼容,有助于加速处理过程。

总结:

在数据存储和计算中,处理器更倾向于处理32位数据类型,因为它们更符合处理器的工作方式,能够提高性能和效率。虽然可以使用其他位数的数据类型(如8位),但通常不如32位数据那么高效,尤其是在现代处理器中。

能否简要讲解一下如何将瓦片数据编码成一个 uint32?

在编码tile(或瓷砖)时,数据通常需要以特定的方式存储。首先,32位(32)单位的数据通常用于表示某个瓷砖的占用情况,即通过存储0或1来标示该瓷砖是否被占用。这是最基础的编码方法,主要用于简单的占用标记。

基本步骤:

  1. 基础占用标记:在最简单的实现中,32位的单位可以用于存储是否占用的标志。例如,0表示未占用,1表示已占用。这样可以很高效地标示出每个瓷砖的状态。

  2. 复杂化的瓷砖结构:随着系统的复杂化,单纯的0和1可能无法满足需求。未来的瓷砖结构可能需要包含更多的信息,而不仅仅是占用状态。例如,瓷砖可能需要存储更多的属性,如它是水地、土地、或者其他类型的地形。这样,每个瓷砖不仅仅是一个简单的标记,而是包含了更多的元数据。

  3. 属性管理:瓷砖的属性管理变得更加复杂。比如,可以为每个瓷砖指定具体的属性值,例如是否是“健康”地面,或是否具有某些特殊功能。这使得瓷砖不仅仅是占用或空闲的标记,还可能包含关于环境或状态的更多信息。

总结:

最初,编码瓷砖的占用情况较为简单,只需要存储占用标志(0或1)。但随着系统的扩展,瓷砖的编码将会变得更加复杂,可能包含多种属性信息,这些属性能够为游戏世界中的每个瓷砖提供更多的细节,如地形类型、状态或其他功能。

为什么保存 TileWidth 和 TileHeight 如果这些值从不改变?

碰撞检测中,左右碰撞有效而顶部和底部碰撞无效的原因,与游戏的虚假视角有关。在一些标准的平铺地图游戏中,虽然使用方形瓦片,但游戏中的角色和物体通常以伪三维的角度呈现,好像是从侧面看角色。这种视角造成了角色与障碍物之间的互动表现不同。例如,当角色走到障碍物(如石头)前时,虽然他与障碍物的上面或下面没有直接接触,但由于伪三维视角,角色的碰撞更侧重于左侧和右侧。当角色向前走时,它的碰撞检测只会检查某些点(通常是左、右边的三个点),而不是顶部和底部。因此,角色可以站在障碍物前面,或者稍微穿过它,而不被完全阻挡。

这种做法的代码实现通常只检查某些关键点的碰撞,例如角色的左右边缘,而不是完整的四个边。由于视角问题,顶部和底部的碰撞检测不太起作用,角色能够"穿越"这些区域,而不是完全停下。

结构体和类之间有什么区别?

结构体(struct)和类(class)之间的主要区别在于访问控制。结构体通常没有任何访问限制,成员默认是公开的,可以直接从外部访问。而类的成员默认是私有的,外部代码不能直接访问。可以通过访问控制符(如 publicprivate)来改变成员的访问权限。

举例来说,如果在主函数中创建一个结构体的实例并访问其成员(比如变量 x),是可以直接访问的,因为结构体成员默认是公开的。然而,如果是类,则需要使用访问控制符,若类的成员是私有的,那么外部无法直接访问,必须通过公共方法或属性来访问。

除此之外,结构体和类的其他行为是类似的,尤其是在继承方面。类和结构体都可以继承其他类或结构体,访问控制符(publicprivate)的不同可以影响继承的方式。例如,可以通过继承私有类或结构体,或者使用 publicprivate 来控制子类或子结构体的成员访问权限。

总体而言,结构体和类之间的根本区别就在于默认的访问权限,结构体成员默认是公开的,而类的成员默认是私有的。

你总是使用 int32 吗,还是可以只用 int?

在C语言中,使用数据类型(如 int)时,传统上并不确定其大小。具体大小可能取决于硬件和编译器,可能是8位、16位、32位,甚至在现代计算机上可能是64位。因此,使用 int 时并不知道能存储多大的数字。在一些平台上,可以指定最小的大小,但一般没有强制要求特定的位数。

编程时,通常会根据平台需求指定一个合理的大小。例如,可能会选择32位作为整数大小,因为它适合常见的需求。尽管使用 int 没有错,但它的大小不确定,可能导致更难控制。因此,明确指定数据类型的大小(如32位或64位)通常能确保更好的控制和预期的行为。

那么 int32 是因为你想为 32 位计算机制作游戏吗?

这里的讨论主要围绕数据类型和计算机架构的优化问题,尤其是32位与64位的数据处理。对于某些操作,32位整数足够高效,特别是在许多现代计算机中,它们具有良好的对齐和计算效率。32位整数通常能够满足大多数需求,而且它们的计算成本相对较低,不会占用过多空间。

64位整数虽然在一些情况下提供更多的存储空间,但也带来了更高的计算成本,因为它们需要更多的内存和处理时间。在某些平台上,虽然使用64位整数能够处理更大的数字,但实际上很多时候并不需要额外的32位数据,因此不一定要使用64位数据类型。

当在更现代的64位架构中进行编译时,程序员往往会考虑是否真的需要64位整数,因为它们的存储空间和计算开销可能超过了实际的需求。如果只需要32位的数据处理,使用64位可能会导致性能浪费。

总的来说,选择适当的数据类型取决于平台需求和实际用途,而在某些情况下,32位整数在计算和存储上更为高效。

玩家在对角线方向移动时比预期更快。你打算修复这个问题吗?

在游戏中,玩家在对角线方向上的移动速度比预期的要快,这个问题的解决方法已经在代码中有所提及。通过使用向量来处理移动时,代码将会自动修正对角线速度较快的问题,因此这一点在实现后会得到修复。如果没有查看源代码,可能会错过这一重要细节。

对于代码重复和游戏实体(如敌人)的处理,计划是待进一步开发时再处理。遗传(继承)可能是一个解决重复代码问题的方法,但目前在这方面没有明确的解决方案,未来会根据需求进一步完善。

至于代码的其他问题,讨论似乎已经结束,当前阶段没有更多问题需要解决,基本上完成了当前的开发工作。


http://www.kler.cn/a/418220.html

相关文章:

  • 【目标检测】YOLO:深度挖掘YOLO的性能指标。
  • electron-vite_14窗口默认全屏铺满
  • Mybatis:CRUD数据操作之多条件查询及动态SQL
  • 微信小程序首页实现轮廓图及动态渲染的高级教程
  • Redis主从架构
  • java-a+b 开启java语法学习
  • 文件包含(精讲)
  • 【论文复现】StreamPETR
  • 数据分析自动化工具对比指南Cursor Composer和Google Data Science Agent
  • 第八课 Unity编辑器创建的资源优化_特效篇(Particle System)详解
  • Spring Web MVC(详解上)
  • 【BUUCTF】warmup_csaw_2016
  • [2024年1月28日]第15届蓝桥杯青少组stema选拔赛C++中高级(第二子卷、编程题(1))
  • 给定一个整数可能为正,0,负数,统计这个数据的位数.
  • K8S网络系列--Flannel网络下UDP、VXLAN模式的通信流程机制分析
  • 【接口封装】——11、Qt 的单例模式
  • Python 元组详解
  • pycharm链接neo4j(导入文件)
  • SpringBoot项目的配置文件
  • 零拷贝相关知识点(二)
  • Paper -- 建筑物高度估计 -- 基于深度学习、图像处理和自动地理空间分析的街景图像建筑高度估算
  • 【赵渝强老师】PostgreSQL的段、区和块
  • 太古可口可乐香港通过SAP S/4HANA推动数字化转型
  • 延时系统建模,整数延时与分数延时,连续传函与离散传函,Pade近似与Thiran近似,Matlab实现
  • 会议直击|美格智能亮相2024紫光展锐全球合作伙伴大会,融合5G+AI共拓全球市场
  • SpringBoot条件装配@Conditional