Support for generating creatures on the map, adding the game end screen.

支持在地图上生成生物了,加入了游戏结束的画面。
This commit is contained in:
Cold-Mint 2024-06-03 22:58:59 +08:00
parent 64688252f0
commit 74c85cd5a7
Signed by: Cold-Mint
GPG Key ID: C5A9BF8A98E0CE99
24 changed files with 310 additions and 36 deletions

View File

@ -21,4 +21,5 @@ time_range_debug,当前时间:{0}起始时间:{1},结束时间{2},是否
player_spawn_debug,玩家{0}生成在{1}。,"Player {0} spawned at {1}.",プレイヤー{0}が{1}に生成されました。
player_packed_scene_not_exist,玩家预制场景不存在。,Player packed scene does not exist.,プレイヤーのパックされたシーンが存在しません。
exit_the_room_debug,节点{0}退出房间{1}。,"Node {0} exits room {1}.",ノード{0}が部屋{1}を退出します。
enter_the_room_debug,节点{0}进入房间{1}。,"Node {0} enters room {1}.",ノード{0}が部屋{1}に入ります。
enter_the_room_debug,节点{0}进入房间{1}。,"Node {0} enters room {1}.",ノード{0}が部屋{1}に入ります。
death_info,生物{0}被{1}击败。,"Creature {0} was defeated by {1}.",生物{0}が{1}によって打ち負かされました。
1 id zh en jp
21 player_spawn_debug 玩家{0}生成在{1}。 Player {0} spawned at {1}. プレイヤー{0}が{1}に生成されました。
22 player_packed_scene_not_exist 玩家预制场景不存在。 Player packed scene does not exist. プレイヤーのパックされたシーンが存在しません。
23 exit_the_room_debug 节点{0}退出房间{1}。 Node {0} exits room {1}. ノード{0}が部屋{1}を退出します。
24 enter_the_room_debug 节点{0}进入房间{1}。 Node {0} enters room {1}. ノード{0}が部屋{1}に入ります。
25 death_info 生物{0}被{1}击败。 Creature {0} was defeated by {1}. 生物{0}が{1}によって打ち負かされました。

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -31,4 +31,7 @@ delete_selected_node,删除选中的节点,Delete selected node,選択された
re_create_map,重新创建地图,Re-create map,地図を再作成します
seed_info,种子:{0},Seed: {0},シード:{0}
tags,标签,Tags,と呼ぶ
room_injection_processor,房间注入处理器,Room injection processor,部屋注入処理器
room_injection_processor,房间注入处理器,Room injection processor,部屋注入処理器
game_over_title,游戏结束!,Game Over!,ゲームオーバー!
death_info_describe,死因,death,死因
restart,重新开始,Restart,ぶり返す

1 id zh en jp
31 re_create_map 重新创建地图 Re-create map 地図を再作成します
32 seed_info 种子:{0} Seed: {0} シード:{0}
33 tags 标签 Tags と呼ぶ
34 room_injection_processor 房间注入处理器 Room injection processor 部屋注入処理器
35 game_over_title 游戏结束! Game Over! ゲームオーバー!
36 death_info_describe 死因 death 死因
37 restart 重新开始 Restart ぶり返す

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=6 format=3 uid="uid://b0uurp551pku"]
[gd_scene load_steps=7 format=3 uid="uid://b0uurp551pku"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_a15hy"]
[ext_resource type="Script" path="res://scripts/map/AiCharacterSpawn.cs" id="2_wamhd"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(443, 118)
@ -53,3 +54,8 @@ shape = SubResource("RectangleShape2D_30r3c")
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D3"]
position = Vector2(193, 15)
shape = SubResource("RectangleShape2D_7tsse")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(220, 103)
script = ExtResource("2_wamhd")
metadata/ResPath = "res://prefab/entitys/DelivererOfDarkMagic.tscn"

View File

@ -1,6 +1,7 @@
[gd_scene load_steps=6 format=3 uid="uid://dslr5tdbp4noq"]
[gd_scene load_steps=7 format=3 uid="uid://dslr5tdbp4noq"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_rn2om"]
[ext_resource type="Script" path="res://scripts/map/AiCharacterSpawn.cs" id="2_7q101"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(441, 122)
@ -54,3 +55,8 @@ position = Vector2(498, 109)
[node name="CollisionShape2D" type="CollisionShape2D" parent="RoomSlotList/Area2D2"]
position = Vector2(0, 17)
shape = SubResource("RectangleShape2D_131jn")
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(183, 72)
script = ExtResource("2_7q101")
metadata/ResPath = "res://prefab/entitys/DelivererOfDarkMagic.tscn"

View File

@ -1,7 +1,8 @@
[gd_scene load_steps=5 format=3 uid="uid://du5ldsp613fei"]
[gd_scene load_steps=6 format=3 uid="uid://du5ldsp613fei"]
[ext_resource type="TileSet" uid="uid://c4wpp12rr44hi" path="res://tileSets/dungeon.tres" id="1_rn2om"]
[ext_resource type="Script" path="res://scripts/map/PlayerSpawn.cs" id="2_6p8mv"]
[ext_resource type="PackedScene" uid="uid://dnnn2xyayiehk" path="res://prefab/weapons/staffOfTheUndead.tscn" id="3_ud0w8"]
[sub_resource type="RectangleShape2D" id="RectangleShape2D_kiih8"]
size = Vector2(450, 191)
@ -41,3 +42,6 @@ debug_color = Color(0.854902, 0.14902, 0.823529, 0.419608)
[node name="Marker2D" type="Marker2D" parent="."]
position = Vector2(216, 113)
script = ExtResource("2_6p8mv")
[node name="StaffOfTheUndead" parent="." instance=ExtResource("3_ud0w8")]
position = Vector2(231, 116)

View File

@ -1,10 +1,11 @@
[gd_scene load_steps=6 format=3 uid="uid://bnftvkj2cido7"]
[gd_scene load_steps=7 format=3 uid="uid://bnftvkj2cido7"]
[ext_resource type="Script" path="res://scripts/loader/sceneLoader/GameSceneLoader.cs" id="1_mqdgt"]
[ext_resource type="Texture2D" uid="uid://cs6e0af876ss5" path="res://sprites/ui/HeartEmpty.png" id="2_n1yht"]
[ext_resource type="Script" path="res://scripts/inventory/HotBar.cs" id="2_owrhq"]
[ext_resource type="Script" path="res://scripts/HealthBarUi.cs" id="2_xrm3v"]
[ext_resource type="Script" path="res://scripts/FpsLabel.cs" id="5_dis4v"]
[ext_resource type="PackedScene" uid="uid://bb188382q7btp" path="res://scenes/gameOverMenu.tscn" id="6_yjmrv"]
[node name="Game" type="Node2D"]
script = ExtResource("1_mqdgt")
@ -83,6 +84,9 @@ offset_right = 20.0
offset_bottom = 25.0
grow_horizontal = 2
[node name="GameOverMenu" parent="CanvasLayer" instance=ExtResource("6_yjmrv")]
visible = false
[node name="ProjectileContainer" type="Node2D" parent="."]
[node name="DamageNumberContainer" type="Node2D" parent="."]
@ -90,3 +94,5 @@ grow_horizontal = 2
[node name="WeaponContainer" type="Node2D" parent="."]
[node name="PlayerContainer" type="Node2D" parent="."]
[node name="AICharacterContainer" type="Node2D" parent="."]

60
scenes/gameOverMenu.tscn Normal file
View File

@ -0,0 +1,60 @@
[gd_scene load_steps=2 format=3 uid="uid://bb188382q7btp"]
[ext_resource type="Script" path="res://scripts/loader/uiLoader/GameOverLoaderMenuLoader.cs" id="1_vj6du"]
[node name="GameOverMenu" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_vj6du")
[node name="ColorRect" type="ColorRect" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
color = Color(0.941176, 0.243137, 0.243137, 0.258824)
[node name="CenterContainer" type="CenterContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="VBoxContainer" type="VBoxContainer" parent="CenterContainer"]
layout_mode = 2
[node name="CenterContainer" type="CenterContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
[node name="GameOverLabel" type="Label" parent="CenterContainer/VBoxContainer/CenterContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 30
text = "game_over_title"
[node name="MarginContainer" type="MarginContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/margin_top = 18
[node name="CenterContainer2" type="CenterContainer" parent="CenterContainer/VBoxContainer/MarginContainer"]
layout_mode = 2
[node name="DeathInfoLabel" type="Label" parent="CenterContainer/VBoxContainer/MarginContainer/CenterContainer2"]
layout_mode = 2
text = "death_info_describe"
[node name="MarginContainer2" type="MarginContainer" parent="CenterContainer/VBoxContainer"]
layout_mode = 2
theme_override_constants/margin_top = 10
theme_override_constants/margin_bottom = 150
[node name="Button" type="Button" parent="CenterContainer/VBoxContainer/MarginContainer2"]
layout_mode = 2
text = "restart"

27
scripts/EventManager.cs Normal file
View File

@ -0,0 +1,27 @@
using System;
using ColdMint.scripts.map.events;
namespace ColdMint.scripts;
public class EventManager
{
/// <summary>
/// <para>Event when the AI character is generated</para>
/// <para>AI角色生成事件</para>
/// </summary>
public static Action<AiCharacterGenerateEvent>? AiCharacterGenerateEvent;
public static Action<GameOverEvent>? GameOverEvent;
/// <summary>
/// <para>Map starts generating events</para>
/// <para>地图开始生成的事件</para>
/// </summary>
public static Action<MapGenerationStartEvent>? MapGenerationStartEvent;
/// <summary>
/// <para>Map generation completion event</para>
/// <para>地图生成完成事件</para>
/// </summary>
public static Action<MapGenerationCompleteEvent>? MapGenerationCompleteEvent;
}

View File

@ -24,6 +24,12 @@ public static class GameSceneNodeHolder
public static Node2D? PlayerContainer { get; set; }
/// <summary>
/// <para>AICharacterContainer</para>
/// <para>AICharacter角色</para>
/// </summary>
public static Node2D? AICharacterContainer { get; set; }
public static HotBar? HotBar { get; set; }

View File

@ -5,6 +5,7 @@ using ColdMint.scripts.damage;
using ColdMint.scripts.debug;
using ColdMint.scripts.health;
using ColdMint.scripts.inventory;
using ColdMint.scripts.map.events;
using ColdMint.scripts.utils;
using ColdMint.scripts.weapon;
using Godot;

View File

@ -1,6 +1,7 @@
using System;
using System.Text;
using ColdMint.scripts.damage;
using ColdMint.scripts.map.events;
using ColdMint.scripts.utils;
using ColdMint.scripts.weapon;
using Godot;
@ -100,7 +101,8 @@ public partial class Player : CharacterTemplate
operationTipBuilder.Append("[color=");
operationTipBuilder.Append(Config.OperationTipActionColor);
operationTipBuilder.Append(']');
operationTipBuilder.Append(TranslationServerUtils.Translate(InputMap.ActionGetEvents("ui_down")[0].AsText()));
operationTipBuilder.Append(
TranslationServerUtils.Translate(InputMap.ActionGetEvents("ui_down")[0].AsText()));
operationTipBuilder.Append("[/color]");
operationTipBuilder.Append(TranslationServerUtils.Translate("jump_down"));
}
@ -292,6 +294,7 @@ public partial class Player : CharacterTemplate
rigidBody2D.LinearVelocity = GetThrowVelocity();
break;
}
CurrentItem = null;
var hotBar = GameSceneNodeHolder.HotBar;
hotBar?.RemoveItemFromItemSlotBySelectIndex(1);
@ -363,6 +366,20 @@ public partial class Player : CharacterTemplate
}
}
protected override void OnDie(DamageTemplate damageTemplate)
{
if (EventManager.GameOverEvent != null)
{
var gameOverEvent = new GameOverEvent
{
DeathInfo = "\"白纸\"失手将自己杀死。"
};
EventManager.GameOverEvent(gameOverEvent);
}
Visible = false;
}
protected override void EnterThePickingRangeBody(Node node)
{
base.EnterThePickingRangeBody(node);

View File

@ -31,6 +31,10 @@ public partial class GameSceneLoader : SceneLoaderTemplate
//加载武器容器
var weaponContainer = GetNode<Node2D>("WeaponContainer");
GameSceneNodeHolder.WeaponContainer = weaponContainer;
//Load AICharacter container
//加载AICharacter容器
var aiCharacterContainer = GetNode<Node2D>("AICharacterContainer");
GameSceneNodeHolder.AICharacterContainer = aiCharacterContainer;
//Load player container
//加载玩家容器
var playerContainer = GetNode<Node2D>("PlayerContainer");
@ -58,13 +62,6 @@ public partial class GameSceneLoader : SceneLoaderTemplate
MapGenerator.LayoutStrategy = new TestLayoutStrategy();
MapGenerator.LayoutParsingStrategy = new SequenceLayoutParsingStrategy();
MapGenerator.RoomPlacementStrategy = new PatchworkRoomPlacementStrategy();
MapGenerator.MapGenerationCompleteEvent += (_) =>
{
};
MapGenerator.MapGenerationStartEvent+= (_) =>
{
};
await GenerateMap();
}

View File

@ -0,0 +1,43 @@
using System.Threading.Tasks;
using ColdMint.scripts.map.events;
using Godot;
namespace ColdMint.scripts.loader.uiLoader;
/// <summary>
/// <para>GameOverLoaderMenuLoader</para>
/// <para>游戏结束菜单加载器</para>
/// </summary>
public partial class GameOverLoaderMenuLoader : UiLoaderTemplate
{
private Label? _deathInfoLabel;
public override void InitializeUi()
{
Visible = false;
}
public override void InitializeData()
{
_deathInfoLabel =
GetNode<Label>("CenterContainer/VBoxContainer/MarginContainer/CenterContainer2/DeathInfoLabel");
EventManager.GameOverEvent += OnGameOver;
}
private void OnGameOver(GameOverEvent gameOverEvent)
{
if (_deathInfoLabel == null)
{
return;
}
Visible = true;
_deathInfoLabel.Text = gameOverEvent.DeathInfo;
}
public override void _ExitTree()
{
base._ExitTree();
EventManager.GameOverEvent -= OnGameOver;
}
}

View File

@ -0,0 +1,54 @@
using ColdMint.scripts.character;
using ColdMint.scripts.debug;
using ColdMint.scripts.map.events;
using Godot;
namespace ColdMint.scripts.map;
/// <summary>
/// <para>Ai character generation point</para>
/// <para>Ai角色生成点</para>
/// </summary>
public partial class AiCharacterSpawn : Marker2D
{
private PackedScene? _packedScene;
public override void _Ready()
{
base._Ready();
var resPath = GetMeta("ResPath", Name).AsString();
if (!string.IsNullOrEmpty(resPath))
{
_packedScene = GD.Load<PackedScene>(resPath);
}
EventManager.AiCharacterGenerateEvent += OnAiCharacterGenerateEvent;
}
/// <summary>
/// <para>When an event is triggered</para>
/// <para>当触发事件时</para>
/// </summary>
/// <param name="aiCharacterGenerateEvent"></param>
public void OnAiCharacterGenerateEvent(AiCharacterGenerateEvent aiCharacterGenerateEvent)
{
var node = _packedScene?.Instantiate();
if (node is not AiCharacter aiCharacter)
{
return;
}
if (GameSceneNodeHolder.AICharacterContainer == null)
{
return;
}
GameSceneNodeHolder.AICharacterContainer.AddChild(aiCharacter);
aiCharacter.Position = GlobalPosition;
}
public override void _ExitTree()
{
EventManager.AiCharacterGenerateEvent -= OnAiCharacterGenerateEvent;
}
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ColdMint.scripts.debug;
using ColdMint.scripts.levelGraphEditor;
@ -83,21 +84,6 @@ public static class MapGenerator
return _roomInjectionProcessorsDictionary.Remove(id);
}
public delegate void MapGenerationStartEventHandler(MapGenerationStartEvent mapGenerationStartEvent);
public delegate void MapGenerationCompleteEventHandler(MapGenerationCompleteEvent mapGenerationCompleteEvent);
/// <summary>
/// <para>Map starts generating events</para>
/// <para>地图开始生成的事件</para>
/// </summary>
public static event MapGenerationStartEventHandler? MapGenerationStartEvent;
/// <summary>
/// <para>Map generation completion event</para>
/// <para>地图生成完成事件</para>
/// </summary>
public static event MapGenerationCompleteEventHandler? MapGenerationCompleteEvent;
/// <summary>
/// <para>Set seed</para>
@ -154,7 +140,7 @@ public static class MapGenerator
}
_running = true;
MapGenerationStartEvent?.Invoke(new MapGenerationStartEvent());
EventManager.MapGenerationStartEvent?.Invoke(new MapGenerationStartEvent());
if (_layoutStrategy == null || _roomPlacementStrategy == null || _layoutParsingStrategy == null ||
_mapRoot == null)
{
@ -163,6 +149,11 @@ public static class MapGenerator
return;
}
if (GameSceneNodeHolder.AICharacterContainer != null)
{
NodeUtils.DeleteAllChild(GameSceneNodeHolder.AICharacterContainer);
}
NodeUtils.DeleteAllChild(_mapRoot);
if (!await _roomPlacementStrategy.StartGeneration(_mapRoot))
{
@ -238,18 +229,21 @@ public static class MapGenerator
{
foreach (var injectionProcessorData in roomInjectionProcessorDataArray)
{
if (string.IsNullOrEmpty(injectionProcessorData.Id) || string.IsNullOrEmpty(injectionProcessorData.Config))
if (string.IsNullOrEmpty(injectionProcessorData.Id) ||
string.IsNullOrEmpty(injectionProcessorData.Config))
{
//The data is incomplete, and the injectionProcessorData is ignored.
//数据不全忽略injectionProcessorData。
continue;
}
if (!_roomInjectionProcessorsDictionary.TryGetValue(injectionProcessorData.Id,
out var roomInjectionProcessor))
{
//If the room injection processor cannot be found, a print error occurs.
//如果找不到房间注入处理器,那么打印错误。
LogCat.LogErrorWithFormat("room_injection_processor_does_not_exist", injectionProcessorData.Id);
LogCat.LogErrorWithFormat("room_injection_processor_does_not_exist",
injectionProcessorData.Id);
continue;
}
@ -262,10 +256,12 @@ public static class MapGenerator
}
}
}
if (!canBePlaced)
{
continue;
}
var nextParentNodeId = await _layoutParsingStrategy.GetNextParentNodeId();
Room? parentRoomNode = null;
if (nextParentNodeId != null)
@ -300,7 +296,13 @@ public static class MapGenerator
{
RandomNumberGenerator = randomNumberGenerator
};
MapGenerationCompleteEvent?.Invoke(eventObj);
EventManager.MapGenerationCompleteEvent?.Invoke(eventObj);
var aiCharacterGenerateEvent = new AiCharacterGenerateEvent
{
Tag = AiCharacterGenerateEvent.TagMapGenerationComplete
};
LogCat.Log("触发事件" + (EventManager.AiCharacterGenerateEvent == null));
EventManager.AiCharacterGenerateEvent?.Invoke(aiCharacterGenerateEvent);
}
/// <summary>

View File

@ -17,12 +17,12 @@ public partial class PlayerSpawn : Marker2D
{
base._Ready();
_playerPackedScene = GD.Load<PackedScene>("res://prefab/entitys/Character.tscn");
MapGenerator.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
EventManager.MapGenerationCompleteEvent += MapGenerationCompleteEvent;
}
private void MapGenerationCompleteEvent(MapGenerationCompleteEvent mapGenerationCompleteEvent)
{
MapGenerator.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
//After the map is generated, create the player instance.
//当地图生成完成后,创建玩家实例。
if (GameSceneNodeHolder.Player != null)
@ -56,4 +56,10 @@ public partial class PlayerSpawn : Marker2D
player.Position = GlobalPosition;
LogCat.LogWithFormat("player_spawn_debug", player.ReadOnlyCharacterName, player.Position);
}
public override void _ExitTree()
{
base._ExitTree();
EventManager.MapGenerationCompleteEvent -= MapGenerationCompleteEvent;
}
}

View File

@ -0,0 +1,21 @@
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>
public string? Tag { get; set; }
}

View File

@ -0,0 +1,14 @@
namespace ColdMint.scripts.map.events;
/// <summary>
/// <para>Game over event</para>
/// <para>游戏结束事件</para>
/// </summary>
public class GameOverEvent
{
/// <summary>
/// <para>Death information</para>
/// <para>死亡信息</para>
/// </summary>
public string? DeathInfo { get; set; }
}