diff --git a/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/Start/Preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/Start/Preinstall.json
index c43c818..7a68eda 100644
--- a/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/Start/Preinstall.json
+++ b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/Start/Preinstall.json
@@ -1 +1 @@
-[{"Name":"Preinstall1","Weight":100,"Remark":"","AutoFill":true,"WaveList":[[{"Position":{"X":39,"Y":8},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":-16,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":52,"Y":65},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"$RandomProp","Weight":100,"Attr":null,"Altitude":16,"VerticalSpeed":0}]}],[{"Position":{"X":59,"Y":-5},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"$RandomGun","Weight":100,"Attr":null,"Altitude":16,"VerticalSpeed":0}]},{"Position":{"X":11,"Y":-46},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"$RandomProp","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":72,"Y":-39},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":2,"MarkList":[{"Id":"$RandomEnemy","Weight":100,"Attr":null,"Altitude":0,"VerticalSpeed":0}]}]]}]
\ No newline at end of file
+[{"Name":"Preinstall1","Weight":100,"Remark":"","AutoFill":true,"WaveList":[[{"Position":{"X":39,"Y":8},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":-16,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]}]]}]
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/common/SeedRandom.cs b/DungeonShooting_Godot/src/framework/common/SeedRandom.cs
index 11acb6f..20e88c5 100644
--- a/DungeonShooting_Godot/src/framework/common/SeedRandom.cs
+++ b/DungeonShooting_Godot/src/framework/common/SeedRandom.cs
@@ -192,77 +192,73 @@
///
/// 返回指定区域内的随机坐标点, 该函数比较慢, 请谨慎调用
///
- /// 碰撞区域数据
- /// 需要随机点的数量
- public Vector2[] GetRandomPositionInPolygon(List polygonDataList, int count)
+ public Vector2[] GetRandomPositionInPolygon(List vertices, List polygons, int count)
{
+ if (vertices.Count == 0 || polygons.Count == 0)
+ {
+ return Vector2.Zero.MakeArray(count);
+ }
var minX = int.MaxValue;
var maxX = int.MinValue;
var minY = int.MaxValue;
var maxY = int.MinValue;
-
- var outCount = 0;
// 遍历多边形的顶点,找到最小和最大的x、y坐标
- foreach (var navigationPolygonData in polygonDataList)
+ foreach (var vertex in vertices)
{
- if (navigationPolygonData.Type == NavigationPolygonType.Out)
+ if (vertex.X < minX)
{
- outCount++;
+ minX = Mathf.CeilToInt(vertex.X);
}
- foreach (var vertex in navigationPolygonData.GetPoints())
+ else if (vertex.X > maxX)
{
- if (vertex.X < minX)
- {
- minX = Mathf.CeilToInt(vertex.X);
- }
- else if (vertex.X > maxX)
- {
- maxX = Mathf.FloorToInt(vertex.X);
- }
- if (vertex.Y < minY)
- {
- minY = Mathf.CeilToInt(vertex.Y);
- }
- else if (vertex.Y > maxY)
- {
- maxY = Mathf.FloorToInt(vertex.Y);
- }
+ maxX = Mathf.FloorToInt(vertex.X);
+ }
+ if (vertex.Y < minY)
+ {
+ minY = Mathf.CeilToInt(vertex.Y);
+ }
+ else if (vertex.Y > maxY)
+ {
+ maxY = Mathf.FloorToInt(vertex.Y);
}
}
var list = new List();
+ var tryCount = 0;
while (true)
{
- var flag = outCount == 0;
- var point = new Vector2(RandomRangeInt(minX, maxX), RandomRangeInt(minY, maxY));
-
- foreach (var navigationPolygonData in polygonDataList)
+ if (tryCount >= 2000) //尝试2000次后放弃
{
- if (navigationPolygonData.Type == NavigationPolygonType.Out)
+ while (list.Count < count)
{
- if (!flag && Utils.IsPointInPolygon(navigationPolygonData.GetPoints(), point))
- {
- flag = true;
- }
+ list.Add(Vector2.Zero);
}
- else
- {
- if (flag && Utils.IsPointInPolygon(navigationPolygonData.GetPoints(), point))
- {
- flag = false;
- }
- }
+ break;
}
- if (flag)
+ tryCount++;
+ var point = new Vector2(RandomRangeInt(minX, maxX), RandomRangeInt(minY, maxY));
+ foreach (var ps in polygons)
{
- list.Add(point);
- if (list.Count >= count)
+ var arr = new List();
+ foreach (var i in ps)
{
- return list.ToArray();
+ arr.Add(vertices[i]);
+ }
+
+ if (Utils.IsPointInPolygon(arr, point))
+ {
+ tryCount = 0;
+ list.Add(point);
+ if (list.Count >= count)
+ {
+ return list.ToArray();
+ }
}
}
}
+
+ return list.ToArray();
}
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/common/Utils.cs b/DungeonShooting_Godot/src/framework/common/Utils.cs
index da9d36d..04657df 100644
--- a/DungeonShooting_Godot/src/framework/common/Utils.cs
+++ b/DungeonShooting_Godot/src/framework/common/Utils.cs
@@ -330,6 +330,27 @@
return isInside;
}
+
+ ///
+ /// 返回一个点是否在 Polygon 内部
+ ///
+ /// 多边形顶点
+ /// 目标点
+ public static bool IsPointInPolygon(List polygon, Vector2 point)
+ {
+ var isInside = false;
+ for (int i = 0, j = polygon.Count - 1; i < polygon.Count; j = i++)
+ {
+ if ((polygon[i].Y > point.Y) != (polygon[j].Y > point.Y) &&
+ point.X < (polygon[j].X - polygon[i].X) * (point.Y - polygon[i].Y) / (polygon[j].Y - polygon[i].Y) +
+ polygon[i].X)
+ {
+ isInside = !isInside;
+ }
+ }
+
+ return isInside;
+ }
///
/// 根据法线翻转向量
diff --git a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs
index 23dd77f..55c9ed3 100644
--- a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs
+++ b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs
@@ -191,36 +191,56 @@
}
//自动填充操作
- if (RoomPreinstallInfo.AutoFill)
+ if (RoomPreinstallInfo.AutoFill && RoomInfo.RoomType == DungeonRoomType.Battle)
{
var count = world.Random.RandomRangeInt(3, 10);
- //world.Random.GetRandomPositionInPolygon(RoomInfo.RoomSplit.TileInfo.NavigationVertices)
+ var tileInfo = RoomInfo.RoomSplit.TileInfo;
+ var serializeVector2s = tileInfo.NavigationVertices;
+ var vertices = new List();
+ foreach (var sv2 in serializeVector2s)
+ {
+ vertices.Add(sv2.AsVector2());
+ }
+ var positionArray = world.Random.GetRandomPositionInPolygon(vertices, tileInfo.NavigationPolygon, count);
var arr = new ActivityType[] { ActivityType.Enemy, ActivityType.Weapon, ActivityType.Prop };
- for (int i = 0; i < count; i++)
+ var weight = new int[] { 15, 2, 1 };
+ for (var i = 0; i < count; i++)
{
var tempWave = GetOrCreateWave(world.Random.RandomRangeInt(0, 2));
var mark = new ActivityMark();
- var activityType = world.Random.RandomChoose(arr);
- if (activityType == ActivityType.Enemy)
+ mark.Attr = new Dictionary();
+ var index = world.Random.RandomWeight(weight);
+ var activityType = arr[index];
+ if (activityType == ActivityType.Enemy) //敌人
{
mark.Id = world.RandomPool.GetRandomEnemy().Id;
+ mark.Attr.Add("Face", "0");
+ mark.DerivedAttr = new Dictionary();
+ mark.DerivedAttr.Add("Face", world.Random.RandomChoose((int)FaceDirection.Left, (int)FaceDirection.Right).ToString()); //链朝向
+ if (world.Random.RandomBoolean(0.8f)) //手持武器
+ {
+ var weapon = world.RandomPool.GetRandomWeapon();
+ var weaponAttribute = Weapon.GetWeaponAttribute(weapon.Id);
+ mark.Attr.Add("Weapon", weapon.Id); //武器id
+ mark.Attr.Add("CurrAmmon", weaponAttribute.AmmoCapacity.ToString()); //弹夹弹药量
+ mark.Attr.Add("ResidueAmmo", weaponAttribute.AmmoCapacity.ToString()); //剩余弹药量
+ }
}
- else if (activityType == ActivityType.Weapon)
+ else if (activityType == ActivityType.Weapon) //武器
{
mark.Id = world.RandomPool.GetRandomWeapon().Id;
}
- else if (activityType == ActivityType.Prop)
+ else if (activityType == ActivityType.Prop) //道具
{
mark.Id = world.RandomPool.GetRandomProp().Id;
}
mark.ActivityType = activityType;
mark.MarkType = SpecialMarkType.Normal;
- mark.Attr = null;
mark.VerticalSpeed = 0;
- mark.Altitude = 8;
- mark.DelayTime = 0;
- mark.Position = RoomInfo.ToGlobalPosition(Vector2.Zero);
+ mark.Altitude = activityType == ActivityType.Enemy ? 0 : 8;
+ mark.DelayTime = i * 0.3f;
+ mark.Position = RoomInfo.ToGlobalPosition(positionArray[i]);
tempWave.Add(mark);
}
}
@@ -521,7 +541,7 @@
else if (activityMark.ActivityType == ActivityType.Enemy) //敌人类型
{
var role = (Role)activityObject;
- if (role is Enemy enemy && activityMark.Attr.TryGetValue("Weapon", out var weaponId)) //使用的武器
+ if (role.WeaponPack.Capacity > 0 && role is Enemy enemy && activityMark.Attr.TryGetValue("Weapon", out var weaponId)) //使用的武器
{
if (!string.IsNullOrEmpty(weaponId))
{
diff --git a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs
index 7207dcb..e257b69 100644
--- a/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs
+++ b/DungeonShooting_Godot/src/framework/map/room/RoomInfo.cs
@@ -135,6 +135,10 @@
///
public Vector2I Waypoints { get; set; }
+ ///
+ /// 导航网格对象
+ ///
+ public NavigationRegion2D NavigationRegion { get; set; }
public bool IsDestroyed { get; private set; }
private bool _openDoorFlag = true;
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/NoWeaponEnemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/NoWeaponEnemy.cs
index f3ee163..937f133 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/NoWeaponEnemy.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/NoWeaponEnemy.cs
@@ -14,6 +14,7 @@
{
base.OnInit();
NoWeaponAttack = true;
+ WeaponPack.SetCapacity(0);
AnimationPlayer.AnimationFinished += OnAnimationFinished;
_brushData = LiquidBrushManager.GetBrush("0002");
diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs
index 16f626f..032bc8d 100644
--- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs
+++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs
@@ -405,6 +405,7 @@
navigationPolygon.Name = "NavigationRegion" + (GetChildCount() + 1);
navigationPolygon.NavigationPolygon = polygonData;
World.NavigationRoot.AddChild(navigationPolygon);
+ roomInfo.NavigationRegion = navigationPolygon;
}
//创建门