FunGame-Godot/scripts/NovelController.cs
2025-04-14 21:54:29 +08:00

292 lines
7.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Linq;
using System.Threading.Tasks;
using Godot;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Model;
namespace Milimoe.GodotGame;
public partial class NovelController : CanvasLayer, ISaveSelectionEvent
{
public string NovelName { get; set; } = "";
public string SceneName { get; set; } = "";
public NovelConfig NovelConfig { get; set; } = null;
public NovelNode Current { get; set; } = null;
public INovelEndEvent ChapterObject { get; set; } = null;
public IMenuObject MenuObject { get; set; } = null;
public IFadeInFadeOutBlack FadeObject { get; set; } = null;
public bool Automatic { get; set; } = false;
[Export]
public SavedSelection SavedSelection;
[Signal]
public delegate void CloseSavedSelectionEventHandler(bool selected, int index);
private TextureRect _portrait1;
private TextureRect _portrait2left;
private TextureRect _portrait2right;
private TextureRect _image1;
private TextureRect _image2left;
private TextureRect _image2right;
private Panel _panel;
private Panel _namePanel;
private Label _name;
private RichTextLabel _content;
private AnimatedRichTextLabel _content_richLabel;
private VBoxContainer _vBoxContainer;
private ColorRect _colorRect;
private Button _autoPlay;
private Button _load;
private Button _save;
private Button _menu;
public override void _Ready()
{
Visible = false;
_portrait1 = GetNode<TextureRect>("立绘1");
_portrait2left = GetNode<TextureRect>("立绘2左");
_portrait2right = GetNode<TextureRect>("立绘2右");
_image1 = _portrait1.GetNode<TextureRect>("Image");
_image2left = _portrait2left.GetNode<TextureRect>("Image");
_image2right = _portrait2right.GetNode<TextureRect>("Image");
_panel = GetNode<Panel>("Panel");
_namePanel = _panel.GetNode<Panel>("NamePanel");
_name = _namePanel.GetNode<Label>("Name");
_content = _panel.GetNode<RichTextLabel>("Content");
if (_content is AnimatedRichTextLabel richLabel)
{
_content_richLabel = richLabel;
_content_richLabel.NovelController = this;
}
_colorRect = GetNode<ColorRect>("透明挡板");
_vBoxContainer = GetNode<VBoxContainer>("选项框");
if (_colorRect != null)
{
_colorRect.GuiInput += ColorRect_GuiInput;
}
_autoPlay = GetNode<Button>("自动播放");
_load = GetNode<Button>("读取存档");
_save = GetNode<Button>("保存存档");
_menu = GetNode<Button>("游戏菜单");
if (_autoPlay != null)
{
_autoPlay.Pressed += () => Automatic = _autoPlay.ButtonPressed;
}
if (_load != null)
{
_load.Pressed += () => OnLoadSaveButtonPressed(false);
}
if (_save != null)
{
_save.Pressed += () => OnLoadSaveButtonPressed(true);
}
if (_menu != null)
{
_menu.Pressed += OnMenuButtonPressed;
}
}
public void InitNovel(string novel_name, string scene_name)
{
NovelName = novel_name;
SceneName = scene_name;
if (NovelName != "" && SceneName != "")
{
NovelConfig ??= NovelConfig.LoadFrom(ProjectSettings.GlobalizePath("res://resources/novels/第一章/场景一.json"), NovelName, false);
if (NovelConfig.Count > 0)
{
ShowNode(NovelConfig.Values.First());
}
}
}
public void ShowNode(NovelNode node)
{
if (node != null)
{
GameConstant.NovelName = NovelName;
GameConstant.SceneName = SceneName;
GameConstant.NovelNodeKey = node.Key;
_name.Text = node.Name;
_namePanel.Visible = _name.Text != "";
_name.Visible = _name.Text != "";
if (node.PortraitImagePath != "")
{
using Texture2D texture = GD.Load<CompressedTexture2D>(node.PortraitImagePath);
_image1.Texture = texture;
_image1.Visible = true;
}
else _image1.Visible = false;
if (_content_richLabel != null)
{
_content_richLabel.SetText(node.Content);
_content_richLabel.StartAnimation();
}
else _content.Text = node.Content;
foreach (Node child in _vBoxContainer.GetChildren())
{
child.QueueFree();
}
_vBoxContainer.Visible = false;
_colorRect.Visible = true;
Current = node;
Visible = true;
}
else Visible = false;
}
public async void TextAnimationHasFinished()
{
if (Current != null)
{
await Task.Delay(500);
if (_vBoxContainer.Visible)
{
return;
}
foreach (NovelOption option in Current.AvailableOptions)
{
Button button = new()
{
Text = option.Name,
Theme = GD.Load<Theme>("res://resources/themes/option.tres")
};
button.Pressed += () => OnOptionButtonClick(option);
_vBoxContainer.AddChild(button);
}
if (Current.AvailableOptions.Count == 0)
{
// 透明挡板用于控制在没有选项时继续
_colorRect.Visible = true;
// 如果是自动播放剧情则在800ms后自动下一句
if (Automatic)
{
await Task.Delay(800);
// 需要再次判断
if (Automatic && !_content_richLabel.IsAnimationRunning)
{
NovelNode next = Current.Next;
if (next != null)
{
ShowNode(next);
}
else
{
ChapterObject.OnNovelEnd(this, NovelName, SceneName);
}
}
}
}
else
{
// 显示选项框
_vBoxContainer.Visible = true;
}
}
}
public void OnOptionButtonClick(NovelOption option)
{
if (option != null && option.Targets.Count > 0)
{
NovelNode next = option.Targets.First();
ShowNode(next);
}
}
private void ColorRect_GuiInput(InputEvent @event)
{
if (@event is InputEventMouseButton mouseButtonEvent)
{
if (mouseButtonEvent.ButtonIndex == MouseButton.Left && mouseButtonEvent.Pressed)
{
if (_content_richLabel.IsAnimationRunning)
{
_content_richLabel.SkipAnimation();
}
else
{
if (Current.AvailableOptions.Count > 0)
{
return;
}
NovelNode next = Current.Next;
if (next != null)
{
ShowNode(next);
}
else
{
ChapterObject.OnNovelEnd(this, NovelName, SceneName);
}
}
}
}
}
private void OnLoadSaveButtonPressed(bool isSave)
{
if (isSave)
{
// 保存游戏
GD.Print("Save Game!");
SavedSelection.SetIsSave(true);
}
else
{
// 载入游戏
GD.Print("Load Game!");
SavedSelection.SetIsSave(false);
}
// 使用动画效果显示存档列表
if (SavedSelection != null)
{
SavedSelection.Show();
SavedSelection.GetNode<ColorRect>("ColorRect").GetNode<AnimationPlayer>("AnimationPlayer").Play("flyin");
}
}
private void OnMenuButtonPressed()
{
// 打开游戏菜单
GD.Print("Open Game Menu!");
if (MenuObject is IMenuObject obj)
{
obj.ChangeState();
}
}
public async void OnSaveSelectionClosed(bool selected, int index, bool isSave)
{
if (SavedSelection != null && !SavedSelection.IsClosing)
{
// 关闭存档选择界面
SavedSelection.IsClosing = true;
SavedSelection.GetNode<ColorRect>("ColorRect").GetNode<AnimationPlayer>("AnimationPlayer").Play("flyout");
await Task.Delay(300);
SavedSelection.IsClosing = false;
SavedSelection.Hide();
if (selected && index >= 0)
{
if (!isSave)
{
// 载入游戏
GD.Print($"Selected Saved: {index}!");
if (FadeObject != null)
{
await FadeObject.FadeInBlack(1f);
}
else await Task.Delay(1000);
GetTree().Quit();
}
}
else
{
GD.Print("Close SavedSelection!");
}
}
}
}