Adjust the time of spawns of items and enemies in the map to when the player first enters the room.
将地图中物品,敌人生成的时机调整到玩家首次进入房间时。
This commit is contained in:
parent
5371d31d99
commit
d80c49ab02
|
@ -55,7 +55,6 @@ shape = SubResource("RectangleShape2D_7tsse")
|
||||||
[node name="Marker2D" type="Marker2D" parent="."]
|
[node name="Marker2D" type="Marker2D" parent="."]
|
||||||
position = Vector2(260, 87)
|
position = Vector2(260, 87)
|
||||||
script = ExtResource("1_y2vgj")
|
script = ExtResource("1_y2vgj")
|
||||||
ResPath = "res://prefab/entitys/DelivererOfDarkMagic.tscn"
|
|
||||||
|
|
||||||
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
|
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
|
||||||
navigation_polygon = SubResource("NavigationPolygon_rh1gx")
|
navigation_polygon = SubResource("NavigationPolygon_rh1gx")
|
||||||
|
|
|
@ -54,7 +54,6 @@ shape = SubResource("RectangleShape2D_7tsse")
|
||||||
[node name="Marker2D" type="Marker2D" parent="."]
|
[node name="Marker2D" type="Marker2D" parent="."]
|
||||||
position = Vector2(260, 87)
|
position = Vector2(260, 87)
|
||||||
script = ExtResource("2_wamhd")
|
script = ExtResource("2_wamhd")
|
||||||
ResPath = "res://prefab/entitys/DelivererOfDarkMagic.tscn"
|
|
||||||
|
|
||||||
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
|
[node name="NavigationRegion2D" type="NavigationRegion2D" parent="."]
|
||||||
navigation_polygon = SubResource("NavigationPolygon_rh1gx")
|
navigation_polygon = SubResource("NavigationPolygon_rh1gx")
|
||||||
|
|
|
@ -37,7 +37,7 @@ position = Vector2(751.5, 289.438)
|
||||||
shape = SubResource("RectangleShape2D_jxmys")
|
shape = SubResource("RectangleShape2D_jxmys")
|
||||||
debug_color = Color(0, 0.6, 0.701961, 0.419608)
|
debug_color = Color(0, 0.6, 0.701961, 0.419608)
|
||||||
|
|
||||||
[node name="Marker2D" type="Marker2D" parent="."]
|
[node name="PlayerSpawn" type="Marker2D" parent="."]
|
||||||
position = Vector2(54, 256)
|
position = Vector2(54, 256)
|
||||||
script = ExtResource("1_q04qt")
|
script = ExtResource("1_q04qt")
|
||||||
|
|
||||||
|
@ -73,16 +73,6 @@ position = Vector2(386, 178)
|
||||||
scale = Vector2(23.9375, 11.0625)
|
scale = Vector2(23.9375, 11.0625)
|
||||||
texture = ExtResource("3_atgj7")
|
texture = ExtResource("3_atgj7")
|
||||||
|
|
||||||
[node name="Marker2D2" type="Marker2D" parent="."]
|
|
||||||
position = Vector2(100, 250)
|
|
||||||
script = ExtResource("4_6ihp7")
|
|
||||||
ItemId = "staff_necromancy"
|
|
||||||
|
|
||||||
[node name="Marker2D3" type="Marker2D" parent="."]
|
|
||||||
position = Vector2(134, 248)
|
|
||||||
script = ExtResource("4_6ihp7")
|
|
||||||
ItemId = "necromancy"
|
|
||||||
|
|
||||||
[node name="Label" type="Label" parent="."]
|
[node name="Label" type="Label" parent="."]
|
||||||
offset_left = 37.0
|
offset_left = 37.0
|
||||||
offset_top = 46.0
|
offset_top = 46.0
|
||||||
|
@ -115,3 +105,15 @@ position = Vector2(715, 162)
|
||||||
|
|
||||||
[node name="WoodenBox4" parent="." instance=ExtResource("7_jybe6")]
|
[node name="WoodenBox4" parent="." instance=ExtResource("7_jybe6")]
|
||||||
position = Vector2(714, 122)
|
position = Vector2(714, 122)
|
||||||
|
|
||||||
|
[node name="AutoSpawn" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="necromancy" type="Marker2D" parent="AutoSpawn"]
|
||||||
|
position = Vector2(134, 248)
|
||||||
|
script = ExtResource("4_6ihp7")
|
||||||
|
ItemId = "necromancy"
|
||||||
|
|
||||||
|
[node name="staff_necromancy" type="Marker2D" parent="AutoSpawn"]
|
||||||
|
position = Vector2(100, 250)
|
||||||
|
script = ExtResource("4_6ihp7")
|
||||||
|
ItemId = "staff_necromancy"
|
||||||
|
|
|
@ -91,11 +91,6 @@ offset_right = 453.0
|
||||||
offset_bottom = 151.0
|
offset_bottom = 151.0
|
||||||
text = "ui_tutorial_combine_more_powerful_spells"
|
text = "ui_tutorial_combine_more_powerful_spells"
|
||||||
|
|
||||||
[node name="Marker2D" type="Marker2D" parent="."]
|
|
||||||
position = Vector2(434, 105)
|
|
||||||
script = ExtResource("4_fh50l")
|
|
||||||
ItemId = "x3"
|
|
||||||
|
|
||||||
[node name="WoodenBox" parent="." instance=ExtResource("4_60glh")]
|
[node name="WoodenBox" parent="." instance=ExtResource("4_60glh")]
|
||||||
position = Vector2(711, 179)
|
position = Vector2(711, 179)
|
||||||
|
|
||||||
|
@ -129,3 +124,10 @@ position = Vector2(473, 285)
|
||||||
[node name="TripleShotSpell" type="Sprite2D" parent="."]
|
[node name="TripleShotSpell" type="Sprite2D" parent="."]
|
||||||
position = Vector2(637, 85)
|
position = Vector2(637, 85)
|
||||||
texture = ExtResource("6_2qcf3")
|
texture = ExtResource("6_2qcf3")
|
||||||
|
|
||||||
|
[node name="AutoSpawn" type="Node2D" parent="."]
|
||||||
|
|
||||||
|
[node name="x3" type="Marker2D" parent="AutoSpawn"]
|
||||||
|
position = Vector2(434, 105)
|
||||||
|
script = ExtResource("4_fh50l")
|
||||||
|
ItemId = "x3"
|
||||||
|
|
|
@ -9,12 +9,6 @@ namespace ColdMint.scripts;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class EventBus
|
public static class EventBus
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// <para>Event when the AI character is generated</para>
|
|
||||||
/// <para>AI角色生成事件</para>
|
|
||||||
/// </summary>
|
|
||||||
public static Action<AiCharacterGenerateEvent>? AiCharacterGenerateEvent;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Game Over Event</para>
|
/// <para>Game Over Event</para>
|
||||||
/// <para>游戏结束事件</para>
|
/// <para>游戏结束事件</para>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using ColdMint.scripts.character;
|
using ColdMint.scripts.character;
|
||||||
using ColdMint.scripts.map.events;
|
using ColdMint.scripts.map.room;
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
|
@ -9,52 +9,45 @@ namespace ColdMint.scripts.map;
|
||||||
/// <para>Ai character generation point</para>
|
/// <para>Ai character generation point</para>
|
||||||
/// <para>Ai角色生成点</para>
|
/// <para>Ai角色生成点</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class AiCharacterSpawn : Marker2D
|
public partial class AiCharacterSpawn : Marker2D, ISpawnMarker
|
||||||
{
|
{
|
||||||
private PackedScene? _packedScene;
|
private PackedScene? _packedScene;
|
||||||
[Export]
|
[Export] private string? _resPath;
|
||||||
public string? ResPath;
|
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
base._Ready();
|
base._Ready();
|
||||||
if (!string.IsNullOrEmpty(ResPath))
|
if (!string.IsNullOrEmpty(_resPath))
|
||||||
{
|
{
|
||||||
_packedScene = GD.Load<PackedScene>(ResPath);
|
_packedScene = GD.Load<PackedScene>(_resPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventBus.AiCharacterGenerateEvent += OnAiCharacterGenerateEvent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public Node2D? Spawn()
|
||||||
/// <para>When an event is triggered</para>
|
|
||||||
/// <para>当触发事件时</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="aiCharacterGenerateEvent"></param>
|
|
||||||
public void OnAiCharacterGenerateEvent(AiCharacterGenerateEvent aiCharacterGenerateEvent)
|
|
||||||
{
|
{
|
||||||
if (GameSceneDepend.AiCharacterContainer == null)
|
if (GameSceneDepend.AiCharacterContainer == null || _packedScene == null)
|
||||||
{
|
{
|
||||||
return;
|
return null;
|
||||||
}
|
|
||||||
|
|
||||||
if (_packedScene == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var aiCharacter = NodeUtils.InstantiatePackedScene<AiCharacter>(_packedScene);
|
var aiCharacter = NodeUtils.InstantiatePackedScene<AiCharacter>(_packedScene);
|
||||||
if (aiCharacter == null)
|
if (aiCharacter == null)
|
||||||
{
|
{
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeUtils.CallDeferredAddChild(GameSceneDepend.AiCharacterContainer, aiCharacter);
|
NodeUtils.CallDeferredAddChild(GameSceneDepend.AiCharacterContainer, aiCharacter);
|
||||||
aiCharacter.GlobalPosition = GlobalPosition;
|
aiCharacter.GlobalPosition = GlobalPosition;
|
||||||
|
return aiCharacter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ExitTree()
|
public bool CanQueueFree()
|
||||||
{
|
{
|
||||||
EventBus.AiCharacterGenerateEvent -= OnAiCharacterGenerateEvent;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DoQueueFree()
|
||||||
|
{
|
||||||
|
QueueFree();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using ColdMint.scripts.debug;
|
using ColdMint.scripts.debug;
|
||||||
using ColdMint.scripts.inventory;
|
using ColdMint.scripts.inventory;
|
||||||
using ColdMint.scripts.map.events;
|
using ColdMint.scripts.map.room;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace ColdMint.scripts.map;
|
namespace ColdMint.scripts.map;
|
||||||
|
@ -9,36 +9,34 @@ namespace ColdMint.scripts.map;
|
||||||
/// <para>ItemSpawn</para>
|
/// <para>ItemSpawn</para>
|
||||||
/// <para>物品出生点</para>
|
/// <para>物品出生点</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ItemSpawn : Marker2D
|
public partial class ItemSpawn : Marker2D, ISpawnMarker
|
||||||
{
|
{
|
||||||
[Export] public string? ItemId { get; private set; }
|
[Export] private string? ItemId { get; set; }
|
||||||
|
|
||||||
public override void _Ready()
|
public Node2D? Spawn()
|
||||||
{
|
{
|
||||||
base._Ready();
|
if (string.IsNullOrEmpty(ItemId))
|
||||||
EventBus.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
|
|
||||||
{
|
|
||||||
//After the map is generated, create the item instance.
|
|
||||||
//当地图生成完成后,创建物品实例。
|
|
||||||
if (ItemId == null)
|
|
||||||
{
|
{
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var item = ItemTypeManager.CreateItem(ItemId, this);
|
var item = ItemTypeManager.CreateItem(ItemId, this);
|
||||||
LogCat.LogWithFormat("generated_item_is_empty",LogCat.LogLabel.ItemSpawn,true,ItemId,item == null);
|
LogCat.LogWithFormat("generated_item_is_empty", LogCat.LogLabel.ItemSpawn, true, ItemId, item == null);
|
||||||
if (item is Node2D node2D)
|
if (item is not Node2D node2D)
|
||||||
{
|
{
|
||||||
node2D.GlobalPosition = GlobalPosition;
|
return null;
|
||||||
}
|
}
|
||||||
|
node2D.GlobalPosition = GlobalPosition;
|
||||||
|
return node2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ExitTree()
|
public bool CanQueueFree()
|
||||||
{
|
{
|
||||||
base._ExitTree();
|
return true;
|
||||||
EventBus.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
|
}
|
||||||
|
|
||||||
|
public void DoQueueFree()
|
||||||
|
{
|
||||||
|
QueueFree();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -311,11 +311,6 @@ public static class MapGenerator
|
||||||
RoomDictionary = roomDictionary
|
RoomDictionary = roomDictionary
|
||||||
};
|
};
|
||||||
EventBus.MapGenerationCompleteEvent?.Invoke(eventObj);
|
EventBus.MapGenerationCompleteEvent?.Invoke(eventObj);
|
||||||
var aiCharacterGenerateEvent = new AiCharacterGenerateEvent
|
|
||||||
{
|
|
||||||
Tag = AiCharacterGenerateEvent.TagMapGenerationComplete
|
|
||||||
};
|
|
||||||
EventBus.AiCharacterGenerateEvent?.Invoke(aiCharacterGenerateEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using ColdMint.scripts.character;
|
using ColdMint.scripts.character;
|
||||||
using ColdMint.scripts.debug;
|
using ColdMint.scripts.debug;
|
||||||
using ColdMint.scripts.map.events;
|
using ColdMint.scripts.map.events;
|
||||||
|
using ColdMint.scripts.map.room;
|
||||||
using ColdMint.scripts.utils;
|
using ColdMint.scripts.utils;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
|
@ -11,7 +12,7 @@ namespace ColdMint.scripts.map;
|
||||||
/// <para>PlayerSpawn</para>
|
/// <para>PlayerSpawn</para>
|
||||||
/// <para>玩家出生点</para>
|
/// <para>玩家出生点</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class PlayerSpawn : Marker2D
|
public partial class PlayerSpawn : Marker2D,ISpawnMarker
|
||||||
{
|
{
|
||||||
private PackedScene? _playerPackedScene;
|
private PackedScene? _playerPackedScene;
|
||||||
|
|
||||||
|
@ -31,32 +32,49 @@ public partial class PlayerSpawn : Marker2D
|
||||||
GameSceneDepend.Player.GlobalPosition = GlobalPosition;
|
GameSceneDepend.Player.GlobalPosition = GlobalPosition;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Spawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SpawnPlayer();
|
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
|
||||||
|
{
|
||||||
|
//After the map is generated, create the player instance.
|
||||||
|
//当地图生成完成后,创建玩家实例。
|
||||||
|
if (GameSceneDepend.Player != null)
|
||||||
|
{
|
||||||
|
//An existing player instance will not be created.
|
||||||
|
//已经存在玩家实例,不再创建。
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Spawn();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public override void _ExitTree()
|
||||||
/// <para>Generate player instance</para>
|
{
|
||||||
/// <para>生成玩家实例</para>
|
base._ExitTree();
|
||||||
/// </summary>
|
EventBus.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
|
||||||
private void SpawnPlayer()
|
EventBus.GameReplayEvent -= GameReplayEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node2D? Spawn()
|
||||||
{
|
{
|
||||||
if (GameSceneDepend.PlayerContainer == null)
|
if (GameSceneDepend.PlayerContainer == null)
|
||||||
{
|
{
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_playerPackedScene == null)
|
if (_playerPackedScene == null)
|
||||||
{
|
{
|
||||||
LogCat.LogError("player_packed_scene_not_exist");
|
LogCat.LogError("player_packed_scene_not_exist");
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var playerNode =
|
var playerNode =
|
||||||
NodeUtils.InstantiatePackedScene<Player>(_playerPackedScene);
|
NodeUtils.InstantiatePackedScene<Player>(_playerPackedScene);
|
||||||
if (playerNode == null)
|
if (playerNode == null)
|
||||||
{
|
{
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//The player's parent node must be GameSceneDepend PlayerContainer.
|
//The player's parent node must be GameSceneDepend PlayerContainer.
|
||||||
|
@ -73,26 +91,16 @@ public partial class PlayerSpawn : Marker2D
|
||||||
playerNode.ItemContainer = itemContainer;
|
playerNode.ItemContainer = itemContainer;
|
||||||
GameSceneDepend.Player = playerNode;
|
GameSceneDepend.Player = playerNode;
|
||||||
playerNode.GlobalPosition = GlobalPosition;
|
playerNode.GlobalPosition = GlobalPosition;
|
||||||
|
return playerNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
|
public bool CanQueueFree()
|
||||||
{
|
{
|
||||||
//After the map is generated, create the player instance.
|
return false;
|
||||||
//当地图生成完成后,创建玩家实例。
|
|
||||||
if (GameSceneDepend.Player != null)
|
|
||||||
{
|
|
||||||
//An existing player instance will not be created.
|
|
||||||
//已经存在玩家实例,不再创建。
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpawnPlayer();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ExitTree()
|
public void DoQueueFree()
|
||||||
{
|
{
|
||||||
base._ExitTree();
|
QueueFree();
|
||||||
EventBus.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
|
|
||||||
EventBus.GameReplayEvent -= GameReplayEvent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,23 +0,0 @@
|
||||||
namespace ColdMint.scripts.map.events;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>AiCharacterGenerateEvent</para>
|
|
||||||
/// <para>Ai角色生成事件</para>
|
|
||||||
/// </summary>
|
|
||||||
public class AiCharacterGenerateEvent
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Map generation completed Tag</para>
|
|
||||||
/// <para>地图生成完成的Tag</para>
|
|
||||||
/// </summary>
|
|
||||||
public const string TagMapGenerationComplete = "MapGenerationComplete";
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>The Tag used to generate the role</para>
|
|
||||||
/// <para>生成角色时使用的Tag</para>
|
|
||||||
/// </summary>
|
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
|
||||||
public string? Tag { get; set; }
|
|
||||||
// ReSharper restore UnusedAutoPropertyAccessor.Global
|
|
||||||
}
|
|
|
@ -19,7 +19,11 @@ public interface IEnterRoomEventHandler
|
||||||
/// <para>When entering the room</para>
|
/// <para>When entering the room</para>
|
||||||
/// <para>当进入房间时</para>
|
/// <para>当进入房间时</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="playerRoomVisitCount">
|
||||||
|
///<para>The number of times the player visits the room, 1 is the first visit.</para>
|
||||||
|
///<para>玩家访问房间的次数,为1则代表首次访问。</para>
|
||||||
|
/// </param>
|
||||||
/// <param name="node"></param>
|
/// <param name="node"></param>
|
||||||
/// <param name="room"></param>
|
/// <param name="room"></param>
|
||||||
void OnEnterRoom(Node node,Room room);
|
void OnEnterRoom(int playerRoomVisitCount,Node node,Room room);
|
||||||
}
|
}
|
33
scripts/map/room/ISpawnMarker.cs
Normal file
33
scripts/map/room/ISpawnMarker.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
namespace ColdMint.scripts.map.room;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>The tag of the generated entity</para>
|
||||||
|
/// <para>生成实体的标记</para>
|
||||||
|
/// </summary>
|
||||||
|
public interface ISpawnMarker
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Generating entity</para>
|
||||||
|
/// <para>生成实体</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Return the result of the generation. If null is returned, the generation fails.</para>
|
||||||
|
///<para>返回生成结果,为null则生成失败。</para>
|
||||||
|
/// </remarks>
|
||||||
|
Node2D? Spawn();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Can Queue Free</para>
|
||||||
|
/// <para>可释放节点吗</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
bool CanQueueFree();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Execute Queue Free</para>
|
||||||
|
/// <para>执行释放节点</para>
|
||||||
|
/// </summary>
|
||||||
|
void DoQueueFree();
|
||||||
|
}
|
|
@ -28,6 +28,18 @@ public class Room
|
||||||
private CollisionShape2D? _collisionShape2D;
|
private CollisionShape2D? _collisionShape2D;
|
||||||
private bool _hasPlayer;
|
private bool _hasPlayer;
|
||||||
private readonly List<CharacterTemplate> _characterTemplateList = [];
|
private readonly List<CharacterTemplate> _characterTemplateList = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>When the player first enters the room, all <see cref="ISpawnMarker"/> nodes under this node are executed</para>
|
||||||
|
/// <para>当玩家首次进入房间时,会执行此节点下所有<see cref="ISpawnMarker"/>节点</para>
|
||||||
|
/// </summary>
|
||||||
|
private Node2D? _autoSpawn;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>The number of times the player visits the room</para>
|
||||||
|
/// <para>玩家访问房间的次数</para>
|
||||||
|
/// </summary>
|
||||||
|
private int PlayerRoomVisitCount { get; set; }
|
||||||
|
|
||||||
public string? EnterRoomEventHandlerId { get; set; }
|
public string? EnterRoomEventHandlerId { get; set; }
|
||||||
|
|
||||||
|
@ -51,47 +63,31 @@ public class Room
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Places a barrier in a slot where a match has been found.</para>
|
/// <para>Place barriers in all slots</para>
|
||||||
/// <para>在找到匹配的槽位放置屏障。</para>
|
/// <para>在所有的槽位放置屏障</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void PlaceBarrierInMatchedSlot()
|
public void PlaceBarriersInAllSlots()
|
||||||
{
|
{
|
||||||
ProcessRoomSlots(action: (roomSlot, ground, barrier, i) =>
|
var barrier = GetTileMapLayer(Config.TileMapLayerName.Barrier);
|
||||||
|
if (barrier == null)
|
||||||
{
|
{
|
||||||
if (!roomSlot.Matched)
|
return;
|
||||||
{
|
}
|
||||||
return;
|
barrier.Enabled = true;
|
||||||
}
|
|
||||||
var cellSourceId = barrier.GetCellSourceId(i);
|
|
||||||
if (cellSourceId == -1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ground.SetCell(i, cellSourceId, barrier.GetCellAtlasCoords(i), barrier.GetCellAlternativeTile(i));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Clear the barrier that finds a matching slot</para>
|
/// <para>Clear all matched barriers</para>
|
||||||
/// <para>清空找到匹配的槽位的屏障。</para>
|
/// <para>清空所有已匹配位置的屏障</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void ClearBarriersInMatchedSlots()
|
public void ClearAllMatchedBarriers()
|
||||||
{
|
{
|
||||||
ProcessRoomSlots(action: (roomSlot, ground, barrier, i) =>
|
var barrier = GetTileMapLayer(Config.TileMapLayerName.Barrier);
|
||||||
|
if (barrier == null)
|
||||||
{
|
{
|
||||||
if (!roomSlot.Matched)
|
return;
|
||||||
{
|
}
|
||||||
return;
|
barrier.Enabled = false;
|
||||||
}
|
|
||||||
var cellSourceId = barrier.GetCellSourceId(i);
|
|
||||||
if (cellSourceId == -1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ground.SetCell(i, cellSourceId, barrier.GetCellAtlasCoords(i), barrier.GetCellAlternativeTile(i));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -99,32 +95,6 @@ public class Room
|
||||||
/// <para>在未匹配的槽位放置屏障。</para>
|
/// <para>在未匹配的槽位放置屏障。</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void PlaceBarrierInUnmatchedSlots()
|
public void PlaceBarrierInUnmatchedSlots()
|
||||||
{
|
|
||||||
ProcessRoomSlots(action: (roomSlot, ground, barrier, i) =>
|
|
||||||
{
|
|
||||||
if (roomSlot.Matched)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var cellSourceId = barrier.GetCellSourceId(i);
|
|
||||||
if (cellSourceId == -1)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ground.SetCell(i, cellSourceId, barrier.GetCellAtlasCoords(i), barrier.GetCellAlternativeTile(i));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Executes a callback for each room slot, providing the corresponding coordinates in the barrier and ground layers.</para>
|
|
||||||
/// <para>对每个房间槽位执行回调,提供barrier层和ground层对应的坐标。</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="action">
|
|
||||||
///<para>The callback action to be executed, which takes the barrier layer, ground layer, and coordinates as parameters.</para>
|
|
||||||
///<para>要执行的回调操作,它以屏障层、底层和坐标作为参数。</para>
|
|
||||||
/// </param>
|
|
||||||
private void ProcessRoomSlots(Action<RoomSlot, TileMapLayer, TileMapLayer, Vector2I> action)
|
|
||||||
{
|
{
|
||||||
var ground = GetTileMapLayer(Config.TileMapLayerName.Ground);
|
var ground = GetTileMapLayer(Config.TileMapLayerName.Ground);
|
||||||
var barrier = GetTileMapLayer(Config.TileMapLayerName.Barrier);
|
var barrier = GetTileMapLayer(Config.TileMapLayerName.Barrier);
|
||||||
|
@ -144,17 +114,27 @@ public class Room
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Place the corresponding coordinate tiles of the barrier layer on the ground level.
|
//Place the corresponding coordinate tiles of the barrier layer on the ground level.
|
||||||
//将屏障层的对应坐标瓦片放到地面层。
|
//将屏障层的对应坐标瓦片放到地面层。
|
||||||
CoordinateUtils.ForEachCell(roomSlot.StartPosition, roomSlot.EndPosition, i =>
|
CoordinateUtils.ForEachCell(roomSlot.StartPosition, roomSlot.EndPosition, i =>
|
||||||
{
|
{
|
||||||
action.Invoke(roomSlot, ground, barrier, i);
|
if (roomSlot.Matched)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var cellSourceId = barrier.GetCellSourceId(i);
|
||||||
|
if (cellSourceId == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ground.SetCell(i, cellSourceId, barrier.GetCellAtlasCoords(i), barrier.GetCellAlternativeTile(i));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
barrier.QueueFree();
|
barrier.Enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>ShowAllCharacterTemplate</para>
|
/// <para>ShowAllCharacterTemplate</para>
|
||||||
/// <para>显示所有角色模板</para>
|
/// <para>显示所有角色模板</para>
|
||||||
|
@ -200,6 +180,15 @@ public class Room
|
||||||
{
|
{
|
||||||
_characterTemplateList.Add(player);
|
_characterTemplateList.Add(player);
|
||||||
_hasPlayer = true;
|
_hasPlayer = true;
|
||||||
|
PlayerRoomVisitCount++;
|
||||||
|
if (PlayerRoomVisitCount == 1 && _autoSpawn != null)
|
||||||
|
{
|
||||||
|
NodeUtils.ForEachNode<ISpawnMarker>(_autoSpawn, marker =>
|
||||||
|
{
|
||||||
|
marker.Spawn();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
//The player enters the room, opening up their view.
|
//The player enters the room, opening up their view.
|
||||||
//玩家进入了房间,开放视野。
|
//玩家进入了房间,开放视野。
|
||||||
if (_pointLight2D != null)
|
if (_pointLight2D != null)
|
||||||
|
@ -231,7 +220,7 @@ public class Room
|
||||||
}
|
}
|
||||||
|
|
||||||
var enterRoomEventHandler = RoomEventManager.GetEnterRoomEventHandler(EnterRoomEventHandlerId);
|
var enterRoomEventHandler = RoomEventManager.GetEnterRoomEventHandler(EnterRoomEventHandlerId);
|
||||||
enterRoomEventHandler?.OnEnterRoom(node, this);
|
enterRoomEventHandler?.OnEnterRoom(PlayerRoomVisitCount, node, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -260,8 +249,18 @@ public class Room
|
||||||
_pointLight2D.Show();
|
_pointLight2D.Show();
|
||||||
_pointLight2D.Texture = AssetHolder.White25;
|
_pointLight2D.Texture = AssetHolder.White25;
|
||||||
}
|
}
|
||||||
|
|
||||||
HideAllCharacterTemplate();
|
HideAllCharacterTemplate();
|
||||||
|
if (PlayerRoomVisitCount == 1 && _autoSpawn != null)
|
||||||
|
{
|
||||||
|
NodeUtils.ForEachNode<ISpawnMarker>(_autoSpawn, marker =>
|
||||||
|
{
|
||||||
|
if (marker.CanQueueFree())
|
||||||
|
{
|
||||||
|
marker.DoQueueFree();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (node is CharacterTemplate characterTemplate && characterTemplate.Visible)
|
else if (node is CharacterTemplate characterTemplate && characterTemplate.Visible)
|
||||||
{
|
{
|
||||||
|
@ -312,8 +311,8 @@ public class Room
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var node2D = NodeUtils.InstantiatePackedScene<Node2D>(packedScene);
|
var rootNode = NodeUtils.InstantiatePackedScene<Node2D>(packedScene);
|
||||||
if (node2D == null)
|
if (rootNode == null)
|
||||||
{
|
{
|
||||||
//The room node is not of Node2D type. An exception is thrown
|
//The room node is not of Node2D type. An exception is thrown
|
||||||
//房间节点不是Node2D类型,抛出异常
|
//房间节点不是Node2D类型,抛出异常
|
||||||
|
@ -321,15 +320,15 @@ public class Room
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_rootNode = node2D;
|
_rootNode = rootNode;
|
||||||
var tileMapNode = node2D.GetNode<Node2D>("TileMap");
|
var tileMapNode = rootNode.GetNode<Node2D>("TileMap");
|
||||||
NodeUtils.ForEachNode<TileMapLayer>(tileMapNode, node =>
|
NodeUtils.ForEachNode<TileMapLayer>(tileMapNode, node =>
|
||||||
{
|
{
|
||||||
_tileMapLayers ??= [];
|
_tileMapLayers ??= [];
|
||||||
_tileMapLayers.Add(node);
|
_tileMapLayers.Add(node);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
_area2D = node2D.GetNode<Area2D>("RoomArea");
|
_area2D = rootNode.GetNode<Area2D>("RoomArea");
|
||||||
_area2D.Monitoring = true;
|
_area2D.Monitoring = true;
|
||||||
_area2D.SetCollisionLayerValue(Config.LayerNumber.RoomArea, true);
|
_area2D.SetCollisionLayerValue(Config.LayerNumber.RoomArea, true);
|
||||||
//Sets the collision layer that can be detected in the current room area.
|
//Sets the collision layer that can be detected in the current room area.
|
||||||
|
@ -340,12 +339,13 @@ public class Room
|
||||||
_area2D.BodyEntered += OnEnterRoom;
|
_area2D.BodyEntered += OnEnterRoom;
|
||||||
_collisionShape2D = _area2D.GetChild<CollisionShape2D>(0);
|
_collisionShape2D = _area2D.GetChild<CollisionShape2D>(0);
|
||||||
_roomSlots = GetRoomSlots(GetTileMapLayer(Config.TileMapLayerName.Ground), _area2D,
|
_roomSlots = GetRoomSlots(GetTileMapLayer(Config.TileMapLayerName.Ground), _area2D,
|
||||||
node2D.GetNode<Node2D>("RoomSlotList"));
|
rootNode.GetNode<Node2D>("RoomSlotList"));
|
||||||
_pointLight2D = node2D.GetNodeOrNull<PointLight2D>("PointLight2D");
|
_pointLight2D = rootNode.GetNodeOrNull<PointLight2D>("PointLight2D");
|
||||||
if (_pointLight2D != null)
|
if (_pointLight2D != null)
|
||||||
{
|
{
|
||||||
_pointLight2D.BlendMode = Light2D.BlendModeEnum.Mix;
|
_pointLight2D.BlendMode = Light2D.BlendModeEnum.Mix;
|
||||||
}
|
}
|
||||||
|
_autoSpawn = rootNode.GetNodeOrNull<Node2D>("AutoSpawn");
|
||||||
}
|
}
|
||||||
|
|
||||||
public Node2D? RootNode => _rootNode;
|
public Node2D? RootNode => _rootNode;
|
||||||
|
|
|
@ -131,17 +131,17 @@ public static class NodeUtils
|
||||||
///<para>用于处理回调的函数,返回true终止遍历节点</para>
|
///<para>用于处理回调的函数,返回true终止遍历节点</para>
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <typeparam name="T">
|
/// <typeparam name="T">
|
||||||
///<para>When the type is specified as Node, all child nodes are returned.</para>
|
///<para>Specifies the generic type</para>
|
||||||
///<para>当指定类型为Node时,将返回所有子节点。</para>
|
///<para>指定的泛型</para>
|
||||||
/// </typeparam>
|
/// </typeparam>
|
||||||
public static void ForEachNode<T>(Node parent, Func<T, bool> func) where T : Node
|
public static void ForEachNode<T>(Node parent, Func<T, bool> func) where T : class
|
||||||
{
|
{
|
||||||
var count = parent.GetChildCount();
|
var count = parent.GetChildCount();
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < count; i++)
|
for (var i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
var node = parent.GetChild(i);
|
var node = parent.GetChild(i);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user