This commit is contained in:
milimoe 2026-02-03 01:38:51 +08:00
parent c18ea77b66
commit d2e53df415
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
55 changed files with 2451 additions and 366 deletions

View File

@ -1,8 +1,8 @@
<Project Sdk="Godot.NET.Sdk/4.4.1"> <Project Sdk="Godot.NET.Sdk/4.6.0">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net8.0</TargetFramework> <TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net10.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework> <TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net10.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading> <EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>Milimoe.GodotGame</RootNamespace> <RootNamespace>Milimoe.GodotGame</RootNamespace>
</PropertyGroup> </PropertyGroup>
@ -24,5 +24,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\FunGame.Core\FunGame.Core.csproj" /> <ProjectReference Include="..\FunGame.Core\FunGame.Core.csproj" />
<ProjectReference Include="..\OshimaGameModule\OshimaModules\OshimaModules.csproj" />
<ProjectReference Include="..\OshimaGameModule\OshimaServers\OshimaServers.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

28
FunGame-Godot.csproj.old Normal file
View File

@ -0,0 +1,28 @@
<Project Sdk="Godot.NET.Sdk/4.4.1">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net8.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>Milimoe.GodotGame</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;IDE0130</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ExportDebug|AnyCPU'">
<NoWarn>1701;1702;IDE0130</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ExportRelease|AnyCPU'">
<NoWarn>1701;1702;IDE0130</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="novels\**" />
<EmbeddedResource Remove="novels\**" />
</ItemGroup>
<ItemGroup>
<None Include="scripts\.editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunGame.Core\FunGame.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,28 @@
<Project Sdk="Godot.NET.Sdk/4.5.0">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net10.0</TargetFramework>
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net10.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>Milimoe.GodotGame</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<NoWarn>1701;1702;IDE0130</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ExportDebug|AnyCPU'">
<NoWarn>1701;1702;IDE0130</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ExportRelease|AnyCPU'">
<NoWarn>1701;1702;IDE0130</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Remove="novels\**" />
<EmbeddedResource Remove="novels\**" />
</ItemGroup>
<ItemGroup>
<None Include="scripts\.editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FunGame.Core\FunGame.Core.csproj" />
</ItemGroup>
</Project>

View File

@ -1,12 +1,16 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17 # Visual Studio Version 18
VisualStudioVersion = 17.12.35527.113 d17.12 VisualStudioVersion = 18.2.11415.280 d18.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunGame-Godot", "FunGame-Godot.csproj", "{11453713-5BCC-49E5-829F-10A8AD8438AA}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunGame-Godot", "FunGame-Godot.csproj", "{11453713-5BCC-49E5-829F-10A8AD8438AA}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunGame.Core", "..\FunGame.Core\FunGame.Core.csproj", "{3566E2B2-160C-435E-871D-A9B9C158096C}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunGame.Core", "..\FunGame.Core\FunGame.Core.csproj", "{3566E2B2-160C-435E-871D-A9B9C158096C}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OshimaModules", "..\OshimaGameModule\OshimaModules\OshimaModules.csproj", "{F183B6D6-2318-B752-7174-813D1D01556B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OshimaServers", "..\OshimaGameModule\OshimaServers\OshimaServers.csproj", "{18980301-3D5E-C66E-E575-D2B7A110A638}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -26,8 +30,23 @@ Global
{3566E2B2-160C-435E-871D-A9B9C158096C}.ExportDebug|Any CPU.Build.0 = Debug|Any CPU {3566E2B2-160C-435E-871D-A9B9C158096C}.ExportDebug|Any CPU.Build.0 = Debug|Any CPU
{3566E2B2-160C-435E-871D-A9B9C158096C}.ExportRelease|Any CPU.ActiveCfg = Release|Any CPU {3566E2B2-160C-435E-871D-A9B9C158096C}.ExportRelease|Any CPU.ActiveCfg = Release|Any CPU
{3566E2B2-160C-435E-871D-A9B9C158096C}.ExportRelease|Any CPU.Build.0 = Release|Any CPU {3566E2B2-160C-435E-871D-A9B9C158096C}.ExportRelease|Any CPU.Build.0 = Release|Any CPU
{F183B6D6-2318-B752-7174-813D1D01556B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F183B6D6-2318-B752-7174-813D1D01556B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F183B6D6-2318-B752-7174-813D1D01556B}.ExportDebug|Any CPU.ActiveCfg = Release|Any CPU
{F183B6D6-2318-B752-7174-813D1D01556B}.ExportDebug|Any CPU.Build.0 = Release|Any CPU
{F183B6D6-2318-B752-7174-813D1D01556B}.ExportRelease|Any CPU.ActiveCfg = Release|Any CPU
{F183B6D6-2318-B752-7174-813D1D01556B}.ExportRelease|Any CPU.Build.0 = Release|Any CPU
{18980301-3D5E-C66E-E575-D2B7A110A638}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18980301-3D5E-C66E-E575-D2B7A110A638}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18980301-3D5E-C66E-E575-D2B7A110A638}.ExportDebug|Any CPU.ActiveCfg = Release|Any CPU
{18980301-3D5E-C66E-E575-D2B7A110A638}.ExportDebug|Any CPU.Build.0 = Release|Any CPU
{18980301-3D5E-C66E-E575-D2B7A110A638}.ExportRelease|Any CPU.ActiveCfg = Release|Any CPU
{18980301-3D5E-C66E-E575-D2B7A110A638}.ExportRelease|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A071C9E0-3717-4D00-AE3B-5A14E660AF9B}
EndGlobalSection
EndGlobal EndGlobal

View File

@ -8,14 +8,18 @@
config_version=5 config_version=5
[animation]
compatibility/default_parent_skeleton_in_mesh_instance_3d=true
[application] [application]
config/name="FunGame-Godot" config/name="FunGame-Godot"
run/main_scene="res://scenes/SplashScreen.tscn" run/main_scene="res://scenes/SplashScreen.tscn"
config/features=PackedStringArray("4.4", "C#", "GL Compatibility") config/features=PackedStringArray("4.6", "C#", "GL Compatibility")
boot_splash/bg_color=Color(1, 1, 1, 1) boot_splash/bg_color=Color(1, 1, 1, 1)
boot_splash/show_image=false boot_splash/show_image=false
config/icon="res://icon.svg" config/icon="uid://cfskdmaw15liu"
[display] [display]
@ -23,7 +27,7 @@ window/size/viewport_width=1280
window/size/viewport_height=720 window/size/viewport_height=720
window/size/resizable=false window/size/resizable=false
window/size/borderless=true window/size/borderless=true
window/stretch/mode="viewport" window/stretch/mode="canvas_items"
window/stretch/scale_mode="integer" window/stretch/scale_mode="integer"
[dotnet] [dotnet]
@ -62,6 +66,15 @@ move_down={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
] ]
} }
toggle_fight_log={
"deadzone": 0.2,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":76,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
]
}
[physics]
common/physics_interpolation=true
[rendering] [rendering]

View File

@ -0,0 +1,38 @@
[gd_scene format=3 uid="uid://dmbm52c5kvhvh"]
[ext_resource type="Texture2D" uid="uid://cgplv5ykpqldu" path="res://assets/buffs/adpup.png" id="1_rgoo2"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="2_8uwtf"]
[ext_resource type="Script" uid="uid://mjetytpyq51i" path="res://scripts/UIScripts/BuffItem.cs" id="2_ne11y"]
[node name="BuffItem" type="Control" unique_id=811979895 node_paths=PackedStringArray("TextureRect", "Label")]
custom_minimum_size = Vector2(64, 64)
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("2_ne11y")
TextureRect = NodePath("TextureRect")
Label = NodePath("Label")
[node name="TextureRect" type="TextureRect" parent="." unique_id=2058418070]
custom_minimum_size = Vector2(64, 64)
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
texture = ExtResource("1_rgoo2")
expand_mode = 1
stretch_mode = 5
[node name="Label" type="Label" parent="." unique_id=2070266169]
layout_mode = 0
offset_left = 40.0
offset_top = 32.0
offset_right = 64.0
offset_bottom = 67.0
theme_override_colors/font_color = Color(0.70514816, 0.9927334, 0.96567994, 1)
theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.7058824)
theme_override_fonts/font = ExtResource("2_8uwtf")
theme_override_font_sizes/font_size = 24
text = "2"

View File

@ -0,0 +1,38 @@
[gd_scene format=3 uid="uid://cl0i6y6a6b6a8"]
[ext_resource type="Script" uid="uid://bf1lfbuoq3nkh" path="res://scripts/UIScripts/CharacterItem.cs" id="1_i8qtq"]
[ext_resource type="Texture2D" uid="uid://biooen7y20ks8" path="res://assets/character/雷恩.png" id="1_qsnl3"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="2_i8qtq"]
[node name="CharacterItem" type="Control" unique_id=1745827206 node_paths=PackedStringArray("TextureRect", "Label")]
custom_minimum_size = Vector2(96, 96)
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_i8qtq")
TextureRect = NodePath("TextureRect")
Label = NodePath("Label")
[node name="TextureRect" type="TextureRect" parent="." unique_id=462435124]
custom_minimum_size = Vector2(96, 96)
layout_mode = 0
offset_right = 40.0
offset_bottom = 40.0
texture = ExtResource("1_qsnl3")
expand_mode = 1
stretch_mode = 5
[node name="Label" type="Label" parent="." unique_id=472633575]
layout_mode = 0
offset_right = 88.0
offset_bottom = 44.0
theme_override_colors/font_color = Color(0.97762054, 0.9024748, 0.9525201, 1)
theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.7058824)
theme_override_fonts/font = ExtResource("2_i8qtq")
theme_override_font_sizes/font_size = 30
text = "2"
horizontal_alignment = 2
vertical_alignment = 1

View File

@ -0,0 +1,209 @@
[gd_scene format=3 uid="uid://boa4gvdodn6is"]
[ext_resource type="Script" uid="uid://ne34ebenkjmd" path="res://scripts/CharacterStatus.cs" id="1_n6t88"]
[ext_resource type="Theme" uid="uid://d0pi6io7y7tky" path="res://resources/themes/dialog.tres" id="1_xafvb"]
[ext_resource type="Texture2D" uid="uid://biooen7y20ks8" path="res://assets/character/雷恩.png" id="1_xdbvw"]
[ext_resource type="Theme" uid="uid://d1gp4l4cwgtw4" path="res://resources/themes/button.tres" id="2_xdbvw"]
[ext_resource type="PackedScene" uid="uid://dmbm52c5kvhvh" path="res://resources/controls/BuffItem.tscn" id="5_gni6q"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dugby"]
bg_color = Color(0.6, 0.6, 0.6, 0)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jet3t"]
bg_color = Color(0, 0.7137255, 0.40784314, 0.39215687)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cnh2t"]
bg_color = Color(0.36078432, 0.60784316, 0.91764706, 0.39215687)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_arpqe"]
bg_color = Color(0.8784314, 0.48235294, 0, 0.39215687)
[node name="CharacterStatus" type="Panel" unique_id=1496252882 node_paths=PackedStringArray("Image", "HPBar", "MPBar", "EPBar", "HP", "MP", "EP", "Level")]
size_flags_horizontal = 0
theme_override_styles/panel = SubResource("StyleBoxFlat_dugby")
script = ExtResource("1_n6t88")
Image = NodePath("Image")
HPBar = NodePath("HPBar")
MPBar = NodePath("MPBar")
EPBar = NodePath("EPBar")
HP = NodePath("HP")
MP = NodePath("MP")
EP = NodePath("EP")
Level = NodePath("Level")
[node name="Image" type="TextureRect" parent="." unique_id=332789227]
layout_mode = 1
anchors_preset = -1
anchor_left = -0.045
anchor_top = -0.36400002
anchor_right = -0.045
anchor_bottom = -0.36400002
offset_left = -55.999996
offset_right = 967.99994
offset_bottom = 1024.0001
scale = Vector2(0.4, 0.4)
texture = ExtResource("1_xdbvw")
expand_mode = 1
[node name="HPBar" type="ProgressBar" parent="." unique_id=250999659]
layout_mode = 1
anchors_preset = -1
anchor_left = -0.045
anchor_top = -0.36400002
anchor_right = -0.045
anchor_bottom = -0.36400002
offset_left = 320.0
offset_top = 173.0
offset_right = 832.0
offset_bottom = 236.99998
theme = ExtResource("1_xafvb")
theme_override_styles/fill = SubResource("StyleBoxFlat_jet3t")
max_value = 21424.0
value = 17110.0
show_percentage = false
[node name="MPBar" type="ProgressBar" parent="." unique_id=1188464978]
layout_mode = 1
anchors_preset = -1
anchor_left = -0.045
anchor_top = -0.36400002
anchor_right = -0.045
anchor_bottom = -0.36400002
offset_left = 320.0
offset_top = 245.0
offset_right = 832.0
offset_bottom = 309.0
theme = ExtResource("1_xafvb")
theme_override_styles/fill = SubResource("StyleBoxFlat_cnh2t")
max_value = 2533.0
value = 795.0
show_percentage = false
[node name="EPBar" type="ProgressBar" parent="." unique_id=923755045]
layout_mode = 1
anchors_preset = -1
anchor_left = -0.045
anchor_top = -0.36400002
anchor_right = -0.045
anchor_bottom = -0.36400002
offset_left = 320.0
offset_top = 319.0
offset_right = 832.0
offset_bottom = 383.0
theme = ExtResource("1_xafvb")
theme_override_styles/fill = SubResource("StyleBoxFlat_arpqe")
max_value = 200.0
value = 15.0
show_percentage = false
[node name="HP" type="Label" parent="." unique_id=1388418558]
layout_mode = 1
anchors_preset = -1
anchor_left = -0.045
anchor_top = -0.36400002
anchor_right = -0.045
anchor_bottom = -0.36400002
offset_left = 320.0
offset_top = 173.0
offset_right = 832.0
offset_bottom = 236.99998
theme = ExtResource("2_xdbvw")
theme_override_colors/font_color = Color(0, 0.715563, 0.406543, 1)
text = "17110 / 21424"
horizontal_alignment = 2
vertical_alignment = 1
[node name="MP" type="Label" parent="." unique_id=380541733]
layout_mode = 1
anchors_preset = -1
anchor_left = -0.045
anchor_top = -0.36400002
anchor_right = -0.045
anchor_bottom = -0.36400002
offset_left = 320.0
offset_top = 244.0
offset_right = 832.0
offset_bottom = 308.0
theme = ExtResource("2_xdbvw")
theme_override_colors/font_color = Color(0.360998, 0.609236, 0.919164, 1)
text = "795 / 2533"
horizontal_alignment = 2
vertical_alignment = 1
[node name="EP" type="Label" parent="." unique_id=1083411746]
layout_mode = 1
anchors_preset = -1
anchor_left = -0.045
anchor_top = -0.36400002
anchor_right = -0.045
anchor_bottom = -0.36400002
offset_left = 320.0
offset_top = 319.0
offset_right = 832.0
offset_bottom = 383.0
theme = ExtResource("2_xdbvw")
theme_override_colors/font_color = Color(0.879745, 0.48415, 7.70092e-07, 1)
text = "15 / 200"
horizontal_alignment = 2
vertical_alignment = 1
[node name="Level" type="Label" parent="." unique_id=847018324]
layout_mode = 1
anchors_preset = -1
anchor_left = -0.045
anchor_top = -0.36400002
anchor_right = -0.045
anchor_bottom = -0.36400002
offset_left = 320.0
offset_top = 88.0
offset_right = 832.0
offset_bottom = 158.0
theme = ExtResource("2_xdbvw")
theme_override_colors/font_color = Color(0.3311984, 0.5930991, 1, 1)
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1)
theme_override_font_sizes/font_size = 48
text = "雷恩 - 等级 1"
vertical_alignment = 1
[node name="ScrollContainer" type="ScrollContainer" parent="." unique_id=1548306844]
layout_mode = 0
offset_left = 320.0
offset_top = 16.0
offset_right = 832.0
offset_bottom = 88.0
[node name="HBoxContainer" type="HBoxContainer" parent="ScrollContainer" unique_id=1944009762]
layout_mode = 2
[node name="BuffItem" parent="ScrollContainer/HBoxContainer" unique_id=1032115207 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem2" parent="ScrollContainer/HBoxContainer" unique_id=1569074178 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem3" parent="ScrollContainer/HBoxContainer" unique_id=1855281629 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem4" parent="ScrollContainer/HBoxContainer" unique_id=433622243 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem5" parent="ScrollContainer/HBoxContainer" unique_id=998345842 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem6" parent="ScrollContainer/HBoxContainer" unique_id=758729347 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem7" parent="ScrollContainer/HBoxContainer" unique_id=811979895 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem8" parent="ScrollContainer/HBoxContainer" unique_id=363183697 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem9" parent="ScrollContainer/HBoxContainer" unique_id=349761587 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem10" parent="ScrollContainer/HBoxContainer" unique_id=1518968312 instance=ExtResource("5_gni6q")]
layout_mode = 2
[node name="BuffItem11" parent="ScrollContainer/HBoxContainer" unique_id=1477306808 instance=ExtResource("5_gni6q")]
layout_mode = 2

View File

@ -0,0 +1,48 @@
[gd_scene format=3 uid="uid://b3bby7t653g41"]
[ext_resource type="PackedScene" uid="uid://cl0i6y6a6b6a8" path="res://resources/controls/CharacterItem.tscn" id="1_6h0n6"]
[node name="RoundQueue" type="Control" unique_id=1897105738]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HScrollBar" type="ScrollContainer" parent="." unique_id=730469931]
layout_mode = 1
anchors_preset = 5
anchor_left = 0.5
anchor_right = 0.5
offset_left = -640.0
offset_right = 640.0
offset_bottom = 96.0
grow_horizontal = 2
vertical_scroll_mode = 3
[node name="HBoxContainer" type="HBoxContainer" parent="HScrollBar" unique_id=1065765625]
layout_mode = 2
size_flags_horizontal = 3
alignment = 1
[node name="CharacterItem" parent="HScrollBar/HBoxContainer" unique_id=1745827206 instance=ExtResource("1_6h0n6")]
layout_mode = 2
[node name="CharacterItem2" parent="HScrollBar/HBoxContainer" unique_id=1029207147 instance=ExtResource("1_6h0n6")]
layout_mode = 2
[node name="CharacterItem3" parent="HScrollBar/HBoxContainer" unique_id=966971552 instance=ExtResource("1_6h0n6")]
layout_mode = 2
[node name="CharacterItem4" parent="HScrollBar/HBoxContainer" unique_id=1433760264 instance=ExtResource("1_6h0n6")]
layout_mode = 2
[node name="CharacterItem5" parent="HScrollBar/HBoxContainer" unique_id=1339521788 instance=ExtResource("1_6h0n6")]
layout_mode = 2
[node name="CharacterItem6" parent="HScrollBar/HBoxContainer" unique_id=671057065 instance=ExtResource("1_6h0n6")]
layout_mode = 2
[node name="CharacterItem7" parent="HScrollBar/HBoxContainer" unique_id=2137228680 instance=ExtResource("1_6h0n6")]
layout_mode = 2

View File

@ -0,0 +1,62 @@
[gd_scene format=3 uid="uid://dj16n8yvwwgr7"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_dg3fm"]
[ext_resource type="Script" uid="uid://b8alcxaoi45xq" path="res://scripts/CharacterBody/CharacterBody.cs" id="1_xfrxc"]
[ext_resource type="Texture2D" uid="uid://dbyovpk0xc6jo" path="res://assets/character/2D雷恩.png" id="2_xfrxc"]
[ext_resource type="Texture2D" uid="uid://c85yg8bcpdvvr" path="res://assets/character/走路雷恩.png" id="3_7totm"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_s5ben"]
bg_color = Color(0, 0.701961, 0.54902, 0.784314)
[sub_resource type="SpriteFrames" id="SpriteFrames_7totm"]
animations = [{
"frames": [],
"loop": true,
"name": &"default",
"speed": 5.0
}, {
"frames": [{
"duration": 1.0,
"texture": ExtResource("2_xfrxc")
}],
"loop": true,
"name": &"idle",
"speed": 5.0
}, {
"frames": [{
"duration": 3.0,
"texture": ExtResource("2_xfrxc")
}, {
"duration": 1.0,
"texture": ExtResource("3_7totm")
}],
"loop": true,
"name": &"walk",
"speed": 5.0
}]
[node name="Rayne" type="CharacterBody2D" unique_id=796512133 node_paths=PackedStringArray("AnimatedSprite2D")]
collision_mask = 7
script = ExtResource("1_xfrxc")
IdleTexture = ExtResource("2_xfrxc")
WalkTexture = ExtResource("3_7totm")
AnimatedSprite2D = NodePath("CollisionPolygon2D/AnimatedSprite2D")
[node name="ProgressBar" type="ProgressBar" parent="." unique_id=431755658]
visible = false
offset_left = -592.0
offset_top = -728.0
offset_right = 618.0
offset_bottom = -576.0
theme_override_fonts/font = ExtResource("1_dg3fm")
theme_override_font_sizes/font_size = 48
theme_override_styles/fill = SubResource("StyleBoxFlat_s5ben")
value = 100.0
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="." unique_id=831580699]
polygon = PackedVector2Array(0, 0, 0, 440, 160, 440, 304, 408, 320, 160, 280, 40, 248, -32, 304, -152, 176, -176, 56, -176, -96, -176, -240, -160, -360, 0, -360, 200, -296, 320, -272, 424, -200, 440, 0, 440)
[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="CollisionPolygon2D" unique_id=399839730]
sprite_frames = SubResource("SpriteFrames_7totm")
animation = &"walk"
frame_progress = 0.7747467

View File

@ -0,0 +1,15 @@
[gd_scene format=3 uid="uid://cxdm6onxptvbm"]
[ext_resource type="Texture2D" uid="uid://wf8vq1p42frw" path="res://assets/character/2.png" id="1_htads"]
[node name="Enemy" type="CharacterBody2D" unique_id=1205480849]
collision_layer = 4
collision_mask = 7
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="." unique_id=1829645491]
polygon = PackedVector2Array(-8, 8, 8, 8, 8, 0, 8, -8, -8, -8)
[node name="Sprite2D" type="Sprite2D" parent="CollisionPolygon2D" unique_id=1428890555]
position = Vector2(0, -3.8)
scale = Vector2(0.014, 0.014)
texture = ExtResource("1_htads")

View File

@ -1,4 +1,4 @@
[gd_resource type="Theme" load_steps=3 format=3 uid="uid://d1gp4l4cwgtw4"] [gd_resource type="Theme" format=3 uid="uid://d1gp4l4cwgtw4"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_qn7vl"] [ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_qn7vl"]

View File

@ -1,4 +1,4 @@
[gd_resource type="Theme" load_steps=6 format=3 uid="uid://bi5n6j6qn74xi"] [gd_resource type="Theme" format=3 uid="uid://bi5n6j6qn74xi"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_74oji"] [ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_74oji"]

View File

@ -1,4 +1,4 @@
[gd_resource type="Theme" load_steps=3 format=3 uid="uid://cc3c0kkawa67y"] [gd_resource type="Theme" format=3 uid="uid://cc3c0kkawa67y"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_f2lmy"] [ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_f2lmy"]

View File

@ -1,4 +1,4 @@
[gd_resource type="Theme" load_steps=7 format=3 uid="uid://clwk8wh5003m8"] [gd_resource type="Theme" format=3 uid="uid://clwk8wh5003m8"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_ul7ps"] [ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_ul7ps"]

View File

@ -1,4 +1,4 @@
[gd_resource type="Theme" load_steps=4 format=3 uid="uid://bs3813xiv8ivn"] [gd_resource type="Theme" format=3 uid="uid://bs3813xiv8ivn"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_edkmk"] [ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_edkmk"]

View File

@ -1,100 +0,0 @@
[gd_scene load_steps=7 format=3 uid="uid://boa4gvdodn6is"]
[ext_resource type="Theme" uid="uid://d0pi6io7y7tky" path="res://resources/themes/dialog.tres" id="1_21m4e"]
[ext_resource type="Theme" uid="uid://d1gp4l4cwgtw4" path="res://resources/themes/button.tres" id="2_jet3t"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_dugby"]
bg_color = Color(0.6, 0.6, 0.6, 0)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_jet3t"]
bg_color = Color(0, 0.715563, 0.406543, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cnh2t"]
bg_color = Color(0.360998, 0.609236, 0.919164, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_arpqe"]
bg_color = Color(0.879745, 0.48415, 7.70092e-07, 1)
[node name="CharacterStatus" type="Panel"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_right = -88.0
offset_bottom = -368.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/panel = SubResource("StyleBoxFlat_dugby")
[node name="Image" type="TextureRect" parent="."]
layout_mode = 1
offset_right = 320.0
offset_bottom = 320.0
[node name="HPBar" type="ProgressBar" parent="."]
layout_mode = 1
offset_left = 352.0
offset_top = 64.0
offset_right = 1152.0
offset_bottom = 128.0
theme = ExtResource("1_21m4e")
theme_override_styles/fill = SubResource("StyleBoxFlat_jet3t")
value = 70.0
show_percentage = false
[node name="MPBar" type="ProgressBar" parent="."]
layout_mode = 1
offset_left = 352.0
offset_top = 160.0
offset_right = 1152.0
offset_bottom = 224.0
theme = ExtResource("1_21m4e")
theme_override_styles/fill = SubResource("StyleBoxFlat_cnh2t")
value = 30.0
show_percentage = false
[node name="EPBar" type="ProgressBar" parent="."]
layout_mode = 1
offset_left = 352.0
offset_top = 256.0
offset_right = 1152.0
offset_bottom = 320.0
theme = ExtResource("1_21m4e")
theme_override_styles/fill = SubResource("StyleBoxFlat_arpqe")
value = 10.0
show_percentage = false
[node name="HP" type="Label" parent="."]
layout_mode = 1
offset_left = 352.0
offset_top = 64.0
offset_right = 1152.0
offset_bottom = 128.0
theme = ExtResource("2_jet3t")
theme_override_colors/font_color = Color(0, 0.715563, 0.406543, 1)
text = "17110"
horizontal_alignment = 2
vertical_alignment = 1
[node name="MP" type="Label" parent="."]
layout_mode = 1
offset_left = 352.0
offset_top = 160.0
offset_right = 1152.0
offset_bottom = 224.0
theme = ExtResource("2_jet3t")
theme_override_colors/font_color = Color(0.360998, 0.609236, 0.919164, 1)
text = "7945"
horizontal_alignment = 2
vertical_alignment = 1
[node name="EP" type="Label" parent="."]
layout_mode = 1
offset_left = 352.0
offset_top = 256.0
offset_right = 1152.0
offset_bottom = 320.0
theme = ExtResource("2_jet3t")
theme_override_colors/font_color = Color(0.879745, 0.48415, 7.70092e-07, 1)
text = "15"
horizontal_alignment = 2
vertical_alignment = 1

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=11 format=3 uid="uid://exqgca0e7vay"] [gd_scene format=3 uid="uid://exqgca0e7vay"]
[ext_resource type="Script" uid="uid://cgcdu4cg7u28g" path="res://scripts/NovelController.cs" id="1_0tl37"] [ext_resource type="Script" uid="uid://cgcdu4cg7u28g" path="res://scripts/NovelController.cs" id="1_0tl37"]
[ext_resource type="Texture2D" uid="uid://0dkwmsresstm" path="res://assets/character/艾琳.png" id="1_af382"] [ext_resource type="Texture2D" uid="uid://0dkwmsresstm" path="res://assets/character/艾琳.png" id="1_af382"]
@ -10,18 +10,20 @@
[ext_resource type="Script" uid="uid://c4ny5p54lotj0" path="res://scripts/AnimatedRichTextLabel.cs" id="7_vvt2q"] [ext_resource type="Script" uid="uid://c4ny5p54lotj0" path="res://scripts/AnimatedRichTextLabel.cs" id="7_vvt2q"]
[ext_resource type="Theme" uid="uid://cc3c0kkawa67y" path="res://resources/themes/novelbutton.tres" id="9_bp2jl"] [ext_resource type="Theme" uid="uid://cc3c0kkawa67y" path="res://resources/themes/novelbutton.tres" id="9_bp2jl"]
[ext_resource type="PackedScene" uid="uid://b25umg4d0y13" path="res://resources/ui/SavedSelection.tscn" id="10_sk065"] [ext_resource type="PackedScene" uid="uid://b25umg4d0y13" path="res://resources/ui/SavedSelection.tscn" id="10_sk065"]
[ext_resource type="AudioStream" uid="uid://bad5gahdr5j4n" path="res://assets/sound/button.mp3" id="11_tgcqi"]
[ext_resource type="AudioStream" uid="uid://corefqbddmijy" path="res://assets/sound/select.mp3" id="12_oe1al"]
[node name="Novel" type="CanvasLayer" node_paths=PackedStringArray("SavedSelection")] [node name="Novel" type="CanvasLayer" unique_id=715567244 node_paths=PackedStringArray("SavedSelection")]
script = ExtResource("1_0tl37") script = ExtResource("1_0tl37")
SavedSelection = NodePath("SavedSelection") SavedSelection = NodePath("SavedSelection")
[node name="立绘1" type="TextureRect" parent="."] [node name="立绘1" type="TextureRect" parent="." unique_id=1582436083]
offset_left = 451.0 offset_left = 451.0
offset_right = 899.0 offset_right = 899.0
offset_bottom = 720.0 offset_bottom = 720.0
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Image" type="TextureRect" parent="立绘1"] [node name="Image" type="TextureRect" parent="立绘1" unique_id=110010410]
visible = false visible = false
layout_mode = 1 layout_mode = 1
anchors_preset = 8 anchors_preset = 8
@ -38,13 +40,13 @@ grow_vertical = 2
texture = ExtResource("1_u842g") texture = ExtResource("1_u842g")
expand_mode = 2 expand_mode = 2
[node name="立绘2左" type="TextureRect" parent="."] [node name="立绘2左" type="TextureRect" parent="." unique_id=1075463687]
offset_left = 131.0 offset_left = 131.0
offset_right = 579.0 offset_right = 579.0
offset_bottom = 720.0 offset_bottom = 720.0
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Image" type="TextureRect" parent="立绘2左"] [node name="Image" type="TextureRect" parent="立绘2左" unique_id=845506044]
visible = false visible = false
layout_mode = 1 layout_mode = 1
anchors_preset = 8 anchors_preset = 8
@ -61,13 +63,13 @@ grow_vertical = 2
texture = ExtResource("1_u842g") texture = ExtResource("1_u842g")
expand_mode = 2 expand_mode = 2
[node name="立绘2右" type="TextureRect" parent="."] [node name="立绘2右" type="TextureRect" parent="." unique_id=1356622611]
offset_left = 707.0 offset_left = 707.0
offset_right = 1155.0 offset_right = 1155.0
offset_bottom = 720.0 offset_bottom = 720.0
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Image" type="TextureRect" parent="立绘2右"] [node name="Image" type="TextureRect" parent="立绘2右" unique_id=1788333383]
visible = false visible = false
layout_mode = 1 layout_mode = 1
anchors_preset = 8 anchors_preset = 8
@ -84,21 +86,21 @@ grow_vertical = 2
texture = ExtResource("1_af382") texture = ExtResource("1_af382")
expand_mode = 2 expand_mode = 2
[node name="Panel" type="Panel" parent="."] [node name="Panel" type="Panel" parent="." unique_id=1891703129]
offset_top = 512.0 offset_top = 512.0
offset_right = 1280.0 offset_right = 1280.0
offset_bottom = 720.0 offset_bottom = 720.0
theme = ExtResource("1_fmroo") theme = ExtResource("1_fmroo")
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="NamePanel" type="Panel" parent="Panel"] [node name="NamePanel" type="Panel" parent="Panel" unique_id=1726050406]
layout_mode = 0 layout_mode = 0
offset_top = -64.0 offset_top = -64.0
offset_right = 256.0 offset_right = 256.0
theme = ExtResource("1_fmroo") theme = ExtResource("1_fmroo")
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Name" type="Label" parent="Panel/NamePanel"] [node name="Name" type="Label" parent="Panel/NamePanel" unique_id=1885702795]
layout_mode = 0 layout_mode = 0
offset_right = 256.0 offset_right = 256.0
offset_bottom = 64.0 offset_bottom = 64.0
@ -108,7 +110,7 @@ horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Content" type="RichTextLabel" parent="Panel"] [node name="Content" type="RichTextLabel" parent="Panel" unique_id=751432425]
layout_mode = 0 layout_mode = 0
offset_left = 64.0 offset_left = 64.0
offset_top = 24.0 offset_top = 24.0
@ -123,15 +125,15 @@ autowrap_mode = 0
script = ExtResource("7_vvt2q") script = ExtResource("7_vvt2q")
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Timer" type="Timer" parent="Panel/Content"] [node name="Timer" type="Timer" parent="Panel/Content" unique_id=890981820]
[node name="透明挡板" type="ColorRect" parent="."] [node name="透明挡板" type="ColorRect" parent="." unique_id=1499755186]
offset_right = 1280.0 offset_right = 1280.0
offset_bottom = 720.0 offset_bottom = 720.0
color = Color(1, 1, 1, 0) color = Color(1, 1, 1, 0)
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="选项框" type="VBoxContainer" parent="."] [node name="选项框" type="VBoxContainer" parent="." unique_id=1122310456]
anchors_preset = -1 anchors_preset = -1
anchor_left = 1.0 anchor_left = 1.0
anchor_top = 0.704 anchor_top = 0.704
@ -147,25 +149,25 @@ alignment = 2
metadata/_edit_use_anchors_ = true metadata/_edit_use_anchors_ = true
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Button3" type="Button" parent="选项框"] [node name="Button3" type="Button" parent="选项框" unique_id=1359028598]
layout_mode = 2 layout_mode = 2
theme = ExtResource("5_b05s4") theme = ExtResource("5_b05s4")
text = "选项三" text = "选项三"
icon_alignment = 1 icon_alignment = 1
[node name="Button2" type="Button" parent="选项框"] [node name="Button2" type="Button" parent="选项框" unique_id=534612404]
layout_mode = 2 layout_mode = 2
theme = ExtResource("5_b05s4") theme = ExtResource("5_b05s4")
text = "选项二" text = "选项二"
icon_alignment = 1 icon_alignment = 1
[node name="Button1" type="Button" parent="选项框"] [node name="Button1" type="Button" parent="选项框" unique_id=501649633]
layout_mode = 2 layout_mode = 2
theme = ExtResource("5_b05s4") theme = ExtResource("5_b05s4")
text = "选项一" text = "选项一"
icon_alignment = 1 icon_alignment = 1
[node name="自动播放" type="Button" parent="."] [node name="自动播放" type="Button" parent="." unique_id=2065835822]
offset_left = 1208.0 offset_left = 1208.0
offset_top = 528.0 offset_top = 528.0
offset_right = 1256.0 offset_right = 1256.0
@ -174,7 +176,7 @@ theme = ExtResource("9_bp2jl")
toggle_mode = true toggle_mode = true
text = "自动" text = "自动"
[node name="读取存档" type="Button" parent="."] [node name="读取存档" type="Button" parent="." unique_id=957875887]
offset_left = 1208.0 offset_left = 1208.0
offset_top = 576.0 offset_top = 576.0
offset_right = 1256.0 offset_right = 1256.0
@ -182,7 +184,7 @@ offset_bottom = 608.0
theme = ExtResource("9_bp2jl") theme = ExtResource("9_bp2jl")
text = "读档" text = "读档"
[node name="保存存档" type="Button" parent="."] [node name="保存存档" type="Button" parent="." unique_id=844062084]
offset_left = 1208.0 offset_left = 1208.0
offset_top = 624.0 offset_top = 624.0
offset_right = 1256.0 offset_right = 1256.0
@ -190,7 +192,7 @@ offset_bottom = 656.0
theme = ExtResource("9_bp2jl") theme = ExtResource("9_bp2jl")
text = "存档" text = "存档"
[node name="游戏菜单" type="Button" parent="."] [node name="游戏菜单" type="Button" parent="." unique_id=549452688]
offset_left = 1208.0 offset_left = 1208.0
offset_top = 672.0 offset_top = 672.0
offset_right = 1256.0 offset_right = 1256.0
@ -198,6 +200,14 @@ offset_bottom = 704.0
theme = ExtResource("9_bp2jl") theme = ExtResource("9_bp2jl")
text = "菜单" text = "菜单"
[node name="SavedSelection" parent="." node_paths=PackedStringArray("Parent") instance=ExtResource("10_sk065")] [node name="SavedSelection" parent="." unique_id=847631279 node_paths=PackedStringArray("Parent") instance=ExtResource("10_sk065")]
visible = false visible = false
Parent = NodePath("..") Parent = NodePath("..")
[node name="ButtonPlayer" type="AudioStreamPlayer" parent="." unique_id=1689862777]
stream = ExtResource("11_tgcqi")
volume_db = -8.0
[node name="SelectPlayer" type="AudioStreamPlayer" parent="." unique_id=526554960]
stream = ExtResource("12_oe1al")
volume_db = -8.0

View File

@ -1,28 +0,0 @@
[gd_scene load_steps=5 format=3 uid="uid://dj16n8yvwwgr7"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="1_dg3fm"]
[ext_resource type="Script" uid="uid://b8alcxaoi45xq" path="res://scripts/CharacterBody/CharacterBody.cs" id="1_xfrxc"]
[ext_resource type="Texture2D" uid="uid://dbyovpk0xc6jo" path="res://assets/character/2D雷恩.png" id="2_xfrxc"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_s5ben"]
bg_color = Color(0, 0.701961, 0.54902, 0.784314)
[node name="Rayne" type="CharacterBody2D"]
script = ExtResource("1_xfrxc")
[node name="ProgressBar" type="ProgressBar" parent="."]
visible = false
offset_left = -592.0
offset_top = -728.0
offset_right = 618.0
offset_bottom = -576.0
theme_override_fonts/font = ExtResource("1_dg3fm")
theme_override_font_sizes/font_size = 48
theme_override_styles/fill = SubResource("StyleBoxFlat_s5ben")
value = 100.0
[node name="CollisionPolygon2D" type="CollisionPolygon2D" parent="."]
polygon = PackedVector2Array(0, 0, 0, 440, 160, 440, 320, 360, 320, 160, 280, 40, 200, 0, 240, -80, 280, -80, 320, -120, 320, -280, 280, -400, 160, -520, -40, -520, -160, -440, -240, -320, -240, -160, -360, 0, -360, 200, -280, 240, -240, 360, -200, 440, 0, 440)
[node name="Sprite2D" type="Sprite2D" parent="CollisionPolygon2D"]
texture = ExtResource("2_xfrxc")

View File

@ -1,10 +1,12 @@
[gd_scene load_steps=4 format=3 uid="uid://dewev77kmbwre"] [gd_scene format=3 uid="uid://dewev77kmbwre"]
[ext_resource type="Theme" uid="uid://d1gp4l4cwgtw4" path="res://resources/themes/button.tres" id="1_r31ah"] [ext_resource type="Theme" uid="uid://d1gp4l4cwgtw4" path="res://resources/themes/button.tres" id="1_r31ah"]
[ext_resource type="PackedScene" uid="uid://boa4gvdodn6is" path="res://resources/ui/CharacterStatus.tscn" id="2_infd8"] [ext_resource type="PackedScene" uid="uid://boa4gvdodn6is" path="res://resources/controls/CharacterStatus.tscn" id="2_infd8"]
[ext_resource type="Script" uid="uid://bc5cucvklcmrd" path="res://scripts/UserInterface.cs" id="3_mwlxn"] [ext_resource type="Script" uid="uid://bc5cucvklcmrd" path="res://scripts/UserInterface.cs" id="3_mwlxn"]
[ext_resource type="PackedScene" uid="uid://b3bby7t653g41" path="res://resources/controls/RoundQueue.tscn" id="4_vufsu"]
[ext_resource type="Theme" uid="uid://bs3813xiv8ivn" path="res://resources/themes/panel.tres" id="5_flasd"]
[node name="UserInterface" type="Control" node_paths=PackedStringArray("CharacterStatus1", "CharacterStatus2")] [node name="UserInterface" type="Control" unique_id=2140201054 node_paths=PackedStringArray("Location", "Rayne", "Irene", "RoundQueue", "FightLog")]
layout_mode = 3 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
@ -12,32 +14,59 @@ anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
script = ExtResource("3_mwlxn") script = ExtResource("3_mwlxn")
CharacterStatus1 = NodePath("CharacterStatus") Location = NodePath("Label")
CharacterStatus2 = NodePath("CharacterStatus2") Rayne = NodePath("Rayne")
Irene = NodePath("Irene")
RoundQueue = NodePath("RoundQueue")
FightLog = NodePath("FightLog")
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Label" type="Label" parent="."] [node name="Label" type="Label" parent="." unique_id=1964672114]
layout_mode = 0 layout_mode = 0
offset_right = 448.0 offset_left = 16.0
offset_right = 464.0
offset_bottom = 72.0 offset_bottom = 72.0
theme = ExtResource("1_r31ah") theme = ExtResource("1_r31ah")
text = "当前位置" text = "当前位置"
horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
[node name="CharacterStatus" parent="." instance=ExtResource("2_infd8")] [node name="Rayne" parent="." unique_id=601075864 instance=ExtResource("2_infd8")]
visible = false
layout_mode = 1 layout_mode = 1
offset_top = 648.0 offset_top = 520.0
offset_right = -85.0 offset_bottom = 520.0
offset_bottom = 269.0 scale = Vector2(0.5, 0.5)
scale = Vector2(0.2, 0.2) CharacterId = 1
[node name="CharacterStatus2" parent="." instance=ExtResource("2_infd8")] [node name="Irene" parent="." unique_id=1781627172 instance=ExtResource("2_infd8")]
visible = false visible = false
layout_mode = 1 layout_mode = 1
offset_left = 240.0 offset_left = 424.0
offset_top = 648.0 offset_top = 520.0
offset_right = 155.0 offset_right = 424.0
offset_bottom = 269.0 offset_bottom = 520.0
scale = Vector2(0.2, 0.2) scale = Vector2(0.5, 0.5)
CharacterId = 2
[node name="RoundQueue" parent="." unique_id=1897105738 instance=ExtResource("4_vufsu")]
layout_mode = 1
offset_bottom = -624.0
[node name="FightLog" type="Panel" parent="." unique_id=1924320390]
self_modulate = Color(1, 1, 1, 0.34509805)
layout_mode = 0
offset_left = 768.0
offset_top = 128.0
offset_right = 1280.0
offset_bottom = 720.0
[node name="RichTextLabel" type="RichTextLabel" parent="FightLog" unique_id=1360173978]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = ExtResource("5_flasd")
theme_override_colors/font_shadow_color = Color(0, 0, 0, 0.88235295)
bbcode_enabled = true
text = "战斗日志记录"

12
scenes/Fighting.tscn Normal file
View File

@ -0,0 +1,12 @@
[gd_scene format=3 uid="uid://bj1mvs2yuu3i4"]
[ext_resource type="Script" uid="uid://c5ebf2dx20ptw" path="res://scripts/UIScripts/Fighting.cs" id="1_2qlhq"]
[node name="Fighting" type="Control" unique_id=1532091140]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_2qlhq")

View File

@ -1,15 +1,15 @@
[gd_scene load_steps=5 format=3 uid="uid://dhvw4k0vyu1aa"] [gd_scene load_steps=5 format=3 uid="uid://dhvw4k0vyu1aa"]
[ext_resource type="Texture2D" uid="uid://dsuuk4kdoevn3" path="res://assets/raincandy.png" id="1_8ukic"]
[ext_resource type="Script" uid="uid://dbyq6vgnnib7w" path="res://scripts/SplashScreen.cs" id="1_v5ida"] [ext_resource type="Script" uid="uid://dbyq6vgnnib7w" path="res://scripts/SplashScreen.cs" id="1_v5ida"]
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="3_jobkp"] [ext_resource type="Texture2D" uid="uid://cfskdmaw15liu" path="res://assets/milimoe.png" id="2_m7gka"]
[ext_resource type="FontFile" uid="uid://b36tv7dlp0wco" path="res://assets/fonts/LanaPixel.ttf" id="3_m7gka"]
[ext_resource type="Texture2D" uid="uid://b7mtjukcndwbc" path="res://assets/logo_large_color_light.png" id="5_s88rl"] [ext_resource type="Texture2D" uid="uid://b7mtjukcndwbc" path="res://assets/logo_large_color_light.png" id="5_s88rl"]
[node name="SplashScreen" type="CanvasLayer" node_paths=PackedStringArray("GodotLogo", "Logo", "Label")] [node name="SplashScreen" type="CanvasLayer" node_paths=PackedStringArray("GodotLogo", "Logo", "Label")]
script = ExtResource("1_v5ida") script = ExtResource("1_v5ida")
GodotLogo = NodePath("Godot") GodotLogo = NodePath("Godot")
Logo = NodePath("Raincandy") Logo = NodePath("MiliLogo")
Label = NodePath("Raincandy/Milimoe") Label = NodePath("MiliLogo/Milimoe")
[node name="ColorRect" type="ColorRect" parent="."] [node name="ColorRect" type="ColorRect" parent="."]
anchors_preset = 8 anchors_preset = 8
@ -25,38 +25,38 @@ grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="Raincandy" type="TextureRect" parent="."] [node name="MiliLogo" type="TextureRect" parent="."]
anchors_preset = 5 anchors_preset = 5
anchor_left = 0.5 anchor_left = 0.5
anchor_right = 0.5 anchor_right = 0.5
offset_left = -290.5 offset_left = -304.0
offset_right = 290.5 offset_top = 16.0
offset_bottom = 581.0 offset_right = 546.0
offset_bottom = 866.0
grow_horizontal = 2 grow_horizontal = 2
scale = Vector2(0.7, 0.7)
size_flags_horizontal = 4 size_flags_horizontal = 4
texture = ExtResource("1_8ukic") texture = ExtResource("2_m7gka")
metadata/_edit_lock_ = true
[node name="Milimoe" type="Label" parent="Raincandy"] [node name="Milimoe" type="Label" parent="MiliLogo"]
layout_mode = 1 layout_mode = 1
anchors_preset = 7 anchors_preset = -1
anchor_left = 0.5 anchor_left = 0.502
anchor_top = 1.0 anchor_top = 1.0
anchor_right = 0.5 anchor_right = 0.502
anchor_bottom = 1.0 anchor_bottom = 1.0
offset_left = -313.0 offset_left = -392.414
offset_top = -102.0 offset_top = -130.0
offset_right = 335.0 offset_right = 414.586
offset_bottom = 26.0 offset_bottom = -2.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 0 grow_vertical = 0
theme_override_colors/font_color = Color(0.940591, 0.290397, 0.55787, 1) theme_override_colors/font_color = Color(0.839216, 0.572549, 0.694118, 1)
theme_override_fonts/font = ExtResource("3_jobkp") theme_override_fonts/font = ExtResource("3_m7gka")
theme_override_font_sizes/font_size = 50 theme_override_font_sizes/font_size = 120
text = "Milimoe Presents" text = "Milimoe Presents"
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
metadata/_edit_lock_ = true
[node name="Godot" type="TextureRect" parent="."] [node name="Godot" type="TextureRect" parent="."]
anchors_preset = 5 anchors_preset = 5

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=15 format=3 uid="uid://b8tj5ccjo6lqe"] [gd_scene format=3 uid="uid://b8tj5ccjo6lqe"]
[ext_resource type="Script" uid="uid://cyi0j3meewtyt" path="res://scripts/TitleScreen.cs" id="1_mgv04"] [ext_resource type="Script" uid="uid://cyi0j3meewtyt" path="res://scripts/TitleScreen.cs" id="1_mgv04"]
[ext_resource type="Texture2D" uid="uid://ghgridyqby8w" path="res://assets/backgrounds/EclipticSonata.png" id="2_t3h42"] [ext_resource type="Texture2D" uid="uid://ghgridyqby8w" path="res://assets/backgrounds/EclipticSonata.png" id="2_t3h42"]
@ -6,8 +6,11 @@
[ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="4_xoekp"] [ext_resource type="FontFile" uid="uid://ch6s7n1ri81gt" path="res://assets/fonts/思源宋体.TTF" id="4_xoekp"]
[ext_resource type="Theme" uid="uid://d0pi6io7y7tky" path="res://resources/themes/dialog.tres" id="6_bdtiy"] [ext_resource type="Theme" uid="uid://d0pi6io7y7tky" path="res://resources/themes/dialog.tres" id="6_bdtiy"]
[ext_resource type="Texture2D" uid="uid://cy8hsxd2nn0i8" path="res://assets/EclipticSonataLogo.png" id="6_nf1md"] [ext_resource type="Texture2D" uid="uid://cy8hsxd2nn0i8" path="res://assets/EclipticSonataLogo.png" id="6_nf1md"]
[ext_resource type="AudioStream" uid="uid://l6k3d3408tj" path="res://assets/music/Wolfgang Amadeus Mozart - 莫扎特 摇篮曲.mp3" id="7_68hpm"] [ext_resource type="AudioStream" uid="uid://by67v6qb2rct1" path="res://assets/music/main1.mp3" id="7_3ej01"]
[ext_resource type="PackedScene" uid="uid://b25umg4d0y13" path="res://resources/ui/SavedSelection.tscn" id="8_88cje"] [ext_resource type="PackedScene" uid="uid://b25umg4d0y13" path="res://resources/ui/SavedSelection.tscn" id="8_88cje"]
[ext_resource type="Script" uid="uid://o6s6k2kojfe5" path="res://scenes/audio_stream_player.gd" id="8_w20ru"]
[ext_resource type="AudioStream" uid="uid://bad5gahdr5j4n" path="res://assets/sound/button.mp3" id="10_1vfo2"]
[ext_resource type="AudioStream" uid="uid://corefqbddmijy" path="res://assets/sound/select.mp3" id="11_hjcsb"]
[sub_resource type="Animation" id="Animation_yw73o"] [sub_resource type="Animation" id="Animation_yw73o"]
length = 0.001 length = 0.001
@ -81,7 +84,7 @@ _data = {
&"flyin": SubResource("Animation_86lmj") &"flyin": SubResource("Animation_86lmj")
} }
[node name="TitleScreen" type="Node2D" node_paths=PackedStringArray("StartGameButton", "LoadGameButton", "GameSettingsButton", "ExitGameButton", "StartConfirmationDialog", "ExitConfirmationDialog", "SavedSelection")] [node name="TitleScreen" type="Node2D" unique_id=486042896 node_paths=PackedStringArray("StartGameButton", "LoadGameButton", "GameSettingsButton", "ExitGameButton", "StartConfirmationDialog", "ExitConfirmationDialog", "SavedSelection", "ButtonPlayer", "SelectPlayer")]
script = ExtResource("1_mgv04") script = ExtResource("1_mgv04")
StartGameButton = NodePath("VBoxContainer/新的开始") StartGameButton = NodePath("VBoxContainer/新的开始")
LoadGameButton = NodePath("VBoxContainer/载入游戏") LoadGameButton = NodePath("VBoxContainer/载入游戏")
@ -90,13 +93,15 @@ ExitGameButton = NodePath("VBoxContainer/退出游戏")
StartConfirmationDialog = NodePath("StartNew?") StartConfirmationDialog = NodePath("StartNew?")
ExitConfirmationDialog = NodePath("ExitGame?") ExitConfirmationDialog = NodePath("ExitGame?")
SavedSelection = NodePath("SavedSelection") SavedSelection = NodePath("SavedSelection")
ButtonPlayer = NodePath("ButtonPlayer")
SelectPlayer = NodePath("SelectPlayer")
[node name="bg" type="Sprite2D" parent="."] [node name="bg" type="Sprite2D" parent="." unique_id=1228377383]
position = Vector2(640, 360) position = Vector2(640, 360)
texture = ExtResource("2_t3h42") texture = ExtResource("2_t3h42")
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="CopyRight" type="Label" parent="."] [node name="CopyRight" type="Label" parent="." unique_id=1451225559]
offset_left = 8.0 offset_left = 8.0
offset_top = 688.0 offset_top = 688.0
offset_right = 272.0 offset_right = 272.0
@ -105,19 +110,19 @@ theme_override_colors/font_color = Color(0.219608, 0.0823529, 0.254902, 1)
theme_override_colors/font_shadow_color = Color(0.983899, 0.825836, 0.867247, 0.458824) theme_override_colors/font_shadow_color = Color(0.983899, 0.825836, 0.867247, 0.458824)
theme_override_fonts/font = ExtResource("4_xoekp") theme_override_fonts/font = ExtResource("4_xoekp")
theme_override_font_sizes/font_size = 18 theme_override_font_sizes/font_size = 18
text = "©2025 Milimoe. 米粒的糖果屋" text = "©2026 Milimoe. 米粒的糖果屋"
horizontal_alignment = 1 horizontal_alignment = 1
vertical_alignment = 1 vertical_alignment = 1
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="ExitGame?" type="ConfirmationDialog" parent="."] [node name="ExitGame?" type="ConfirmationDialog" parent="." unique_id=1410976409]
title = "提示" title = "提示"
theme = ExtResource("6_bdtiy") theme = ExtResource("6_bdtiy")
ok_button_text = "是" ok_button_text = "是"
dialog_text = "是否退出游戏?" dialog_text = "是否退出游戏?"
cancel_button_text = "否" cancel_button_text = "否"
[node name="StartNew?" type="ConfirmationDialog" parent="."] [node name="StartNew?" type="ConfirmationDialog" parent="." unique_id=1897562920]
auto_translate_mode = 1 auto_translate_mode = 1
title = "提示" title = "提示"
theme = ExtResource("6_bdtiy") theme = ExtResource("6_bdtiy")
@ -125,7 +130,7 @@ ok_button_text = "是"
dialog_text = "开始新的游戏吗?" dialog_text = "开始新的游戏吗?"
cancel_button_text = "否" cancel_button_text = "否"
[node name="EclipticSonataLogo" type="TextureRect" parent="."] [node name="EclipticSonataLogo" type="TextureRect" parent="." unique_id=1646132829]
offset_left = 64.0 offset_left = 64.0
offset_top = -300.0 offset_top = -300.0
offset_right = 940.0 offset_right = 940.0
@ -134,22 +139,20 @@ scale = Vector2(0.7, 0.7)
texture = ExtResource("6_nf1md") texture = ExtResource("6_nf1md")
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="AnimationPlayer" type="AnimationPlayer" parent="EclipticSonataLogo"] [node name="AnimationPlayer" type="AnimationPlayer" parent="EclipticSonataLogo" unique_id=1935482813]
libraries = { libraries/ = SubResource("AnimationLibrary_csld4")
&"": SubResource("AnimationLibrary_csld4") autoplay = &"flyin"
}
autoplay = "flyin"
playback_auto_capture = false playback_auto_capture = false
playback_default_blend_time = 0.3 playback_default_blend_time = 0.3
[node name="VBoxContainer" type="VBoxContainer" parent="."] [node name="VBoxContainer" type="VBoxContainer" parent="." unique_id=585678813]
offset_left = 1520.0 offset_left = 1520.0
offset_top = 470.0 offset_top = 470.0
offset_right = 1656.0 offset_right = 1656.0
offset_bottom = 702.0 offset_bottom = 702.0
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="新的开始" type="Button" parent="VBoxContainer"] [node name="新的开始" type="Button" parent="VBoxContainer" unique_id=88592048]
layout_mode = 2 layout_mode = 2
theme = ExtResource("2_xbc5l") theme = ExtResource("2_xbc5l")
text = "新的开始" text = "新的开始"
@ -157,7 +160,7 @@ flat = true
icon_alignment = 1 icon_alignment = 1
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="载入游戏" type="Button" parent="VBoxContainer"] [node name="载入游戏" type="Button" parent="VBoxContainer" unique_id=762912014]
layout_mode = 2 layout_mode = 2
theme = ExtResource("2_xbc5l") theme = ExtResource("2_xbc5l")
text = "载入游戏" text = "载入游戏"
@ -165,7 +168,7 @@ flat = true
icon_alignment = 1 icon_alignment = 1
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="游戏设置" type="Button" parent="VBoxContainer"] [node name="游戏设置" type="Button" parent="VBoxContainer" unique_id=1806920198]
layout_mode = 2 layout_mode = 2
theme = ExtResource("2_xbc5l") theme = ExtResource("2_xbc5l")
text = "游戏设置" text = "游戏设置"
@ -173,7 +176,7 @@ flat = true
icon_alignment = 1 icon_alignment = 1
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="退出游戏" type="Button" parent="VBoxContainer"] [node name="退出游戏" type="Button" parent="VBoxContainer" unique_id=100760810]
layout_mode = 2 layout_mode = 2
theme = ExtResource("2_xbc5l") theme = ExtResource("2_xbc5l")
text = "退出游戏" text = "退出游戏"
@ -181,28 +184,35 @@ flat = true
icon_alignment = 1 icon_alignment = 1
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="AnimationPlayer" type="AnimationPlayer" parent="VBoxContainer"] [node name="AnimationPlayer" type="AnimationPlayer" parent="VBoxContainer" unique_id=1011201155]
callback_mode_method = 1 callback_mode_method = 1
libraries = { libraries/ = SubResource("AnimationLibrary_5laux")
&"": SubResource("AnimationLibrary_5laux") autoplay = &"flyin"
}
autoplay = "flyin"
playback_auto_capture = false playback_auto_capture = false
playback_default_blend_time = 0.3 playback_default_blend_time = 0.3
[node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="." unique_id=1368992756]
stream = ExtResource("7_68hpm") stream = ExtResource("7_3ej01")
volume_db = -8.0 volume_db = -8.0
autoplay = true autoplay = true
parameters/looping = true script = ExtResource("8_w20ru")
autoPlay = true
[node name="SavedSelection" parent="." node_paths=PackedStringArray("Parent") instance=ExtResource("8_88cje")] [node name="SavedSelection" parent="." unique_id=2048079397 node_paths=PackedStringArray("Parent") instance=ExtResource("8_88cje")]
visible = false visible = false
Parent = NodePath("..") Parent = NodePath("..")
[node name="ColorRect" type="ColorRect" parent="."] [node name="ColorRect" type="ColorRect" parent="." unique_id=348732101]
visible = false visible = false
offset_right = 1280.0 offset_right = 1280.0
offset_bottom = 720.0 offset_bottom = 720.0
color = Color(0, 0, 0, 1) color = Color(0, 0, 0, 1)
metadata/_edit_lock_ = true metadata/_edit_lock_ = true
[node name="ButtonPlayer" type="AudioStreamPlayer" parent="." unique_id=546906284]
stream = ExtResource("10_1vfo2")
volume_db = -8.0
[node name="SelectPlayer" type="AudioStreamPlayer" parent="." unique_id=321658143]
stream = ExtResource("11_hjcsb")
volume_db = -8.0

View File

@ -0,0 +1,37 @@
extends AudioStreamPlayer
# 两首循环
@export var bgm1: AudioStream = preload("res://assets/music/main1.mp3")
@export var bgm2: AudioStream = preload("res://assets/music/main2.mp3")
@export var autoPlay: bool = false
var current_song: int = 1
func _ready() -> void:
# 连接 finished 信号
finished.connect(_on_music_finished)
current_song = 1
stream = bgm1
# 开始播放第一首
if autoPlay:
play_bgm1()
func play_bgm1() -> void:
current_song = 1
stream = bgm1
play()
func play_bgm2() -> void:
current_song = 2
stream = bgm2
play()
func _on_music_finished() -> void:
if current_song == 1:
play_bgm2()
else:
play_bgm1()

View File

@ -0,0 +1 @@
uid://o6s6k2kojfe5

21
scenes/第一章.gdshader Normal file
View File

@ -0,0 +1,21 @@
shader_type canvas_item;
// 获取屏幕内容注意Godot 4 必须写这个提示符)
uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;
// 模糊强度
uniform float blur_amount : hint_range(0.0, 5.0) = 0.0;
// 边缘硬度
uniform float vignette_softness : hint_range(0.0, 1.0) = 0.5;
void fragment() {
// 1. 计算当前像素距离中心点的距离
float dist = distance(UV, vec2(0.5));
// 2. 根据距离计算权重中心为0四周渐变为1
float mask = smoothstep(0.2, vignette_softness + 0.5, dist);
// 3. 采样屏幕图像,根据权重决定该像素的模糊程度
vec4 screen_color = textureLod(screen_texture, SCREEN_UV, mask * blur_amount);
COLOR = screen_color;
}

View File

@ -0,0 +1 @@
uid://dwo7wvlhcfwo7

View File

@ -1,10 +1,13 @@
[gd_resource type="TileSet" load_steps=9 format=3 uid="uid://bgpctug81w5n3"] [gd_resource type="TileSet" format=3 uid="uid://bgpctug81w5n3"]
[ext_resource type="Texture2D" uid="uid://bxk7lljpqml15" path="res://assets/kenney_1-bit-pack/Tilemap/tileset_legacy.png" id="1_2ipr8"] [ext_resource type="Texture2D" uid="uid://bxk7lljpqml15" path="res://assets/kenney_1-bit-pack/Tilemap/tileset_legacy.png" id="1_2ipr8"]
[ext_resource type="Texture2D" uid="uid://bhvyfmyt8dkch" path="res://assets/kenney_monochrome-rpg/Default/Tilemap/tilemap.png" id="2_npjt2"] [ext_resource type="Texture2D" uid="uid://bhvyfmyt8dkch" path="res://assets/kenney_monochrome-rpg/Default/Tilemap/tilemap.png" id="2_npjt2"]
[ext_resource type="Texture2D" uid="uid://caws1nopk6ka8" path="res://assets/kenney_tiny-dungeon/Tilemap/tilemap.png" id="3_2vnky"] [ext_resource type="Texture2D" uid="uid://caws1nopk6ka8" path="res://assets/kenney_tiny-dungeon/Tilemap/tilemap.png" id="3_2vnky"]
[ext_resource type="Texture2D" uid="uid://qoabg46a4b4g" path="res://assets/kenney_rpg-urban-pack/Tilemap/tilemap.png" id="4_xfnij"] [ext_resource type="Texture2D" uid="uid://qoabg46a4b4g" path="res://assets/kenney_rpg-urban-pack/Tilemap/tilemap.png" id="4_xfnij"]
[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_xvv1l"]
bounce = 1.0
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_0netd"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_0netd"]
texture = ExtResource("1_2ipr8") texture = ExtResource("1_2ipr8")
separation = Vector2i(1, 1) separation = Vector2i(1, 1)
@ -1038,89 +1041,157 @@ texture = ExtResource("2_npjt2")
separation = Vector2i(1, 1) separation = Vector2i(1, 1)
0:0/0 = 0 0:0/0 = 0
1:0/0 = 0 1:0/0 = 0
1:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, -5.5756207, -5.2159023, -8, 8)
2:0/0 = 0 2:0/0 = 0
2:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -6.4749136, 8, -6.834631, 8, -8, -8, -8)
3:0/0 = 0 3:0/0 = 0
3:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, 6.115196, -5.3957615)
4:0/0 = 0 4:0/0 = 0
4:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, -4.136751, -3.956891, -8, 8)
5:0/0 = 0 5:0/0 = 0
5:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, -6.4749136, -8, -6.115196)
6:0/0 = 0 6:0/0 = 0
6:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, 3.7770329, -3.956891)
7:0/0 = 0 7:0/0 = 0
7:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, -4.6763268, -4.6763268, -8, 8)
8:0/0 = 0 8:0/0 = 0
8:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, -6.115196, -8, -6.2950544)
9:0/0 = 0 9:0/0 = 0
9:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, 4.3166084, -4.3166084)
10:0/0 = 0 10:0/0 = 0
10:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:0/0 = 0 11:0/0 = 0
11:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
12:0/0 = 0 12:0/0 = 0
12:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
13:0/0 = 0 13:0/0 = 0
13:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
14:0/0 = 0 14:0/0 = 0
14:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:0/0 = 0 15:0/0 = 0
15:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:0/0 = 0 16:0/0 = 0
16:0/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:1/0 = 0 0:1/0 = 0
1:1/0 = 0 1:1/0 = 0
1:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, -6.115197, -8, -6.115197, 10.251947, -8, 8)
2:1/0 = 0 2:1/0 = 0
3:1/0 = 0 3:1/0 = 0
3:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(6.2950554, -8, 8, -8, 8, 8, 6.6547737, 8)
4:1/0 = 0 4:1/0 = 0
4:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, -5.935338, -8, -5.75548, 8, -8, 8)
5:1/0 = 0 5:1/0 = 0
6:1/0 = 0 6:1/0 = 0
6:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(6.2950554, -8, 8, -8, 8, 8, 6.2950554, 8)
7:1/0 = 0 7:1/0 = 0
7:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, -5.75548, -8, -5.935338, 8, -8, 8)
8:1/0 = 0 8:1/0 = 0
9:1/0 = 0 9:1/0 = 0
9:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(6.115196, -8, 8, -8, 8, 8, 6.2950554, 8)
10:1/0 = 0 10:1/0 = 0
10:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:1/0 = 0 11:1/0 = 0
11:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
12:1/0 = 0 12:1/0 = 0
12:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
13:1/0 = 0 13:1/0 = 0
13:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
14:1/0 = 0 14:1/0 = 0
14:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:1/0 = 0 15:1/0 = 0
15:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:1/0 = 0 16:1/0 = 0
16:1/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:2/0 = 0 0:2/0 = 0
1:2/0 = 0 1:2/0 = 0
1:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -4.6763268, 8, 8, -8, 8)
2:2/0 = 0 2:2/0 = 0
2:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -4.3166084, 8, -4.4964676, 8, 8, -8, 8)
3:2/0 = 0 3:2/0 = 0
3:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -4.13675, 8, -8, 8, 8, -8, 8)
4:2/0 = 0 4:2/0 = 0
4:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, -3.7770338, 3.2374573, 8, 8, -8, 8)
5:2/0 = 0 5:2/0 = 0
5:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 5.215904, 8, 5.036045, 8, 8, -8, 8)
6:2/0 = 0 6:2/0 = 0
6:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(3.4173164, 3.4173164, 8, -8, 8, 8, -8, 8)
7:2/0 = 0 7:2/0 = 0
7:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, -3.956892, 4.3166103, 8, 8, -8, 8)
8:2/0 = 0 8:2/0 = 0
8:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, 6.6547737, 8, 6.6547737, 8, 8, -8, 8)
9:2/0 = 0 9:2/0 = 0
9:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(4.4964676, 4.6763268, 8, -8, 8, 8, -8, 8)
10:2/0 = 0 10:2/0 = 0
10:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:2/0 = 0 11:2/0 = 0
11:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
12:2/0 = 0 12:2/0 = 0
12:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
13:2/0 = 0 13:2/0 = 0
13:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
14:2/0 = 0 14:2/0 = 0
14:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:2/0 = 0 15:2/0 = 0
15:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:2/0 = 0 16:2/0 = 0
16:2/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:3/0 = 0 0:3/0 = 0
1:3/0 = 0 1:3/0 = 0
2:3/0 = 0 2:3/0 = 0
2:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:3/0 = 0 3:3/0 = 0
4:3/0 = 0 4:3/0 = 0
5:3/0 = 0 5:3/0 = 0
5:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:3/0 = 0 6:3/0 = 0
6:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:3/0 = 0 7:3/0 = 0
8:3/0 = 0 8:3/0 = 0
8:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
9:3/0 = 0 9:3/0 = 0
9:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:3/0 = 0 10:3/0 = 0
10:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:3/0 = 0 11:3/0 = 0
11:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
12:3/0 = 0 12:3/0 = 0
12:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
13:3/0 = 0 13:3/0 = 0
13:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
14:3/0 = 0 14:3/0 = 0
14:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:3/0 = 0 15:3/0 = 0
15:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:3/0 = 0 16:3/0 = 0
16:3/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:4/0 = 0 0:4/0 = 0
1:4/0 = 0 1:4/0 = 0
2:4/0 = 0 2:4/0 = 0
3:4/0 = 0 3:4/0 = 0
3:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
4:4/0 = 0 4:4/0 = 0
5:4/0 = 0 5:4/0 = 0
5:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:4/0 = 0 6:4/0 = 0
6:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:4/0 = 0 7:4/0 = 0
8:4/0 = 0 8:4/0 = 0
8:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
9:4/0 = 0 9:4/0 = 0
9:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:4/0 = 0 10:4/0 = 0
10:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:4/0 = 0 11:4/0 = 0
11:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
12:4/0 = 0 12:4/0 = 0
12:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
13:4/0 = 0 13:4/0 = 0
13:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
14:4/0 = 0 14:4/0 = 0
14:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:4/0 = 0 15:4/0 = 0
16:4/0 = 0 16:4/0 = 0
16:4/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:5/0 = 0 0:5/0 = 0
1:5/0 = 0 1:5/0 = 0
2:5/0 = 0 2:5/0 = 0
@ -1129,49 +1200,88 @@ separation = Vector2i(1, 1)
5:5/0 = 0 5:5/0 = 0
6:5/0 = 0 6:5/0 = 0
7:5/0 = 0 7:5/0 = 0
7:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:5/0 = 0 8:5/0 = 0
8:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
9:5/0 = 0 9:5/0 = 0
9:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:5/0 = 0 10:5/0 = 0
10:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:5/0 = 0 11:5/0 = 0
11:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
12:5/0 = 0 12:5/0 = 0
12:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
13:5/0 = 0 13:5/0 = 0
13:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
14:5/0 = 0 14:5/0 = 0
14:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:5/0 = 0 15:5/0 = 0
15:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:5/0 = 0 16:5/0 = 0
16:5/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:6/0 = 0 0:6/0 = 0
1:6/0 = 0 1:6/0 = 0
2:6/0 = 0 2:6/0 = 0
3:6/0 = 0 3:6/0 = 0
4:6/0 = 0 4:6/0 = 0
5:6/0 = 0 5:6/0 = 0
5:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:6/0 = 0 6:6/0 = 0
6:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:6/0 = 0 7:6/0 = 0
7:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:6/0 = 0 8:6/0 = 0
8:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
9:6/0 = 0 9:6/0 = 0
9:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:6/0 = 0 10:6/0 = 0
10:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:6/0 = 0 11:6/0 = 0
11:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
12:6/0 = 0 12:6/0 = 0
12:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
13:6/0 = 0 13:6/0 = 0
13:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
14:6/0 = 0 14:6/0 = 0
14:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:6/0 = 0 15:6/0 = 0
15:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:6/0 = 0 16:6/0 = 0
16:6/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
0:7/0 = 0 0:7/0 = 0
0:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
1:7/0 = 0 1:7/0 = 0
1:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
2:7/0 = 0 2:7/0 = 0
2:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
3:7/0 = 0 3:7/0 = 0
3:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
4:7/0 = 0 4:7/0 = 0
4:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
5:7/0 = 0 5:7/0 = 0
5:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
6:7/0 = 0 6:7/0 = 0
6:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
7:7/0 = 0 7:7/0 = 0
7:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
8:7/0 = 0 8:7/0 = 0
8:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
9:7/0 = 0 9:7/0 = 0
9:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
10:7/0 = 0 10:7/0 = 0
10:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
11:7/0 = 0 11:7/0 = 0
11:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
12:7/0 = 0 12:7/0 = 0
12:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
13:7/0 = 0 13:7/0 = 0
13:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
14:7/0 = 0 14:7/0 = 0
14:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
15:7/0 = 0 15:7/0 = 0
15:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
16:7/0 = 0 16:7/0 = 0
16:7/0/physics_layer_0/polygon_0/points = PackedVector2Array(-8, -8, 8, -8, 8, 8, -8, 8)
[sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_bqb68"] [sub_resource type="TileSetAtlasSource" id="TileSetAtlasSource_bqb68"]
texture = ExtResource("3_2vnky") texture = ExtResource("3_2vnky")
@ -1800,6 +1910,9 @@ separation = Vector2i(1, 1)
26:17/0 = 0 26:17/0 = 0
[resource] [resource]
physics_layer_0/collision_layer = 2
physics_layer_0/collision_mask = 7
physics_layer_0/physics_material = SubResource("PhysicsMaterial_xvv1l")
sources/0 = SubResource("TileSetAtlasSource_0netd") sources/0 = SubResource("TileSetAtlasSource_0netd")
sources/4 = SubResource("TileSetAtlasSource_06fw3") sources/4 = SubResource("TileSetAtlasSource_06fw3")
sources/1 = SubResource("TileSetAtlasSource_2cwrk") sources/1 = SubResource("TileSetAtlasSource_2cwrk")

File diff suppressed because one or more lines are too long

9
scenes/第二章.tscn Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,118 @@
using Godot;
namespace Milimoe.GodotGame
{
public partial class CameraFight : Camera2D
{
[Export]
public float MoveSpeed = 200f;
[Export]
public TileMapLayer BattleTileLayer;
public override void _Ready()
{
// 默认关闭处理,只有进入战斗信号触发后才开启
SetPhysicsProcess(false);
}
public override void _PhysicsProcess(double delta)
{
// 这里的控制逻辑和角色类似,但作用于摄像机
Vector2 inputDir = Input.GetVector("move_left", "move_right", "move_up", "move_down");
if (inputDir != Vector2.Zero)
{
Vector2 targetPos = GlobalPosition + inputDir * MoveSpeed * (float)delta;
// 获取带缩放的屏幕尺寸
Vector2 viewSize = GetViewportRect().Size / Zoom;
Vector2 halfView = viewSize / 2;
// --- 核心修复逻辑 ---
// 1. 处理 X 轴
float minX = LimitLeft + halfView.X;
float maxX = LimitRight - halfView.X;
if (minX <= maxX)
{
// 如果地图够大,正常限位
targetPos.X = Mathf.Clamp(targetPos.X, minX, maxX);
}
else
{
// 如果地图比屏幕窄,强行居中,防止报错
targetPos.X = (LimitLeft + LimitRight) / 2f;
}
// 2. 处理 Y 轴
float minY = LimitTop + halfView.Y;
float maxY = LimitBottom - halfView.Y;
if (minY <= maxY)
{
targetPos.Y = Mathf.Clamp(targetPos.Y, minY, maxY);
}
else
{
// 如果地图比屏幕短,强行居中
targetPos.Y = (LimitTop + LimitBottom) / 2f;
}
GlobalPosition = targetPos;
}
// (可选) 按下某个键退出战斗模式
if (Input.IsActionJustPressed("ui_cancel"))
{
ExitBattleMode();
}
}
public void ExitBattleMode()
{
AudioStreamPlayer FightMusic = GetParent().GetNode<AudioStreamPlayer>("FightMusic");
FightMusic.Stop();
AudioStreamPlayer MapMusic = GetParent().GetNode<AudioStreamPlayer>("MapMusic");
if (MapMusic.StreamPaused)
{
MapMusic.StreamPaused = false;
}
SetPhysicsProcess(false);
GameConstant.Pause = false;
// 切换回角色的摄像机(假设角色下有个 Camera2D
GetParent().GetNode<Camera2D>("Player/Camera2D").MakeCurrent();
Enabled = false;
}
public void UpdateLimitsFromTileMap()
{
if (BattleTileLayer is null) return;
// 1. 定义你的格子坐标
Vector2I cellTopLeft = new(88, 4);
Vector2I cellBottomRight = new(115, 15);
// 2. 获取 Tile 的大小 (通常是 16x16 或 32x32)
Vector2I tileSize = BattleTileLayer.TileSet.TileSize;
// 3. 计算像素坐标
// MapToLocal 返回的是格子的中心点,所以我们要减去/加上半个 Tile 大小来对齐边缘
Vector2 topLeftPixel = BattleTileLayer.MapToLocal(cellTopLeft) - (Vector2)tileSize / 2;
Vector2 bottomRightPixel = BattleTileLayer.MapToLocal(cellBottomRight) + (Vector2)tileSize / 2;
// 4. 如果你的 TileMapLayer 本身有位移或缩放,需要转为全局坐标
Vector2 globalTopLeft = BattleTileLayer.ToGlobal(topLeftPixel);
Vector2 globalBottomRight = BattleTileLayer.ToGlobal(bottomRightPixel);
// 5. 设置摄像机界限
LimitLeft = (int)globalTopLeft.X;
LimitTop = (int)globalTopLeft.Y;
LimitRight = (int)globalBottomRight.X;
LimitBottom = (int)globalBottomRight.Y;
GD.Print($"摄像机界限已设置:左{LimitLeft}, 上{LimitTop}, 右{LimitRight}, 下{LimitBottom}");
}
}
}

View File

@ -0,0 +1 @@
uid://ck6sos4ntuxbs

View File

@ -3,7 +3,7 @@ using Godot;
namespace Milimoe.GodotGame; namespace Milimoe.GodotGame;
public partial class ChapterScene : Node2D, INovelEndEvent, IMenuObject, IFadeInFadeOutBlack public partial class ChapterScene : Node2D, INovelStartEvent, INovelEndEvent, IMenuObject, IFadeInFadeOutBlack
{ {
[Export] [Export]
public PackedScene NovelScene { get; set; } public PackedScene NovelScene { get; set; }
@ -26,17 +26,81 @@ public partial class ChapterScene : Node2D, INovelEndEvent, IMenuObject, IFadeIn
[Export] [Export]
public string SceneName { get; set; } public string SceneName { get; set; }
[Export]
public CameraFight CameraFight { get; set; }
[Export]
public CharacterBody Player { get; set; }
[Export]
public PackedScene Fighting { get; set; }
public string NovelNodeKey { get; set; } = "";
private CanvasLayer _novelCanvasLayer; private CanvasLayer _novelCanvasLayer;
private CanvasLayer _menuCanvasLayer; private CanvasLayer _menuCanvasLayer;
private Node _novelInterface; private Node _novelInterface;
private Node _menuInterface; private Node _menuInterface;
private AudioStreamPlayer _buttonPlayer;
private AudioStreamPlayer _selectPlayer;
private AudioStreamPlayer _enterFightPlayer;
private Node _fighting;
private UserInterface _userInterface;
public override async void _Ready() public override async void _Ready()
{ {
GameConstant.ChapterInGame = ChapterInGame; _buttonPlayer = GetNode<AudioStreamPlayer>("ButtonPlayer");
GameConstant.AreaInGame = AreaInGame; _selectPlayer = GetNode<AudioStreamPlayer>("SelectPlayer");
GameConstant.NovelName = NovelName; _enterFightPlayer = GetNode<AudioStreamPlayer>("EnterFightPlayer");
GameConstant.SceneName = SceneName; if (UI.GetNode<Control>("UserInterface") is UserInterface userInterface)
{
_userInterface = userInterface;
}
GameConstant.InitGame();
Player.BattleStarted += OnBattleStarted;
// 实例化菜单界面场景
if (MenuScene != null)
{
_menuCanvasLayer = GetNode<CanvasLayer>("Menu");
_menuCanvasLayer.Visible = false;
_menuInterface = MenuScene.Instantiate();
if (_menuInterface is MenuController menuController)
{
menuController.Parent = this;
}
_menuCanvasLayer.AddChild(_menuInterface);
}
OnNovelStart(ChapterInGame, AreaInGame, NovelName, SceneName, NovelNodeKey);
}
public override void _Input(InputEvent @event)
{
if (@event.IsActionPressed("toggle_fight_log"))
{
ToggleFightLog();
}
if (@event is InputEventKey keyEvent)
{
if (keyEvent.Pressed && keyEvent.Keycode == Key.Escape)
{
if (_menuCanvasLayer != null)
{
ChangeState();
}
}
}
}
public async void OnNovelStart(string chapter_in_game, string area_in_game, string novel_name, string scene_name, string node_key = "")
{
GameConstant.Pause = true;
GameConstant.ChapterInGame = chapter_in_game;
GameConstant.AreaInGame = area_in_game;
GameConstant.NovelName = novel_name;
GameConstant.SceneName = scene_name;
_novelCanvasLayer = GetNode<CanvasLayer>("Novel"); _novelCanvasLayer = GetNode<CanvasLayer>("Novel");
_novelCanvasLayer.Visible = true; _novelCanvasLayer.Visible = true;
@ -56,37 +120,10 @@ public partial class ChapterScene : Node2D, INovelEndEvent, IMenuObject, IFadeIn
novelController.MenuObject = this; novelController.MenuObject = this;
novelController.FadeObject = this; novelController.FadeObject = this;
await FadeOutBlack(1f, true); await FadeOutBlack(1f, true);
novelController.InitNovel(NovelName, SceneName); novelController.InitNovel(novel_name, scene_name, node_key);
GameConstant.AutoSave(0); GameConstant.AutoSave(0);
} }
} }
// 实例化菜单界面场景
if (MenuScene != null)
{
_menuCanvasLayer = GetNode<CanvasLayer>("Menu");
_menuCanvasLayer.Visible = false;
_menuInterface = MenuScene.Instantiate();
if (_menuInterface is MenuController menuController)
{
menuController.Parent = this;
}
_menuCanvasLayer.AddChild(_menuInterface);
}
}
public override void _Input(InputEvent @event)
{
if (@event is InputEventKey keyEvent)
{
if (keyEvent.Pressed && keyEvent.Keycode == Key.Escape)
{
if (_menuCanvasLayer != null)
{
ChangeState();
}
}
}
} }
public async void OnNovelEnd(CanvasLayer node, string novel_name, string scene_name) public async void OnNovelEnd(CanvasLayer node, string novel_name, string scene_name)
@ -97,21 +134,36 @@ public partial class ChapterScene : Node2D, INovelEndEvent, IMenuObject, IFadeIn
await FadeOutBlack(0.5f, true); await FadeOutBlack(0.5f, true);
if (UI != null) if (UI != null)
{ {
GameConstant.Pause = false;
UI.Visible = true; UI.Visible = true;
if (UI.GetNode<Control>("UserInterface") is UserInterface userInterface) if (UI.GetNode<Control>("UserInterface") is UserInterface userInterface)
{ {
if (GameConstant.Characters.Count == 1) if (userInterface.Location != null)
{ {
userInterface.CharacterStatus1.Visible = true; userInterface.Location.Text = GameConstant.AreaInGame;
TextureRect image = userInterface.CharacterStatus1.GetNode<TextureRect>("Image");
using Texture2D texture = GD.Load<CompressedTexture2D>("res://assets/character/雷恩.png");
image.Texture = texture;
} }
else if (GameConstant.Characters.Count == 2) if (userInterface.Rayne is CharacterStatus cs1)
{ {
userInterface.CharacterStatus1.Visible = true; cs1.UpdateLabel();
userInterface.CharacterStatus2.Visible = true;
} }
if (userInterface.Irene is CharacterStatus cs2)
{
cs2.UpdateLabel();
}
userInterface.FightLog.Visible = false;
userInterface.RoundQueue.Visible = false;
//if (GameConstant.Characters.Count == 1)
//{
// userInterface.CharacterStatus1.Visible = true;
// TextureRect image = userInterface.CharacterStatus1.GetNode<TextureRect>("Image");
// using Texture2D texture = GD.Load<CompressedTexture2D>("res://assets/character/雷恩.png");
// image.Texture = texture;
//}
//else if (GameConstant.Characters.Count == 2)
//{
// userInterface.CharacterStatus1.Visible = true;
// userInterface.CharacterStatus2.Visible = true;
//}
} }
} }
} }
@ -148,4 +200,153 @@ public partial class ChapterScene : Node2D, INovelEndEvent, IMenuObject, IFadeIn
_menuCanvasLayer.Visible = !_menuCanvasLayer.Visible; _menuCanvasLayer.Visible = !_menuCanvasLayer.Visible;
} }
} }
private async void OnBattleStarted(CharacterBody2D player, CharacterBody2D enemy)
{
EnemyBody enemyBody = null;
if (enemy is EnemyBody body)
{
enemyBody = body;
enemyBody.Enabled = false;
}
GD.Print("信号已接收:开始切换至战斗摄像机");
GameConstant.Pause = true;
Camera2D Camera = GetNode<Camera2D>("Player/Camera2D");
Vector2 targetZoom = Camera.Zoom;
CanvasLayer ColorRectCanvasLayer = GetNode<CanvasLayer>("ColorRectCanvasLayer");
ColorRectCanvasLayer.Visible = true;
ColorRect BlurOverlay = ColorRectCanvasLayer.GetNode<ColorRect>("BlurOverlay");
_enterFightPlayer.Play();
GetNode<AnimationPlayer>("战斗提示动画").Play("fight_start");
PlayZoomBlurTransition(Camera, BlurOverlay);
Engine.TimeScale = 0.05f;
ShakeCamera(Camera, 0.2f, 35.0f);
await Task.Delay(1000);
Engine.TimeScale = 1.0f;
AudioStreamPlayer MapMusic = GetNode<AudioStreamPlayer>("MapMusic");
if (MapMusic.Playing)
{
MapMusic.StreamPaused = true;
}
AudioStreamPlayer FightMusic = GetNode<AudioStreamPlayer>("FightMusic");
FightMusic.Play();
FightMusic.StreamPaused = false;
Vector2I battleStartCell = new(100, 10);
// 如果 player 脚本里实现了上面的 TeleportToTile
if (player is CharacterBody myPlayer)
{
myPlayer.TeleportToTile(GetNode<TileMapLayer>("TileMapLayer"), battleStartCell);
}
// 切换当前摄像机
if (CameraFight != null)
{
CameraFight.Enabled = true;
CameraFight.UpdateLimitsFromTileMap();
CameraFight.MakeCurrent();
// 激活摄像机的移动逻辑
CameraFight.SetPhysicsProcess(true);
}
_fighting = Fighting.Instantiate();
Panel fightLog = null;
UserInterface userInterface = null;
if (UI.GetNode<Control>("UserInterface") is UserInterface tempUI)
{
userInterface = tempUI;
userInterface.Location.Text = "";
fightLog = userInterface.FightLog;
fightLog.Visible = true;
userInterface.RoundQueue.Visible = true;
}
GetTree().CreateTween().TweenProperty(Camera, "zoom", targetZoom, 0.2f);
ColorRectCanvasLayer.Visible = false;
if (_fighting is Fighting fighting)
{
fighting.ParentUI = this;
fighting.TileMapLayer = GetNode<TileMapLayer>("TileMapLayer");
fighting.CameraFight = CameraFight;
fighting.Character = GameConstant.Characters[1];
fighting.FightLog = fightLog?.GetNode<RichTextLabel>("RichTextLabel");
fighting.StartCell = battleStartCell;
fighting.Enemy = enemyBody;
await fighting.StartGame(false, true);
// 战斗结束恢复场景
if (enemyBody != null && enemyBody.Dead && IsInstanceValid(enemy))
{
enemy.QueueFree();
}
CameraFight?.ExitBattleMode();
if (player is CharacterBody myPlayer2)
{
myPlayer2.ReturnToSavedPosition();
}
if (userInterface != null)
{
userInterface.Location.Text = GameConstant.AreaInGame;
userInterface.FightLog.Visible = false;
userInterface.RoundQueue.Visible = false;
}
}
}
private void ShakeCamera(Camera2D camera, float duration, float intensity)
{
Tween tween = GetTree().CreateTween();
for (int i = 0; i < 5; i++)
{
Vector2 randomOffset = new(
(float)GD.RandRange(-intensity, intensity),
(float)GD.RandRange(-intensity, intensity)
);
// 快速来回摆动
tween.TweenProperty(camera, "offset", randomOffset, duration / 5);
}
// 最后归位
tween.TweenProperty(camera, "offset", Vector2.Zero, 0.5f);
}
private void PlayZoomBlurTransition(Camera2D camera, ColorRect BlurOverlay)
{
// 确保模糊层可见
BlurOverlay.Visible = true;
ShaderMaterial mat = BlurOverlay.Material as ShaderMaterial;
// 创建补间动画
Tween tween = GetTree().CreateTween();
tween.SetIgnoreTimeScale(true);
// 设置并行播放,让拉近和模糊同时发生
tween.SetParallel(true);
// 1. 镜头拉近动画 (ExpoOut 效果最像“冲刺”)
Vector2 targetZoom = camera.Zoom * 1.5f;
tween.TweenProperty(camera, "zoom", targetZoom, 0.3f)
.SetTrans(Tween.TransitionType.Expo)
.SetEase(Tween.EaseType.Out);
// 2. Shader 模糊强度动画
tween.TweenMethod(Callable.From<float>((val) => {
mat.SetShaderParameter("blur_amount", val);
}), 0.0f, 5f, 0.2f);
// 3. (可选) 稍微等待一下后,执行下一步逻辑
tween.Chain().SetParallel(false);
tween.TweenCallback(Callable.From(() => {
GD.Print("拉近完成切换到战斗UI或开始战斗");
}));
}
private void ToggleFightLog()
{
if (_userInterface != null && _userInterface.FightLog != null)
{
// 这一行代码就能实现“可见”与“不可见”的快速取反
_userInterface.FightLog.Visible = !_userInterface.FightLog.Visible;
GD.Print($"战斗日志状态: {(_userInterface.FightLog.Visible ? "" : "")}");
}
}
} }

View File

@ -1,14 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Xml.Linq;
using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
using Oshima.FunGame.OshimaModules;
using Oshima.FunGame.OshimaModules.Models;
namespace Milimoe.GodotGame namespace Milimoe.GodotGame
{ {
public class GameConstant public class GameConstant
{ {
public static bool Initialized { get; set; } = false;
public static bool Pause { get; set; } = false;
public static Dictionary<long, Character> Characters { get; set; } = []; public static Dictionary<long, Character> Characters { get; set; } = [];
public static Dictionary<Character, Region> CharacterInRegion { get; set; } = []; public static Dictionary<Character, Region> CharacterInRegion { get; set; } = [];
public static Dictionary<long, Region> Regions { get; set; } = []; public static Dictionary<long, Region> Regions { get; set; } = [];
@ -17,14 +20,28 @@ namespace Milimoe.GodotGame
public static string NovelName { get; set; } = ""; public static string NovelName { get; set; } = "";
public static string SceneName { get; set; } = ""; public static string SceneName { get; set; } = "";
public static string NovelNodeKey { get; set; } = ""; public static string NovelNodeKey { get; set; } = "";
public static CharacterModule CharacterModule { get; set; } = new();
public static SkillModule SkillModule { get; set; } = new();
public static ItemModule ItemModule { get; set; } = new();
public static void InitGame() public static void InitGame()
{ {
if (Initialized)
{
return;
}
Initialized = true;
FunGameConstant.InitFunGame();
CharacterModule.Load();
SkillModule.Load();
ItemModule.Load();
General.GameplayEquilibriumConstant.MaxLevel = 100;
Character character = Factory.GetCharacter(); Character character = Factory.GetCharacter();
character.Id = 1; character.Id = 1;
character.Name = "雷恩"; character.Name = "雷恩";
character.FirstName = "Rayne"; character.FirstName = "";
character.NickName = "雷恩"; character.NickName = "Rayne";
character.PrimaryAttribute = PrimaryAttribute.AGI; character.PrimaryAttribute = PrimaryAttribute.AGI;
character.InitialATK = 21; character.InitialATK = 21;
character.InitialHP = 120; character.InitialHP = 120;
@ -38,12 +55,14 @@ namespace Milimoe.GodotGame
character.InitialSPD = 300; character.InitialSPD = 300;
character.InitialHR = 4; character.InitialHR = 4;
character.InitialMR = 2; character.InitialMR = 2;
character.Level = 100;
character.Recovery();
Characters.Add(character.Id, character); Characters.Add(character.Id, character);
character = Factory.GetCharacter(); character = Factory.GetCharacter();
character.Id = 2; character.Id = 2;
character.Name = "艾琳"; character.Name = "艾琳";
character.FirstName = "Irene"; character.FirstName = "";
character.NickName = "艾琳"; character.NickName = "Irene";
character.PrimaryAttribute = PrimaryAttribute.INT; character.PrimaryAttribute = PrimaryAttribute.INT;
character.InitialATK = 17; character.InitialATK = 17;
character.InitialHP = 110; character.InitialHP = 110;
@ -57,6 +76,8 @@ namespace Milimoe.GodotGame
character.InitialSPD = 270; character.InitialSPD = 270;
character.InitialHR = 4; character.InitialHR = 4;
character.InitialMR = 2; character.InitialMR = 2;
character.Level = 100;
character.Recovery();
Characters.Add(character.Id, character); Characters.Add(character.Id, character);
Region region = new() Region region = new()
{ {

View File

@ -0,0 +1,33 @@
using Godot;
namespace Milimoe.GodotGame;
public class SceneSwitcher
{
public static void ChangeSceneWithSetup<T>(Node node, string scenePath, System.Action<T> setupAction = null) where T : Node
{
PackedScene packedScene = GD.Load<PackedScene>(scenePath);
if (packedScene == null)
{
GD.PrintErr($"场景加载失败: {scenePath}");
return;
}
T newRoot = packedScene.Instantiate<T>();
// 在这里执行你的初始化逻辑
setupAction?.Invoke(newRoot);
// 切换
SceneTree tree = node.GetTree();
Node oldScene = tree.CurrentScene;
if (oldScene != null)
{
tree.Root.RemoveChild(oldScene);
oldScene.QueueFree();
}
tree.Root.AddChild(newRoot);
tree.CurrentScene = newRoot;
}
}

View File

@ -0,0 +1 @@
uid://d2ekruse5iuq7

View File

@ -8,7 +8,48 @@ namespace Milimoe.GodotGame
/// 移动速度 (像素/秒) /// 移动速度 (像素/秒)
/// </summary> /// </summary>
[Export] [Export]
public float Speed = 200.0f; public float Speed = 100f;
/// <summary>
/// 加速度 (像素/秒^2) - 控制从静止加速到最大速度的快慢
/// 值越大,加速越快,惯性越小。
/// </summary>
[Export]
public float Acceleration = 500f;
/// <summary>
/// 减速度 (像素/秒^2) - 控制从运动减速到静止的快慢
/// 值越大,减速越快,惯性越小。
/// 通常减速度可以比加速度大,让停止更迅速。
/// </summary>
[Export]
public float Deceleration = 800f;
/// <summary>
/// 静止图片
/// </summary>
[Export]
public Texture2D IdleTexture;
/// <summary>
/// 行走图片
/// </summary>
[Export]
public Texture2D WalkTexture;
/// <summary>
/// 精灵节点
/// </summary>
[Export]
public AnimatedSprite2D AnimatedSprite2D;
/// <summary>
/// 战斗开始信号
/// </summary>
/// <param name="player"></param>
/// <param name="enemy"></param>
[Signal]
public delegate void BattleStartedEventHandler(CharacterBody2D player, CharacterBody2D enemy);
/// <summary> /// <summary>
/// _PhysicsProcess 是 Godot 进行物理计算和运动更新的函数 /// _PhysicsProcess 是 Godot 进行物理计算和运动更新的函数
@ -16,47 +57,131 @@ namespace Milimoe.GodotGame
/// <param name="delta"></param> /// <param name="delta"></param>
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
{ {
// --- 1. 获取输入向量 --- if (GameConstant.Pause)
{
return;
}
// 获取输入向量
// 获取水平输入轴的值 (-1 到 1) // 获取水平输入轴的值 (-1 到 1)
float inputX = Input.GetAxis("move_left", "move_right"); float inputX = Input.GetAxis("move_left", "move_right");
// 获取垂直输入轴的值 (-1 到 1) // 获取垂直输入轴的值 (-1 到 1)
// 你需要在项目设置 -> Input Map 中设置 "move_up" 和 "move_down" 动作,
// 并绑定相应的按键(如 W/上箭头 和 S/下箭头)。
float inputY = Input.GetAxis("move_up", "move_down"); float inputY = Input.GetAxis("move_up", "move_down");
// 创建一个表示输入方向的向量 // 创建一个表示输入方向的向量
Vector2 inputVector = new Vector2(inputX, inputY); Vector2 inputVector = new(inputX, inputY);
// --- 2. 计算目标速度 --- // 目标速度
Vector2 targetVelocity; Vector2 targetVelocity;
// 当前帧应该使用的加速度/减速度
float currentAcceleration;
// 检查是否有输入 if (inputVector.LengthSquared() > 0)
if (inputVector.LengthSquared() > 0) // 使用 LengthSquared() 比 Length() 性能稍好只需要判断是否大于0
{ {
// 如果有输入,将输入向量标准化 (避免对角线移动过快) // 有输入时,目标速度是输入方向乘以最大速度
// 然后乘以速度得到目标速度
targetVelocity = inputVector.Normalized() * Speed; targetVelocity = inputVector.Normalized() * Speed;
// 使用加速度
currentAcceleration = Acceleration;
} }
else else
{ {
// 如果没有输入,目标速度为零 (停止) // 没有输入时,目标速度是零
targetVelocity = Vector2.Zero; targetVelocity = Vector2.Zero;
// 使用减速度
currentAcceleration = Deceleration;
} }
// --- 3. 平滑过渡到目标速度 ---
// 使用 Mathf.MoveToward 平滑地改变当前速度到目标速度 // 使用 Mathf.MoveToward 平滑地改变当前速度到目标速度
// 这样角色移动和停止会更平滑,而不是瞬间加速/停止 Velocity = Velocity.MoveToward(targetVelocity, currentAcceleration * (float)delta);
// 这里的 Speed 用作最大步长确保在1秒内能达到最大速度如果 delta 累积到1
Velocity = Velocity.MoveToward(targetVelocity, Speed * (float)delta);
// --- 4. 调用 MoveAndSlide() --- // 处理与墙壁、障碍物等的碰撞,阻止角色穿过它们
// 这是关键步骤!它会根据当前的 Velocity 向量移动 CharacterBody2D
// 并自动处理与场景中其他碰撞体的碰撞。
// 在俯视角游戏中MoveAndSlide() 会处理与墙壁、障碍物等的碰撞,阻止角色穿过它们。
MoveAndSlide(); MoveAndSlide();
// --- 5. (可选) 其他逻辑 --- UpdateAnimation();
// 你可以在这里添加其他逻辑,比如播放动画、处理交互等。
for (int i = 0; i < GetSlideCollisionCount(); i++)
{
KinematicCollision2D collision = GetSlideCollision(i);
GodotObject collider = collision.GetCollider();
if (collider is EnemyBody enemy && enemy.Enabled && !enemy.Dead && enemy.CollisionLayer == 4)
{
GameConstant.Pause = true;
EmitSignal(SignalName.BattleStarted, this, enemy);
break;
}
}
}
/// <summary>
/// 根据速度更新贴图
/// </summary>
private void UpdateAnimation()
{
if (AnimatedSprite2D == null) return;
// 获取当前实时速度的长度
float currentSpeed = Velocity.Length();
if (currentSpeed > 0.1f) // 如果正在移动
{
// 播放行走动画
if (AnimatedSprite2D.Animation != "walk")
{
AnimatedSprite2D.Play("walk");
}
// --- 核心算法:动画速度匹配 ---
// 计算比例:当前速度越快,动画播得越快
// 1.2f 是一个“手感系数”,如果觉得脚还是打滑,就调大这个值
float speedFactor = currentSpeed / Speed;
AnimatedSprite2D.SpeedScale = speedFactor * 5f;
// 处理左右翻转
if (Velocity.X != 0)
{
AnimatedSprite2D.FlipH = Velocity.X < 0;
}
}
else // 停止移动
{
AnimatedSprite2D.Play("idle");
AnimatedSprite2D.SpeedScale = 1.0f; // 回归正常倍率
}
}
// 用于存储返回时的位置
private Vector2 _savedOverworldPosition;
/// <summary>
/// 记录当前位置并传送到指定的 Tile 坐标
/// </summary>
/// <param name="targetLayer">目标 TileMapLayer</param>
/// <param name="tileCoords">目标格子坐标 (例如 new Vector2I(88, 4))</param>
public void TeleportToTile(TileMapLayer targetLayer, Vector2I tileCoords)
{
// 1. 记录当前的绝对坐标 (用于战斗结束后传回来)
_savedOverworldPosition = this.GlobalPosition;
GD.Print($"已记录当前位置: {_savedOverworldPosition}");
// 2. 将 Tile 坐标转换为该图层的本地像素坐标
// MapToLocal 返回的是该格子中心的相对坐标
Vector2 localPos = targetLayer.MapToLocal(tileCoords);
// 3. 将本地坐标转换为全局绝对坐标
Vector2 globalPos = targetLayer.ToGlobal(localPos);
// 4. 设置角色的全局位置(实现瞬移)
this.GlobalPosition = globalPos;
GD.Print($"角色已传送到 Tile {tileCoords},绝对坐标为: {globalPos}");
}
/// <summary>
/// 返回之前记录的位置
/// </summary>
public void ReturnToSavedPosition()
{
this.GlobalPosition = _savedOverworldPosition;
} }
} }
} }

View File

@ -0,0 +1,16 @@
using Godot;
using Milimoe.FunGame.Core.Entity;
namespace Milimoe.GodotGame
{
public partial class EnemyBody : CharacterBody2D
{
[Export]
public bool Enabled { get; set; } = true;
[Export]
public bool Dead { get; set; } = false;
public Character[] Characters { get; set; } = [];
}
}

View File

@ -0,0 +1 @@
uid://dxcfxeuwvl32l

View File

@ -0,0 +1,65 @@
using Godot;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.GodotGame
{
public partial class CharacterStatus : Panel
{
[Export]
public long CharacterId { get; set; }
[Export]
public TextureRect Image { get; set; }
[Export]
public ProgressBar HPBar { get; set; }
[Export]
public ProgressBar MPBar { get; set; }
[Export]
public ProgressBar EPBar { get; set; }
[Export]
public Label HP { get; set; }
[Export]
public Label MP { get; set; }
[Export]
public Label EP { get; set; }
[Export]
public Label Level { get; set; }
public void UpdateLabel()
{
if (CharacterId == 1)
{
HPBar.MaxValue = GameConstant.Characters[1].MaxHP;
HPBar.Value = GameConstant.Characters[1].HP;
MPBar.MaxValue = GameConstant.Characters[1].MaxMP;
MPBar.Value = GameConstant.Characters[1].MP;
EPBar.MaxValue = General.GameplayEquilibriumConstant.MaxEP;
EPBar.Value = GameConstant.Characters[1].EP;
HP.Text = $"{GameConstant.Characters[1].HP:0.##} / {GameConstant.Characters[1].MaxHP:0.##}";
MP.Text = $"{GameConstant.Characters[1].MP:0.##} / {GameConstant.Characters[1].MaxMP:0.##}";
EP.Text = $"{GameConstant.Characters[1].EP:0.##} / {General.GameplayEquilibriumConstant.MaxEP:0.##}";
Level.Text = GameConstant.Characters[1].ToStringWithLevelWithOutUser();
}
else if (CharacterId == 2)
{
HPBar.MaxValue = GameConstant.Characters[2].MaxHP;
HPBar.Value = GameConstant.Characters[2].HP;
MPBar.MaxValue = GameConstant.Characters[2].MaxMP;
MPBar.Value = GameConstant.Characters[2].MP;
EPBar.MaxValue = General.GameplayEquilibriumConstant.MaxEP;
EPBar.Value = GameConstant.Characters[2].EP;
HP.Text = $"{GameConstant.Characters[2].HP:0.##} / {GameConstant.Characters[2].MaxHP:0.##}";
MP.Text = $"{GameConstant.Characters[2].MP:0.##} / {GameConstant.Characters[2].MaxMP:0.##}";
EP.Text = $"{GameConstant.Characters[2].EP:0.##} / {General.GameplayEquilibriumConstant.MaxEP:0.##}";
Level.Text = GameConstant.Characters[2].ToStringWithLevelWithOutUser();
}
}
}
}

View File

@ -0,0 +1 @@
uid://ne34ebenkjmd

View File

@ -0,0 +1,9 @@
using Godot;
namespace Milimoe.GodotGame
{
public interface INovelStartEvent
{
public void OnNovelStart(string chapter_in_game, string area_in_game, string novel_name, string scene_name, string node_key = "");
}
}

View File

@ -0,0 +1 @@
uid://ci2ps8uimid7x

View File

@ -40,8 +40,10 @@ public partial class NovelController : CanvasLayer, ISaveSelectionEvent
private Button _load; private Button _load;
private Button _save; private Button _save;
private Button _menu; private Button _menu;
private AudioStreamPlayer _buttonPlayer;
private AudioStreamPlayer _selectPlayer;
public override void _Ready() public override void _Ready()
{ {
Visible = false; Visible = false;
_portrait1 = GetNode<TextureRect>("立绘1"); _portrait1 = GetNode<TextureRect>("立绘1");
@ -64,47 +66,83 @@ public partial class NovelController : CanvasLayer, ISaveSelectionEvent
if (_colorRect != null) if (_colorRect != null)
{ {
_colorRect.GuiInput += ColorRect_GuiInput; _colorRect.GuiInput += ColorRect_GuiInput;
} }
_autoPlay = GetNode<Button>("自动播放"); _buttonPlayer = GetNode<AudioStreamPlayer>("ButtonPlayer");
_selectPlayer = GetNode<AudioStreamPlayer>("SelectPlayer");
_autoPlay = GetNode<Button>("自动播放");
_load = GetNode<Button>("读取存档"); _load = GetNode<Button>("读取存档");
_save = GetNode<Button>("保存存档"); _save = GetNode<Button>("保存存档");
_menu = GetNode<Button>("游戏菜单"); _menu = GetNode<Button>("游戏菜单");
if (_autoPlay != null) if (_autoPlay != null)
{ {
_autoPlay.Pressed += () => Automatic = _autoPlay.ButtonPressed; _autoPlay.MouseEntered += () => _buttonPlayer?.Play();
_autoPlay.Pressed += () =>
{
_selectPlayer?.Play();
Automatic = _autoPlay.ButtonPressed;
if (!_content_richLabel.IsAnimationRunning)
{
NovelNode next = Current.Next;
if (next != null)
{
ShowNode(next);
}
else
{
GameConstant.NovelNodeKey = "$nothing";
ChapterObject.OnNovelEnd(this, NovelName, SceneName);
}
}
};
} }
if (_load != null) if (_load != null)
{ {
_load.Pressed += () => OnLoadSaveButtonPressed(false); _load.MouseEntered += () => _buttonPlayer?.Play();
_load.Pressed += () => OnLoadSaveButtonPressed(false);
} }
if (_save != null) if (_save != null)
{ {
_save.Pressed += () => OnLoadSaveButtonPressed(true); _save.MouseEntered += () => _buttonPlayer?.Play();
_save.Pressed += () => OnLoadSaveButtonPressed(true);
} }
if (_menu != null) if (_menu != null)
{ {
_menu.Pressed += OnMenuButtonPressed; _menu.MouseEntered += () => _buttonPlayer?.Play();
} _menu.Pressed += OnMenuButtonPressed;
} }
}
public void InitNovel(string novel_name, string scene_name) public void InitNovel(string novel_name, string scene_name, string node_key = "")
{ {
NovelName = novel_name; NovelName = novel_name;
SceneName = scene_name; SceneName = scene_name;
if (NovelName != "" && SceneName != "") if (NovelName != "" && SceneName != "")
{ {
NovelConfig ??= NovelConfig.LoadFrom(ProjectSettings.GlobalizePath("res://resources/novels/第一章/场景一.json"), NovelName, false); NovelConfig ??= NovelConfig.LoadFrom(ProjectSettings.GlobalizePath("res://resources/novels/第一章/场景一.json"), NovelName, false);
if (NovelConfig.Count > 0) if (node_key != "$nothing")
{ {
ShowNode(NovelConfig.Values.First()); if (node_key != "" && NovelConfig.Values.FirstOrDefault(node => node.Key == node_key) is NovelNode node)
} {
} ShowNode(node);
}
else if (NovelConfig.Count > 0)
{
ShowNode(NovelConfig.Values.First());
}
}
else
{
GameConstant.NovelNodeKey = "$nothing";
ChapterObject.OnNovelEnd(this, NovelName, SceneName);
}
}
} }
public void ShowNode(NovelNode node) public void ShowNode(NovelNode node)
{ {
if (node != null) if (node != null)
{ {
_buttonPlayer?.Play();
GameConstant.NovelName = NovelName; GameConstant.NovelName = NovelName;
GameConstant.SceneName = SceneName; GameConstant.SceneName = SceneName;
GameConstant.NovelNodeKey = node.Key; GameConstant.NovelNodeKey = node.Key;
@ -173,7 +211,8 @@ public partial class NovelController : CanvasLayer, ISaveSelectionEvent
} }
else else
{ {
ChapterObject.OnNovelEnd(this, NovelName, SceneName); GameConstant.NovelNodeKey = "$nothing";
ChapterObject.OnNovelEnd(this, NovelName, SceneName);
} }
} }
} }
@ -187,8 +226,9 @@ public partial class NovelController : CanvasLayer, ISaveSelectionEvent
} }
public void OnOptionButtonClick(NovelOption option) public void OnOptionButtonClick(NovelOption option)
{ {
if (option != null && option.Targets.Count > 0) _selectPlayer?.Play();
if (option != null && option.Targets.Count > 0)
{ {
NovelNode next = option.Targets.First(); NovelNode next = option.Targets.First();
ShowNode(next); ShowNode(next);
@ -217,8 +257,9 @@ public partial class NovelController : CanvasLayer, ISaveSelectionEvent
ShowNode(next); ShowNode(next);
} }
else else
{ {
ChapterObject.OnNovelEnd(this, NovelName, SceneName); GameConstant.NovelNodeKey = "$nothing";
ChapterObject.OnNovelEnd(this, NovelName, SceneName);
} }
} }
} }
@ -227,7 +268,9 @@ public partial class NovelController : CanvasLayer, ISaveSelectionEvent
private void OnLoadSaveButtonPressed(bool isSave) private void OnLoadSaveButtonPressed(bool isSave)
{ {
if (isSave) _selectPlayer?.Play();
if (isSave)
{ {
// 保存游戏 // 保存游戏
GD.Print("Save Game!"); GD.Print("Save Game!");
@ -250,6 +293,7 @@ public partial class NovelController : CanvasLayer, ISaveSelectionEvent
private void OnMenuButtonPressed() private void OnMenuButtonPressed()
{ {
_selectPlayer?.Play();
// 打开游戏菜单 // 打开游戏菜单
GD.Print("Open Game Menu!"); GD.Print("Open Game Menu!");
if (MenuObject is IMenuObject obj) if (MenuObject is IMenuObject obj)
@ -274,13 +318,18 @@ public partial class NovelController : CanvasLayer, ISaveSelectionEvent
{ {
// 载入游戏 // 载入游戏
GD.Print($"Selected Saved: {index}!"); GD.Print($"Selected Saved: {index}!");
Visible = false;
if (FadeObject != null) if (FadeObject != null)
{ {
await FadeObject.FadeInBlack(1f); await FadeObject.FadeInBlack(1f);
} }
else await Task.Delay(1000); InitNovel(GameConstant.NovelName, GameConstant.SceneName, GameConstant.NovelNodeKey);
GetTree().Quit(); if (FadeObject != null)
} {
await FadeObject.FadeOutBlack(1f);
}
//GetTree().Quit();
}
} }
else else
{ {

68
scripts/Other/GodotMap.cs Normal file
View File

@ -0,0 +1,68 @@
using System.Linq;
using Godot;
using Godot.Collections;
using Milimoe.FunGame.Core.Interface.Base;
using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Model;
namespace Milimoe.GodotGame
{
public class GodotMap(TileMapLayer layer) : GameMap
{
public override string Name => "GodotMap";
public override string Description => "Milimoe's Godot Map";
public override string Version => "1.0.0";
public override string Author => "Milimoe";
public override int Length => 26;
public override int Width => 10;
public override int Height => 1;
public override float Size => 16;
public TileMapLayer TileMapLayer { get; set; } = layer;
public Dictionary<long, Vector2I> GridToVector2I { get; set; } = [];
public override GameMap InitGamingQueue(IGamingQueue queue)
{
GodotMap map = new(TileMapLayer);
map.Load();
if (queue is GamingQueue gq)
{
gq.WriteLine($"地图 {map.Name} 已加载。");
}
// 绑定坐标数据
long gridId = 0;
for (int j = 5; j <= 14; j++)
{
for (int i = 89; i <= 114; i++)
{
if (Grids.ContainsKey(gridId))
{
Vector2I v = new(i, j);
GridToVector2I[gridId] = v;
}
}
}
return map;
}
public Vector2I GetVector2IByGrid(Grid grid)
{
return GridToVector2I.FirstOrDefault(kv => kv.Key == grid.Id).Value;
}
public Grid GetGridByVector2I(Vector2I vector)
{
return Grids[GridToVector2I.FirstOrDefault(kv => kv.Value.X == vector.X && kv.Value.Y == vector.Y).Key];
}
}
}

View File

@ -0,0 +1 @@
uid://cgy66iphui7lv

View File

@ -134,11 +134,7 @@ public partial class SavedNode : PanelContainer
private void LoadDialogConfirmed() private void LoadDialogConfirmed()
{ {
GD.Print("LoadDialogConfirmed"); Load();
if (Parent is ISaveSelectionEvent e)
{
e.OnSaveSelectionClosed(true, Index, IsSave);
}
} }
private void Save() private void Save()
@ -158,6 +154,27 @@ public partial class SavedNode : PanelContainer
} }
} }
private void Load()
{
GD.Print("LoadDialogConfirmed");
if (Parent is ISaveSelectionEvent e)
{
Config.LoadConfig();
GameConstant.ChapterInGame = Config.GetValue<string>("ChapterInGame");
GameConstant.AreaInGame = Config.GetValue<string>("AreaInGame");
GameConstant.NovelName = Config.GetValue<string>("NovelName");
GameConstant.SceneName = Config.GetValue<string>("SceneName");
GameConstant.NovelNodeKey = Config.GetValue<string>("NovelNodeKey");
GameConstant.Characters.Clear();
List<Character> characters = Config.Get<List<Character>>("Characters");
foreach (Character character in characters)
{
GameConstant.Characters.Add(character.Id, character);
}
e.OnSaveSelectionClosed(true, Index, IsSave);
}
}
public void ShowAlert(string message) public void ShowAlert(string message)
{ {
// 创建并配置 AcceptDialog // 创建并配置 AcceptDialog

View File

@ -26,8 +26,15 @@ public partial class TitleScreen : Node, ISaveSelectionEvent
[Export] [Export]
public SavedSelection SavedSelection; public SavedSelection SavedSelection;
[Export]
public AudioStreamPlayer ButtonPlayer;
[Export]
public AudioStreamPlayer SelectPlayer;
public override async void _Ready() public override async void _Ready()
{ {
GameConstant.InitGame();
ColorRect colorRect = GetNode<ColorRect>("ColorRect"); ColorRect colorRect = GetNode<ColorRect>("ColorRect");
colorRect.SelfModulate = new Color(0, 0, 0, 1); colorRect.SelfModulate = new Color(0, 0, 0, 1);
colorRect.Show(); colorRect.Show();
@ -35,21 +42,25 @@ public partial class TitleScreen : Node, ISaveSelectionEvent
// 检查按钮是否已连接 // 检查按钮是否已连接
if (StartGameButton != null) if (StartGameButton != null)
{ {
StartGameButton.MouseEntered += () => ButtonPlayer?.Play();
StartGameButton.Pressed += OnStartGameButtonPressed; StartGameButton.Pressed += OnStartGameButtonPressed;
} }
if (LoadGameButton != null) if (LoadGameButton != null)
{ {
LoadGameButton.MouseEntered += () => ButtonPlayer?.Play();
LoadGameButton.Pressed += OnLoadGameButtonPressed; LoadGameButton.Pressed += OnLoadGameButtonPressed;
} }
if (GameSettingsButton != null) if (GameSettingsButton != null)
{ {
GameSettingsButton.MouseEntered += () => ButtonPlayer?.Play();
GameSettingsButton.Pressed += OnGameSettingsButtonPressed; GameSettingsButton.Pressed += OnGameSettingsButtonPressed;
} }
if (ExitGameButton != null) if (ExitGameButton != null)
{ {
ExitGameButton.MouseEntered += () => ButtonPlayer?.Play();
ExitGameButton.Pressed += OnExitGameButtonPressed; ExitGameButton.Pressed += OnExitGameButtonPressed;
} }
@ -92,6 +103,7 @@ public partial class TitleScreen : Node, ISaveSelectionEvent
private void OnStartGameButtonPressed() private void OnStartGameButtonPressed()
{ {
SelectPlayer?.Play();
// 开始新游戏 // 开始新游戏
GD.Print("Start New Game!"); GD.Print("Start New Game!");
StartConfirmationDialog?.PopupCentered(); StartConfirmationDialog?.PopupCentered();
@ -99,6 +111,7 @@ public partial class TitleScreen : Node, ISaveSelectionEvent
private void OnLoadGameButtonPressed() private void OnLoadGameButtonPressed()
{ {
SelectPlayer?.Play();
// 载入游戏 // 载入游戏
GD.Print("Load Game!"); GD.Print("Load Game!");
@ -124,12 +137,14 @@ public partial class TitleScreen : Node, ISaveSelectionEvent
private void OnGameSettingsButtonPressed() private void OnGameSettingsButtonPressed()
{ {
SelectPlayer?.Play();
// 打开游戏设置 // 打开游戏设置
GD.Print("Open Game Settings!"); GD.Print("Open Game Settings!");
} }
private void OnExitGameButtonPressed() private void OnExitGameButtonPressed()
{ {
SelectPlayer?.Play();
// 退出游戏 // 退出游戏
if (ExitConfirmationDialog != null) if (ExitConfirmationDialog != null)
{ {
@ -159,8 +174,15 @@ public partial class TitleScreen : Node, ISaveSelectionEvent
// 载入游戏 // 载入游戏
GD.Print($"Selected Saved: {index}!"); GD.Print($"Selected Saved: {index}!");
await FadeInBlack(1f); await FadeInBlack(1f);
await Task.Delay(1000); SceneSwitcher.ChangeSceneWithSetup<ChapterScene>(this, "res://scenes/第一章.tscn", async (chapter) =>
GetTree().Quit(); {
chapter.ChapterInGame = GameConstant.ChapterInGame;
chapter.AreaInGame = GameConstant.AreaInGame;
chapter.NovelName = GameConstant.NovelName;
chapter.SceneName = GameConstant.SceneName;
chapter.NovelNodeKey = GameConstant.NovelNodeKey;
});
//GetTree().Quit();
} }
} }
else else

View File

@ -0,0 +1,39 @@
using Godot;
namespace Milimoe.GodotGame
{
public partial class BuffItem : Control
{
[Export]
public TextureRect TextureRect { get; set; }
[Export]
public Label Label { get; set; }
[Export]
public bool Durative { get; set; } = true;
[Export]
public double Duration { get; set; } = 0;
[Export]
public int DurationTurn { get; set; } = 0;
public void UpdateUI(bool? durative = null, double? duration = null, int? durationTurn = null)
{
if (durative != null)
{
Durative = durative.Value;
}
if (duration != null)
{
Duration = duration.Value;
}
if (durationTurn != null)
{
DurationTurn = durationTurn.Value;
}
Label.Text = Durative ? $"{Duration:0.##}s" : DurationTurn.ToString();
}
}
}

View File

@ -0,0 +1 @@
uid://mjetytpyq51i

View File

@ -0,0 +1,24 @@
using Godot;
namespace Milimoe.GodotGame
{
public partial class CharacterItem : Control
{
[Export]
public TextureRect TextureRect { get; set; }
[Export]
public Label Label { get; set; }
[Export]
public double HardnessTime
{
get;
set
{
field = value;
Label.Text = $"{field:0.##}";
}
}
}
}

View File

@ -0,0 +1 @@
uid://bf1lfbuoq3nkh

View File

@ -0,0 +1,487 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Godot;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Common.Addon;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Model;
using Oshima.Core.Constant;
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
using Oshima.FunGame.OshimaModules.Models;
using Oshima.FunGame.OshimaServers.Service;
namespace Milimoe.GodotGame;
public partial class Fighting : Control
{
[Export]
public TileMapLayer TileMapLayer { get; set; }
[Export]
public Camera2D CameraFight { get; set; }
public Character Character { get; set; }
public Node ParentUI { get; set; }
public Node NovelUI { get; set; }
public RichTextLabel FightLog { get; set; }
public Vector2I StartCell { get; set; }
public EnemyBody Enemy { get; set; }
public GamingQueue GamingQueue => _gamingQueue;
public Dictionary<Character, CharacterStatistics> CharacterStatistics { get; } = [];
public static Dictionary<Character, CharacterStatistics> TeamCharacterStatistics { get; } = [];
public PluginConfig StatsConfig { get; } = new(nameof(Fighting), nameof(CharacterStatistics));
public PluginConfig TeamStatsConfig { get; } = new(nameof(Fighting), nameof(TeamCharacterStatistics));
public bool IsWeb { get; set; } = false;
public bool TeamMode { get; set; } = false;
public string Msg { get; set; } = "";
private GamingQueue _gamingQueue = null;
private bool _fastMode = false;
public override void _Ready()
{
InitCharacter();
}
public async Task<List<string>> StartGame(bool isWeb = false, bool isTeam = false)
{
IsWeb = isWeb;
TeamMode = isTeam;
try
{
List<string> result = [];
Msg = "";
List<Character> allCharactersInGame = [.. FunGameConstant.Characters.OrderBy(o => Random.Shared.Next()).Take(3)];
TeamGamingQueue tgq = null;
MixGamingQueue mgq = null;
int clevel = 60;
int slevel = 6;
int mlevel = 8;
// 升级和赋能
List<Character> characters = [];
for (int index = 0; index < allCharactersInGame.Count; index++)
{
Character c = allCharactersInGame[index];
c.Level = clevel;
c.NormalAttack.Level = mlevel;
FunGameService.AddCharacterSkills(c, 1, slevel, slevel);
foreach (Skill skillLoop in FunGameConstant.Skills)
{
Skill skill = skillLoop.Copy();
skill.Character = c;
skill.Level = slevel;
c.Skills.Add(skill);
}
foreach (Skill skillLoop in FunGameConstant.CommonPassiveSkills)
{
Skill passive = skillLoop.Copy();
passive.Character = c;
passive.Level = 1;
c.Skills.Add(passive);
}
c.EP = 100;
characters.Add(c);
}
Character.NormalAttack.Level = mlevel;
foreach (Skill skillLoop in FunGameConstant.Skills)
{
Skill skill = skillLoop.Copy();
skill.Character = Character;
skill.Level = slevel;
Character.Skills.Add(skill);
}
foreach (Skill skillLoop in FunGameConstant.CommonPassiveSkills)
{
Skill passive = skillLoop.Copy();
passive.Character = Character;
passive.Level = 1;
Character.Skills.Add(passive);
}
Character.EP = 100;
characters.Add(Character);
// 询问玩家需要选择哪个角色 (通过UI界面选择)
Character player = Character ?? throw new Exception("没有选择角色,游戏结束。");
// 创建顺序表并排序
Team team1 = null, team2 = null;
if (isTeam)
{
tgq = new(WriteLine)
{
GameplayEquilibriumConstant = OshimaGameModuleConstant.GameplayEquilibriumConstant
};
_gamingQueue = tgq;
WriteLine("=== 团队模式随机分组 ===");
// 打乱角色列表
List<Character> shuffledCharacters = [.. characters.OrderBy(c => Random.Shared.Next())];
// 创建两个团队
List<Character> group1 = [];
List<Character> group2 = [];
// 将角色交替分配到两个团队中
for (int cid = 0; cid < shuffledCharacters.Count; cid++)
{
Character thisCharacter = shuffledCharacters[cid];
if (cid % 2 == 0)
{
group1.Add(thisCharacter);
}
else
{
group2.Add(thisCharacter);
}
}
// 添加到团队字典,第一个为队长
tgq.AddTeam($"{group1.First().NickName}的小队", group1);
tgq.AddTeam($"{group2.First().NickName}的小队", group2);
foreach (Team team in tgq.Teams.Values)
{
WriteLine($"团队【{team.Name}】的成员:\r\n{string.Join("\r\n", team.Members)}\r\n");
if (team.IsOnThisTeam(player))
{
foreach (Character c in team.Members.Except([player]))
{
c.Promotion = 300;
}
team1 = team;
}
else
{
team.Members.ForEach(c => c.Promotion = 400);
team2 = team;
}
}
// 初始化角色
_gamingQueue.InitCharacters(characters);
}
else
{
mgq = new MixGamingQueue(characters, WriteLine)
{
GameplayEquilibriumConstant = OshimaGameModuleConstant.GameplayEquilibriumConstant
};
_gamingQueue = mgq;
}
// 启用调试模式
//_gamingQueue.IsDebug = true;
// 加载地图和绑定事件
_gamingQueue.LoadGameMap(new GodotMap(TileMapLayer));
_gamingQueue.UseQueueProtected = false;
if (_gamingQueue.Map != null)
{
GodotMap map = (GodotMap)_gamingQueue.Map;
HashSet<Grid> allocated = [];
List<Grid> allGrids = [.. map.Grids.Values];
if (isTeam && tgq != null && team1 != null && team2 != null)
{
// 团队模式放置角色
Grid currentGrid = map.GetGridByVector2I(StartCell);
List<Grid> grids = map.GetGridsByRange(currentGrid, 10);
foreach (Character character in characters)
{
Grid grid = grids.OrderBy(o => Random.Shared.Next()).FirstOrDefault(g => g.Characters.Count == 0);
map.SetCharacterCurrentGrid(character, grid);
}
map.SetCharacterCurrentGrid(Character, currentGrid);
}
else
{
// 非团队模式,随机放置角色
foreach (Character character in characters)
{
character.NormalAttack.GamingQueue = _gamingQueue;
Grid grid = Grid.Empty;
do
{
grid = allGrids[Random.Shared.Next(allGrids.Count)];
}
while (allocated.Contains(grid));
allocated.Add(grid);
map.SetCharacterCurrentGrid(character, grid);
}
}
}
// 绑定事件
//await Controller.SetQueue(_gamingQueue.HardnessTime);
//await Controller.SetCharacterStatistics(_gamingQueue.CharacterStatistics);
//_gamingQueue.TurnStartEvent += GamingQueue_TurnStart;
//_gamingQueue.DecideActionEvent += GamingQueue_DecideAction;
//_gamingQueue.SelectNormalAttackTargetsEvent += GamingQueue_SelectNormalAttackTargets;
//_gamingQueue.SelectSkillEvent += GamingQueue_SelectSkill;
//_gamingQueue.SelectSkillTargetsEvent += GamingQueue_SelectSkillTargets;
//_gamingQueue.SelectNonDirectionalSkillTargetsEvent += GamingQueue_SelectNonDirectionalSkillTargets;
//_gamingQueue.SelectItemEvent += GamingQueue_SelectItem;
//_gamingQueue.QueueUpdatedEvent += GamingQueue_QueueUpdated;
//_gamingQueue.TurnEndEvent += GamingQueue_TurnEnd;
//_gamingQueue.CharacterInquiryEvent += GamingQueue_CharacterInquiryEvent;
//_gamingQueue.CharacterActionTakenEvent += GamingQueue_CharacterActionTakenEvent
//_gamingQueue.SelectTargetGridEvent += GamingQueue_SelectTargetGrid;
//_gamingQueue.CharacterMoveEvent += GamingQueue_CharacterMove;
// 总游戏时长
double totalTime = 0;
// 开始空投
Msg = "";
int qMagicCardPack = 5;
int qWeapon = 5;
int qArmor = 5;
int qShoes = 5;
int qAccessory = 5;
DropItems(_gamingQueue, qMagicCardPack, qWeapon, qArmor, qShoes, qAccessory);
double nextDropItemTime = 40;
if (qMagicCardPack < 5) qMagicCardPack++;
if (qWeapon < 5) qWeapon++;
if (qArmor < 5) qArmor++;
if (qShoes < 5) qShoes++;
if (qAccessory < 5) qAccessory++;
// 初始化队列,准备开始游戏
_gamingQueue.InitActionQueue();
_gamingQueue.SetCharactersToAIControl(false, characters);
_gamingQueue.SetCharactersToAIControl(false, player);
_gamingQueue.CustomData.Add("player", player);
// 显示初始顺序表
_gamingQueue.DisplayQueue();
WriteLine($"你的角色是 [ {player} ],详细信息:{player.GetInfo()}");
// 总回合数
int maxRound = isTeam ? 9999 : 999;
// 随机回合奖励
Dictionary<long, bool> effects = [];
foreach (EffectID id in FunGameConstant.RoundRewards.Keys)
{
long effectID = (long)id;
bool isActive = false;
if (effectID > (long)EffectID.Active_Start)
{
isActive = true;
}
effects.Add(effectID, isActive);
}
_gamingQueue.InitRoundRewards(maxRound, 1, effects, id => FunGameConstant.RoundRewards[(EffectID)id]);
int i = 1;
while (i < maxRound)
{
Msg = "";
if (i == maxRound - 1)
{
if (isTeam)
{
WriteLine("两队打到天昏地暗,流局了!!");
break;
}
else
{
WriteLine($"=== 终局审判 ===");
Dictionary<Character, double> hpPercentage = [];
foreach (Character c in characters)
{
hpPercentage.TryAdd(c, c.HP / c.MaxHP);
}
double max = hpPercentage.Values.Max();
Character winner = hpPercentage.Keys.Where(c => hpPercentage[c] == max).First();
WriteLine("[ " + winner + " ] 成为了天选之人!!");
foreach (Character c in characters.Where(c => c != winner && c.HP > 0))
{
WriteLine("[ " + winner + " ] 对 [ " + c + " ] 造成了 99999999999 点真实伤害。");
_gamingQueue.DeathCalculation(winner, c);
}
mgq?.EndGameInfo(winner);
}
result.Add(Msg);
break;
}
// 检查是否有角色可以行动
Character characterToAct = _gamingQueue.NextCharacter();
// 处理回合
if (characterToAct != null)
{
// 获取该角色当前位置
if (_gamingQueue.Map != null)
{
Grid currentGrid = _gamingQueue.Map.GetCharacterCurrentGrid(characterToAct);
if (currentGrid != null) _gamingQueue.CustomData["currentGrid"] = currentGrid;
}
bool isGameEnd = false;
try
{
isGameEnd = _gamingQueue.ProcessTurn(characterToAct);
}
catch (Exception e)
{
WriteLine(e.ToString());
}
if (isGameEnd)
{
result.Add(Msg);
break;
}
if (isWeb) _gamingQueue.DisplayQueue();
}
string roundMsg = "";
if (_gamingQueue.LastRound.HasKill)
{
roundMsg = Msg;
Msg = "";
}
// 模拟时间流逝
double timeLapse = _gamingQueue.TimeLapse();
totalTime += timeLapse;
nextDropItemTime -= timeLapse;
if (roundMsg != "")
{
if (isWeb)
{
roundMsg += "\r\n" + Msg;
}
result.Add(roundMsg);
}
if (nextDropItemTime <= 0)
{
// 空投
Msg = "";
DropItems(_gamingQueue, qMagicCardPack, qWeapon, qArmor, qShoes, qAccessory);
WriteLine("");
nextDropItemTime = 40;
if (qMagicCardPack < 5) qMagicCardPack++;
if (qWeapon < 5) qWeapon++;
if (qArmor < 5) qArmor++;
if (qShoes < 5) qShoes++;
if (qAccessory < 5) qAccessory++;
}
await Task.Delay(1);
}
WriteLine("--- 游戏结束 ---");
WriteLine($"总游戏时长:{totalTime:0.##} {_gamingQueue.GameplayEquilibriumConstant.InGameTime}");
// 赛后统计
FunGameService.GetCharacterRating(_gamingQueue.CharacterStatistics, isTeam, tgq != null ? tgq.EliminatedTeams : []);
if ((isTeam && tgq != null && tgq.EliminatedTeams.Any(t => t.IsOnThisTeam(Character) && t.IsWinner)) || _gamingQueue.Eliminated.Last() == Character)
{
Enemy.Dead = true;
}
result.Add(Msg);
return result;
}
catch (Exception ex)
{
WriteLine(ex.ToString());
return [ex.ToString()];
}
}
public void WriteLine(string str = "")
{
Msg += str + "\r\n";
FightLog.AppendText(str.Trim() + "\r\n");
FightLog.ScrollToLine(FightLog.GetLineCount());
}
public void InitCharacter()
{
foreach (Character c in FunGameConstant.Characters)
{
CharacterStatistics.Add(c, new());
TeamCharacterStatistics.Add(c, new());
}
StatsConfig.LoadConfig();
TeamStatsConfig.LoadConfig();
foreach (Character character in CharacterStatistics.Keys)
{
if (StatsConfig.ContainsKey(character.ToStringWithOutUser()))
{
CharacterStatistics[character] = StatsConfig.Get<CharacterStatistics>(character.ToStringWithOutUser()) ?? CharacterStatistics[character];
}
}
foreach (Character character in TeamCharacterStatistics.Keys)
{
if (TeamStatsConfig.ContainsKey(character.ToStringWithOutUser()))
{
TeamCharacterStatistics[character] = TeamStatsConfig.Get<CharacterStatistics>(character.ToStringWithOutUser()) ?? TeamCharacterStatistics[character];
}
}
}
public static void DropItems(GamingQueue queue, int mQuality, int wQuality, int aQuality, int sQuality, int acQuality)
{
Item[] weapons = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("11") && (int)i.QualityType == wQuality)];
Item[] armors = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("12") && (int)i.QualityType == aQuality)];
Item[] shoes = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("13") && (int)i.QualityType == sQuality)];
Item[] accessorys = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("14") && (int)i.QualityType == acQuality)];
Item[] consumables = [.. FunGameConstant.AllItems.Where(i => i.ItemType == ItemType.Consumable && i.IsInGameItem)];
foreach (Character character in queue.AllCharacters)
{
Item a = null, b = null, c = null, d = null;
if (weapons.Length > 0) a = weapons[Random.Shared.Next(weapons.Length)];
if (armors.Length > 0) b = armors[Random.Shared.Next(armors.Length)];
if (shoes.Length > 0) c = shoes[Random.Shared.Next(shoes.Length)];
if (accessorys.Length > 0) d = accessorys[Random.Shared.Next(accessorys.Length)];
List<Item> drops = [];
if (a != null) drops.Add(a);
if (b != null) drops.Add(b);
if (c != null) drops.Add(c);
if (d != null) drops.Add(d);
mQuality = 2;
Item magicCardPack = FunGameService.GenerateMagicCardPack(8, (QualityType)mQuality);
if (magicCardPack != null)
{
foreach (Skill magic in magicCardPack.Skills.Magics)
{
magic.Level = 8;
}
magicCardPack.SetGamingQueue(queue);
queue.Equip(character, magicCardPack);
}
foreach (Item item in drops)
{
Item realItem = item.Copy();
realItem.SetGamingQueue(queue);
queue.Equip(character, realItem);
}
if (consumables.Length > 0 && character.Items.Count < 5)
{
for (int i = 0; i < 2; i++)
{
Item consumable = consumables[Random.Shared.Next(consumables.Length)].Copy();
consumable.Character = character;
character.Items.Add(consumable);
}
}
}
}
}

View File

@ -0,0 +1 @@
uid://c5ebf2dx20ptw

View File

@ -5,13 +5,19 @@ namespace Milimoe.GodotGame;
public partial class UserInterface : Control public partial class UserInterface : Control
{ {
[Export] [Export]
public Panel CharacterStatus1 { get; set; } public Label Location { get; set; }
[Export] [Export]
public Panel CharacterStatus2 { get; set; } public Panel Rayne { get; set; }
[Export] [Export]
public Panel CharacterStatus3 { get; set; } public Panel Irene { get; set; }
[Export]
public Control RoundQueue { get; set; }
[Export]
public Panel FightLog { get; set; }
public override void _Ready() public override void _Ready()
{ {