diff --git "a/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.md" "b/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.md"
index d7a93f1..36afd4a 100644
--- "a/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.md"
+++ "b/DungeonShooting_Document/\345\274\200\345\217\221\346\227\245\345\277\227.md"
@@ -1,5 +1,27 @@
---
+### 2023-10-20
+项目从Godot4.1升级到4.2bate, 使用了部分新功能以提升视觉效果, 本月主要完善`Role`的动作和提升地牢视觉效果, 项目已正式开源
+将项目的Ui框架抽成一个单独的Ui插件, 命名为`DsUi`
+近一个半月主要工作内容如下:
+* 项目已经开启2Dhdr, 也就是辉光效果, 现在子弹, 开火特效等都有了高光效果
+* 敌人子弹添加红色描边, 更加容易区分敌方子弹
+* 未被拾起的武器现在也能正常开火, 调用`Weapon.Trigger()`, 也就是在地上开火
+* 玩家新增翻滚动作, 移动时按下鼠标右键就可以向运动方向翻滚移动一段距离, 并且期间无敌
+* 新增武器近战攻击动作, 按空格键, 近战可以抵消地方子弹
+* 新增近战武器反弹敌方子弹的功能
+* 新增`Role`击退效果, 被子弹击中, 武器近战等都可以击退`Role`对象, 但是玩家不能被击退
+* 新增房间迷雾功能, 未探索的房间完全变暗, 当玩家第一次进入时迷雾消散, 并开始刷怪, 当玩家离开房间时房间稍微变暗
+* 新增敌人是否显示瞄准辅助线, 开火时是否可以移动, 锁定目标时是否可以旋转枪口朝向的配置
+* 新增`debug`浮动窗口, 用于游戏中查看日志, 代码日志改用`Debug.Log()`和`Debug.LogError()`函数
+* 更换玩家, 门等游戏素材
+* 游戏暂停功能, 按下`esc`键可以呼出暂停菜单
+* 游戏自适应分辨率, 新增全屏设置
+* 修复房间关门后, 物体到达房间门连接处会被判断离开房间的bug
+* 修复拾起敌人掉落的汤姆逊冲锋枪第一次按扳机有概率无法开火的bug
+* 修复房间门会在消灭所有敌人之前打开的bug
+
+---
### 2023-09-06
经过两个月漫长的开发, 新版地牢编辑器初版已经开发完成, 目的为了更加方便开发者和玩家制作地图, 新版地牢编辑器提供功能如下:
* 地牢项目管理功能, 可以管理地牢组和房间, 支持房间预览, 支持显示异常房间, 房间支持配置权重
diff --git a/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj b/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj
index 9a963c3..d171c69 100644
--- a/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj
+++ b/DungeonShooting_ExcelTool/DungeonShooting_ExcelTool.csproj
@@ -2,7 +2,7 @@
Exe
- net6.0
+ net7.0
enable
enable
diff --git a/DungeonShooting_ExcelTool/ExcelGenerator.cs b/DungeonShooting_ExcelTool/ExcelGenerator.cs
index b400039..d76af05 100644
--- a/DungeonShooting_ExcelTool/ExcelGenerator.cs
+++ b/DungeonShooting_ExcelTool/ExcelGenerator.cs
@@ -578,9 +578,20 @@
return false;
}
- return cell.BooleanCellValue;
+ if (cell.CellType == CellType.Boolean)
+ {
+ return cell.BooleanCellValue;
+ }
+
+ var value = cell.StringCellValue;
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ return false;
+ }
+
+ return bool.Parse(value);
}
-
+
private static MappingData ConvertToType(string str, int depth = 0)
{
if (Regex.IsMatch(str, "^\\w+$"))
diff --git a/DungeonShooting_Godot/DungeonShooting.csproj b/DungeonShooting_Godot/DungeonShooting.csproj
index e36028f..65ee589 100644
--- a/DungeonShooting_Godot/DungeonShooting.csproj
+++ b/DungeonShooting_Godot/DungeonShooting.csproj
@@ -1,4 +1,4 @@
-
+
net7.0
true
diff --git a/DungeonShooting_Godot/DungeonShooting.csproj.old b/DungeonShooting_Godot/DungeonShooting.csproj.old
new file mode 100644
index 0000000..e36028f
--- /dev/null
+++ b/DungeonShooting_Godot/DungeonShooting.csproj.old
@@ -0,0 +1,11 @@
+
+
+ net7.0
+ true
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.deps.json b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.deps.json
index df88148..98c2130 100644
--- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.deps.json
+++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.deps.json
@@ -1,12 +1,12 @@
{
"runtimeTarget": {
- "name": ".NETCoreApp,Version=v6.0/win-x64",
+ "name": ".NETCoreApp,Version=v7.0/win-x64",
"signature": ""
},
"compilationOptions": {},
"targets": {
- ".NETCoreApp,Version=v6.0": {},
- ".NETCoreApp,Version=v6.0/win-x64": {
+ ".NETCoreApp,Version=v7.0": {},
+ ".NETCoreApp,Version=v7.0/win-x64": {
"DungeonShooting_ExcelTool/1.0.0": {
"dependencies": {
"NPOI": "2.6.0"
diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll
index d8ba4b8..f91239a 100644
--- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll
+++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.dll
Binary files differ
diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe
index bb1931a..9c2c323 100644
--- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe
+++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.exe
Binary files differ
diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb
index a963cf3..86422eb 100644
--- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb
+++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.pdb
Binary files differ
diff --git a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.runtimeconfig.json b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.runtimeconfig.json
index e7b3b03..398903e 100644
--- a/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.runtimeconfig.json
+++ b/DungeonShooting_Godot/excel/DungeonShooting_ExcelTool.runtimeconfig.json
@@ -1,9 +1,9 @@
{
"runtimeOptions": {
- "tfm": "net6.0",
+ "tfm": "net7.0",
"framework": {
"name": "Microsoft.NETCore.App",
- "version": "6.0.0"
+ "version": "7.0.0"
},
"configProperties": {
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false
diff --git a/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx b/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx
index dbdd157..508bcd9 100644
--- a/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx
+++ b/DungeonShooting_Godot/excel/excelFile/ActivityObject.xlsx
Binary files differ
diff --git a/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx b/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx
new file mode 100644
index 0000000..152aabd
--- /dev/null
+++ b/DungeonShooting_Godot/excel/excelFile/AiAttackAttr.xlsx
Binary files differ
diff --git a/DungeonShooting_Godot/excel/excelFile/Sound.xlsx b/DungeonShooting_Godot/excel/excelFile/Sound.xlsx
index b2185d4..a17d8a7 100644
--- a/DungeonShooting_Godot/excel/excelFile/Sound.xlsx
+++ b/DungeonShooting_Godot/excel/excelFile/Sound.xlsx
Binary files differ
diff --git a/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx b/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx
index bba5663..7602be4 100644
--- a/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx
+++ b/DungeonShooting_Godot/excel/excelFile/Weapon.xlsx
Binary files differ
diff --git a/DungeonShooting_Godot/prefab/bullet/Bullet0001.tscn b/DungeonShooting_Godot/prefab/bullet/Bullet0001.tscn
index 0a44b2f..858cd81 100644
--- a/DungeonShooting_Godot/prefab/bullet/Bullet0001.tscn
+++ b/DungeonShooting_Godot/prefab/bullet/Bullet0001.tscn
@@ -13,6 +13,7 @@
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
+shader_parameter/outline_use_blend = true
[sub_resource type="ShaderMaterial" id="ShaderMaterial_qhkgc"]
resource_local_to_scene = true
@@ -23,6 +24,7 @@
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
+shader_parameter/outline_use_blend = true
[sub_resource type="SpriteFrames" id="SpriteFrames_5wvmf"]
animations = [{
@@ -51,7 +53,6 @@
material = SubResource("ShaderMaterial_w5w0i")
[node name="AnimatedSprite" type="AnimatedSprite2D" parent="."]
-modulate = Color(1.6, 1.6, 1.6, 1)
material = SubResource("ShaderMaterial_qhkgc")
sprite_frames = SubResource("SpriteFrames_5wvmf")
diff --git a/DungeonShooting_Godot/prefab/bullet/Bullet0002.tscn b/DungeonShooting_Godot/prefab/bullet/Bullet0002.tscn
index 1cb086c..7ff1c64 100644
--- a/DungeonShooting_Godot/prefab/bullet/Bullet0002.tscn
+++ b/DungeonShooting_Godot/prefab/bullet/Bullet0002.tscn
@@ -13,6 +13,7 @@
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
+shader_parameter/outline_use_blend = true
[sub_resource type="ShaderMaterial" id="ShaderMaterial_p0wfd"]
resource_local_to_scene = true
@@ -23,6 +24,7 @@
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
+shader_parameter/outline_use_blend = true
[sub_resource type="CircleShape2D" id="CircleShape2D_0vxfv"]
radius = 3.0
diff --git a/DungeonShooting_Godot/prefab/map/RoomDoor_E.tscn b/DungeonShooting_Godot/prefab/map/RoomDoor_E.tscn
index b40786c..3a07eb2 100644
--- a/DungeonShooting_Godot/prefab/map/RoomDoor_E.tscn
+++ b/DungeonShooting_Godot/prefab/map/RoomDoor_E.tscn
@@ -1,8 +1,9 @@
-[gd_scene load_steps=7 format=3 uid="uid://yhewdkpru0up"]
+[gd_scene load_steps=8 format=3 uid="uid://yhewdkpru0up"]
[ext_resource type="Script" path="res://src/game/room/RoomDoor.cs" id="1_4c6sw"]
[ext_resource type="Shader" path="res://resource/material/Blend.gdshader" id="2_lwx51"]
-[ext_resource type="SpriteFrames" uid="uid://3ps6h2f54qa5" path="res://resource/spriteFrames/other/RoomDoor_EW.tres" id="3_pjvd8"]
+[ext_resource type="SpriteFrames" uid="uid://3ps6h2f54qa5" path="res://resource/spriteFrames/other/RoomDoor_E_Up.tres" id="3_pjvd8"]
+[ext_resource type="SpriteFrames" uid="uid://b34tddsmqnj8s" path="res://resource/spriteFrames/other/RoomDoor_E_Down.tres" id="4_ln8k4"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_yvwpk"]
resource_local_to_scene = true
@@ -40,10 +41,21 @@
[node name="AnimatedSprite" type="AnimatedSprite2D" parent="."]
material = SubResource("ShaderMaterial_t4ayq")
-position = Vector2(0, -8)
+position = Vector2(9, -10)
sprite_frames = ExtResource("3_pjvd8")
-animation = &"closeDoor"
+animation = &"openDoor"
autoplay = "default"
+frame = 4
+frame_progress = 1.0
+
+[node name="AnimatedSpriteDown" type="AnimatedSprite2D" parent="."]
+material = SubResource("ShaderMaterial_t4ayq")
+position = Vector2(9, -10)
+sprite_frames = ExtResource("4_ln8k4")
+animation = &"openDoor"
+autoplay = "default"
+frame = 4
+frame_progress = 1.0
[node name="Collision" type="CollisionShape2D" parent="."]
position = Vector2(0, 4)
diff --git a/DungeonShooting_Godot/prefab/map/RoomDoor_N.tscn b/DungeonShooting_Godot/prefab/map/RoomDoor_N.tscn
index 461cf04..52a7d64 100644
--- a/DungeonShooting_Godot/prefab/map/RoomDoor_N.tscn
+++ b/DungeonShooting_Godot/prefab/map/RoomDoor_N.tscn
@@ -2,14 +2,14 @@
[ext_resource type="Script" path="res://src/game/room/RoomDoor.cs" id="1_220be"]
[ext_resource type="Shader" path="res://resource/material/Blend.gdshader" id="2_h5ru6"]
-[ext_resource type="SpriteFrames" uid="uid://xs72aopsgpg6" path="res://resource/spriteFrames/other/RoomDoor_NS.tres" id="3_apluc"]
+[ext_resource type="SpriteFrames" uid="uid://xs72aopsgpg6" path="res://resource/spriteFrames/other/RoomDoor_N.tres" id="3_apluc"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_yvwpk"]
resource_local_to_scene = true
shader = ExtResource("2_h5ru6")
shader_parameter/blend = Color(0, 0, 0, 0.470588)
shader_parameter/schedule = 1.0
-shader_parameter/alpha = 1.0
+shader_parameter/modulate = Color(1, 1, 1, 1)
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
@@ -19,7 +19,7 @@
shader = ExtResource("2_h5ru6")
shader_parameter/blend = Color(1, 1, 1, 1)
shader_parameter/schedule = 0.0
-shader_parameter/alpha = 1.0
+shader_parameter/modulate = Color(1, 1, 1, 1)
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
@@ -42,8 +42,10 @@
material = SubResource("ShaderMaterial_t4ayq")
position = Vector2(0, -8)
sprite_frames = ExtResource("3_apluc")
-animation = &"openDoor"
+animation = &"closeDoor"
autoplay = "default"
+frame = 4
+frame_progress = 1.0
[node name="Collision" type="CollisionShape2D" parent="."]
position = Vector2(0, -3.5)
diff --git a/DungeonShooting_Godot/prefab/map/RoomDoor_S.tscn b/DungeonShooting_Godot/prefab/map/RoomDoor_S.tscn
index b8cd815..6c07aba 100644
--- a/DungeonShooting_Godot/prefab/map/RoomDoor_S.tscn
+++ b/DungeonShooting_Godot/prefab/map/RoomDoor_S.tscn
@@ -2,14 +2,14 @@
[ext_resource type="Script" path="res://src/game/room/RoomDoor.cs" id="1_f3qbq"]
[ext_resource type="Shader" path="res://resource/material/Blend.gdshader" id="2_6vvcd"]
-[ext_resource type="SpriteFrames" uid="uid://xs72aopsgpg6" path="res://resource/spriteFrames/other/RoomDoor_NS.tres" id="3_at5v2"]
+[ext_resource type="SpriteFrames" uid="uid://ciqijjxup5356" path="res://resource/spriteFrames/other/RoomDoor_S.tres" id="3_hhmd5"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_yvwpk"]
resource_local_to_scene = true
shader = ExtResource("2_6vvcd")
shader_parameter/blend = Color(0, 0, 0, 0.470588)
shader_parameter/schedule = 1.0
-shader_parameter/alpha = 1.0
+shader_parameter/modulate = Color(1, 1, 1, 1)
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
@@ -19,7 +19,7 @@
shader = ExtResource("2_6vvcd")
shader_parameter/blend = Color(1, 1, 1, 1)
shader_parameter/schedule = 0.0
-shader_parameter/alpha = 1.0
+shader_parameter/modulate = Color(1, 1, 1, 1)
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
@@ -41,8 +41,11 @@
[node name="AnimatedSprite" type="AnimatedSprite2D" parent="."]
material = SubResource("ShaderMaterial_t4ayq")
position = Vector2(0, -8)
-sprite_frames = ExtResource("3_at5v2")
+sprite_frames = ExtResource("3_hhmd5")
+animation = &"openDoor"
autoplay = "default"
+frame = 4
+frame_progress = 1.0
[node name="Collision" type="CollisionShape2D" parent="."]
position = Vector2(0, -3.5)
diff --git a/DungeonShooting_Godot/prefab/map/RoomDoor_W.tscn b/DungeonShooting_Godot/prefab/map/RoomDoor_W.tscn
index 855e540..d3c5a08 100644
--- a/DungeonShooting_Godot/prefab/map/RoomDoor_W.tscn
+++ b/DungeonShooting_Godot/prefab/map/RoomDoor_W.tscn
@@ -1,15 +1,16 @@
-[gd_scene load_steps=7 format=3 uid="uid://wmedlesabvr3"]
+[gd_scene load_steps=8 format=3 uid="uid://wmedlesabvr3"]
[ext_resource type="Script" path="res://src/game/room/RoomDoor.cs" id="1_agux2"]
[ext_resource type="Shader" path="res://resource/material/Blend.gdshader" id="2_wx2w3"]
-[ext_resource type="SpriteFrames" uid="uid://3ps6h2f54qa5" path="res://resource/spriteFrames/other/RoomDoor_EW.tres" id="3_a2hvw"]
+[ext_resource type="SpriteFrames" uid="uid://cpdt5ywrsruu3" path="res://resource/spriteFrames/other/RoomDoor_W_Up.tres" id="3_veggu"]
+[ext_resource type="SpriteFrames" uid="uid://qq3h0mh4r12i" path="res://resource/spriteFrames/other/RoomDoor_W_Down.tres" id="4_dnjb6"]
[sub_resource type="ShaderMaterial" id="ShaderMaterial_yvwpk"]
resource_local_to_scene = true
shader = ExtResource("2_wx2w3")
shader_parameter/blend = Color(0, 0, 0, 0.470588)
shader_parameter/schedule = 1.0
-shader_parameter/alpha = 1.0
+shader_parameter/modulate = Color(1, 1, 1, 1)
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
@@ -19,7 +20,7 @@
shader = ExtResource("2_wx2w3")
shader_parameter/blend = Color(1, 1, 1, 1)
shader_parameter/schedule = 0.0
-shader_parameter/alpha = 1.0
+shader_parameter/modulate = Color(1, 1, 1, 1)
shader_parameter/show_outline = false
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
@@ -40,9 +41,21 @@
[node name="AnimatedSprite" type="AnimatedSprite2D" parent="."]
material = SubResource("ShaderMaterial_t4ayq")
-position = Vector2(0, -8)
-sprite_frames = ExtResource("3_a2hvw")
+position = Vector2(-9, -10)
+sprite_frames = ExtResource("3_veggu")
+animation = &"openDoor"
autoplay = "default"
+frame = 4
+frame_progress = 1.0
+
+[node name="AnimatedSpriteDown" type="AnimatedSprite2D" parent="."]
+material = SubResource("ShaderMaterial_t4ayq")
+position = Vector2(-9, -10)
+sprite_frames = ExtResource("4_dnjb6")
+animation = &"openDoor"
+autoplay = "default"
+frame = 4
+frame_progress = 1.0
[node name="Collision" type="CollisionShape2D" parent="."]
position = Vector2(0, 4)
diff --git a/DungeonShooting_Godot/prefab/role/Enemy0001.tscn b/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
index 46e01b2..866f829 100644
--- a/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
+++ b/DungeonShooting_Godot/prefab/role/Enemy0001.tscn
@@ -14,6 +14,7 @@
shader_parameter/show_outline = true
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
+shader_parameter/outline_use_blend = true
[sub_resource type="ShaderMaterial" id="ShaderMaterial_k8mt5"]
resource_local_to_scene = true
@@ -24,6 +25,7 @@
shader_parameter/show_outline = true
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
+shader_parameter/outline_use_blend = true
[node name="Enemy0001" node_paths=PackedStringArray("HurtArea", "HurtCollision", "MountPoint", "BackMountPoint", "InteractiveArea", "InteractiveCollision", "MeleeAttackArea", "MeleeAttackCollision", "ShadowSprite", "AnimatedSprite", "Collision") instance=ExtResource("1_5po38")]
collision_layer = 16
diff --git a/DungeonShooting_Godot/prefab/ui/Setting.tscn b/DungeonShooting_Godot/prefab/ui/Setting.tscn
index c6b1075..85242df 100644
--- a/DungeonShooting_Godot/prefab/ui/Setting.tscn
+++ b/DungeonShooting_Godot/prefab/ui/Setting.tscn
@@ -285,7 +285,7 @@
[node name="Value" type="Label" parent="ScrollContainer/KeySetting/Key12"]
layout_mode = 2
-text = "空格"
+text = "鼠标右键"
[node name="Key13" type="HBoxContainer" parent="ScrollContainer/KeySetting"]
custom_minimum_size = Vector2(600, 0)
@@ -300,7 +300,7 @@
[node name="Value" type="Label" parent="ScrollContainer/KeySetting/Key13"]
layout_mode = 2
-text = "鼠标右键"
+text = "空格"
[node name="Back" type="Button" parent="ScrollContainer/KeySetting"]
layout_mode = 2
diff --git a/DungeonShooting_Godot/prefab/weapon/WeaponTemplate.tscn b/DungeonShooting_Godot/prefab/weapon/WeaponTemplate.tscn
index 81179a1..7b22ce1 100644
--- a/DungeonShooting_Godot/prefab/weapon/WeaponTemplate.tscn
+++ b/DungeonShooting_Godot/prefab/weapon/WeaponTemplate.tscn
@@ -11,6 +11,7 @@
shader_parameter/show_outline = true
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
+shader_parameter/outline_use_blend = true
[sub_resource type="ShaderMaterial" id="ShaderMaterial_o36tv"]
resource_local_to_scene = true
@@ -21,6 +22,7 @@
shader_parameter/show_outline = true
shader_parameter/outline_color = Color(0, 0, 0, 1)
shader_parameter/outline_rainbow = false
+shader_parameter/outline_use_blend = true
[sub_resource type="Animation" id="Animation_x136i"]
length = 0.001
@@ -79,6 +81,7 @@
[node name="GripPoint" type="Marker2D" parent="."]
[node name="Collision" type="CollisionShape2D" parent="."]
+visible = false
[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
libraries = {
diff --git a/DungeonShooting_Godot/resource/config/AiAttackAttr.json b/DungeonShooting_Godot/resource/config/AiAttackAttr.json
new file mode 100644
index 0000000..010c512
--- /dev/null
+++ b/DungeonShooting_Godot/resource/config/AiAttackAttr.json
@@ -0,0 +1,68 @@
+[
+ {
+ "Id": "0001",
+ "Remark": "",
+ "FiringStand": true,
+ "ShowSubline": false,
+ "LockingTime": 1,
+ "LockAngleTime": 0,
+ "AttackLockAngle": true,
+ "BulletSpeedScale": 0.4,
+ "AmmoConsumptionProbability": 0
+ },
+ {
+ "Id": "0002",
+ "Remark": "",
+ "FiringStand": true,
+ "ShowSubline": false,
+ "LockingTime": 2,
+ "LockAngleTime": 0,
+ "AttackLockAngle": false,
+ "BulletSpeedScale": 0.35,
+ "AmmoConsumptionProbability": 0
+ },
+ {
+ "Id": "0003",
+ "Remark": "",
+ "FiringStand": true,
+ "ShowSubline": false,
+ "LockingTime": 1,
+ "LockAngleTime": 0,
+ "AttackLockAngle": false,
+ "BulletSpeedScale": 0.35,
+ "AmmoConsumptionProbability": 0
+ },
+ {
+ "Id": "0004",
+ "Remark": "\u79FB\u52A8\u5C04\u51FB",
+ "FiringStand": false,
+ "ShowSubline": false,
+ "LockingTime": 0.7,
+ "LockAngleTime": 0,
+ "AttackLockAngle": true,
+ "BulletSpeedScale": 0.35,
+ "AmmoConsumptionProbability": 0
+ },
+ {
+ "Id": "0005",
+ "Remark": "\u4F7F\u7528\u8FDC\u8DDD\u79BB\u6B66\u5668",
+ "FiringStand": true,
+ "ShowSubline": true,
+ "LockingTime": 1.5,
+ "LockAngleTime": 0.5,
+ "AttackLockAngle": true,
+ "BulletSpeedScale": 0.5,
+ "AmmoConsumptionProbability": 0
+ },
+ {
+ "Id": "0006",
+ "Remark": "",
+ "FiringStand": true,
+ "ShowSubline": false,
+ "LockingTime": 0.5,
+ "LockAngleTime": 0.5,
+ "AttackLockAngle": false,
+ "BulletSpeedScale": 0.35,
+ "AmmoConsumptionProbability": 0
+ }
+]
\ No newline at end of file
diff --git a/DungeonShooting_Godot/resource/config/Weapon.json b/DungeonShooting_Godot/resource/config/Weapon.json
index 57bbf71..11a4daf 100644
--- a/DungeonShooting_Godot/resource/config/Weapon.json
+++ b/DungeonShooting_Godot/resource/config/Weapon.json
@@ -88,9 +88,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "0002",
- "AiTargetLockingTime": 0,
- "AiBulletSpeedScale": 0,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": ""
},
{
"Id": "0002",
@@ -181,9 +179,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "",
- "AiTargetLockingTime": 0.5,
- "AiBulletSpeedScale": 0.5,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": "0001"
},
{
"Id": "0003",
@@ -275,9 +271,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "0004",
- "AiTargetLockingTime": 0,
- "AiBulletSpeedScale": 0,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": ""
},
{
"Id": "0004",
@@ -369,9 +363,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "",
- "AiTargetLockingTime": 0.4,
- "AiBulletSpeedScale": 0.5,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": "0002"
},
{
"Id": "0005",
@@ -462,9 +454,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "0006",
- "AiTargetLockingTime": 0,
- "AiBulletSpeedScale": 0,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": ""
},
{
"Id": "0006",
@@ -555,9 +545,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "",
- "AiTargetLockingTime": 1,
- "AiBulletSpeedScale": 0.5,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": "0003"
},
{
"Id": "0007",
@@ -645,9 +633,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "0008",
- "AiTargetLockingTime": 0,
- "AiBulletSpeedScale": 0,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": ""
},
{
"Id": "0008",
@@ -735,9 +721,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "",
- "AiTargetLockingTime": 0.7,
- "AiBulletSpeedScale": 0.5,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": "0004"
},
{
"Id": "0009",
@@ -828,9 +812,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "0010",
- "AiTargetLockingTime": 0,
- "AiBulletSpeedScale": 0,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": ""
},
{
"Id": "0010",
@@ -921,9 +903,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "",
- "AiTargetLockingTime": 1.5,
- "AiBulletSpeedScale": 0.5,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": "0005"
},
{
"Id": "0011",
@@ -1014,9 +994,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "0012",
- "AiTargetLockingTime": 0,
- "AiBulletSpeedScale": 0,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": ""
},
{
"Id": "0012",
@@ -1107,9 +1085,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "",
- "AiTargetLockingTime": 0.5,
- "AiBulletSpeedScale": 0.5,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": "0004"
},
{
"Id": "0013",
@@ -1200,9 +1176,7 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "0014",
- "AiTargetLockingTime": 0,
- "AiBulletSpeedScale": 0,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": ""
},
{
"Id": "0014",
@@ -1293,8 +1267,6 @@
"BeLoadedSoundDelayTime": 0,
"__OtherSoundMap": null,
"__AiUseAttribute": "",
- "AiTargetLockingTime": 0.5,
- "AiBulletSpeedScale": 0.5,
- "AiAmmoConsumptionProbability": 0
+ "__AiAttackAttr": "0006"
}
]
\ No newline at end of file
diff --git a/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json b/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json
index f5cded9..d9e69c2 100644
--- a/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json
+++ b/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json
@@ -1,40 +1,40 @@
{
"TestGroup1": {
- "GroupName": "TestGroup1",
- "BattleList": [
- {
- "ErrorType": 0,
- "Path": "resource/map/tileMaps/TestGroup1/battle/Battle1"
- },
- {
- "ErrorType": 0,
- "Path": "resource/map/tileMaps/TestGroup1/battle/Battle2"
- },
- {
- "ErrorType": 0,
- "Path": "resource/map/tileMaps/TestGroup1/battle/Battle3"
- }
- ],
- "InletList": [
- {
- "ErrorType": 0,
- "Path": "resource/map/tileMaps/TestGroup1/inlet/Start1"
- },
- {
- "ErrorType": 0,
- "Path": "resource/map/tileMaps/TestGroup1/inlet/Start2"
- }
- ],
- "OutletList": [
- {
- "ErrorType": 0,
- "Path": "resource/map/tileMaps/TestGroup1/outlet/End1"
- }
- ],
- "BossList": [],
- "RewardList": [],
- "ShopList": [],
- "EventList": [],
- "Remark": "\u6D4B\u8BD5\u7EC4"
+ "GroupName": "TestGroup1",
+ "BattleList": [
+ {
+ "ErrorType": 0,
+ "Path": "resource/map/tileMaps/TestGroup1/battle/Battle1"
+ },
+ {
+ "ErrorType": 0,
+ "Path": "resource/map/tileMaps/TestGroup1/battle/Battle2"
+ },
+ {
+ "ErrorType": 0,
+ "Path": "resource/map/tileMaps/TestGroup1/battle/Battle3"
+ }
+ ],
+ "InletList": [
+ {
+ "ErrorType": 0,
+ "Path": "resource/map/tileMaps/TestGroup1/inlet/Start1"
+ },
+ {
+ "ErrorType": 0,
+ "Path": "resource/map/tileMaps/TestGroup1/inlet/Start2"
+ }
+ ],
+ "OutletList": [
+ {
+ "ErrorType": 0,
+ "Path": "resource/map/tileMaps/TestGroup1/outlet/End1"
+ }
+ ],
+ "BossList": [],
+ "RewardList": [],
+ "ShopList": [],
+ "EventList": [],
+ "Remark": "\u6D4B\u8BD5\u7EC4"
}
-}
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json
index fd75129..582ee5f 100644
--- a/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json
+++ b/DungeonShooting_Godot/resource/map/tileMaps/TestGroup1/inlet/Start1/Preinstall.json
@@ -1 +1 @@
-[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":19,"Y":2},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":-76,"Y":35},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-79,"Y":46},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":2},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":67},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-73,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-76,"Y":21},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-74,"Y":-30},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":55,"Y":67},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":24},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":0},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":23},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":55,"Y":44},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":-24},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]}]]}]
\ No newline at end of file
+[{"Name":"test1","Weight":100,"Remark":"","WaveList":[[{"Position":{"X":19,"Y":2},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]},{"Position":{"X":-76,"Y":35},"Size":{"X":0,"Y":0},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0001","Weight":100,"Attr":{"CurrAmmon":"30","ResidueAmmo":"210"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-79,"Y":46},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0002","Weight":100,"Attr":{"CurrAmmon":"7","ResidueAmmo":"70"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":2},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0004","Weight":100,"Attr":{"CurrAmmon":"180","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-75,"Y":67},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0005","Weight":100,"Attr":{"CurrAmmon":"10","ResidueAmmo":"40"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-73,"Y":-18},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0003","Weight":100,"Attr":{"CurrAmmon":"12","ResidueAmmo":"90"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-76,"Y":21},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0006","Weight":100,"Attr":{"CurrAmmon":"20","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-74,"Y":-30},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"weapon0007","Weight":100,"Attr":{"CurrAmmon":"60","ResidueAmmo":"300"},"Altitude":8,"VerticalSpeed":0}]}],[{"Position":{"X":55,"Y":67},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop0003","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":24},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0.5,"MarkList":[{"Id":"prop5000","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":0},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":34,"Y":23},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":1.5,"MarkList":[{"Id":"prop0002","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":55,"Y":44},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":56,"Y":-24},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"prop5001","Weight":100,"Attr":null,"Altitude":8,"VerticalSpeed":0}]},{"Position":{"X":-16,"Y":16},"Size":{"X":16,"Y":16},"SpecialMarkType":0,"DelayTime":0,"MarkList":[{"Id":"enemy0001","Weight":100,"Attr":{"Face":"0","Weapon":"weapon0005","CurrAmmon":"10","ResidueAmmo":"10"},"Altitude":0,"VerticalSpeed":0}]}]]}]
\ No newline at end of file
diff --git a/DungeonShooting_Godot/resource/material/Blend.gdshader b/DungeonShooting_Godot/resource/material/Blend.gdshader
index f83601b..f952fc5 100644
--- a/DungeonShooting_Godot/resource/material/Blend.gdshader
+++ b/DungeonShooting_Godot/resource/material/Blend.gdshader
@@ -4,8 +4,7 @@
uniform vec4 blend : source_color = vec4(1.0, 1.0, 1.0, 1.0);
//混合度
uniform float schedule : hint_range(0.0, 1.0) = 0.0;
-//透明度
-//uniform float alpha : hint_range(0.0, 1.0) = 1.0;
+//
uniform vec4 modulate : source_color = vec4(1.0, 1.0, 1.0, 1.0);
//------------------ 轮廓相关 --------------
@@ -13,15 +12,18 @@
//轮廓颜色
uniform vec4 outline_color : source_color = vec4(0.0, 0.0, 0.0, 1.0);
//是否是彩虹轮廓
-uniform bool outline_rainbow = false;
+uniform bool outline_rainbow = false;
+//轮廓是否使用 blend
+uniform bool outline_use_blend = true;
+
//彩虹轮廓变化周期
const float frequency = 0.25;
const float light_offset = 0.5;
void fragment() {
+ float a = COLOR.a;
//显示轮廓
- if (show_outline) {
- vec4 color = texture(TEXTURE, UV);
+ if (show_outline && a == 0.0) {
vec2 size = TEXTURE_PIXEL_SIZE;
float outline;
outline = texture(TEXTURE, UV + vec2(-size.x, 0)).a;
@@ -29,25 +31,28 @@
outline += texture(TEXTURE, UV + vec2(size.x, 0)).a;
outline += texture(TEXTURE, UV + vec2(0, -size.y)).a;
outline = min(outline, 1.0);
-
- if (color.a == 0.0 && outline > 0.0) {
- vec4 animated_line_color = vec4(
- light_offset + sin(2.0 * 3.14 * frequency * TIME),
- light_offset + sin(2.0 * 3.14 * frequency * TIME + radians(120.0)),
- light_offset + sin(2.0 * 3.14 * frequency * TIME + radians(240.0)),
- 1.0
- );
-
+ if (outline > 0.0) {
if (outline_rainbow){
- COLOR = mix(color, animated_line_color, 1);
+ vec4 animated_line_color = vec4(
+ light_offset + sin(2.0 * 3.14 * frequency * TIME),
+ light_offset + sin(2.0 * 3.14 * frequency * TIME + radians(120.0)),
+ light_offset + sin(2.0 * 3.14 * frequency * TIME + radians(240.0)),
+ 1.0
+ );
+ COLOR = mix(COLOR, animated_line_color, 1);
+ a = animated_line_color.a;
} else {
- COLOR = mix(color, outline_color , 1);
+ COLOR = mix(COLOR, outline_color , 1);
+ a = outline_color.a;
}
}
+ if (outline_use_blend) {
+ COLOR = mix(COLOR, blend, schedule);
+ }
+ } else { //非轮廓
+ COLOR = mix(COLOR, blend, schedule);
}
- vec4 col = mix(COLOR, blend, schedule);
- col = mix(vec4(0.0, 0.0, 0.0, 0.0), col, COLOR.a);
- col *= modulate;
- COLOR = col;
+ COLOR.a *= a;
+ COLOR *= modulate;
}
diff --git a/DungeonShooting_Godot/resource/sprite/map/door.png b/DungeonShooting_Godot/resource/sprite/map/door.png
new file mode 100644
index 0000000..5a02887
--- /dev/null
+++ b/DungeonShooting_Godot/resource/sprite/map/door.png
Binary files differ
diff --git a/DungeonShooting_Godot/resource/sprite/map/door.png.import b/DungeonShooting_Godot/resource/sprite/map/door.png.import
new file mode 100644
index 0000000..d2fa145
--- /dev/null
+++ b/DungeonShooting_Godot/resource/sprite/map/door.png.import
@@ -0,0 +1,34 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://f7d7qsdxqx28"
+path="res://.godot/imported/door.png-df89cda31b3be3b13dd6a96afcb773e6.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://resource/sprite/map/door.png"
+dest_files=["res://.godot/imported/door.png-df89cda31b3be3b13dd6a96afcb773e6.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
diff --git a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_EW.tres b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_EW.tres
deleted file mode 100644
index 2c7c77e..0000000
--- a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_EW.tres
+++ /dev/null
@@ -1,161 +0,0 @@
-[gd_resource type="SpriteFrames" load_steps=22 format=3 uid="uid://3ps6h2f54qa5"]
-
-[ext_resource type="Texture2D" uid="uid://dviv44fhwvkb1" path="res://resource/sprite/map/door1_down.png" id="1_peglf"]
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_5m6ya"]
-atlas = ExtResource("1_peglf")
-region = Rect2(144, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_kmhtl"]
-atlas = ExtResource("1_peglf")
-region = Rect2(128, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_umaop"]
-atlas = ExtResource("1_peglf")
-region = Rect2(112, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_aqex7"]
-atlas = ExtResource("1_peglf")
-region = Rect2(96, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_hdocg"]
-atlas = ExtResource("1_peglf")
-region = Rect2(80, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_aiymw"]
-atlas = ExtResource("1_peglf")
-region = Rect2(64, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_8f7dv"]
-atlas = ExtResource("1_peglf")
-region = Rect2(32, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_iv82l"]
-atlas = ExtResource("1_peglf")
-region = Rect2(16, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_ycmnv"]
-atlas = ExtResource("1_peglf")
-region = Rect2(0, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_o7xw0"]
-atlas = ExtResource("1_peglf")
-region = Rect2(144, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_j8iw2"]
-atlas = ExtResource("1_peglf")
-region = Rect2(0, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_823if"]
-atlas = ExtResource("1_peglf")
-region = Rect2(16, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_7hyae"]
-atlas = ExtResource("1_peglf")
-region = Rect2(32, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_6lhu3"]
-atlas = ExtResource("1_peglf")
-region = Rect2(48, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_a026j"]
-atlas = ExtResource("1_peglf")
-region = Rect2(64, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_wfjf7"]
-atlas = ExtResource("1_peglf")
-region = Rect2(80, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_rhj60"]
-atlas = ExtResource("1_peglf")
-region = Rect2(96, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_06y08"]
-atlas = ExtResource("1_peglf")
-region = Rect2(112, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_1200j"]
-atlas = ExtResource("1_peglf")
-region = Rect2(128, 48, 16, 48)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_mbnbx"]
-atlas = ExtResource("1_peglf")
-region = Rect2(144, 48, 16, 48)
-
-[resource]
-animations = [{
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_5m6ya")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_kmhtl")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_umaop")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_aqex7")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_hdocg")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_aiymw")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_8f7dv")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_iv82l")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_ycmnv")
-}],
-"loop": false,
-"name": &"closeDoor",
-"speed": 20.0
-}, {
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_o7xw0")
-}],
-"loop": false,
-"name": &"default",
-"speed": 20.0
-}, {
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_j8iw2")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_823if")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_7hyae")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_6lhu3")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_a026j")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_wfjf7")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_rhj60")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_06y08")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_1200j")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_mbnbx")
-}],
-"loop": false,
-"name": &"openDoor",
-"speed": 20.0
-}]
diff --git a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_E_Down.tres b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_E_Down.tres
new file mode 100644
index 0000000..9669b44
--- /dev/null
+++ b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_E_Down.tres
@@ -0,0 +1,98 @@
+[gd_resource type="SpriteFrames" load_steps=13 format=3 uid="uid://b34tddsmqnj8s"]
+
+[ext_resource type="Texture2D" uid="uid://f7d7qsdxqx28" path="res://resource/sprite/map/door.png" id="1_nc77d"]
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_4o2e1"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(128, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_d1gjl"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(96, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_g4rm7"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(64, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_5d5bq"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(32, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_ekma7"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(0, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_7y01b"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(128, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_jm1e2"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(0, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_1bb60"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(32, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_oylje"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(64, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_truep"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(96, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_lfr82"]
+atlas = ExtResource("1_nc77d")
+region = Rect2(128, 104, 32, 52)
+
+[resource]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_4o2e1")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_d1gjl")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_g4rm7")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_5d5bq")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_ekma7")
+}],
+"loop": false,
+"name": &"closeDoor",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_7y01b")
+}],
+"loop": false,
+"name": &"default",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_jm1e2")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_1bb60")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_oylje")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_truep")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_lfr82")
+}],
+"loop": false,
+"name": &"openDoor",
+"speed": 10.0
+}]
diff --git a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_E_Up.tres b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_E_Up.tres
new file mode 100644
index 0000000..8e74aa6
--- /dev/null
+++ b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_E_Up.tres
@@ -0,0 +1,98 @@
+[gd_resource type="SpriteFrames" load_steps=13 format=3 uid="uid://3ps6h2f54qa5"]
+
+[ext_resource type="Texture2D" uid="uid://f7d7qsdxqx28" path="res://resource/sprite/map/door.png" id="2_u3fum"]
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_8f67t"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(128, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_qlja2"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(96, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_glno6"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(64, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_frnbt"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(32, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_2ytfc"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(0, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_oyi3c"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(128, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_e68us"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(0, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_e7wqp"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(32, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_qcket"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(64, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_genp5"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(96, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_krdph"]
+atlas = ExtResource("2_u3fum")
+region = Rect2(128, 52, 32, 52)
+
+[resource]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_8f67t")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_qlja2")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_glno6")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_frnbt")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_2ytfc")
+}],
+"loop": false,
+"name": &"closeDoor",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_oyi3c")
+}],
+"loop": false,
+"name": &"default",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_e68us")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_e7wqp")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_qcket")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_genp5")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_krdph")
+}],
+"loop": false,
+"name": &"openDoor",
+"speed": 10.0
+}]
diff --git a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_N.tres b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_N.tres
new file mode 100644
index 0000000..1d7086c
--- /dev/null
+++ b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_N.tres
@@ -0,0 +1,98 @@
+[gd_resource type="SpriteFrames" load_steps=13 format=3 uid="uid://xs72aopsgpg6"]
+
+[ext_resource type="Texture2D" uid="uid://f7d7qsdxqx28" path="res://resource/sprite/map/door.png" id="1_6mlq3"]
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_jiqrp"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(288, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_id4d1"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(256, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_dun04"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(224, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_1rfr2"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(192, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_c8ka5"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(160, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_3jbbr"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(288, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_xuwj8"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(160, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_xx0rn"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(192, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_5h1on"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(224, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_rwd5l"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(256, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_wov8g"]
+atlas = ExtResource("1_6mlq3")
+region = Rect2(288, 0, 32, 52)
+
+[resource]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_jiqrp")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_id4d1")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_dun04")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_1rfr2")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_c8ka5")
+}],
+"loop": false,
+"name": &"closeDoor",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_3jbbr")
+}],
+"loop": false,
+"name": &"default",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_xuwj8")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_xx0rn")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_5h1on")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_rwd5l")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_wov8g")
+}],
+"loop": false,
+"name": &"openDoor",
+"speed": 10.0
+}]
diff --git a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_NS.tres b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_NS.tres
deleted file mode 100644
index dfc5109..0000000
--- a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_NS.tres
+++ /dev/null
@@ -1,155 +0,0 @@
-[gd_resource type="SpriteFrames" load_steps=21 format=3 uid="uid://xs72aopsgpg6"]
-
-[ext_resource type="Texture2D" uid="uid://dviv44fhwvkb1" path="res://resource/sprite/map/door1_down.png" id="1_ugffo"]
-
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_77i3w"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(256, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_112lq"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(224, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_2ojr8"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(192, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_q58ag"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(160, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_ghweb"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(128, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_28y4l"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(96, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_0fk5y"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(64, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_eu8jg"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(32, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_rw4x5"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(0, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_5dlkq"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(256, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_dnc85"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(0, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_8wepo"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(32, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_s2c1g"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(64, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_umj5m"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(96, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_sceep"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(128, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_0vntu"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(160, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_66ox7"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(192, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_o2uxo"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(224, 0, 32, 32)
-
-[sub_resource type="AtlasTexture" id="AtlasTexture_m6v3e"]
-atlas = ExtResource("1_ugffo")
-region = Rect2(256, 0, 32, 32)
-
-[resource]
-animations = [{
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_77i3w")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_112lq")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_2ojr8")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_q58ag")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_ghweb")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_28y4l")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_0fk5y")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_eu8jg")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_rw4x5")
-}],
-"loop": false,
-"name": &"closeDoor",
-"speed": 20.0
-}, {
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_5dlkq")
-}],
-"loop": false,
-"name": &"default",
-"speed": 20.0
-}, {
-"frames": [{
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_dnc85")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_8wepo")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_s2c1g")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_umj5m")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_sceep")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_0vntu")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_66ox7")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_o2uxo")
-}, {
-"duration": 1.0,
-"texture": SubResource("AtlasTexture_m6v3e")
-}],
-"loop": false,
-"name": &"openDoor",
-"speed": 20.0
-}]
diff --git a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_S.tres b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_S.tres
new file mode 100644
index 0000000..5988cc3
--- /dev/null
+++ b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_S.tres
@@ -0,0 +1,98 @@
+[gd_resource type="SpriteFrames" load_steps=13 format=3 uid="uid://ciqijjxup5356"]
+
+[ext_resource type="Texture2D" uid="uid://f7d7qsdxqx28" path="res://resource/sprite/map/door.png" id="1_46oik"]
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_w2vr1"]
+atlas = ExtResource("1_46oik")
+region = Rect2(128, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_3akio"]
+atlas = ExtResource("1_46oik")
+region = Rect2(96, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_xxpwm"]
+atlas = ExtResource("1_46oik")
+region = Rect2(64, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_vjx8u"]
+atlas = ExtResource("1_46oik")
+region = Rect2(32, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_clyvp"]
+atlas = ExtResource("1_46oik")
+region = Rect2(0, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_1vfst"]
+atlas = ExtResource("1_46oik")
+region = Rect2(128, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_8wrb5"]
+atlas = ExtResource("1_46oik")
+region = Rect2(0, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_nwt0b"]
+atlas = ExtResource("1_46oik")
+region = Rect2(32, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_ohokj"]
+atlas = ExtResource("1_46oik")
+region = Rect2(64, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_wqsd1"]
+atlas = ExtResource("1_46oik")
+region = Rect2(96, 0, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_i6sro"]
+atlas = ExtResource("1_46oik")
+region = Rect2(128, 0, 32, 52)
+
+[resource]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_w2vr1")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_3akio")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_xxpwm")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_vjx8u")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_clyvp")
+}],
+"loop": false,
+"name": &"closeDoor",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_1vfst")
+}],
+"loop": false,
+"name": &"default",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_8wrb5")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_nwt0b")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_ohokj")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_wqsd1")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_i6sro")
+}],
+"loop": false,
+"name": &"openDoor",
+"speed": 10.0
+}]
diff --git a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_W_Down.tres b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_W_Down.tres
new file mode 100644
index 0000000..86fc6ad
--- /dev/null
+++ b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_W_Down.tres
@@ -0,0 +1,98 @@
+[gd_resource type="SpriteFrames" load_steps=13 format=3 uid="uid://qq3h0mh4r12i"]
+
+[ext_resource type="Texture2D" uid="uid://f7d7qsdxqx28" path="res://resource/sprite/map/door.png" id="1_b4js3"]
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_526no"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(288, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_84kmd"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(256, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_km4i6"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(224, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_wtul1"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(192, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_vbu5n"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(160, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_yxx5v"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(288, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_4ncdo"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(160, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_bxfu1"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(192, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_8082a"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(224, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_mjuqg"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(256, 104, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_rc634"]
+atlas = ExtResource("1_b4js3")
+region = Rect2(288, 104, 32, 52)
+
+[resource]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_526no")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_84kmd")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_km4i6")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_wtul1")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_vbu5n")
+}],
+"loop": false,
+"name": &"closeDoor",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_yxx5v")
+}],
+"loop": false,
+"name": &"default",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_4ncdo")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_bxfu1")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_8082a")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_mjuqg")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_rc634")
+}],
+"loop": false,
+"name": &"openDoor",
+"speed": 10.0
+}]
diff --git a/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_W_Up.tres b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_W_Up.tres
new file mode 100644
index 0000000..6c18e9e
--- /dev/null
+++ b/DungeonShooting_Godot/resource/spriteFrames/other/RoomDoor_W_Up.tres
@@ -0,0 +1,98 @@
+[gd_resource type="SpriteFrames" load_steps=13 format=3 uid="uid://cpdt5ywrsruu3"]
+
+[ext_resource type="Texture2D" uid="uid://f7d7qsdxqx28" path="res://resource/sprite/map/door.png" id="2_klr41"]
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_skb20"]
+atlas = ExtResource("2_klr41")
+region = Rect2(288, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_dk55p"]
+atlas = ExtResource("2_klr41")
+region = Rect2(256, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_78qdb"]
+atlas = ExtResource("2_klr41")
+region = Rect2(224, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_sqirq"]
+atlas = ExtResource("2_klr41")
+region = Rect2(192, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_c65nc"]
+atlas = ExtResource("2_klr41")
+region = Rect2(160, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_6tswf"]
+atlas = ExtResource("2_klr41")
+region = Rect2(288, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_hg8wo"]
+atlas = ExtResource("2_klr41")
+region = Rect2(160, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_qkhur"]
+atlas = ExtResource("2_klr41")
+region = Rect2(192, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_6rqcm"]
+atlas = ExtResource("2_klr41")
+region = Rect2(224, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_y0tub"]
+atlas = ExtResource("2_klr41")
+region = Rect2(256, 52, 32, 52)
+
+[sub_resource type="AtlasTexture" id="AtlasTexture_w8xe5"]
+atlas = ExtResource("2_klr41")
+region = Rect2(288, 52, 32, 52)
+
+[resource]
+animations = [{
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_skb20")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_dk55p")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_78qdb")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_sqirq")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_c65nc")
+}],
+"loop": false,
+"name": &"closeDoor",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_6tswf")
+}],
+"loop": false,
+"name": &"default",
+"speed": 10.0
+}, {
+"frames": [{
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_hg8wo")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_qkhur")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_6rqcm")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_y0tub")
+}, {
+"duration": 1.0,
+"texture": SubResource("AtlasTexture_w8xe5")
+}],
+"loop": false,
+"name": &"openDoor",
+"speed": 10.0
+}]
diff --git a/DungeonShooting_Godot/src/config/ExcelConfig.cs b/DungeonShooting_Godot/src/config/ExcelConfig.cs
index 86550d4..6416ead 100644
--- a/DungeonShooting_Godot/src/config/ExcelConfig.cs
+++ b/DungeonShooting_Godot/src/config/ExcelConfig.cs
@@ -17,6 +17,15 @@
public static Dictionary ActivityObject_Map { get; private set; }
///
+ /// AiAttackAttr.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同
+ ///
+ public static List AiAttackAttr_List { get; private set; }
+ ///
+ /// AiAttackAttr.xlsx表数据集合, 里 Map 形式存储, key 为 Id
+ ///
+ public static Dictionary AiAttackAttr_Map { get; private set; }
+
+ ///
/// Sound.xlsx表数据集合, 以 List 形式存储, 数据顺序与 Excel 表相同
///
public static List Sound_List { get; private set; }
@@ -45,6 +54,7 @@
_init = true;
_InitActivityObjectConfig();
+ _InitAiAttackAttrConfig();
_InitSoundConfig();
_InitWeaponConfig();
@@ -64,10 +74,28 @@
}
catch (Exception e)
{
- Debug.LogError(e.ToString());
+ GD.PrintErr(e.ToString());
throw new Exception("初始化表'ActivityObject'失败!");
}
}
+ private static void _InitAiAttackAttrConfig()
+ {
+ try
+ {
+ var text = _ReadConfigAsText("res://resource/config/AiAttackAttr.json");
+ AiAttackAttr_List = JsonSerializer.Deserialize>(text);
+ AiAttackAttr_Map = new Dictionary();
+ foreach (var item in AiAttackAttr_List)
+ {
+ AiAttackAttr_Map.Add(item.Id, item);
+ }
+ }
+ catch (Exception e)
+ {
+ GD.PrintErr(e.ToString());
+ throw new Exception("初始化表'AiAttackAttr'失败!");
+ }
+ }
private static void _InitSoundConfig()
{
try
@@ -82,7 +110,7 @@
}
catch (Exception e)
{
- Debug.LogError(e.ToString());
+ GD.PrintErr(e.ToString());
throw new Exception("初始化表'Sound'失败!");
}
}
@@ -100,7 +128,7 @@
}
catch (Exception e)
{
- Debug.LogError(e.ToString());
+ GD.PrintErr(e.ToString());
throw new Exception("初始化表'Weapon'失败!");
}
}
@@ -150,10 +178,15 @@
item.AiUseAttribute = Weapon_Map[item.__AiUseAttribute];
}
+ if (!string.IsNullOrEmpty(item.__AiAttackAttr))
+ {
+ item.AiAttackAttr = AiAttackAttr_Map[item.__AiAttackAttr];
+ }
+
}
catch (Exception e)
{
- Debug.LogError(e.ToString());
+ GD.PrintErr(e.ToString());
throw new Exception("初始化'Weapon'引用其他表数据失败, 当前行id: " + item.Id);
}
}
diff --git a/DungeonShooting_Godot/src/config/ExcelConfig_AiAttackAttr.cs b/DungeonShooting_Godot/src/config/ExcelConfig_AiAttackAttr.cs
new file mode 100644
index 0000000..0dceead
--- /dev/null
+++ b/DungeonShooting_Godot/src/config/ExcelConfig_AiAttackAttr.cs
@@ -0,0 +1,88 @@
+using System.Text.Json.Serialization;
+using System.Collections.Generic;
+
+namespace Config;
+
+public static partial class ExcelConfig
+{
+ public class AiAttackAttr
+ {
+ ///
+ /// Id
+ ///
+ [JsonInclude]
+ public string Id;
+
+ ///
+ /// 备注
+ ///
+ [JsonInclude]
+ public string Remark;
+
+ ///
+ /// 开火时是否站立不动
+ ///
+ [JsonInclude]
+ public bool FiringStand;
+
+ ///
+ /// 是否显示射击辅助线
+ ///
+ [JsonInclude]
+ public bool ShowSubline;
+
+ ///
+ /// Ai属性
+ /// 目标锁定时间, 也就是瞄准目标多久才会开火, (单位: 秒)
+ ///
+ [JsonInclude]
+ public float LockingTime;
+
+ ///
+ /// 从锁定目标到开火前有多少时间不能够改变枪口角度
+ /// 这个值必须小于LockingTime
+ /// 如果为0, 则不会锁定开火角度
+ /// (单位: 秒)
+ ///
+ [JsonInclude]
+ public float LockAngleTime;
+
+ ///
+ /// 开火时是否锁定枪口角度
+ ///
+ [JsonInclude]
+ public bool AttackLockAngle;
+
+ ///
+ /// Ai属性
+ /// Ai使用该武器发射的子弹速度缩放比
+ ///
+ [JsonInclude]
+ public float BulletSpeedScale;
+
+ ///
+ /// Ai属性
+ /// Ai使用该武器消耗弹药的概率, (0 - 1)
+ ///
+ [JsonInclude]
+ public float AmmoConsumptionProbability;
+
+ ///
+ /// 返回浅拷贝出的新对象
+ ///
+ public AiAttackAttr Clone()
+ {
+ var inst = new AiAttackAttr();
+ inst.Id = Id;
+ inst.Remark = Remark;
+ inst.FiringStand = FiringStand;
+ inst.ShowSubline = ShowSubline;
+ inst.LockingTime = LockingTime;
+ inst.LockAngleTime = LockAngleTime;
+ inst.AttackLockAngle = AttackLockAngle;
+ inst.BulletSpeedScale = BulletSpeedScale;
+ inst.AmmoConsumptionProbability = AmmoConsumptionProbability;
+ return inst;
+ }
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/config/ExcelConfig_Weapon.cs b/DungeonShooting_Godot/src/config/ExcelConfig_Weapon.cs
index 2496449..c9dd584 100644
--- a/DungeonShooting_Godot/src/config/ExcelConfig_Weapon.cs
+++ b/DungeonShooting_Godot/src/config/ExcelConfig_Weapon.cs
@@ -392,25 +392,10 @@
public Weapon AiUseAttribute;
///
- /// Ai属性
- /// 目标锁定时间, 也就是瞄准目标多久才会开火, (单位: 秒)
+ /// Ai使用该武器开火时的一些额外配置属性
+ /// 玩家使用的武器不需要填写该字段
///
- [JsonInclude]
- public float AiTargetLockingTime;
-
- ///
- /// Ai属性
- /// Ai使用该武器发射的子弹速度缩放比
- ///
- [JsonInclude]
- public float AiBulletSpeedScale;
-
- ///
- /// Ai属性
- /// Ai使用该武器消耗弹药的概率, (0 - 1)
- ///
- [JsonInclude]
- public float AiAmmoConsumptionProbability;
+ public AiAttackAttr AiAttackAttr;
///
/// 返回浅拷贝出的新对象
@@ -480,9 +465,7 @@
inst.BeLoadedSoundDelayTime = BeLoadedSoundDelayTime;
inst.OtherSoundMap = OtherSoundMap;
inst.AiUseAttribute = AiUseAttribute;
- inst.AiTargetLockingTime = AiTargetLockingTime;
- inst.AiBulletSpeedScale = AiBulletSpeedScale;
- inst.AiAmmoConsumptionProbability = AiAmmoConsumptionProbability;
+ inst.AiAttackAttr = AiAttackAttr;
return inst;
}
}
@@ -509,5 +492,8 @@
[JsonInclude]
public string __AiUseAttribute;
+ [JsonInclude]
+ public string __AiAttackAttr;
+
}
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
index 3a6a47a..03cead3 100644
--- a/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
+++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject.cs
@@ -753,7 +753,22 @@
{
var component = new T();
_components.Add(new KeyValuePair(typeof(T), component));
- component.ActivityInstance = this;
+ component.Master = this;
+ component.Ready();
+ component.OnEnable();
+ return component;
+ }
+
+ ///
+ /// 往当前物体上挂载一个组件
+ ///
+ public Component AddComponent(Type type)
+ {
+ var component = (Component)Activator.CreateInstance(type);
+ _components.Add(new KeyValuePair(type, component));
+ component.Master = this;
+ component.Ready();
+ component.OnEnable();
return component;
}
@@ -877,14 +892,8 @@
{
if (IsDestroyed) return;
var temp = arr[i].Value;
- if (temp != null && temp.ActivityInstance == this && temp.Enable)
+ if (temp != null && temp.Master == this && temp.Enable)
{
- if (!temp.IsReady)
- {
- temp.Ready();
- temp.IsReady = true;
- }
-
temp.Process(newDelta);
}
}
@@ -893,12 +902,6 @@
{
if (MoveController.Enable)
{
- if (!MoveController.IsReady)
- {
- MoveController.Ready();
- MoveController.IsReady = true;
- }
-
MoveController.Process(newDelta);
}
}
@@ -1089,14 +1092,8 @@
{
if (IsDestroyed) return;
var temp = arr[i].Value;
- if (temp != null && temp.ActivityInstance == this && temp.Enable)
+ if (temp != null && temp.Master == this && temp.Enable)
{
- if (!temp.IsReady)
- {
- temp.Ready();
- temp.IsReady = true;
- }
-
temp.PhysicsProcess(newDelta);
}
}
@@ -1105,12 +1102,6 @@
{
if (MoveController.Enable)
{
- if (!MoveController.IsReady)
- {
- MoveController.Ready();
- MoveController.IsReady = true;
- }
-
MoveController.PhysicsProcess(newDelta);
}
}
@@ -1140,7 +1131,7 @@
{
if (IsDestroyed) return;
var temp = arr[i].Value;
- if (temp != null && temp.ActivityInstance == this && temp.Enable)
+ if (temp != null && temp.Master == this && temp.Enable)
{
temp.DebugDraw();
}
diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject_Init.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject_Init.cs
index 8b3dd8a..3ff5957 100644
--- a/DungeonShooting_Godot/src/framework/activity/ActivityObject_Init.cs
+++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject_Init.cs
@@ -1,8 +1,6 @@
using Config;
-///
-/// 根据配置表注册物体, 该类是自动生成的, 请不要手动编辑!
-///
+// 根据配置表注册物体, 该类是自动生成的, 请不要手动编辑!
public partial class ActivityObject
{
///
diff --git a/DungeonShooting_Godot/src/framework/activity/Component.cs b/DungeonShooting_Godot/src/framework/activity/Component.cs
index ec1897d..a33d5e2 100644
--- a/DungeonShooting_Godot/src/framework/activity/Component.cs
+++ b/DungeonShooting_Godot/src/framework/activity/Component.cs
@@ -1,24 +1,36 @@
+using System;
using System.Collections;
using Godot;
///
/// 组件基类, 用于挂载到游戏物体上, 相比于原生 Node 更加轻量化, 实例化 Component 不会创建额外的 Node, 可以大量添加组件
///
+public abstract class Component : Component where T : ActivityObject
+{
+ ///
+ /// 当前组件所挂载的游戏对象
+ ///
+ public new T Master => (T)base.Master;
+}
+
+///
+/// 组件基类, 用于挂载到游戏物体上, 相比于原生 Node 更加轻量化, 实例化 Component 不会创建额外的 Node, 可以大量添加组件
+///
public abstract class Component : IProcess, IDestroy, ICoroutine
{
///
/// 当前组件所挂载的游戏对象
///
- public ActivityObject ActivityInstance { get; internal set; }
+ public ActivityObject Master { get; internal set; }
///
/// 当前组件所挂载的物体的坐标
///
public Vector2 Position
{
- get => ActivityInstance.Position;
- set => ActivityInstance.Position = value;
+ get => Master.Position;
+ set => Master.Position = value;
}
///
@@ -26,8 +38,8 @@
///
public Vector2 GlobalPosition
{
- get => ActivityInstance.GlobalPosition;
- set => ActivityInstance.GlobalPosition = value;
+ get => Master.GlobalPosition;
+ set => Master.GlobalPosition = value;
}
///
@@ -35,8 +47,8 @@
///
public Vector2 Scale
{
- get => ActivityInstance.Scale;
- set => ActivityInstance.Scale = value;
+ get => Master.Scale;
+ set => Master.Scale = value;
}
///
@@ -44,8 +56,8 @@
///
public Vector2 GlobalScale
{
- get => ActivityInstance.GlobalScale;
- set => ActivityInstance.GlobalScale = value;
+ get => Master.GlobalScale;
+ set => Master.GlobalScale = value;
}
///
@@ -53,8 +65,8 @@
///
public float Rotation
{
- get => ActivityInstance.Rotation;
- set => ActivityInstance.Rotation = value;
+ get => Master.Rotation;
+ set => Master.Rotation = value;
}
///
@@ -62,8 +74,8 @@
///
public float GlobalRotation
{
- get => ActivityInstance.GlobalRotation;
- set => ActivityInstance.GlobalRotation = value;
+ get => Master.GlobalRotation;
+ set => Master.GlobalRotation = value;
}
///
@@ -71,8 +83,8 @@
///
public float RotationDegrees
{
- get => ActivityInstance.RotationDegrees;
- set => ActivityInstance.RotationDegrees = value;
+ get => Master.RotationDegrees;
+ set => Master.RotationDegrees = value;
}
///
@@ -80,8 +92,8 @@
///
public float GlobalRotationDegrees
{
- get => ActivityInstance.GlobalRotationDegrees;
- set => ActivityInstance.GlobalRotationDegrees = value;
+ get => Master.GlobalRotationDegrees;
+ set => Master.GlobalRotationDegrees = value;
}
///
@@ -89,8 +101,8 @@
///
public int ZIndex
{
- get => ActivityInstance.ZIndex;
- set => ActivityInstance.ZIndex = value;
+ get => Master.ZIndex;
+ set => Master.ZIndex = value;
}
///
@@ -98,22 +110,26 @@
///
public bool Visible
{
- get => ActivityInstance.Visible;
- set => ActivityInstance.Visible = value;
+ get => Master.Visible;
+ set => Master.Visible = value;
}
///
/// 挂载物体的动画节点
///
- public AnimatedSprite2D AnimatedSprite2D => ActivityInstance.AnimatedSprite;
+ public AnimatedSprite2D AnimatedSprite => Master.AnimatedSprite;
///
/// 挂载物体的阴影节点
///
- public Sprite2D ShadowSprite => ActivityInstance.ShadowSprite;
+ public Sprite2D ShadowSprite => Master.ShadowSprite;
///
/// 挂载物体的碰撞器节点
///
- public CollisionShape2D Collision => ActivityInstance.Collision;
+ public CollisionShape2D Collision => Master.Collision;
+ ///
+ /// 移动控制器
+ ///
+ public MoveController MoveController => Master.MoveController;
///
/// 是否启用当前组件, 如果禁用, 则不会调用 Process 和 PhysicsProcess
@@ -125,14 +141,14 @@
{
if (!_enable && value)
{
+ _enable = true;
OnEnable();
}
else if (_enable && !value)
{
+ _enable = false;
OnDisable();
}
-
- _enable = value;
}
}
@@ -144,12 +160,7 @@
public bool IsDestroyed { get; private set; }
///
- /// 是否调用过 Ready 函数
- ///
- public bool IsReady { get; set; }
-
- ///
- /// 第一次调用 Process 或 PhysicsProcess 之前调用
+ /// 初始化时调用
///
public virtual void Ready()
{
@@ -210,27 +221,122 @@
}
IsDestroyed = true;
- ActivityInstance.RemoveComponent(this);
+ Master.RemoveComponent(this);
OnDestroy();
}
+ public T AddComponent() where T : Component, new()
+ {
+ return Master.AddComponent();
+ }
+
+ public Component AddComponent(Type type)
+ {
+ return Master.AddComponent(type);
+ }
+
+ public T GetComponent() where T : Component, new()
+ {
+ return Master.GetComponent();
+ }
+
+ public Component GetComponent(Type type)
+ {
+ return Master.GetComponent(type);
+ }
+
+ public void RemoveComponent(Component component)
+ {
+ Master.RemoveComponent(component);
+ }
+
+ public void AddChild(Node node)
+ {
+ Master.AddChild(node);
+ }
+
+ public void RemoveChild(Node node)
+ {
+ Master.RemoveChild(node);
+ }
+
+ public int GetChildCount()
+ {
+ return Master.GetChildCount();
+ }
+
+ public Node GetNode(NodePath path)
+ {
+ return Master.GetNode(path);
+ }
+
+ public T GetNode(NodePath path) where T : class
+ {
+ return Master.GetNode(path);
+ }
+
+ public Node GetNodeOrNull(NodePath path)
+ {
+ return Master.GetNodeOrNull(path);
+ }
+
+ public T GetNodeOrNull(NodePath path) where T : class
+ {
+ return Master.GetNodeOrNull(path);
+ }
+
+ public Node GetParent()
+ {
+ return Master.GetParent();
+ }
+
+ public T GetParent() where T : class
+ {
+ return Master.GetParent();
+ }
+
+ public void Reparent(Node node)
+ {
+ Master.Reparent(node);
+ }
+
+ public float GetProcessDeltaTime()
+ {
+ return (float)Master.GetProcessDeltaTime();
+ }
+
+ public float GetPhysicsProcessDeltaTime()
+ {
+ return (float)Master.GetPhysicsProcessDeltaTime();
+ }
+
+ public Vector2 GetGlobalMousePosition()
+ {
+ return Master.GetGlobalMousePosition();
+ }
+
+ public Vector2 GetLocalMousePosition()
+ {
+ return Master.GetLocalMousePosition();
+ }
+
public long StartCoroutine(IEnumerator able)
{
- return ActivityInstance.StartCoroutine(able);
+ return Master.StartCoroutine(able);
}
public void StopCoroutine(long coroutineId)
{
- ActivityInstance.StopCoroutine(coroutineId);
+ Master.StopCoroutine(coroutineId);
}
public bool IsCoroutineOver(long coroutineId)
{
- return ActivityInstance.IsCoroutineOver(coroutineId);
+ return Master.IsCoroutineOver(coroutineId);
}
public void StopAllCoroutine()
{
- ActivityInstance.StopAllCoroutine();
+ Master.StopAllCoroutine();
}
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs b/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs
index 36167b1..9056451 100644
--- a/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs
+++ b/DungeonShooting_Godot/src/framework/activity/components/MoveController.cs
@@ -18,7 +18,7 @@
/// 这个速度就是物体当前物理帧移动的真实速率, 该速度由物理帧循环计算, 并不会马上更新
/// 该速度就是 BasisVelocity + 外力总和
///
- public Vector2 Velocity => ActivityInstance.Velocity;
+ public Vector2 Velocity => Master.Velocity;
///
/// 物体的基础移动速率
@@ -267,7 +267,7 @@
{
if (_basisVelocity == Vector2.Zero && _forceList.Count == 0)
{
- ActivityInstance.Velocity = Vector2.Zero;
+ Master.Velocity = Vector2.Zero;
return;
}
@@ -304,13 +304,13 @@
//处理旋转
if (rotationSpeed != 0)
{
- ActivityInstance.Rotation += rotationSpeed * delta;
+ Master.Rotation += rotationSpeed * delta;
}
//衰减旋转速率
for (var i = 0; i < _forceList.Count; i++)
{
var force = _forceList[i];
- if (force.RotationResistance != 0 && (force.EnableResistanceInTheAir || !ActivityInstance.IsThrowing))
+ if (force.RotationResistance != 0 && (force.EnableResistanceInTheAir || !Master.IsThrowing))
{
force.RotationSpeed = Mathf.MoveToward(force.RotationSpeed, 0, force.RotationResistance * delta);
}
@@ -322,10 +322,10 @@
if (finallyVelocity != Vector2.Zero)
{
//计算移动
- ActivityInstance.Velocity = finallyVelocity;
- ActivityInstance.MoveAndSlide();
+ Master.Velocity = finallyVelocity;
+ Master.MoveAndSlide();
//新速度
- var newVelocity = ActivityInstance.Velocity;
+ var newVelocity = Master.Velocity;
if (newVelocity.X == 0f && _basisVelocity.X * finallyVelocity.X > 0)
{
@@ -338,13 +338,13 @@
}
//是否撞到物体
- var collision = ActivityInstance.GetLastSlideCollision();
+ var collision = Master.GetLastSlideCollision();
if (collision != null) //执行反弹操作
{
var no = collision.GetNormal().Rotated(Mathf.Pi * 0.5f);
newVelocity = (finallyVelocity - _basisVelocity).Reflect(no);
var length = _forceList.Count;
- var v = newVelocity / (length / ActivityInstance.BounceStrength);
+ var v = newVelocity / (length / Master.BounceStrength);
for (var i = 0; i < _forceList.Count; i++)
{
_forceList[i].Velocity = v;
@@ -365,7 +365,7 @@
);
//力速度衰减
- if (force.VelocityResistance != 0 && (force.EnableResistanceInTheAir || !ActivityInstance.IsThrowing))
+ if (force.VelocityResistance != 0 && (force.EnableResistanceInTheAir || !Master.IsThrowing))
{
force.Velocity = force.Velocity.MoveToward(Vector2.Zero, force.VelocityResistance * delta);
}
@@ -375,7 +375,7 @@
}
else
{
- ActivityInstance.Velocity = Vector2.Zero;
+ Master.Velocity = Vector2.Zero;
}
}
@@ -389,33 +389,33 @@
{
//绘制力大小和方向
- if (ActivityInstance is Bullet) //不绘制子弹的力
+ if (Master is Bullet) //不绘制子弹的力
{
return;
}
var globalRotation = GlobalRotation;
- var flag = ActivityInstance.Scale.Y < 0;
+ var flag = Master.Scale.Y < 0;
if (flag)
{
- ActivityInstance.DrawLine(Vector2.Zero, (BasisVelocity * new Vector2(1, -1)).Rotated(-globalRotation),
+ Master.DrawLine(Vector2.Zero, (BasisVelocity * new Vector2(1, -1)).Rotated(-globalRotation),
Colors.Yellow);
}
else
{
- ActivityInstance.DrawLine(Vector2.Zero, BasisVelocity.Rotated(-globalRotation), Colors.Yellow);
+ Master.DrawLine(Vector2.Zero, BasisVelocity.Rotated(-globalRotation), Colors.Yellow);
}
foreach (var force in _forceList)
{
if (flag)
{
- ActivityInstance.DrawLine(Vector2.Zero, (force.Velocity * new Vector2(1, -1)).Rotated(globalRotation),
+ Master.DrawLine(Vector2.Zero, (force.Velocity * new Vector2(1, -1)).Rotated(globalRotation),
Colors.YellowGreen);
}
else
{
- ActivityInstance.DrawLine(Vector2.Zero, force.Velocity.Rotated(-globalRotation), Colors.YellowGreen);
+ Master.DrawLine(Vector2.Zero, force.Velocity.Rotated(-globalRotation), Colors.YellowGreen);
}
}
}
diff --git a/DungeonShooting_Godot/src/framework/activity/components/StateController.cs b/DungeonShooting_Godot/src/framework/activity/components/StateController.cs
index d3c1e20..bb1bbd8 100644
--- a/DungeonShooting_Godot/src/framework/activity/components/StateController.cs
+++ b/DungeonShooting_Godot/src/framework/activity/components/StateController.cs
@@ -60,7 +60,7 @@
return;
}
- stateBase.Master = ActivityInstance as T;
+ stateBase.Master = Master as T;
stateBase.StateController = this;
_states.Add(stateBase.State, stateBase);
}
diff --git a/DungeonShooting_Godot/src/framework/generator/ExcelGenerator.cs b/DungeonShooting_Godot/src/framework/generator/ExcelGenerator.cs
index cd72216..ee59049 100644
--- a/DungeonShooting_Godot/src/framework/generator/ExcelGenerator.cs
+++ b/DungeonShooting_Godot/src/framework/generator/ExcelGenerator.cs
@@ -56,9 +56,7 @@
}
var str = $"using Config;\n\n";
- str += $"/// \n";
- str += $"/// 根据配置表注册物体, 该类是自动生成的, 请不要手动编辑!\n";
- str += $"/// \n";
+ str += $"// 根据配置表注册物体, 该类是自动生成的, 请不要手动编辑!\n";
str += $"public partial class ActivityObject\n";
str += $"{{\n";
diff --git a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs
index d390aef..409eeab 100644
--- a/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs
+++ b/DungeonShooting_Godot/src/framework/map/preinstall/RoomPreinstall.cs
@@ -251,7 +251,7 @@
if (_currWaveIndex < WaveList.Count)
{
Debug.Log($"执行第{_currWaveIndex}波");
- _coroutineId = GameApplication.Instance.World.StartCoroutine(RunMark(WaveList[_currWaveIndex]));
+ _coroutineId = World.Current.StartCoroutine(RunMark(WaveList[_currWaveIndex]));
_currWaveIndex++;
}
}
@@ -268,7 +268,7 @@
}
Debug.Log($"执行第{_currWaveIndex}波");
- _coroutineId = GameApplication.Instance.World.StartCoroutine(RunMark(WaveList[_currWaveIndex]));
+ _coroutineId = World.Current.StartCoroutine(RunMark(WaveList[_currWaveIndex]));
_currWaveIndex++;
}
@@ -347,7 +347,7 @@
///
public bool IsCurrWaveOver()
{
- return _coroutineId < 0 || GameApplication.Instance.IsCoroutineOver(_coroutineId);
+ return _coroutineId < 0 || World.Current.IsCoroutineOver(_coroutineId);
}
//创建物体
@@ -396,7 +396,7 @@
IsDestroyed = true;
if (_coroutineId >= 0)
{
- GameApplication.Instance.StopCoroutine(_coroutineId);
+ World.Current.StopCoroutine(_coroutineId);
}
WaveList.Clear();
diff --git a/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs b/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs
index e14b273..0cf2a33 100644
--- a/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs
+++ b/DungeonShooting_Godot/src/game/activity/bullet/Bullet.cs
@@ -43,9 +43,9 @@
public int MaxHarm { get; set; } = 4;
///
- /// 发射该子弹的角色
+ /// 发射该子弹的角色是否是Ai
///
- public Role Trigger { get; private set; }
+ public bool TriggerRoleIsAi { get; set; }
// 最大飞行距离
private float MaxDistance;
@@ -59,28 +59,28 @@
///
/// 初始化子弹属性
///
- /// 触发开火的角色
+ /// 触发开火的角色
/// 射出该子弹的武器
/// 速度
/// 最大飞行距离
/// 位置
/// 角度
/// 攻击目标层级
- public void Init(Role trigger, Weapon weapon, float speed, float maxDistance, Vector2 position, float rotation, uint targetLayer)
+ public void Init(bool triggerIsAi, Weapon weapon, float speed, float maxDistance, Vector2 position, float rotation, uint targetLayer)
{
- Trigger = trigger;
+ TriggerRoleIsAi = triggerIsAi;
Weapon = weapon;
Role = weapon.Master;
AttackLayer = targetLayer;
CollisionArea.AreaEntered += OnArea2dEntered;
- if (trigger != null && !trigger.IsAi) //只有玩家使用该武器才能获得正常速度的子弹
+ if (!triggerIsAi) //只有玩家使用该武器才能获得正常速度的子弹
{
FlySpeed = speed;
}
else
{
- FlySpeed = speed * weapon.AiUseAttribute.AiBulletSpeedScale;
+ FlySpeed = speed * weapon.AiUseAttribute.AiAttackAttr.BulletSpeedScale;
}
MaxDistance = maxDistance;
Position = position;
@@ -163,7 +163,7 @@
//击退
if (role is not Player) //目标不是玩家才会触发击退
{
- var attr = Trigger != null && !Trigger.IsAi ? Weapon.PlayerUseAttribute : Weapon.AiUseAttribute;
+ var attr = TriggerRoleIsAi ? Weapon.AiUseAttribute : Weapon.PlayerUseAttribute;
var repel = Utils.Random.RandomConfigRange(attr.RepelRnage);
role.MoveController.AddForce(Vector2.FromAngle(BasisVelocity.Angle()) * repel, repel * 2);
}
diff --git a/DungeonShooting_Godot/src/game/activity/package/Package.cs b/DungeonShooting_Godot/src/game/activity/package/Package.cs
index ca1ad16..378f7ef 100644
--- a/DungeonShooting_Godot/src/game/activity/package/Package.cs
+++ b/DungeonShooting_Godot/src/game/activity/package/Package.cs
@@ -4,19 +4,12 @@
///
/// 物体背包类
///
-public class Package : IDestroy where T : ActivityObject, IPackageItem
+public class Package : Component where T : ActivityObject, IPackageItem
{
///
/// 当前使用对象改变时回调
///
public event Action ChangeActiveItemEvent;
-
- public bool IsDestroyed { get; private set; }
-
- ///
- /// 归属者
- ///
- public Role Master { get; private set; }
///
/// 当前使用的物体对象
@@ -54,12 +47,6 @@
///
public T[] ItemSlot { get; private set; }
- public Package(Role master, int capacity)
- {
- Master = master;
- SetCapacity(capacity);
- }
-
///
/// 修改物体背包容量
///
@@ -466,14 +453,8 @@
return null;
}
- public void Destroy()
+ public override void OnDestroy()
{
- if (IsDestroyed)
- {
- return;
- }
-
- IsDestroyed = true;
for (var i = 0; i < ItemSlot.Length; i++)
{
var activityObject = ItemSlot[i];
diff --git a/DungeonShooting_Godot/src/game/activity/role/Role.cs b/DungeonShooting_Godot/src/game/activity/role/Role.cs
index d3ed357..7269052 100644
--- a/DungeonShooting_Godot/src/game/activity/role/Role.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/Role.cs
@@ -43,9 +43,14 @@
/// 攻击目标的碰撞器所属层级, 数据源自于:
///
public uint AttackLayer { get; set; } = PhysicsLayer.Wall;
+
+ ///
+ /// 该角色敌对目标的碰撞器所属层级, 数据源自于:
+ ///
+ public uint EnemyLayer { get; set; } = PhysicsLayer.Enemy;
///
- /// 携带的被动道具包裹
+ /// 携带的被动道具列表
///
public List BuffPropPack { get; } = new List();
@@ -254,6 +259,11 @@
/// 是否处于近战攻击中
///
public bool IsMeleeAttack { get; private set; }
+
+ ///
+ /// 瞄准辅助线, 需要手动调用 InitSubLine() 初始化
+ ///
+ public SubLine SubLine { get; private set; }
//翻滚冷却计时器
private float _rollCoolingTimer = 0;
@@ -402,8 +412,11 @@
public override void OnInit()
{
- ActivePropsPack = new Package(this, 1);
- WeaponPack = new Package(this, 4);
+ ActivePropsPack = AddComponent>();
+ ActivePropsPack.SetCapacity(1);
+ WeaponPack = AddComponent>();
+ WeaponPack.SetCapacity(4);
+
_startScale = Scale;
MountPoint.Master = this;
@@ -437,7 +450,7 @@
}
//看向目标
- if (LookTarget != null)
+ if (LookTarget != null && MountLookTarget)
{
Vector2 pos = LookTarget.GlobalPosition;
//脸的朝向
@@ -450,12 +463,8 @@
{
Face = FaceDirection.Left;
}
-
- if (MountLookTarget)
- {
- //枪口跟随目标
- MountPoint.SetLookAt(pos);
- }
+ //枪口跟随目标
+ MountPoint.SetLookAt(pos);
}
//检查可互动的物体
@@ -564,6 +573,19 @@
}
///
+ /// 初始化瞄准辅助线
+ ///
+ public void InitSubLine()
+ {
+ if (SubLine != null)
+ {
+ return;
+ }
+
+ SubLine = AddComponent();
+ }
+
+ ///
/// 当武器放到后背时调用, 用于设置武器位置和角度
///
/// 武器实例
@@ -630,19 +652,18 @@
public void LookTargetPosition(Vector2 pos)
{
LookTarget = null;
- //脸的朝向
- var gPos = GlobalPosition;
- if (pos.X > gPos.X && Face == FaceDirection.Left)
- {
- Face = FaceDirection.Right;
- }
- else if (pos.X < gPos.X && Face == FaceDirection.Right)
- {
- Face = FaceDirection.Left;
- }
-
if (MountLookTarget)
{
+ //脸的朝向
+ var gPos = GlobalPosition;
+ if (pos.X > gPos.X && Face == FaceDirection.Left)
+ {
+ Face = FaceDirection.Right;
+ }
+ else if (pos.X < gPos.X && Face == FaceDirection.Right)
+ {
+ Face = FaceDirection.Left;
+ }
//枪口跟随目标
MountPoint.SetLookAt(pos);
}
@@ -936,7 +957,7 @@
_meleeAttackTimer = RoleState.MeleeAttackTime;
MountLookTarget = false;
- WeaponPack.ActiveItem.TriggerMeleeAttack(this);
+ //WeaponPack.ActiveItem.TriggerMeleeAttack(this);
//播放近战动画
PlayAnimation_MeleeAttack(() =>
{
@@ -1181,4 +1202,35 @@
{
_rollCoolingTimer = RoleState.RollTime;
}
+
+ ///
+ /// 返回当前角色是否是玩家
+ ///
+ public bool IsPlayer()
+ {
+ return this == Player.Current;
+ }
+
+ ///
+ /// 是否是玩家的敌人
+ ///
+ public bool IsEnemyWithPlayer()
+ {
+ return CollisionWithMask(Player.Current.EnemyLayer);
+ }
+
+ ///
+ /// 将 Role 子节点的旋转角度转换为正常的旋转角度
+ /// 因为 Role 受到 Face 影响, 会出现转向动作, 所以需要该函数来转换旋转角度
+ ///
+ /// 角度, 弧度制
+ public float ConvertRotation(float rotation)
+ {
+ if (Face == FaceDirection.Right)
+ {
+ return rotation;
+ }
+
+ return Mathf.Pi - rotation;
+ }
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/role/SubLine.cs b/DungeonShooting_Godot/src/game/activity/role/SubLine.cs
new file mode 100644
index 0000000..33bd409
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/activity/role/SubLine.cs
@@ -0,0 +1,176 @@
+
+using System.Collections;
+using Godot;
+
+///
+/// 瞄准辅助线
+///
+public class SubLine : Component
+{
+ ///
+ /// 是否正在播放警告闪烁动画
+ ///
+ public bool IsPlayWarnAnimation => _cid > 0;
+
+ private Line2D _line2D;
+ private RayCast2D _rayCast2D;
+
+ private bool _enableSubLine;
+ private float _range;
+ private long _cid;
+ private Color _color = Colors.Orange;
+
+ public override void Ready()
+ {
+ //初始化瞄准辅助线
+ _line2D = new Line2D();
+ _line2D.Width = 1;
+ AddChild(_line2D);
+
+ _rayCast2D = new RayCast2D();
+ _rayCast2D.CollisionMask = PhysicsLayer.Wall;
+ AddChild(_rayCast2D);
+
+ Master.WeaponPack.ChangeActiveItemEvent += OnChangeWeapon;
+ }
+
+ public override void OnEnable()
+ {
+ OnChangeWeapon(Master.WeaponPack.ActiveItem);
+ }
+
+ public override void OnDisable()
+ {
+ _enableSubLine = false;
+ _line2D.Visible = false;
+ _rayCast2D.Enabled = false;
+ if (_cid > 0)
+ {
+ StopCoroutine(_cid);
+ }
+ }
+
+ ///
+ /// 设置线条颜色
+ ///
+ public void SetColor(Color color)
+ {
+ _color = color;
+ _line2D.DefaultColor = color;
+ }
+
+ ///
+ /// 播放闪烁警告动画
+ ///
+ /// 持续时间
+ public void PlayWarnAnimation(float time)
+ {
+ if (_cid > 0)
+ {
+ StopCoroutine(_cid);
+ }
+
+ _cid = StartCoroutine(RunWarnAnimation(time));
+ }
+
+ private IEnumerator RunWarnAnimation(float time)
+ {
+ var now = 0f;
+ var t = 0f;
+ var b = false;
+ while (now < time)
+ {
+ var delta = GetProcessDeltaTime();
+ now += delta;
+ t += delta;
+ if (t >= 0.08f)
+ {
+ t %= 0.08f;
+ _line2D.DefaultColor = b ? Colors.Orange : Colors.Red;
+ b = !b;
+ }
+ yield return null;
+ }
+
+ _line2D.DefaultColor = _color;
+ _cid = 0;
+ }
+
+ //切换武器
+ private void OnChangeWeapon(Weapon weapon)
+ {
+ if (!Enable)
+ {
+ return;
+ }
+ if (weapon == null)
+ {
+ _enableSubLine = false;
+ }
+ else
+ {
+ _enableSubLine = true;
+ if (_cid > 0)
+ {
+ StopCoroutine(_cid);
+ _cid = 0;
+ }
+ _range = Utils.GetConfigRangeEnd(weapon.Attribute.BulletDistanceRange);
+ _line2D.DefaultColor = _color;
+ }
+ }
+
+ public override void PhysicsProcess(float delta)
+ {
+ if (_enableSubLine)
+ {
+ _line2D.Visible = true;
+ _rayCast2D.Enabled = true;
+ UpdateSubLine();
+ }
+ else
+ {
+ _line2D.Visible = false;
+ _rayCast2D.Enabled = false;
+ }
+ }
+
+ public override void OnDestroy()
+ {
+ _line2D.QueueFree();
+ _rayCast2D.QueueFree();
+ Master.WeaponPack.ChangeActiveItemEvent -= OnChangeWeapon;
+ }
+
+ private void UpdateSubLine()
+ {
+ var master = Master;
+ var weapon = master.WeaponPack.ActiveItem;
+ float length;
+ var firePointGlobalPosition = weapon.FirePoint.GlobalPosition;
+ if (_rayCast2D.IsColliding())
+ {
+ length = firePointGlobalPosition.DistanceTo(_rayCast2D.GetCollisionPoint());
+ }
+ else
+ {
+ length = _range;
+ }
+
+ var r = master.ConvertRotation(master.MountPoint.RealRotation);
+ //更新 Ray 的位置角度
+ _rayCast2D.GlobalPosition = firePointGlobalPosition;
+ _rayCast2D.TargetPosition = new Vector2(_range, 0);
+ _rayCast2D.Rotation = r;
+
+ //计算 line2D 的点
+ var position = _line2D.ToLocal(firePointGlobalPosition);
+ Vector2 position2 = Vector2.FromAngle(r) * length;
+
+ _line2D.Points = new Vector2[]
+ {
+ position,
+ position + position2
+ };
+ }
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackState.cs
new file mode 100644
index 0000000..62bc132
--- /dev/null
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/AiAttackState.cs
@@ -0,0 +1,43 @@
+
+///
+/// 调用 Enemy.EnemyAttack() 函数返回的结果
+///
+public enum AiAttackState
+{
+ ///
+ /// 未触发 EnemyAttack()
+ ///
+ None,
+ ///
+ /// 触发切换武器
+ ///
+ ExchangeWeapon,
+ ///
+ /// 没有弹药了
+ ///
+ NoAmmo,
+ ///
+ /// 换弹中
+ ///
+ Reloading,
+ ///
+ /// 触发换弹
+ ///
+ TriggerReload,
+ ///
+ /// 没有武器
+ ///
+ NoWeapon,
+ ///
+ /// 正在锁定目标中
+ ///
+ LockingTime,
+ ///
+ /// 攻击间隙时间
+ ///
+ AttackInterval,
+ ///
+ /// 成功触发攻击
+ ///
+ Attack,
+}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
index c333c8c..4736952 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/Enemy.cs
@@ -11,6 +11,7 @@
#endregion
+using System;
using Godot;
///
@@ -20,6 +21,11 @@
public partial class Enemy : Role
{
///
+ /// 目标是否在视野内
+ ///
+ public bool TargetInView { get; set; } = true;
+
+ ///
/// 敌人身上的状态机控制器
///
public StateController StateController { get; private set; }
@@ -54,10 +60,13 @@
///
public Marker2D NavigationPoint { get; private set; }
- //开火间隙时间
- private float _enemyAttackTimer = 0;
- //目标在视野内的时间
- private float _targetInViewTime = 0;
+ ///
+ /// Ai攻击状态, 调用 EnemyAttack() 函数后会刷新
+ ///
+ public AiAttackState AttackState { get; private set; }
+
+ //锁定目标时间
+ private float _lockTargetTime = 0;
public override void OnInit()
{
@@ -66,6 +75,7 @@
StateController = AddComponent>();
AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Prop | PhysicsLayer.Player;
+ EnemyLayer = PhysicsLayer.Player;
Camp = CampEnum.Camp2;
RoleState.MoveSpeed = 20;
@@ -140,19 +150,85 @@
protected override void Process(float delta)
{
base.Process(delta);
- _enemyAttackTimer -= delta;
//目标在视野内的时间
var currState = StateController.CurrState;
if (currState == AiStateEnum.AiSurround || currState == AiStateEnum.AiFollowUp)
{
- _targetInViewTime += delta;
+ var weapon = WeaponPack.ActiveItem;
+ if (weapon != null)
+ {
+ if (weapon.GetBeLoadedStateState() >= 2 && !weapon.IsAttackIntervalTime()) //必须在可以开火时记录时间
+ {
+ _lockTargetTime += delta;
+ }
+ else
+ {
+ _lockTargetTime = 0;
+ }
+
+ if (AttackState == AiAttackState.LockingTime) //锁定玩家状态
+ {
+ var aiLockRemainderTime = weapon.GetAiLockRemainderTime();
+ MountLookTarget = aiLockRemainderTime >= weapon.Attribute.AiAttackAttr.LockAngleTime;
+ //更新瞄准辅助线
+ if (weapon.Attribute.AiAttackAttr.ShowSubline)
+ {
+ if (SubLine == null)
+ {
+ InitSubLine();
+ }
+ else
+ {
+ SubLine.Enable = true;
+ }
+
+ //播放警告删掉动画
+ if (!SubLine.IsPlayWarnAnimation && aiLockRemainderTime <= 0.5f)
+ {
+ SubLine.PlayWarnAnimation(0.5f);
+ }
+ }
+ }
+ else
+ {
+ //关闭辅助线
+ if (SubLine != null)
+ {
+ SubLine.Enable = false;
+ }
+
+ if (AttackState == AiAttackState.Attack || AttackState == AiAttackState.AttackInterval)
+ {
+ if (weapon.Attribute.AiAttackAttr.AttackLockAngle) //开火时锁定枪口角度
+ {
+ //连发状态锁定角度
+ MountLookTarget = !(weapon.GetContinuousCount() > 0 || weapon.GetAttackTimer() > 0);
+ }
+ else
+ {
+ MountLookTarget = true;
+ }
+ }
+ else
+ {
+ MountLookTarget = true;
+ }
+ }
+ }
+ else
+ {
+ MountLookTarget = true;
+ _lockTargetTime = 0;
+ }
}
else
{
- _targetInViewTime = 0;
+ MountLookTarget = true;
+ _lockTargetTime = 0;
}
+ //拾起武器操作
EnemyPickUpWeapon();
}
@@ -277,58 +353,20 @@
return false;
}
-
+
///
/// Ai触发的攻击
///
- public void EnemyAttack(float delta)
+ public void EnemyAttack()
{
var weapon = WeaponPack.ActiveItem;
if (weapon != null)
{
- if (weapon.IsTotalAmmoEmpty()) //当前武器弹药打空
- {
- //切换到有子弹的武器
- var index = WeaponPack.FindIndex((we, i) => !we.IsTotalAmmoEmpty());
- if (index != -1)
- {
- WeaponPack.ExchangeByIndex(index);
- }
- else //所有子弹打光
- {
-
- }
- }
- else if (weapon.Reloading) //换弹中
- {
-
- }
- else if (weapon.IsAmmoEmpty()) //弹夹已经打空
- {
- Reload();
- }
- else if (_targetInViewTime >= weapon.Attribute.AiTargetLockingTime) //正常射击
- {
- if (weapon.GetDelayedAttackTime() > 0)
- {
- Attack();
- }
- else
- {
- if (weapon.Attribute.ContinuousShoot) //连发
- {
- Attack();
- }
- else //单发
- {
- if (_enemyAttackTimer <= 0)
- {
- _enemyAttackTimer = 60f / weapon.Attribute.StartFiringSpeed;
- Attack();
- }
- }
- }
- }
+ AttackState = weapon.AiTriggerAttackState();
+ }
+ else //没有武器
+ {
+ AttackState = AiAttackState.NoWeapon;
}
}
@@ -456,4 +494,20 @@
}
}
+ ///
+ /// 获取锁定目标的时间
+ ///
+ public float GetLockTime()
+ {
+ return _lockTargetTime;
+ }
+
+ ///
+ /// 强制设置锁定目标时间
+ ///
+ public void SetLockTargetTime(float time)
+ {
+ _lockTargetTime = time;
+ }
+
}
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiFollowUpState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiFollowUpState.cs
index e0953eb..50003ec 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiFollowUpState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiFollowUpState.cs
@@ -6,12 +6,6 @@
///
public class AiFollowUpState : StateBase
{
-
- ///
- /// 目标是否在视野内
- ///
- public bool IsInView;
-
//导航目标点刷新计时器
private float _navigationUpdateTimer = 0;
private float _navigationInterval = 0.3f;
@@ -23,7 +17,7 @@
public override void Enter(AiStateEnum prev, params object[] args)
{
_navigationUpdateTimer = 0;
- IsInView = true;
+ Master.TargetInView = true;
}
public override void Process(float delta)
@@ -75,11 +69,20 @@
if (!Master.NavigationAgent2D.IsNavigationFinished())
{
- //计算移动
- var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
- Master.AnimatedSprite.Play(AnimatorNames.Run);
- Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() *
- Master.RoleState.MoveSpeed;
+ if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand ||
+ (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack))
+ {
+ //计算移动
+ var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
+ Master.AnimatedSprite.Play(AnimatorNames.Run);
+ Master.BasisVelocity = (nextPos - masterPosition - Master.NavigationPoint.Position).Normalized() *
+ Master.RoleState.MoveSpeed;
+ }
+ else
+ {
+ Master.AnimatedSprite.Play(AnimatorNames.Idle);
+ Master.BasisVelocity = Vector2.Zero;
+ }
}
else
{
@@ -89,21 +92,22 @@
//检测玩家是否在视野内
if (Master.IsInTailAfterViewRange(playerPos))
{
- IsInView = !Master.TestViewRayCast(playerPos);
+ Master.TargetInView = !Master.TestViewRayCast(playerPos);
//关闭射线检测
Master.TestViewRayCastOver();
}
else
{
- IsInView = false;
+ Master.TargetInView = false;
}
- if (IsInView)
+ //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑
+ if (Master.TargetInView || Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack)
{
if (inAttackRange) //在攻击范围内
{
//发起攻击
- Master.EnemyAttack(delta);
+ Master.EnemyAttack();
//距离够近, 可以切换到环绕模式
if (Master.GlobalPosition.DistanceSquaredTo(playerPos) <= Mathf.Pow(Utils.GetConfigRangeStart(weapon.Attribute.BulletDistanceRange), 2) * 0.7f)
@@ -112,7 +116,7 @@
}
}
}
- else
+ else //不在视野中
{
ChangeState(AiStateEnum.AiTailAfter);
}
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiSurroundState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiSurroundState.cs
index 1e7f4c4..321419f 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiSurroundState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiSurroundState.cs
@@ -6,11 +6,6 @@
///
public class AiSurroundState : StateBase
{
- ///
- /// 目标是否在视野内
- ///
- public bool IsInView = true;
-
//是否移动结束
private bool _isMoveOver;
@@ -32,7 +27,7 @@
public override void Enter(AiStateEnum prev, params object[] args)
{
- IsInView = true;
+ Master.TargetInView = true;
_isMoveOver = true;
_pauseTimer = 0;
_moveFlag = false;
@@ -61,16 +56,20 @@
//检测玩家是否在视野内
if (Master.IsInTailAfterViewRange(playerPos))
{
- IsInView = !Master.TestViewRayCast(playerPos);
+ Master.TargetInView = !Master.TestViewRayCast(playerPos);
//关闭射线检测
Master.TestViewRayCastOver();
}
else
{
- IsInView = false;
+ Master.TargetInView = false;
}
- if (IsInView)
+ //在视野中, 或者锁敌状态下, 或者攻击状态下, 继续保持原本逻辑
+ if (Master.TargetInView ||
+ (weapon != null && weapon.Attribute.AiAttackAttr.FiringStand &&
+ (Master.AttackState == AiAttackState.LockingTime || Master.AttackState == AiAttackState.Attack)
+ ))
{
if (_pauseTimer >= 0)
{
@@ -101,11 +100,11 @@
{
_moveFlag = true;
//计算移动
- var pos = Master.GlobalPosition;
var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
Master.AnimatedSprite.Play(AnimatorNames.Run);
- Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
- Master.RoleState.MoveSpeed;
+ Master.BasisVelocity =
+ (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
+ Master.RoleState.MoveSpeed;
}
else
{
@@ -120,13 +119,23 @@
}
else
{
- //计算移动
- var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
- Master.AnimatedSprite.Play(AnimatorNames.Run);
- Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() *
- Master.RoleState.MoveSpeed;
+ //判断开火状态, 进行移动
+ if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand ||
+ (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack))
+ { //正常移动
+ //计算移动
+ var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
+ Master.AnimatedSprite.Play(AnimatorNames.Run);
+ Master.BasisVelocity = (nextPos - pos - Master.NavigationPoint.Position).Normalized() *
+ Master.RoleState.MoveSpeed;
+ }
+ else //站立不动
+ {
+ Master.AnimatedSprite.Play(AnimatorNames.Idle);
+ Master.BasisVelocity = Vector2.Zero;
+ }
}
-
+
if (_prevPos.DistanceSquaredTo(pos) <= 0.01f)
{
_lockTimer += delta;
@@ -147,7 +156,7 @@
else
{
//发起攻击
- Master.EnemyAttack(delta);
+ Master.EnemyAttack();
}
}
}
diff --git a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiTailAfterState.cs b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiTailAfterState.cs
index 455e4ae..87b21aa 100644
--- a/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiTailAfterState.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/enemy/state/AiTailAfterState.cs
@@ -63,11 +63,21 @@
if (!Master.NavigationAgent2D.IsNavigationFinished())
{
- //计算移动
- var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
- Master.AnimatedSprite.Play(AnimatorNames.Run);
- Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
- Master.RoleState.MoveSpeed;
+ var weapon = Master.WeaponPack.ActiveItem;
+ if (weapon == null || !weapon.Attribute.AiAttackAttr.FiringStand ||
+ (Master.AttackState != AiAttackState.LockingTime && Master.AttackState != AiAttackState.Attack))
+ {
+ //计算移动
+ var nextPos = Master.NavigationAgent2D.GetNextPathPosition();
+ Master.AnimatedSprite.Play(AnimatorNames.Run);
+ Master.BasisVelocity = (nextPos - Master.GlobalPosition - Master.NavigationPoint.Position).Normalized() *
+ Master.RoleState.MoveSpeed;
+ }
+ else
+ {
+ Master.AnimatedSprite.Play(AnimatorNames.Idle);
+ Master.BasisVelocity = Vector2.Zero;
+ }
}
else
{
diff --git a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs
index 48bec61..e067187 100644
--- a/DungeonShooting_Godot/src/game/activity/role/player/Player.cs
+++ b/DungeonShooting_Godot/src/game/activity/role/player/Player.cs
@@ -40,6 +40,7 @@
IsAi = false;
StateController = AddComponent>();
AttackLayer = PhysicsLayer.Wall | PhysicsLayer.Prop | PhysicsLayer.Enemy;
+ EnemyLayer = EnemyLayer = PhysicsLayer.Enemy;
Camp = CampEnum.Camp1;
MaxHp = 6;
@@ -62,6 +63,8 @@
StateController.Register(new PlayerRollState());
//默认状态
StateController.ChangeStateInstant(PlayerStateEnum.Idle);
+
+ //InitSubLine();
}
protected override void Process(float delta)
@@ -142,6 +145,7 @@
if (StateController.CurrState != PlayerStateEnum.Roll) //不能是翻滚状态
{
Attack();
+ // //测试用,触发房间内地上的武器开火
// var weaponArray = AffiliationArea.FindEnterItems(o => o is Weapon);
// foreach (Weapon activityObject in weaponArray)
// {
diff --git a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs
index 03ab172..3bead8a 100644
--- a/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs
+++ b/DungeonShooting_Godot/src/game/activity/weapon/Weapon.cs
@@ -145,10 +145,20 @@
///
public bool NoMasterCanTrigger { get; set; } = true;
- //--------------------------------------------------------------------------------------------
+ ///
+ /// 上一次触发改武器开火的角色是否是Ai
+ ///
+ public bool TriggerRoleIsAi { get; private set; }
- //触发按下扳机的角色
- private Role _attackTrigger;
+ ///
+ /// 上一次触发改武器开火的触发开火攻击的层级, 数据源自于:
+ ///
+ public long TriggerRoleAttackLayer { get; private set; }
+
+ //--------------------------------------------------------------------------------------------
+
+ //用于记录是否有角色操作过这把武器
+ private bool _triggerRoleFlag = false;
//是否按下
private bool _triggerFlag = false;
@@ -181,7 +191,7 @@
private float _upTimer = 0;
//连发次数
- private float _continuousCount = 0;
+ private int _continuousCount = 0;
//连发状态记录
private bool _continuousShootFlag = false;
@@ -205,7 +215,7 @@
private float _reloadTimer = 0;
//单独换弹设置下的换弹状态, 0: 未换弹, 1: 装第一颗子弹之前, 2: 单独装弹中, 3: 单独装弹完成
- private byte _aloneReloadState = 0;
+ private byte _aloneReloadState = 3;
//单独换弹状态下是否强制结束换弹过程
private bool _aloneReloadStop = false;
@@ -434,7 +444,7 @@
//这把武器被扔在地上, 或者当前武器没有被使用
//if (Master == null || Master.WeaponPack.ActiveItem != this)
- if (Master != null && Master.WeaponPack.ActiveItem != this) //在背上
+ if ((Master != null && Master.WeaponPack.ActiveItem != this) || !_triggerRoleFlag) //在背上, 或者被扔出去了
{
//_triggerTimer
_triggerTimer = _triggerTimer > 0 ? _triggerTimer - delta : 0;
@@ -455,7 +465,7 @@
if (_dirtyFlag)
{
_dirtyFlag = false;
- _aloneReloadState = 0;
+ //_aloneReloadState = 0;
StopReload();
_attackFlag = false;
_continuousCount = 0;
@@ -672,28 +682,40 @@
{
return Master == null && GetParent() == GameApplication.Instance.World.NormalLayer;
}
-
+
///
/// 扳机函数, 调用即视为按下扳机
///
- /// 按下扳机的角色, 如果传 null, 则视为走火
- public void Trigger(Role trigger)
+ /// 按下扳机的角色, 如果传 null, 则视为走火
+ public void Trigger(Role triggerRole)
{
//不能触发扳机
if (!NoMasterCanTrigger && Master == null) return;
//这一帧已经按过了, 不需要再按下
if (_triggerFlag) return;
-
+
+ //更新武器属性信息
_triggerFlag = true;
- _attackTrigger = trigger;
+ _triggerRoleFlag = true;
+ if (triggerRole != null)
+ {
+ TriggerRoleIsAi = triggerRole.IsAi;
+ TriggerRoleAttackLayer = triggerRole.AttackLayer;
+ _weaponAttribute = TriggerRoleIsAi ? _aiWeaponAttribute : _playerWeaponAttribute;
+ }
+ else if (Master != null)
+ {
+ TriggerRoleIsAi = Master.IsAi;
+ TriggerRoleAttackLayer = Master.AttackLayer;
+ _weaponAttribute = TriggerRoleIsAi ? _aiWeaponAttribute : _playerWeaponAttribute;
+ }
//是否第一帧按下
var justDown = _downTimer == 0;
-
if (_beLoadedState == 0 || _beLoadedState == -1) //需要执行上膛操作
{
- if (justDown && !Reloading && trigger != null)
+ if (justDown && !Reloading && triggerRole != null)
{
if (CurrAmmo <= 0)
{
@@ -763,7 +785,7 @@
else if (CurrAmmo <= 0) //子弹不够
{
fireFlag = false;
- if (justDown && trigger != null)
+ if (justDown && triggerRole != null)
{
//第一帧按下, 触发换弹
Reload();
@@ -808,10 +830,7 @@
}
}
}
-
- _attackFlag = true;
}
-
}
}
}
@@ -848,6 +867,38 @@
{
return _delayedTime;
}
+
+ ///
+ /// 获取当前需要连发弹药的数量, 配置了 ContinuousCountRange 时生效
+ ///
+ public int GetContinuousCount()
+ {
+ return _continuousCount;
+ }
+
+ ///
+ /// 获取攻击冷却计时时间, 等于 0 表示冷却完成
+ ///
+ public float GetAttackTimer()
+ {
+ return _attackTimer;
+ }
+
+ ///
+ /// 返回是否是攻击间隙时间
+ ///
+ public bool IsAttackIntervalTime()
+ {
+ return _attackTimer > 0 || _triggerTimer > 0;
+ }
+
+ ///
+ /// 获取上膛状态,-1: 等待执行自动上膛 , 0: 未上膛, 1: 上膛中, 2: 已经完成上膛
+ ///
+ public sbyte GetBeLoadedStateState()
+ {
+ return _beLoadedState;
+ }
///
/// 刚按下扳机
@@ -897,12 +948,13 @@
///
private void TriggerFire()
{
+ _attackFlag = true;
_noAttackTime = 0;
//减子弹数量
if (_playerWeaponAttribute != _weaponAttribute) //Ai使用该武器, 有一定概率不消耗弹药
{
- if (Utils.Random.RandomRangeFloat(0, 1) < _weaponAttribute.AiAmmoConsumptionProbability) //触发消耗弹药
+ if (Utils.Random.RandomRangeFloat(0, 1) < _weaponAttribute.AiAttackAttr.AmmoConsumptionProbability) //触发消耗弹药
{
CurrAmmo -= UseAmmoCount();
}
@@ -1013,13 +1065,13 @@
}
}
- ///
- /// 触发武器的近战攻击
- ///
- public void TriggerMeleeAttack(Role trigger)
- {
-
- }
+ // ///
+ // /// 触发武器的近战攻击
+ // ///
+ // public virtual void TriggerMeleeAttack(Role trigger)
+ // {
+ //
+ // }
///
/// 获取武器攻击的目标层级
@@ -1027,6 +1079,10 @@
///
public uint GetAttackLayer()
{
+ if (TriggerRoleAttackLayer > 0)
+ {
+ return (uint)TriggerRoleAttackLayer;
+ }
return Master != null ? Master.AttackLayer : Role.DefaultAttackLayer;
}
@@ -1159,6 +1215,15 @@
public void StopReload()
{
_aloneReloadState = 0;
+ if (_beLoadedState == -1)
+ {
+ _beLoadedState = 0;
+ }
+ else if (_beLoadedState == 1)
+ {
+ _beLoadedState = 2;
+ }
+
Reloading = false;
_reloadTimer = 0;
_reloadUseTime = 0;
@@ -1703,25 +1768,25 @@
_triggerTimer = 0;
}
GetParent().RemoveChild(this);
- CollisionLayer = _tempLayer;
+ _triggerRoleFlag = false;
_weaponAttribute = _playerWeaponAttribute;
+ CollisionLayer = _tempLayer;
AnimatedSprite.Position = _tempAnimatedSpritePosition;
//清除 Ai 拾起标记
RemoveSign(SignNames.AiFindWeaponSign);
+ //停止换弹
+ if (Reloading)
+ {
+ StopReload();
+ }
OnRemove(Master);
}
public void OnPickUpItem()
{
Pickup();
- if (Master.IsAi)
- {
- _weaponAttribute = _aiWeaponAttribute;
- }
- else
- {
- _weaponAttribute = _playerWeaponAttribute;
- }
+ _triggerRoleFlag = true;
+ _weaponAttribute = Master.IsAi ? _aiWeaponAttribute : _playerWeaponAttribute;
//停止动画
AnimationPlayer.Stop();
//清除泛白效果
@@ -1850,11 +1915,11 @@
deviationAngle = Master.RoleState.CallCalcBulletDeviationAngleEvent(this, deviationAngle);
}
- var attackLayer = _attackTrigger != null ? _attackTrigger.AttackLayer : GetAttackLayer();
+ var attackLayer = GetAttackLayer();
//创建子弹
var bullet = Create(bulletId);
bullet.Init(
- _attackTrigger,
+ TriggerRoleIsAi,
this,
speed,
distance,
@@ -1869,12 +1934,188 @@
}
//-------------------------------- Ai相关 -----------------------------
+
+ ///
+ /// Ai 调用, 刷新 Ai 攻击状态并返回, 并不会调用相应的函数
+ ///
+ public AiAttackState AiRefreshAttackState()
+ {
+ AiAttackState flag;
+ if (IsTotalAmmoEmpty()) //当前武器弹药打空
+ {
+ //切换到有子弹的武器
+ var index = Master.WeaponPack.FindIndex((we, i) => !we.IsTotalAmmoEmpty());
+ if (index != -1)
+ {
+ flag = AiAttackState.ExchangeWeapon;
+ }
+ else //所有子弹打光
+ {
+ flag = AiAttackState.NoAmmo;
+ }
+ }
+ else if (Reloading) //换弹中
+ {
+ flag = AiAttackState.TriggerReload;
+ }
+ else if (IsAmmoEmpty()) //弹夹已经打空
+ {
+ flag = AiAttackState.Reloading;
+ }
+ else if (_beLoadedState == 0 || _beLoadedState == -1) //需要上膛
+ {
+ flag = AiAttackState.AttackInterval;
+ }
+ else if (_beLoadedState == 1) //上膛中
+ {
+ flag = AiAttackState.AttackInterval;
+ }
+ else if (_continuousCount >= 1) //连发中
+ {
+ flag = AiAttackState.Attack;
+ }
+ else if (IsAttackIntervalTime()) //开火间隙
+ {
+ flag = AiAttackState.AttackInterval;
+ }
+ else
+ {
+ var enemy = (Enemy)Master;
+ if (enemy.GetLockTime() >= Attribute.AiAttackAttr.LockingTime) //正常射击
+ {
+ if (GetDelayedAttackTime() > 0)
+ {
+ flag = AiAttackState.Attack;
+ }
+ else
+ {
+ if (Attribute.ContinuousShoot) //连发
+ {
+ flag = AiAttackState.Attack;
+ }
+ else //单发
+ {
+ flag = AiAttackState.Attack;
+ }
+ }
+ }
+ else //锁定时间没到
+ {
+ flag = AiAttackState.LockingTime;
+ }
+ }
+
+ return flag;
+ }
+
+ ///
+ /// Ai调用, 触发扣动扳机, 并返回攻击状态
+ ///
+ public AiAttackState AiTriggerAttackState()
+ {
+ AiAttackState flag;
+ if (IsTotalAmmoEmpty()) //当前武器弹药打空
+ {
+ //切换到有子弹的武器
+ var index = Master.WeaponPack.FindIndex((we, i) => !we.IsTotalAmmoEmpty());
+ if (index != -1)
+ {
+ flag = AiAttackState.ExchangeWeapon;
+ Master.WeaponPack.ExchangeByIndex(index);
+ }
+ else //所有子弹打光
+ {
+ flag = AiAttackState.NoAmmo;
+ }
+ }
+ else if (Reloading) //换弹中
+ {
+ flag = AiAttackState.TriggerReload;
+ }
+ else if (IsAmmoEmpty()) //弹夹已经打空
+ {
+ flag = AiAttackState.Reloading;
+ Reload();
+ }
+ else if (_beLoadedState == 0 || _beLoadedState == -1) //需要上膛
+ {
+ flag = AiAttackState.AttackInterval;
+ if (_attackTimer <= 0)
+ {
+ Master.Attack();
+ }
+ }
+ else if (_beLoadedState == 1) //上膛中
+ {
+ flag = AiAttackState.AttackInterval;
+ }
+ else if (_continuousCount >= 1) //连发中
+ {
+ flag = AiAttackState.Attack;
+ }
+ else if (IsAttackIntervalTime()) //开火间隙
+ {
+ flag = AiAttackState.AttackInterval;
+ }
+ else
+ {
+ var enemy = (Enemy)Master;
+ if (enemy.GetLockTime() >= Attribute.AiAttackAttr.LockingTime) //正常射击
+ {
+ if (GetDelayedAttackTime() > 0)
+ {
+ flag = AiAttackState.Attack;
+ enemy.Attack();
+ if (_attackFlag)
+ {
+ enemy.SetLockTargetTime(0);
+ }
+ }
+ else
+ {
+ if (Attribute.ContinuousShoot) //连发
+ {
+ flag = AiAttackState.Attack;
+ enemy.Attack();
+ if (_attackFlag)
+ {
+ enemy.SetLockTargetTime(0);
+ }
+ }
+ else //单发
+ {
+ flag = AiAttackState.Attack;
+ enemy.Attack();
+ if (_attackFlag)
+ {
+ enemy.SetLockTargetTime(0);
+ }
+ }
+ }
+ }
+ else //锁定时间没到
+ {
+ flag = AiAttackState.LockingTime;
+ }
+ }
+
+ return flag;
+ }
///
- /// 获取 Ai 对于该武器的评分, 评分越高, 代表 Ai 会越优先选择该武器, 如果为 -1, 则表示 Ai 不会使用该武器
+ /// 获取Ai锁定目标的剩余时间
///
- public float GetAiScore()
+ ///
+ public float GetAiLockRemainderTime()
{
- return 1;
+ return Attribute.AiAttackAttr.LockingTime - ((Enemy)Master).GetLockTime();
}
+
+ // ///
+ // /// 获取 Ai 对于该武器的评分, 评分越高, 代表 Ai 会越优先选择该武器, 如果为 -1, 则表示 Ai 不会使用该武器
+ // ///
+ // public float GetAiScore()
+ // {
+ // return 1;
+ // }
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/activity/weapon/gun/Gun.cs b/DungeonShooting_Godot/src/game/activity/weapon/gun/Gun.cs
index b8e288f..f74575e 100644
--- a/DungeonShooting_Godot/src/game/activity/weapon/gun/Gun.cs
+++ b/DungeonShooting_Godot/src/game/activity/weapon/gun/Gun.cs
@@ -28,4 +28,19 @@
{
ShootBullet(fireRotation, Attribute.BulletId);
}
+
+ // //测试用, 敌人被消灭时触发手上武器开火
+ // protected override void OnRemove(Role master)
+ // {
+ // base.OnRemove(master);
+ //
+ // if (master.IsDie && master.IsEnemyWithPlayer())
+ // {
+ // this.CallDelay(0, () =>
+ // {
+ // Debug.Log("敌人扔掉武器触发攻击");
+ // Trigger(master);
+ // });
+ // }
+ // }
}
\ No newline at end of file
diff --git a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs
index d04d4a5..40f2ec7 100644
--- a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs
+++ b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs
@@ -149,6 +149,7 @@
public const string resource_sprite_effects_weapon_KnifeHit1_png = "res://resource/sprite/effects/weapon/KnifeHit1.png";
public const string resource_sprite_effects_weapon_MeleeAttack1_png = "res://resource/sprite/effects/weapon/MeleeAttack1.png";
public const string resource_sprite_effects_weapon_ShotFire_png = "res://resource/sprite/effects/weapon/ShotFire.png";
+ public const string resource_sprite_map_door_png = "res://resource/sprite/map/door.png";
public const string resource_sprite_map_door1_down_png = "res://resource/sprite/map/door1_down.png";
public const string resource_sprite_map_PreviewTransition_png = "res://resource/sprite/map/PreviewTransition.png";
public const string resource_sprite_map_PreviewTransition2_png = "res://resource/sprite/map/PreviewTransition2.png";
@@ -279,8 +280,12 @@
public const string resource_spriteFrames_bullet_Bullet0002_tres = "res://resource/spriteFrames/bullet/Bullet0002.tres";
public const string resource_spriteFrames_bullet_Bullet0003_tres = "res://resource/spriteFrames/bullet/Bullet0003.tres";
public const string resource_spriteFrames_effect_KnifeHit1_tres = "res://resource/spriteFrames/effect/KnifeHit1.tres";
- public const string resource_spriteFrames_other_RoomDoor_EW_tres = "res://resource/spriteFrames/other/RoomDoor_EW.tres";
- public const string resource_spriteFrames_other_RoomDoor_NS_tres = "res://resource/spriteFrames/other/RoomDoor_NS.tres";
+ public const string resource_spriteFrames_other_RoomDoor_E_Down_tres = "res://resource/spriteFrames/other/RoomDoor_E_Down.tres";
+ public const string resource_spriteFrames_other_RoomDoor_E_Up_tres = "res://resource/spriteFrames/other/RoomDoor_E_Up.tres";
+ public const string resource_spriteFrames_other_RoomDoor_N_tres = "res://resource/spriteFrames/other/RoomDoor_N.tres";
+ public const string resource_spriteFrames_other_RoomDoor_S_tres = "res://resource/spriteFrames/other/RoomDoor_S.tres";
+ public const string resource_spriteFrames_other_RoomDoor_W_Down_tres = "res://resource/spriteFrames/other/RoomDoor_W_Down.tres";
+ public const string resource_spriteFrames_other_RoomDoor_W_Up_tres = "res://resource/spriteFrames/other/RoomDoor_W_Up.tres";
public const string resource_spriteFrames_prop_active_ActiveProp5000_tres = "res://resource/spriteFrames/prop/active/ActiveProp5000.tres";
public const string resource_spriteFrames_prop_active_ActiveProp5001_tres = "res://resource/spriteFrames/prop/active/ActiveProp5001.tres";
public const string resource_spriteFrames_prop_buff_BuffProp0001_tres = "res://resource/spriteFrames/prop/buff/BuffProp0001.tres";
diff --git a/DungeonShooting_Godot/src/game/room/RoomDoor.cs b/DungeonShooting_Godot/src/game/room/RoomDoor.cs
index da15cae..4d15411 100644
--- a/DungeonShooting_Godot/src/game/room/RoomDoor.cs
+++ b/DungeonShooting_Godot/src/game/room/RoomDoor.cs
@@ -19,6 +19,7 @@
private RoomDoorInfo _door;
private bool waitDisabledCollision = false;
+ private AnimatedSprite2D _animatedDown;
public override void OnInit()
{
@@ -32,6 +33,10 @@
{
_door = doorInfo;
IsClose = false;
+ if (doorInfo.Direction == DoorDirection.E || doorInfo.Direction == DoorDirection.W)
+ {
+ _animatedDown = GetNode("AnimatedSpriteDown");
+ }
OpenDoorHandler();
}
@@ -47,6 +52,11 @@
{
AnimatedSprite.Play(AnimatorNames.OpenDoor);
}
+
+ if (_animatedDown != null && _animatedDown.SpriteFrames.HasAnimation(AnimatorNames.OpenDoor))
+ {
+ _animatedDown.Play(AnimatorNames.OpenDoor);
+ }
}
///
@@ -64,16 +74,36 @@
_door.Navigation.CloseNavigationNode.Enabled = true;
_door.Navigation.CloseNavigationNode.Visible = true;
}
-
+
if (AnimatedSprite.SpriteFrames.HasAnimation(AnimatorNames.CloseDoor))
{
AnimatedSprite.Play(AnimatorNames.CloseDoor);
}
+
+ if (_animatedDown != null && _animatedDown.SpriteFrames.HasAnimation(AnimatorNames.CloseDoor))
+ {
+ _animatedDown.Play(AnimatorNames.CloseDoor);
+ }
+
//调整门的层级
switch (Direction)
{
case DoorDirection.E:
+ ZIndex = GameConfig.TopMapLayer;
+ if (_animatedDown != null)
+ {
+ _animatedDown.ZIndex = GameConfig.TopMapLayer;
+ }
+
+ break;
case DoorDirection.W:
+ ZIndex = GameConfig.TopMapLayer;
+ if (_animatedDown != null)
+ {
+ _animatedDown.ZIndex = GameConfig.TopMapLayer;
+ }
+
+ break;
case DoorDirection.S:
ZIndex = GameConfig.TopMapLayer;
break;
@@ -103,6 +133,33 @@
_door.Navigation.CloseNavigationNode.Visible = false;
}
//调整门的层级
- ZIndex = GameConfig.FloorMapLayer;
+ //ZIndex = GameConfig.FloorMapLayer;
+
+ //调整门的层级
+ switch (Direction)
+ {
+ case DoorDirection.E:
+ ZIndex = GameConfig.MiddleMapLayer;
+ if (_animatedDown != null)
+ {
+ _animatedDown.ZIndex = GameConfig.TopMapLayer;
+ }
+
+ break;
+ case DoorDirection.W:
+ ZIndex = GameConfig.MiddleMapLayer;
+ if (_animatedDown != null)
+ {
+ _animatedDown.ZIndex = GameConfig.TopMapLayer;
+ }
+
+ break;
+ case DoorDirection.S:
+ ZIndex = GameConfig.TopMapLayer;
+ break;
+ case DoorDirection.N:
+ ZIndex = GameConfig.MiddleMapLayer;
+ break;
+ }
}
}
\ No newline at end of file
diff --git a/README.md b/README.md
index c25219d..8949983 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-一款由Godot开发的地牢射击类型的游戏, 脚本语言使用的是C#, 当前项目使用的Godot版本: Godot_v4.2dev
+一款由Godot开发的地牢射击类型的游戏, 脚本语言使用的是C#, 当前项目使用的Godot版本: Godot_v4.2
---
### 游戏定义