如何在2D侧滚动游戏中检测“房间”?


24

我正在寻找一种能够识别您可以在游戏中创建的某些类型的建筑物和房间的系统,例如Terraria如何检测“住所”。在该游戏中,可以通过构建满足一组条件的区块区域来在基于图块的世界中构建房屋:

  1. 该区域通过玩家放置的块与“外部”完全隔离。
  2. 该区域可以容纳5x7的矩形。
  3. 封闭区域内至少有一张桌子,一个光源和椅子。
  4. 有一个门从该区域引出。
  5. Terraria同时具有前景和背景图块层。该区域的整个背景必须充满玩家放置的方块。

如何有效地检测玩家何时构造了适当大小的区域,以及如何有效地检查该区域是否包含所有必需的家具/组件?

满足所有住房要求的内部区域示例:

在此处输入图片说明


5
您能详细说明一下吗?您所说的“建筑类型”是什么意思,Terraria中的“住宅”是什么?请记住,并不是每个人都玩过该游戏,如果您想让人们提供帮助,也请关注一个问题,并确保该问题有明确的答案(不是意见)
TomTsagk

1
对于类型,我指的是使用的不同组件/平铺。我的问题在下面解决。感谢您的帮助,我将尽力阐述更多信息,并在以后的问题上更加具体。
贝尔纳多·贝克尔

1
顺便说一句,请确保房间住宅之间存在差异。项目符号列表建议您将它们视为相同的定义。以Terraria为例,即使敌人不符合居住条件,他们也不会在房间中产卵(例如,缺少桌子,或只有5x5的尺寸)
扁平化

Answers:


37

我对Terraria不熟悉,但是可以使用Flood-fill算法轻松完成。

您可以检查图块,而不是像素,并检查每个图块,评估算法是否可以继续检查其他图块,同时将其存储在数组中或列出在此过程中找到的对象。

该算法从角色所在的图块开始。您可以每隔1秒钟,2秒钟开始...进行调整即可找到最佳间隔。

防止算法运行太长时间也是一个好主意,这可以通过限制算法每次运行可运行的切片数来实现,否则,当角色处于开放区域时,算法将导致较长的延迟。

编辑

如评论中所述,您可以在何时启动算法时使用其他方法,例如玩家何时更改磁贴,或磁贴具有am I modified?变量,true启动算法。但是,您必须谨慎使用此方法:

  • 如果修改了房间的一部分而不是角色所在的一部分,该怎么办?可能是其他玩家更改了图块,或者发生了环境事件,或者图块的生存期结束了。您的角色将不知道所做的修改,并且不会执行算法来检测更新的房间,这是容易出错的情况。

您可以实施某种方法来检测角色所不在的图块上的这些修改,但是按间隔执行算法是最简单的方法,并且不易出错。只要确保不对每个帧执行泛洪填充。

编辑结束


9
为什么不只在“玩家放置的方块”图块之间填充水?这可以防止或减少在开放区域中的无限洪水泛滥(只要洞穴/豪宅没有被“玩家放置的方块”填满)。
jimbo1qaz

20
为什么要以固定间隔运行它?当然,您可以在放置块(或将其销毁,如果适用,并且两种情况都可以在每个块的摊销固定时间完成)时或在加载地图的特定部分时运行它,然后存储来自那里。
NotThatGuy

3
@immibis:我很确定Terraria不需要您换地板。我也不希望游戏会根据谁放置瓷砖来改变它的房间识别行为。如果我要在悬崖附近建一个房间怎么办?
平坦

3
Terraria要求放置背景墙,并且不会形成具有自然背景污垢/岩石的房屋。它确实只检查玩家放置的方块。
loa_in_

3
为了节省CPU,我只对块更改运行算法,然后存储每个块的状态。有了这个,这很简单isRoom()
Derb先生

3

就像@Ferreira da Selva所说的那样,请尝试洪水填充算法。但是,在运行算法时可以使用一些不同的条件来确定是否将其封闭。

例如,对于每个图块,您检查是否有背景图块,如果没有,则知道它没有被封闭。或者,您也可以通过将其分成多个帧来执行延迟执行,从而减轻处理器的负担并减少延迟。或者,您可以创建玩家必须遵守的房间大小限制。

结合使用这些功能可以使您更高效,更有效地做到这一点。


3

计算机科学中有两个难题。命名,缓存无效和一一错误。

这是一个缓存失效问题。

如果您有“这是里面”的记录,则每当放置或删除一个块时,就很容易通过泛洪填充来更新它及其区域。

要对此进行优化,您可能需要一组“内部”层。

“单元”是被玩家放置的方块(一定大小)包围的区域。

“房间”是带有背景图块的单元格。

“内部”是一间带门,灯和椅子的房间。

放置玩家放置的前景块时,请沿顺时针/逆时针方向走,以查看是否形成了新的单元格。移除放置在播放器上的前景块时,请检查它是否破坏了任何单元格—如果是这样,请查看通过合并这两者而形成的新单元格。

当新的单元格形成或未形成时,请检查其是否为房间或内部。

单元可以跟踪一个房间需要多少背景图块。然后简单地计数一个单元格的形成,在单元格中添加或移除背景图块,就可以确定它是否为房间。

同样,单元可以跟踪其中有多少把椅子和光源(实际上是各种物体)。然后内部检查是微不足道的。

也可以计算入口数。


因此,我们用“单元格”扩充了地图。添加或删除图块时,我们会检查位置的单元格,并增加/减少单元格中的计数。

添加或删除前景块时,请使用顺时针/逆时针行走来定义单元的内部和外部。由于像元的大小有限,因此此步行将采取有限的步骤。

作为奖励,您现在可以以一种便宜的方式谈论“豪华”房间,或“房间被圣泉赐福”,或与房间有关的其他任何东西,因为房间内有每种对象类型的计数。(或者,由于房间的大小有限,只需执行一次迭代;这将删除缓存)。

每个位置最多包含一个单元格,因此您可以在主地图上存储每个位置的单元格ID。


0

当使用泛洪填充算法时,还要设置一个变量,该变量将随着每个被检查的图块而增加,因此,如果它大于35(7 * 5,即房间的最大大小),它将停止检查!


7 * 5是必须容纳在房间内的最小尺寸矩形
Rick
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.