你的建议可行。
您可以通过这种模式来实例化场景:
var room_scene = load("res://zone/room_type/room_1.tscn")
var room_instance = room_scene.instance()
parent.add_child(room_instance)
我还会提醒你给room_instance一个职位。
因此,正如您所说,您可以构建传递给 load 的字符串。
我建议将帽子逻辑放在自动加载中并在需要的地方调用它。
但是,上面的代码会在加载场景时停止游戏。而是使用ResourceLoader 进行后台加载。
首先你需要调用load_interactive,它会给你一个ResourceInteractiveLoader对象:
loader = ResourceLoader.load_interactive(path)
然后你需要在加载器上调用poll。直到它返回ERR_FILE_EOF。在这种情况下,您可以使用get_resource 获取场景:
if loader.poll() == ERR_FILE_EOF:
scene = loader.get_resource()
否则,这意味着对poll 的调用不足以完成加载。
这个想法是将对poll 的调用分散到多个帧中(例如,通过从_process 调用它)。
您可以拨打get_stage_count 来获取您需要拨打poll 的次数,get_stage 会告诉您到目前为止您已经拨打了多少次。
因此,您可以使用它们来计算进度:
var progress = float(loader.get_stage()) / loader.get_stage_count()
这为您提供了从 0 到 1 的值。其中0 根本没有加载,而1 已完成。 乘以 100 得到要显示的百分比。您也可以将它用作进度条。
问题是我不知道这是否是一个好的解决方案,因为它会创建很多场景
这不是问题。
我是否只是使用包含文件夹路径的字符串
是的。
那我假设我把文件夹里的所有文件都拿到了,随机选择一个
不一定。
你可以确保文件夹中的所有场景都具有相同的名称,除了一个数字,那么你只需要知道文件夹中有多少个场景,然后选择一个数字。
但是,您可能不希望完全随机。根据您生成房间的方法,您可能希望:
- 根据房间的连接选择房间。以确保它连接到相邻的房间。
- 衡量一个房间应该有多普通或少见。
因此,拥有包含该信息的文件(例如 json 或 csv 文件)会很有用。然后,负责加载场景的自动加载代码将该文件加载到数据结构(例如字典或数组)中,从中可以选择要加载的场景,考虑到此处指定的任何权重或约束。
我会假设您的房间存在于网格上,并且可以有通往 NORTH、SOUTH、EAST、WEST 的门。我还会假设玩家可以回溯,所以布局必须是持久的。
我不知道你会领先多远。您可以选择一次生成所有地图,或者在玩家尝试进入时生成房间,或者在前面生成几个房间。
如果您要在玩家尝试进入时生成,您将需要一个房间过渡动画,您可以在其中隐藏场景加载(使用背景加载方法)。
但是,您不应该生成已经生成的房间。因此,如果已经生成了房间,请保留一个文本网格(一个数组),您可以在其中存储。您将首先检查网格(数组),如果已生成,则无需执行任何操作。但如果没有,那么你需要随机选择一个房间。
但是等等!例如,如果您从南面进入,您选择的房间必须有南门才能返回。如果您按房间的门来组织房间,那么您可以从有南门的房间中挑选 - 在本例中。
事实上,您需要考虑您已经生成的任何相邻房间的门。因此,将生成的房间有哪些门存储在网格(数组)中。因此,您可以稍后从阵列中读取新房间需要哪些门。如果没有房间,随意决定是否要在那儿有一扇门。然后从有这些门的系列中随机选择一个房间。
您的房间组将是 NORTH、SOUTH、EAST、WEST 的组合。生成列表的一种方法是为每个方向赋予 2 的幂。例如:
然后找出集合,你可以数数,二进制表示给出门。例如 10 = 8 + 2 -> 西和南。
这些是您的房间组合。重申一下,查看进入您要生成的房间的门已经生成的邻居。如果没有房间,随意决定是否要在那儿有一扇门。这应该会告诉您需要从哪组房间中选择生成。
这类似于使用自动平铺解决方案的方法。您可能想了解它是如何工作的。
现在假设集合中的房间有权重(所以有些房间比较常见,有些比较少见),你需要随机挑选。
这是一般算法:
- 对权重求和。
- 将权重归一化(将权重除以总和,因此它们加起来为 1)。
- 累积归一化权重。
- 生成一个从 0 到 1 的随机数,最后累积的大于我们得到的随机数的归一化权重是多少。
由于您可能会多次从同一个集合中挑选房间,因此您可以计算并存储累积的归一化权重(我们称它们为最终权重),因此您不必每次都计算它们。
你可以这样计算它们:
var total_weight:float = 0.0
for option in options:
total_weight = total_weight + option.weight
var final_weight:float = 0.0
var final_weights:Array = []
for option in options:
var normalized_weight = option.weight / total_weight
final_weight = final_weight + normalized_weight
final_weights.append(final_weight)
然后你可以这样选择:
var randomic:float = randf()
for index in final_weights.size():
if final_weights[index] > randomic:
return options[index]
一旦您选择了要生成的房间,您就可以加载它(例如使用背景加载方法)、实例化它并将其添加到场景树中。记得在世界上给出一个位置。
还要记得更新网格(数组)信息。你从一组有特定门的房间中选择了一个房间。您想存储它以考虑生成相邻房间。
顺便说一句,如果您需要大规模寻路(从一个房间到另一个房间),您也可以使用该网格。