自定义房间生成规则, 开发中

This commit is contained in:
小李xl 2024-01-24 21:43:55 +08:00
parent ce45ec6d6a
commit eb4a25a7f7
30 changed files with 371 additions and 142 deletions

1
.gitignore vendored
View File

@ -19,3 +19,4 @@
/DungeonShooting_ExcelTool/bin /DungeonShooting_ExcelTool/bin
/DungeonShooting_Godot/DungeonShooting.sln.DotSettings.user /DungeonShooting_Godot/DungeonShooting.sln.DotSettings.user
/DungeonShooting_Godot/.VSCodeCounter /DungeonShooting_Godot/.VSCodeCounter
**/*.txt

View File

@ -2,11 +2,7 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
<<<<<<< HEAD uid="uid://b72ww741x2t0w"
uid="uid://wew7xnxc4d50"
=======
uid="uid://c08d7xo84ssqp"
>>>>>>> faff39f870b1097c233b529865b4f3ee2311c8a3
path="res://.godot/imported/Preview.png-e48e389971aff40736b911be53ae62ea.ctex" path="res://.godot/imported/Preview.png-e48e389971aff40736b911be53ae62ea.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://mnc7p56vjvd2"
path="res://.godot/imported/gun10.png-f740f5104fd9c145ecc2e63b27a6fb04.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resource/sprite/weapon/weapon0011/gun10.png"
dest_files=["res://.godot/imported/gun10.png-f740f5104fd9c145ecc2e63b27a6fb04.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://b4exgoa8t0wny" uid="uid://b4exgoa8t0wny"
path="res://.godot/imported/bow.png-9ae685914082766e6dbcd1eaddb43b40.ctex" path="res://.godot/imported/bow.png-88942d9562b550ee90573ad2cdb4bb92.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://resource/sprite/weapon/bow.png" source_file="res://resource/sprite/weapon/weapon0012/bow.png"
dest_files=["res://.godot/imported/bow.png-9ae685914082766e6dbcd1eaddb43b40.ctex"] dest_files=["res://.godot/imported/bow.png-88942d9562b550ee90573ad2cdb4bb92.ctex"]
[params] [params]

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cphawlk2w0w6w"
path="res://.godot/imported/weapon0013.png-ebf877c1ae1b135ec79dd1b6a7ae1165.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resource/sprite/weapon/weapon0013/weapon0013.png"
dest_files=["res://.godot/imported/weapon0013.png-ebf877c1ae1b135ec79dd1b6a7ae1165.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://cuivqyq32tjan"
path="res://.godot/imported/weapon0014-export.png-f1691475edd2682499f71dfe7d46110d.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resource/sprite/weapon/weapon0013/weapon0014-export.png"
dest_files=["res://.godot/imported/weapon0014-export.png-f1691475edd2682499f71dfe7d46110d.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://deqflkjkgkebd"
path="res://.godot/imported/weapon0014.png-231a4437579a4dfcadef71f1a72de1ed.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://resource/sprite/weapon/weapon0013/weapon0014.png"
dest_files=["res://.godot/imported/weapon0014.png-231a4437579a4dfcadef71f1a72de1ed.ctex"]
[params]
compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://c1tnh6laf172u" uid="uid://c1tnh6laf172u"
path="res://.godot/imported/gun3.png-d2428e7c1819cfb8a78ef87505aee0a3.ctex" path="res://.godot/imported/gun3.png-3eceb0c7c64a7bf84605307efa15f7f3.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://resource/sprite/weapon/gun3.png" source_file="res://resource/sprite/weapon/weapon0015/gun3.png"
dest_files=["res://.godot/imported/gun3.png-d2428e7c1819cfb8a78ef87505aee0a3.ctex"] dest_files=["res://.godot/imported/gun3.png-3eceb0c7c64a7bf84605307efa15f7f3.ctex"]
[params] [params]

View File

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://xafbhgrxmosy" uid="uid://xafbhgrxmosy"
path="res://.godot/imported/gun4.png-f47ef44de364483b033f38a2d031303c.ctex" path="res://.godot/imported/gun4.png-3a854e99c328550ec802a641bed4ce89.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://resource/sprite/weapon/gun4.png" source_file="res://resource/sprite/weapon/weapon0016/gun4.png"
dest_files=["res://.godot/imported/gun4.png-f47ef44de364483b033f38a2d031303c.ctex"] dest_files=["res://.godot/imported/gun4.png-3a854e99c328550ec802a641bed4ce89.ctex"]
[params] [params]

View File

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://c2eber1v7nb4j" uid="uid://c2eber1v7nb4j"
path="res://.godot/imported/gun5.png-da05c9e18ddc46a7f72168cb9c25449c.ctex" path="res://.godot/imported/gun5.png-dde9a0cdc02e2378517e9d271797761c.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://resource/sprite/weapon/gun5.png" source_file="res://resource/sprite/weapon/weapon0017/gun5.png"
dest_files=["res://.godot/imported/gun5.png-da05c9e18ddc46a7f72168cb9c25449c.ctex"] dest_files=["res://.godot/imported/gun5.png-dde9a0cdc02e2378517e9d271797761c.ctex"]
[params] [params]

View File

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://rlp8f2rgxlbf" uid="uid://rlp8f2rgxlbf"
path="res://.godot/imported/gun6.png-698dacce2603c9d452b55702363db8fc.ctex" path="res://.godot/imported/gun6.png-661eed06db2d1504a8e43f81aca88938.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://resource/sprite/weapon/gun6.png" source_file="res://resource/sprite/weapon/weapon0018/gun6.png"
dest_files=["res://.godot/imported/gun6.png-698dacce2603c9d452b55702363db8fc.ctex"] dest_files=["res://.godot/imported/gun6.png-661eed06db2d1504a8e43f81aca88938.ctex"]
[params] [params]

View File

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://bs6ukbtcmxuiw" uid="uid://bs6ukbtcmxuiw"
path="res://.godot/imported/gun7.png-9068807109603150cd0529909f81d6c1.ctex" path="res://.godot/imported/gun7.png-f1428c4b8a1ac62dafacd70a35e5813b.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://resource/sprite/weapon/gun7.png" source_file="res://resource/sprite/weapon/weapon0019/gun7.png"
dest_files=["res://.godot/imported/gun7.png-9068807109603150cd0529909f81d6c1.ctex"] dest_files=["res://.godot/imported/gun7.png-f1428c4b8a1ac62dafacd70a35e5813b.ctex"]
[params] [params]

View File

@ -3,15 +3,15 @@
importer="texture" importer="texture"
type="CompressedTexture2D" type="CompressedTexture2D"
uid="uid://2lcc20olyi5d" uid="uid://2lcc20olyi5d"
path="res://.godot/imported/gun8.png-a936b61cfb3713c19173bfa954b35ecd.ctex" path="res://.godot/imported/gun8.png-981667783ada37a774730057971adda6.ctex"
metadata={ metadata={
"vram_texture": false "vram_texture": false
} }
[deps] [deps]
source_file="res://resource/sprite/weapon/gun8.png" source_file="res://resource/sprite/weapon/weapon0020/gun8.png"
dest_files=["res://.godot/imported/gun8.png-a936b61cfb3713c19173bfa954b35ecd.ctex"] dest_files=["res://.godot/imported/gun8.png-981667783ada37a774730057971adda6.ctex"]
[params] [params]

View File

@ -41,6 +41,11 @@ public class DungeonConfig
/// </summary> /// </summary>
public int RoomCount => BattleRoomCount + RewardRoomCount + ShopRoomCount + OutRoomCount + BossRoomCount; public int RoomCount => BattleRoomCount + RewardRoomCount + ShopRoomCount + OutRoomCount + BossRoomCount;
/// <summary>
/// 房间最大层级
/// </summary>
public int MaxLayer = 5;
//----------------------- 地牢编辑使用 ------------------------- //----------------------- 地牢编辑使用 -------------------------
/// <summary> /// <summary>
/// 是否指定了房间 /// 是否指定了房间

View File

@ -65,7 +65,7 @@ public class DungeonGenerator
private int _id; private int _id;
//下一个房间类型 //下一个房间类型
private DungeonRoomType _nextRoomType = DungeonRoomType.Battle; private DungeonRoomType _nextRoomType = DungeonRoomType.None;
//间隔 //间隔
private int _roomMinInterval = 2; private int _roomMinInterval = 2;
@ -79,9 +79,6 @@ public class DungeonGenerator
private float _roomVerticalMinDispersion = -0.6f; private float _roomVerticalMinDispersion = -0.6f;
private float _roomVerticalMaxDispersion = 0.6f; private float _roomVerticalMaxDispersion = 0.6f;
//房间最大层级
private int _maxLayer = 5;
//区域限制 //区域限制
private bool _enableLimitRange = true; private bool _enableLimitRange = true;
private int _rangeX = 120; private int _rangeX = 120;
@ -98,18 +95,8 @@ public class DungeonGenerator
//地牢房间规则处理类 //地牢房间规则处理类
private DungeonRule _rule; private DungeonRule _rule;
private enum GenerateRoomErrorCode //上一个房间
{ private RoomInfo prevRoomInfo = null;
NoError,
//超出区域
OutArea,
//没有合适的位置
NoSuitableLocation
// //碰到其他房间或过道
// HasCollision,
// //没有合适的门
// NoProperDoor,
}
public DungeonGenerator(DungeonConfig config, SeedRandom seedRandom) public DungeonGenerator(DungeonConfig config, SeedRandom seedRandom)
{ {
@ -180,62 +167,23 @@ public class DungeonGenerator
if (StartRoomInfo != null) return false; if (StartRoomInfo != null) return false;
_rule = rule; _rule = rule;
_nextRoomType = _rule.GetNextRoomType(null);
//用于排除上一级房间
var excludePrevRoom = new List<RoomInfo>();
//上一个房间
RoomInfo prevRoomInfo = null;
var chainTryCount = 0;
var chainMaxTryCount = 3;
//最大尝试次数 //最大尝试次数
var maxTryCount = 1000; var maxTryCount = 2000;
//当前尝试次数 //当前尝试次数
var currTryCount = 0; var currTryCount = 0;
//如果房间数量不够, 就一直生成 //如果房间数量不够, 就一直生成
while (!_rule.CanOverGenerator() || EndRoomInfos.Count == 0) while (!_rule.CanOverGenerator())
{ {
if (_nextRoomType == DungeonRoomType.None)
{
_nextRoomType = _rule.GetNextRoomType(prevRoomInfo);
}
var nextRoomType = _nextRoomType; var nextRoomType = _nextRoomType;
//上一个房间 //上一个房间
RoomInfo tempPrevRoomInfo; var tempPrevRoomInfo = _rule.GetConnectPrevRoom(prevRoomInfo, nextRoomType);
if (nextRoomType == DungeonRoomType.Inlet)
{
tempPrevRoomInfo = null;
}
else if (nextRoomType == DungeonRoomType.Boss)
{
tempPrevRoomInfo = FindMaxLayerRoom(excludePrevRoom);
}
else if (nextRoomType == DungeonRoomType.Outlet || nextRoomType == DungeonRoomType.Reward || nextRoomType == DungeonRoomType.Shop || nextRoomType == DungeonRoomType.Event)
{
tempPrevRoomInfo = prevRoomInfo;
}
else if (nextRoomType == DungeonRoomType.Battle)
{
if (chainTryCount < chainMaxTryCount)
{
if (prevRoomInfo != null && prevRoomInfo.Layer >= _maxLayer - 1) //层数太高, 下一个房间生成在低层级
{
tempPrevRoomInfo = RoundRoomLessThanLayer(Mathf.Max(1, _maxLayer / 2));
}
else
{
tempPrevRoomInfo = prevRoomInfo;
}
}
else
{
tempPrevRoomInfo = Random.RandomChoose(RoomInfos);
}
}
else
{
tempPrevRoomInfo = Random.RandomChoose(RoomInfos);
}
//生成下一个房间 //生成下一个房间
var errorCode = GenerateRoom(tempPrevRoomInfo, nextRoomType, out var nextRoom); var errorCode = GenerateRoom(tempPrevRoomInfo, nextRoomType, out var nextRoom);
@ -250,7 +198,6 @@ public class DungeonGenerator
else if (nextRoomType == DungeonRoomType.Boss) //boss房间 else if (nextRoomType == DungeonRoomType.Boss) //boss房间
{ {
BossRoomInfos.Add(nextRoom); BossRoomInfos.Add(nextRoom);
excludePrevRoom.Clear();
} }
else if (nextRoomType == DungeonRoomType.Outlet) else if (nextRoomType == DungeonRoomType.Outlet)
{ {
@ -259,8 +206,6 @@ public class DungeonGenerator
else if (nextRoomType == DungeonRoomType.Battle) else if (nextRoomType == DungeonRoomType.Battle)
{ {
BattleRoomInfos.Add(nextRoom); BattleRoomInfos.Add(nextRoom);
chainTryCount = 0;
chainMaxTryCount = Random.RandomRangeInt(1, 3);
} }
else if (nextRoomType == DungeonRoomType.Reward) else if (nextRoomType == DungeonRoomType.Reward)
{ {
@ -270,37 +215,14 @@ public class DungeonGenerator
{ {
ShopRoomInfos.Add(nextRoom); ShopRoomInfos.Add(nextRoom);
} }
var prev = prevRoomInfo;
prevRoomInfo = nextRoom; prevRoomInfo = nextRoom;
_nextRoomType = _rule.GetNextRoomType(prevRoomInfo); _rule.GenerateRoomSuccess(prev, nextRoom);
_nextRoomType = _rule.GetNextRoomType(nextRoom);
} }
else //生成失败 else //生成失败
{ {
if (nextRoomType == DungeonRoomType.Boss) _rule.GenerateRoomFail(prevRoomInfo, nextRoomType);
{
//生成boss房间成功
excludePrevRoom.Add(tempPrevRoomInfo);
if (excludePrevRoom.Count >= RoomInfos.Count)
{
//全都没找到合适的, 那就再来一遍
excludePrevRoom.Clear();
}
}
else if (nextRoomType == DungeonRoomType.Outlet)
{
//生成结束房间失败, 那么只能回滚boss房间
if (prevRoomInfo != null)
{
var bossPrev = prevRoomInfo.Prev;
BossRoomInfos.Remove(prevRoomInfo);
RollbackRoom(prevRoomInfo);
_nextRoomType = _rule.GetNextRoomType(bossPrev);
prevRoomInfo = null;
}
}
else if (nextRoomType == DungeonRoomType.Battle)
{
chainTryCount++;
}
//Debug.Log("生成第" + (_count + 1) + "个房间失败! 失败原因: " + errorCode); //Debug.Log("生成第" + (_count + 1) + "个房间失败! 失败原因: " + errorCode);
if (errorCode == GenerateRoomErrorCode.OutArea) if (errorCode == GenerateRoomErrorCode.OutArea)
@ -348,7 +270,7 @@ public class DungeonGenerator
{ {
//随机选择一个房间 //随机选择一个房间
var list = RoomGroup.GetRoomList(roomType); var list = RoomGroup.GetRoomList(roomType);
if (list.Count == 0) //如果没有指定类型的房间, 就生成战斗房间 if (list.Count == 0) //如果没有指定类型的房间, 或者房间数量不够, 就生成战斗房间
{ {
roomSplit = RoomGroup.GetRandomRoom(DungeonRoomType.Battle); roomSplit = RoomGroup.GetRandomRoom(DungeonRoomType.Battle);
} }
@ -483,8 +405,18 @@ public class DungeonGenerator
return GenerateRoomErrorCode.NoError; return GenerateRoomErrorCode.NoError;
} }
//回滚一个房间 /// <summary>
private bool RollbackRoom(RoomInfo roomInfo) /// 设置上一个房间
/// </summary>
public void SetPrevRoom(RoomInfo roomInfo)
{
prevRoomInfo = roomInfo;
}
/// <summary>
/// 回滚一个房间
/// </summary>
public bool RollbackRoom(RoomInfo roomInfo)
{ {
if (roomInfo.Next.Count > 0) if (roomInfo.Next.Count > 0)
{ {
@ -512,8 +444,33 @@ public class DungeonGenerator
} }
RoomInfos.Remove(roomInfo); RoomInfos.Remove(roomInfo);
switch (roomInfo.RoomType)
{
case DungeonRoomType.Battle:
BattleRoomInfos.Remove(roomInfo);
break;
case DungeonRoomType.Inlet:
StartRoomInfo = null;
break;
case DungeonRoomType.Outlet:
EndRoomInfos.Remove(roomInfo);
break;
case DungeonRoomType.Boss:
BossRoomInfos.Remove(roomInfo);
break;
case DungeonRoomType.Reward:
RewardRoomInfos.Remove(roomInfo);
break;
case DungeonRoomType.Shop:
ShopRoomInfos.Remove(roomInfo);
break;
case DungeonRoomType.Event:
break;
}
roomInfo.Destroy(); roomInfo.Destroy();
_id--; _id--;
_nextRoomType = DungeonRoomType.None;
return true; return true;
} }
@ -521,7 +478,7 @@ public class DungeonGenerator
/// 寻找层级最高的房间 /// 寻找层级最高的房间
/// </summary> /// </summary>
/// <param name="exclude">排除的房间</param> /// <param name="exclude">排除的房间</param>
private RoomInfo FindMaxLayerRoom(List<RoomInfo> exclude) public RoomInfo FindMaxLayerRoom(List<RoomInfo> exclude = null)
{ {
RoomInfo temp = null; RoomInfo temp = null;
foreach (var roomInfo in RoomInfos) foreach (var roomInfo in RoomInfos)
@ -541,7 +498,7 @@ public class DungeonGenerator
/// <summary> /// <summary>
/// 随机抽取层级小于 layer 的房间 /// 随机抽取层级小于 layer 的房间
/// </summary> /// </summary>
private RoomInfo RoundRoomLessThanLayer(int layer) public RoomInfo RoundRoomLessThanLayer(int layer)
{ {
var list = new List<RoomInfo>(); var list = new List<RoomInfo>();
foreach (var roomInfo in RoomInfos) foreach (var roomInfo in RoomInfos)

View File

@ -4,6 +4,10 @@
/// </summary> /// </summary>
public enum DungeonRoomType public enum DungeonRoomType
{ {
/// <summary>
/// 无
/// </summary>
None,
/// <summary> /// <summary>
/// 普通战斗房间, 进入该房间时会关上门, 并刷出若干波敌人, 消灭所有敌人后开门 /// 普通战斗房间, 进入该房间时会关上门, 并刷出若干波敌人, 消灭所有敌人后开门
/// </summary> /// </summary>

View File

@ -10,11 +10,14 @@ public abstract class DungeonRule
public SeedRandom Random { get; } public SeedRandom Random { get; }
public DungeonRoomGroup RoomGroup { get; }
public DungeonRule(DungeonGenerator generator) public DungeonRule(DungeonGenerator generator)
{ {
Generator = generator; Generator = generator;
Config = generator.Config; Config = generator.Config;
Random = generator.Random; Random = generator.Random;
RoomGroup = generator.RoomGroup;
} }
/// <summary> /// <summary>
@ -22,8 +25,23 @@ public abstract class DungeonRule
/// </summary> /// </summary>
public abstract bool CanOverGenerator(); public abstract bool CanOverGenerator();
/// <summary>
/// 获取指定房间类型与之相连的上一个房间对象
/// </summary>
public abstract RoomInfo GetConnectPrevRoom(RoomInfo prevRoomInfo, DungeonRoomType nextRoomType);
/// <summary> /// <summary>
/// 计算下一个房间类型 /// 计算下一个房间类型
/// </summary> /// </summary>
public abstract DungeonRoomType GetNextRoomType(RoomInfo prev); public abstract DungeonRoomType GetNextRoomType(RoomInfo prevRoomInfo);
/// <summary>
/// 执行生成指定房间成功
/// </summary>
public abstract void GenerateRoomSuccess(RoomInfo prevRoomInfo, RoomInfo roomInfo);
/// <summary>
/// 执行生成指定类型房间失败
/// </summary>
public abstract void GenerateRoomFail(RoomInfo prevRoomInfo, DungeonRoomType roomType);
} }

View File

@ -0,0 +1,13 @@
public enum GenerateRoomErrorCode
{
NoError,
//超出区域
OutArea,
//没有合适的位置
NoSuitableLocation
// //碰到其他房间或过道
// HasCollision,
// //没有合适的门
// NoProperDoor,
}

View File

@ -139,6 +139,12 @@ public class RoomInfo : IDestroy
/// 导航网格对象 /// 导航网格对象
/// </summary> /// </summary>
public NavigationRegion2D NavigationRegion { get; set; } public NavigationRegion2D NavigationRegion { get; set; }
/// <summary>
/// 在 DungeonGenerator 中是否可以回滚, 如果可以回滚, 那么当前房间就只会有一个 NextRoom
/// </summary>
public bool CanRollback { get; set; } = false;
public bool IsDestroyed { get; private set; } public bool IsDestroyed { get; private set; }
private bool _openDoorFlag = true; private bool _openDoorFlag = true;

View File

@ -160,6 +160,7 @@ public class DungeonRoomGroup : IClone<DungeonRoomGroup>
foreach (var roomType in Enum.GetValues<DungeonRoomType>()) foreach (var roomType in Enum.GetValues<DungeonRoomType>())
{ {
if (roomType == DungeonRoomType.None) continue;
InitAdRewardWeight(roomType, random); InitAdRewardWeight(roomType, random);
} }
} }

View File

@ -106,7 +106,7 @@ public partial class GameApplication : Node2D, ICoroutine
DungeonConfig = new DungeonConfig(); DungeonConfig = new DungeonConfig();
DungeonConfig.GroupName = "Test1"; DungeonConfig.GroupName = "Test1";
DungeonConfig.BattleRoomCount = 20; DungeonConfig.BattleRoomCount = 5;
} }
public override void _EnterTree() public override void _EnterTree()

View File

@ -61,12 +61,12 @@ public partial class Player : Role
ActivePropsPack.SetCapacity(1); ActivePropsPack.SetCapacity(1);
// debug用 // debug用
// RoleState.Acceleration = 3000; RoleState.Acceleration = 3000;
// RoleState.Friction = 3000; RoleState.Friction = 3000;
// RoleState.MoveSpeed = 500; RoleState.MoveSpeed = 500;
// CollisionLayer = 0; CollisionLayer = 0;
// CollisionMask = 0; CollisionMask = 0;
// GameCamera.Main.Zoom = new Vector2(0.5f, 0.5f); GameCamera.Main.Zoom = new Vector2(0.5f, 0.5f);
//GameCamera.Main.Zoom = new Vector2(0.2f, 0.2f); //GameCamera.Main.Zoom = new Vector2(0.2f, 0.2f);
// this.CallDelay(0.5f, () => // this.CallDelay(0.5f, () =>
// { // {

View File

@ -1,19 +1,65 @@
 
using System.Collections.Generic;
using Godot;
/// <summary> /// <summary>
/// 默认实现地牢房间规则 /// 默认实现地牢房间规则
/// </summary> /// </summary>
public class DefaultDungeonRule : DungeonRule public class DefaultDungeonRule : DungeonRule
{ {
//用于排除上一级房间
private List<RoomInfo> excludePrevRoom = new List<RoomInfo>();
private int chainTryCount = 0;
private int chainMaxTryCount = 3;
public DefaultDungeonRule(DungeonGenerator generator) : base(generator) public DefaultDungeonRule(DungeonGenerator generator) : base(generator)
{ {
} }
public override bool CanOverGenerator() public override bool CanOverGenerator()
{ {
return Generator.BattleRoomInfos.Count >= Config.BattleRoomCount; return Generator.BattleRoomInfos.Count >= Config.BattleRoomCount && Generator.EndRoomInfos.Count > 0;
} }
public override DungeonRoomType GetNextRoomType(RoomInfo prev) public override RoomInfo GetConnectPrevRoom(RoomInfo prevRoomInfo, DungeonRoomType nextRoomType)
{
if (nextRoomType == DungeonRoomType.Inlet)
{
return null;
}
else if (nextRoomType == DungeonRoomType.Boss)
{
return Generator.FindMaxLayerRoom(excludePrevRoom);
}
else if (nextRoomType == DungeonRoomType.Outlet || nextRoomType == DungeonRoomType.Reward || nextRoomType == DungeonRoomType.Shop || nextRoomType == DungeonRoomType.Event)
{
return prevRoomInfo;
}
else if (nextRoomType == DungeonRoomType.Battle)
{
if (chainTryCount < chainMaxTryCount)
{
if (prevRoomInfo != null && prevRoomInfo.Layer >= Config.MaxLayer - 1) //层数太高, 下一个房间生成在低层级
{
return Generator.RoundRoomLessThanLayer(Mathf.Max(1, Config.MaxLayer / 2));
}
else
{
return prevRoomInfo;
}
}
else
{
return Random.RandomChoose(Generator.RoomInfos);
}
}
else
{
return Random.RandomChoose(Generator.RoomInfos);
}
}
public override DungeonRoomType GetNextRoomType(RoomInfo prevRoomInfo)
{ {
if (Generator.StartRoomInfo == null) //生成第一个房间 if (Generator.StartRoomInfo == null) //生成第一个房间
{ {
@ -23,18 +69,64 @@ public class DefaultDungeonRule : DungeonRule
// { // {
// return DungeonRoomType.Reward; // return DungeonRoomType.Reward;
// } // }
else if (Generator.BattleRoomInfos.Count == Config.BattleRoomCount - 1) //最后一个房间是boss房间 else if (prevRoomInfo.RoomType == DungeonRoomType.Boss) //boss房间后生成结束房间
{ {
return DungeonRoomType.Outlet;
}
else if (Generator.BattleRoomInfos.Count >= Config.BattleRoomCount) //战斗房间已满
{
if (Generator.BossRoomInfos.Count < Config.BossRoomCount) //最后一个房间是boss房间
{
if (RoomGroup.BossList.Count == 0) //没有预设boss房间
{
return DungeonRoomType.Battle;
}
//生成boss房间
return DungeonRoomType.Boss; return DungeonRoomType.Boss;
} }
else if (Generator.BattleRoomInfos.Count >= Config.BattleRoomCount) //结束房间
{
return DungeonRoomType.Outlet;
}
else if (prev.RoomType == DungeonRoomType.Boss) //生成结束房间
{
return DungeonRoomType.Outlet;
} }
return DungeonRoomType.Battle; return DungeonRoomType.Battle;
} }
public override void GenerateRoomSuccess(RoomInfo prevRoomInfo, RoomInfo roomInfo)
{
if (roomInfo.RoomType == DungeonRoomType.Boss) //boss房间
{
roomInfo.CanRollback = true;
excludePrevRoom.Clear();
}
else if (roomInfo.RoomType == DungeonRoomType.Battle)
{
chainTryCount = 0;
chainMaxTryCount = Random.RandomRangeInt(1, 3);
}
}
public override void GenerateRoomFail(RoomInfo prevRoomInfo, DungeonRoomType roomType)
{
if (roomType == DungeonRoomType.Boss)
{
//生成boss房间成功
excludePrevRoom.Add(prevRoomInfo);
if (excludePrevRoom.Count >= Generator.RoomInfos.Count)
{
//全都没找到合适的, 那就再来一遍
excludePrevRoom.Clear();
}
}
else if (roomType == DungeonRoomType.Outlet)
{
//生成结束房间失败, 那么只能回滚boss房间
if (prevRoomInfo != null)
{
var bossPrev = prevRoomInfo.Prev;
Generator.RollbackRoom(prevRoomInfo);
Generator.SetPrevRoom(bossPrev);
}
}
else if (roomType == DungeonRoomType.Battle)
{
chainTryCount++;
}
}
} }

View File

@ -81,7 +81,7 @@ public partial class World : CanvasModulate, ICoroutine
public override void _Ready() public override void _Ready()
{ {
Color = Colors.Black; //Color = Colors.Black;
//TileRoot.YSortEnabled = false; //TileRoot.YSortEnabled = false;
NormalLayer = GetNode<Node2D>("TileRoot/NormalLayer"); NormalLayer = GetNode<Node2D>("TileRoot/NormalLayer");
YSortLayer = GetNode<Node2D>("TileRoot/YSortLayer"); YSortLayer = GetNode<Node2D>("TileRoot/YSortLayer");