视觉小说制作
如何利用godot做一个视觉小说
太好了!使用 Godot 制作视觉小说(Visual Novel, VN)是一个非常棒的选择。Godot 轻量、免费、开源,其场景和节点结构非常适合组织VN的各种元素(对话框、立绘、背景、选择支)。
下面我将为你提供一个 从零开始的完整指南,包括核心概念、步骤和一个简单的可运行示例。
一、 核心概念与准备工作
在开始之前,先理解 Godot 实现 VN 的核心思路:
- 场景化思维:每个游戏界面(如主菜单、存档/读档界面、游戏主界面)都是一个独立的场景(
.tscn
文件)。游戏流程就是在这些场景之间切换。 - 节点化组装:一切皆是节点。一个对话框是
TextureRect
(背景) +Label
(文字)节点。一个角色立绘是Sprite2D
节点。你将通过组合节点来构建游戏。 - 信号机制:用于处理交互。例如,当“点击对话框”信号发出时,触发“显示下一句文字”的函数。
准备工作:
- 从官网 https://godotengine.org/ 下载并安装 Godot(推荐 Stable 稳定版)。
- 准备一些素材:一张背景图、一个角色立绘(最好是透明背景的PNG)、一个对话框背景图。
二、 一步步创建你的第一个视觉小说场景
我们将创建一个最简单的场景:显示背景、一个角色和一段可以逐句点击推进的对话。
步骤 1:创建新项目并设置主场景
- 打开 Godot,创建新项目,选择“2D”项目类型。
- 在“场景”面板,右键点击默认的
Node2D
根节点,选择“添加子节点”,搜索并添加一个CanvasLayer
节点。将其命名为Main
。- 为什么用
CanvasLayer
? 它可以固定UI元素的绘制层级,确保对话框总是显示在最前面,不会被背景或角色遮挡。
- 为什么用
步骤 2:构建游戏界面
为 CanvasLayer
节点添加子节点,构建你的游戏界面:
- 背景(Background):
- 添加一个
TextureRect
节点。在右侧“检查器”面板,点击Texture
属性旁边的下拉菜单 -> “快速加载”,选择你的背景图片。将“Stretch Mode”设置为“Cover”,让背景铺满整个屏幕。
- 添加一个
- 角色立绘(Character):
- 添加一个
Sprite2D
节点。将其Texture
设置为你的角色立绘图片。使用鼠标拖动或在“检查器”中调整Position
的X和Y值,将其放在合适的位置。
- 添加一个
- 对话框(DialogBox):
- 添加一个
ColorRect
节点作为对话框背景,命名为DialogBox
。调整其大小(Size)和位置(Position),使其位于屏幕底部。 - 修改其
Color
属性为一个半透明的黑色(如#aa000000
)。 - 为
DialogBox
添加一个Label
节点作为显示文字的控件,命名为Text
。在“检查器”中调整Label
的“自定义字体大小”和“边距”,让文字看起来舒服些。
- 添加一个
现在你的场景树应该大致如下:
Main (CanvasLayer)
├── Background (TextureRect)
├── Character (Sprite2D)
└── DialogBox (ColorRect)
└── Text (Label)
步骤 3:编写对话控制脚本
这是最关键的一步。我们将为 CanvasLayer
节点添加脚本,控制对话的流程。
-
选中
CanvasLayer (Main)
节点,点击工具栏的“附加脚本”按钮(一张纸带个+号)。 -
创建一个新脚本,比如
main.gd
。 -
编写脚本代码:将以下代码复制到
main.gd
中并保存。
extends CanvasLayer
# 定义一个数组(Array)来存储所有的对话内容
var dialog_lines = [
"(你在一个陌生的房间里醒来。)",
"我是谁...这里是哪里?",
"头好痛,一点都想不起来了。",
"窗外,一轮巨大的月亮散发着诡异的光芒。",
"得想办法离开这里..."
]
# 一个索引,用来追踪当前显示到了第几句对话
var current_line_index = 0
# 获取对UI中Text节点的引用
@onready var dialog_text = $DialogBox/Text
func _ready():
# 游戏一开始,显示第一句对话
show_dialog_line()
func _input(event):
# 检测鼠标左键的点击事件
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
# 点击后,显示下一句对话
next_line()
func show_dialog_line():
# 检查索引是否有效,防止超出数组范围
if current_line_index < dialog_lines.size():
# 将Text节点的文字设置为当前索引对应的对话
dialog_text.text = dialog_lines[current_line_index]
else:
# 如果所有对话都显示完了,可以在这里触发场景切换或其他逻辑
print("对话结束!")
func next_line():
# 将索引加一,指向下一句对话
current_line_index += 1
# 调用显示函数
show_dialog_line()
步骤 4:运行测试!
- 点击Godot编辑器右上角的“播放”按钮(一个三角形的播放图标)。
- Godot会让你选择一个主场景,选择你刚刚创建并编写脚本的
.tscn
文件。 - 游戏窗口将会弹出!你应该能看到背景、角色和第一句对话。
- 用鼠标点击屏幕,对话就会逐句推进!
恭喜!你已经做出了一个最基础的视觉小说框架!
三、 如何扩展你的视觉小说?
上面的Demo非常简单,一个真正的VN还需要更多功能。以下是进阶方向:
- 角色名称框:
- 在
DialogBox
里再添加一个Label
节点,放在Text
节点的上方。在脚本中获取它,并在显示对话时同时更新名字。
-
多角色与立绘切换:
-
准备多个角色的
Sprite2D
节点。在对话数据中不仅包含文字,还包含说话的角色。 -
修改
dialog_lines
为字典数组,例如:var dialog_lines = [ {"character": "系统", "text": "(你在一个陌生的房间里醒来。)"}, {"character": "主角", "text": "我是谁...这里是哪里?"}, {"character": "???", "text": "你终于醒了。"} ]
-
在
show_dialog_line()
函数中,根据dialog_lines[current_line_index]["character"]
的值来显示/隐藏对应的Sprite2D
节点。
-
-
选择支:
- 当需要选择时,隐藏
DialogBox
,实例化一个预定义好的“选择支按钮”场景。 - 这个场景包含多个
Button
节点,每个按钮代表一个选项。 - 为每个按钮的
pressed
信号连接函数,根据选择的结果跳转到不同的对话分支。
- 当需要选择时,隐藏
-
存档与读档:
- 使用 Godot 的
FileAccess
功能将游戏数据(当前对话索引、变量状态等)保存到本地文件。 - 读档时再从文件中加载数据,并恢复游戏状态。
- 使用 Godot 的
-
使用更专业的工具(强烈推荐):
- 在Asset Library中搜索 “Dialogic” 插件并安装。它是一个功能极其强大的视觉小说/对话编辑器,为Godot量身定制,提供了可视化的事件编辑、角色管理、时间线等功能,可以让你像使用专业VN制作软件一样工作,而无需从零开始写所有逻辑。
总结
用 Godot 制作视觉小说的流程可以概括为:
- 搭建UI场景:用节点拼出背景、立绘、对话框等元素。
- 编写控制脚本:用数组存储对话,用索引控制流程,用输入事件推进对话。
- 测试并迭代:运行看看效果,然后逐步添加角色切换、选择支、存档等复杂功能。
- 使用插件:当你熟悉基础后,使用 Dialogic 插件来大幅提升开发效率和质量。
希望这个指南能帮助你顺利踏入用 Godot 制作视觉小说的大门!祝你创作顺利!
将“Stretch Mode”设置为“Cover”,没有这个选项啊??
您说得对!非常抱歉,我的描述出现了错误。在 Godot 4 中,TextureRect
节点的属性名称和之前版本有所不同,没有直接的 “Stretch Mode” 叫做 “Cover” 的选项。
正确的设置方法如下,这能实现让背景图片覆盖整个屏幕并不变形的效果:
正确的步骤 (Godot 4):
-
在场景中选中您的 Background (
TextureRect
) 节点。 -
看右侧的 “检查器” (Inspector) 面板。
-
找到 “展开” (Expand) 属性,勾选它。这是最关键的一步,它允许图片缩放至超出其原始大小。
-
找到 “拉伸模式” (Stretch Mode) 属性。点击它,会看到一个下拉菜单。
-
从下拉菜单中,选择 “保持宽高比覆盖” (Keep Aspect Covered) 或者 “保持宽高比居中覆盖” (Keep Aspect Centered)。
- Keep Aspect Covered:缩放纹理以覆盖整个节点的矩形区域,同时保持其宽高比。纹理的较短边可能会被裁剪掉一部分,但能确保屏幕没有黑边。这是最常用的“Cover”模式。
- Keep Aspect Centered:缩放纹理以使其完全适应节点的矩形区域,同时保持其宽高比。可能会在屏幕上下或左右留下黑边,但能确保看到整张图。
-
(可选但重要) 确保您的
TextureRect
节点本身的大小足以覆盖整个屏幕。最简单的方法是:- 选中
TextureRect
节点后,点击工具栏上的 “布局” (Layout) 按钮。 - 从下拉菜单中选择 “全矩形” (Full Rect)。这会自动将节点的锚点设置为充满整个父容器(也就是你的游戏窗口)。
- 选中
为了更清晰,整个过程可以总结为这个表格:
步骤 | 属性名 (Godot 4) | 应选择的值 | 目的 |
---|---|---|---|
1 | Expand | Enabled (打勾 ✅) |
允许图片缩放至超出其原始尺寸 |
2 | Stretch Mode | Keep Aspect Covered |
核心步骤:让图片按比例缩放并填满屏幕,多余部分裁剪掉 |
3 | Layout | Full Rect |
让TextureRect 节点本身充满整个游戏窗口 |
完成这三步后,您的背景图片就应该能够完美地覆盖整个屏幕了。
再次为我之前指令中的错误道歉,Godot 不同版本间的属性名称变化有时会带来混淆。感谢您的指正!现在您应该可以正确设置了。
命名为 DialogBox。调整其大小(Size)和位置(Position)?
您问到了最关键的操作点!在 Godot 4 中,调整节点的大小(Size)和位置(Position)是通过控制节点的锚点、边距和实际尺寸来实现的,这些选项的位置确实不太直观。
找不到直接的“Size”和“Position”输入框是刚接触 Godot 的用户最常见的困惑之一。
以下是两种最有效的方法来调整 DialogBox
(ColorRect) 的大小和位置:
方法一:使用工具栏的“布局”菜单(最快最推荐)
这是最常用且高效的方法。
-
首先,在场景树中选中您的
DialogBox
(ColorRect) 节点。 -
看 Godot 编辑器顶部的工具栏,找到并点击 “布局” (Layout) 按钮。
-
会弹出一个下拉菜单,里面有很多预设的布局选项。为了将对话框放在屏幕底部,您需要两步:
- 第一步:设置水平宽度。选择 “全宽度” (Full Width)。这会让对话框的宽度和父容器(游戏窗口)的宽度一致。
- 第二步:设置底部位置。选择 “底部宽度” (Bottom Width)。这会把对话框紧贴在父容器的底部,并保持全宽度。
-
现在调整高度:完成上面两步后,对话框已经在底部了,但可能高度不合适。
- 将鼠标移动到场景2D视图中的
DialogBox
节点的上边缘,光标会变成一个上下箭头 ↕。 - 按住鼠标左键并向上拖动,即可增加对话框的高度。向下拖动则会减少高度。
- 将鼠标移动到场景2D视图中的
方法二:使用检查器手动设置(更精确)
如果您想进行更精确的控制,可以使用右侧的“检查器”面板。
- 选中
DialogBox
节点后,看右侧的 “检查器” (Inspector) 面板。 - 找到 “变换” (Transform) 栏目(一个3x3网格图标)。这里可以看到:
- Position(位置):这里的
X
和Y
值决定了节点的中心点在屏幕上的坐标。 - Scale(缩放):通常不直接用这个来控制UI大小。
- Position(位置):这里的
- 更重要的是其下方的 “锚点” (Anchors) 和 “边距” (Margins) 栏目(一个钉子图标)。
- 锚点 (Anchors):决定了节点的边角相对于父容器边角的锁定位置。
- 点击 “预设” (Preset) 按钮(一个网格图标),选择 “底部宽度” (Bottom Wide) 预设。这相当于在方法一中一次性完成了锚点设置。
- 边距 (Margins):当锚点设定好后,这里可以设置节点相对于其锚点的偏移量。
- 例如,锚点预设为“底部宽度”后,你可以修改
Top
的负值(如-200
)来定义对话框的高度,或者修改Bottom
的值为-10
让它离屏幕底部有一点边距。
- 例如,锚点预设为“底部宽度”后,你可以修改
- 锚点 (Anchors):决定了节点的边角相对于父容器边角的锁定位置。
总结与最佳实践
对于UI元素(如对话框),强烈推荐使用【方法一】的“布局”菜单。
操作流程可以简化为:
- 创建
ColorRect
并命名为DialogBox
。 - 选中它 -> 点击顶部工具栏的 “布局” (Layout) -> 选择 “底部宽度” (Bottom Width)。
- 用鼠标拖动上边缘,调整到一个你满意的高度。
- 然后再去调整它的颜色和在它里面添加
Label
子节点。
这样操作最符合 Godot 的UI设计逻辑,也最快最直观。希望这次能帮您成功定位并调整对话框的大小和位置!
为对话框添加一个角色名称框
好的,这个功能非常关键!为对话框添加一个角色名称框是视觉小说的标准配置。我们来一步步实现它。
步骤一:在场景中添加并设置 NameLabel 节点
- 添加节点:在场景树中,右键点击你的
DialogBox
(ColorRect
) 节点,选择 “添加子节点”。搜索并添加一个Label
节点。 - 命名节点:确保这个新节点被选中,在右侧“检查器”面板的最上方,将其名称 (Name) 从
Label
修改为NameLabel
。这是良好习惯,便于后续在脚本中获取它。 - 调整位置和样式:
- 用鼠标拖动
NameLabel
,将其放在Text
节点的正上方。 - 在“检查器”面板中,调整它的自定义字体大小,通常名字的字号可以比对话文字稍大或加粗以示区别。
- 你可以修改 “水平对齐” (Horizontal Alignment) 为“居中”,或者保持左对齐。
- (可选)你可以为名字框加个背景。再添加一个
ColorRect
作为NameLabel
的兄弟节点,调整大小和颜色,然后在场景树中将它拖到NameLabel
的下面,这样背景就在文字下层了。
- 用鼠标拖动
现在你的场景树应该看起来像这样:
DialogBox (ColorRect)
├── NameLabel (Label) // 新增的名字标签
├── SomeBackground (ColorRect) // 可选的名字背景
└── Text (Label) // 原来的对话文字标签
步骤二:修改脚本代码
这是核心部分,我们需要做三件事:
- 获取对
NameLabel
节点的引用。 - 修改对话数据结构,加入角色名字。
- 在显示对话时,同时更新名字标签的文字。
以下是修改后的 main.gd
脚本示例:
extends CanvasLayer
# 1. 获取对新节点的引用
@onready var dialog_text = $DialogBox/Text
@onready var name_label = $DialogBox/NameLabel # 新增这行,获取NameLabel节点
# 2. 修改对话数据结构,加入角色名字字段
var dialog_lines = [
{"name": "", "text": "(你在一个陌生的房间里醒来。)"}, # 名字为空,表示叙述
{"name": "???", "text": "我是谁...这里是哪里?"},
{"name": "???", "text": "头好痛,一点都想不起来了。"},
{"name": "", "text": "窗外,一轮巨大的月亮散发着诡异的光芒。"},
{"name": "???", "text": "得想办法离开这里..."}
]
var current_line_index = 0
func _ready():
show_dialog_line()
func _input(event):
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
next_line()
func show_dialog_line():
if current_line_index < dialog_lines.size():
# 3. 同时更新名字和对话文本
var current_line = dialog_lines[current_line_index]
name_label.text = current_line["name"] # 更新名字标签
dialog_text.text = current_line["text"] # 更新对话标签
else:
print("对话结束!")
func next_line():
current_line_index += 1
show_dialog_line()
步骤三:优化体验(处理空名字)
你会发现,当 name
字段为空字符串 ""
时,名字框会显示一个空行,不太美观。我们可以进一步优化:当名字为空时,直接把名字框隐藏起来。
修改 show_dialog_line()
函数中的部分代码:
func show_dialog_line():
if current_line_index < dialog_lines.size():
var current_line = dialog_lines[current_line_index]
# 更新名字标签,并控制其可见性
name_label.text = current_line["name"]
# 如果名字不是空字符串,就显示名字框,否则隐藏它
if current_line["name"] != "":
name_label.show() # 显示节点
else:
name_label.hide() # 隐藏节点
dialog_text.text = current_line["text"]
else:
print("对话结束!")
总结
你完成了一个标准的视觉小说名字框功能!整个过程可以概括为:
- 加节点:在场景UI中添加一个用于显示名字的
Label
。 - 拿引用:在脚本中使用
@onready var
获取这个新节点的引用。 - 改数据:将简单的字符串数组改为字典数组,为每句对话增加归属。
- 双更新:在显示对话的函数里,同时更新名字和对话内容。
- 做优化:根据内容动态显示或隐藏名字框,让UI更整洁。
现在运行你的游戏,你会发现不同的对话行会显示不同的说话者名字了!这是一个巨大的进步。
Dialogic插件
好的,在 Godot 中安装和使用 Dialogic 非常简单。下面是详细的步骤:
一、安装 Dialogic 2
方法一:通过 Godot 资产库安装(最推荐、最直接)
-
打开资产库 (AssetLib):
- 打开你的 Godot 编辑器。
- 在编辑器顶部,点击 “资产库” (AssetLib) 选项卡。
-
搜索并选择 Dialogic:
- 在右上角的搜索框中输入
Dialogic 2
并按下回车。 - 在搜索结果中,找到 “Dialogic 2”(通常是由 “Dialogic” 或 “Emilio” 发布的),然后点击它。
- 在右上角的搜索框中输入
-
下载并安装:
- 点击页面上的 “下载” (Download) 按钮。
- 下载完成后,按钮会变成 “安装” (Install)。点击它。
- 会弹出一个安装窗口。确保所有文件都被勾选,然后再次点击 “安装” (Install)。
-
重启 Godot:
- 安装完成后,Godot 会提示你必须重启编辑器才能使插件生效。点击 “确定” 并关闭 Godot,然后重新打开你的项目。
方法二:手动安装(如果网络问题无法下载)
- 从 GitHub 发布页手动下载:访问 Dialogic 2 的 GitHub Releases 页面,下载最新的
.zip
文件(例如dialogic-2.X.zip
)。 - 解压缩下载的 ZIP 文件。
- 在你的 Godot 项目文件夹内,创建一个名为
addons
的文件夹(如果还没有的话)。路径应该是你的项目根目录/addons/
。 - 将解压后的文件夹(通常名为
dialogic
)复制到addons
文件夹中。 - 重启 Godot 编辑器。
二、启用 Dialogic 插件
安装并重启 Godot 后,你需要启用这个插件:
-
进入 “项目” (Project) -> 项目设置 (Project Settings)。
-
选择 “插件” (Plugins) 选项卡。
-
在列表中找到 “Dialogic”。
-
点击其状态下的 “禁用” (Inactive) 下拉菜单,将其改为 “启用” (Active)。
-
点击右下角的 “关闭”。
启用成功后,你会看到 Godot 编辑器底部出现了 一个名为 Dialogic
的新标签页。这表明安装和启用已经成功!
三、开始使用 Dialogic 创建你的视觉小说
现在你可以开始使用 Dialogic 来制作游戏了:
-
点击
Dialogic
标签页:你会看到它的主界面。 -
配置角色 (Characters):
- 在 Dialogic 面板中,点击 “Characters” 子选项卡。
- 点击 “Add” 按钮创建一个新角色。
- 在右侧检查器中,为角色设置
Name
(在对话中显示的名字)。 - 最重要的:在 “Portraits” 部分,点击 “Add Portrait”,然后点击 “Select Image” 来上传这个角色的立绘图片。你可以为角色添加多个不同表情的立绘。
-
创建时间线 (Timelines):
- 点击 “Timelines” 子选项卡。
- 点击 “Add” 按钮创建你的第一条时间线(比如
intro
)。 - 双击新创建的时间线文件,会打开 Dialogic 编辑器窗口。
-
编辑剧情:
- 在 Dialogic 编辑器窗口中,你可以点击 “Add Event” 来添加各种事件,这是核心步骤:
- Text Event:添加对话文本。你可以选择说话的角色和其对应的立绘(表情)。
- Character Event:让角色加入或离开场景。
- Background Event:切换背景图片。
- Choice Event:为玩家提供选项,创建分支剧情。
- 还有很多其他事件(声音、动画、变量控制等)。
- 在 Dialogic 编辑器窗口中,你可以点击 “Add Event” 来添加各种事件,这是核心步骤:
-
在游戏场景中启动对话:
- 在你的游戏场景中(比如
main.tscn
),添加一个子节点。 - 在节点列表中,现在你可以在 “Dialogic” 分类下找到 “Start” 节点。
- 添加一个
DialogicStart
节点。 - 在检查器中,将 “Timeline” 属性设置为你刚刚创建的时间线文件(如
intro
)。
- 在你的游戏场景中(比如
-
测试运行:
- 运行你的游戏场景,Dialogic 会自动开始播放你设计好的对话!
总结
安装 Dialogic 的流程就是:资产库搜索 -> 下载 -> 安装 -> 重启 -> 启用插件。
启用后,你的工作流就变成了:
- 在
Dialogic
面板中创建角色和时间线。 - 在 Dialogic 编辑器中像做流程图一样编辑剧情。
- 在游戏场景中添加
DialogicStart
节点并关联时间线。 - 运行游戏,体验你创作的视觉小说!
Dialogic 极大地简化了视觉小说的制作过程,让你能更专注于故事本身。快去试试吧!
项目结构
太好了!有一个清晰的项目结构是成功的一半。对于一个使用 Godot 和 Dialogic 的视觉小说项目,我为你推荐一个经过实践检验的、逻辑清晰的结构。
这个结构平衡了规范性和灵活性,既能高效管理资源,又方便团队协作(即使只有你一个人)。
推荐的项目文件结构
你的项目文件夹 (res://
) 应该看起来像这样:
你的项目名称/
├── addons/
│ └── dialogic/ # Dialogic 插件文件(通常自动生成,无需手动改动)
├── assets/ # 【核心】所有原始资源
│ ├── audio/
│ │ ├── music/ # BGM 背景音乐
│ │ └── sounds/ # 音效 (SE)
│ ├── graphics/
│ │ ├── backgrounds/ # 背景图片
│ │ ├── characters/ # 角色立绘(可按角色再分子文件夹)
│ │ ├── gui/ # UI元素:按钮、图标、存档截图等
│ │ └── cgs/ # 特殊CG图
│ └── fonts/ # 自定义字体
├── dialogs/ # 【核心】Dialogic 生成的资源
│ ├── characters/ # Dialogic 角色资源 (.dch)
│ ├── timelines/ # Dialogic 时间线/剧情文件 (.dtl)
│ ├── themes/ # Dialogic 主题(对话框样式)
│ └── events/ # 自定义事件脚本(如存档事件)
├── scenes/ # 【核心】Godot 场景文件
│ ├── system/
│ │ ├── main_menu.tscn # 主菜单场景
│ │ ├── save_load_menu.tscn # 存档/读档界面
│ │ └── gallery.tscn # CG鉴赏廊
│ └── game_root.tscn # 游戏主根场景(用于运行Dialogic)
├── scripts/ # 自定义全局脚本
│ └── autoload/
│ ├── save_manager.gd # 全局存档管理器(自动加载)
│ └── audio_manager.gd # 全局音频管理器(自动加载)
└── project.godot # Godot 项目配置文件
核心目录详解
-
assets/
(资源库)- 目的:存放所有原始素材。像你的“军火库”,所有图片、声音都从这里调用。
- 原则:只读。游戏运行时不会修改这里的文件。按类型分文件夹,方便艺术家和设计师管理。
-
dialogs/
(对话与剧情)- 目的:这是 Dialogic 的“工作区”。所有通过 Dialogic 编辑器创建的内容都会自动放在这里。
timelines/
:这是你的剧本所在!所有剧情线(.dtl
文件)都在这里。你可以按章节创建子文件夹,如chapter_1/
。characters/
:存放 Dialogic 角色配置文件(.dch
),它引用了assets/characters/
中的立绘图片。
-
scenes/
(场景与界面)- 目的:存放 Godot 场景文件(
.tscn
),这些是你自己构建的界面和系统。 system/
:存放游戏的各种功能界面,如主菜单、设置、存档/读档界面。它们独立于剧情之外。game_root.tscn
:这是最重要的游戏场景。它是一个空场景,唯一的作用是挂载脚本、存放DialogicStart
节点,作为运行 Dialogic 剧情的“容器”。
- 目的:存放 Godot 场景文件(
-
scripts/autoload/
(游戏大脑)- 目的:存放全局管理器脚本。设置为“自动加载”后,它们在任何场景中都可以访问。
save_manager.gd
:核心中的核心。负责保存和加载游戏进度、管理全局变量、记录当前剧情点等。
工作流程与数据流
- 玩家在
main_menu.tscn
点击“开始游戏”。 main_menu.tscn
调用SaveManager.start_new_game()
。SaveManager
初始化数据,并加载game_root.tscn
场景。game_root.tscn
场景中的DialogicStart
节点根据SaveManager
提供的 timeline 路径,开始播放dialogs/timelines/intro.dtl
剧情。- 在剧情中:
- 背景事件 -> 从
assets/graphics/backgrounds/
加载图片。 - 角色事件 -> 从
assets/graphics/characters/
加载立绘,并根据dialogs/characters/
中的配置显示。 - 声音事件 -> 从
assets/audio/
加载并播放音乐音效。 - 自定义事件(存档) -> 调用
SaveManager.save_game()
,将进度存入user://
目录。
- 背景事件 -> 从
- 玩家遇到选择支,不同的选择会跳转到不同的时间线(
.dtl
文件),实现分支剧情。 - 玩家打开菜单,
save_load_menu.tscn
场景会读取SaveManager
中的存档数据或读取user://
目录下的存档文件。
这个结构的好处是职责清晰:
assets/
管素材。dialogs/
管剧情。scenes/
管界面。autoload/
管数据和逻辑。
遵循这个结构,你的项目会非常整洁,无论项目规模变得多大,你都能快速找到需要修改的地方。现在就开始创建这些文件夹吧!
主界面
好的!终极简单版来了,不要动画,只要核心功能,三步完成!
最终场景树结构
MainMenu (Control)
├── Background (TextureRect)
├── Title (Label)
└── VBoxContainer (VBoxContainer)
├── StartButton (Button)
├── LoadButton (Button)
└── ExitButton (Button)
步骤一:创建场景和节点(1分钟)
- 新建场景,根节点选
Control
,命名为MainMenu
。 - 设置全屏:选中
MainMenu
,点击顶部 布局 -> 全矩形。 - 添加三个节点:
- 右键点击
MainMenu
-> 添加子节点 -> 搜索添加TextureRect
,命名为Background
。 - 右键点击
MainMenu
-> 添加子节点 -> 搜索添加Label
,命名为Title
。 - 右键点击
MainMenu
-> 添加子节点 -> 搜索添加VBoxContainer
(垂直盒子容器)。
- 右键点击
步骤二:设置节点属性和布局(2分钟)
-
设置背景 (Background):
- 选中
Background
节点。 - 在右侧检查器中,点击 Texture 旁边的 快速加载,选择你的背景图片。
- 点击 布局 -> 全矩形。
- 将 Stretch Mode 设置为 Keep Aspect Covered(保持宽高比覆盖)。
- 选中
-
设置标题 (Title):
- 选中
Title
节点。 - 在检查器的 Text 属性中输入你的游戏名(如“月下奇谭”)。
- 调整位置:用鼠标将它拖到屏幕上半部分。
- 调整样式:在 Theme Overrides -> Fonts 里可以增大字体大小、选择字体。
- 选中
-
设置按钮容器和按钮:
- 选中
VBoxContainer
节点。 - 用鼠标将它拖到屏幕下半部分。
- 在检查器中,找到 Custom Constants -> Separation,设置为
20
(增加按钮间距)。 - 添加按钮:右键点击
VBoxContainer
-> 添加子节点 -> 添加三个Button
节点。 - 逐个选中每个按钮,在检查器的 Text 属性中修改为:“开始游戏”、“加载游戏”、“退出游戏”。
- 选中
步骤三:编写脚本让按钮生效(2分钟)
- 添加脚本:选中根节点
MainMenu
,点击 附加脚本,使用默认设置创建。 - 复制粘贴代码:将以下代码完全替换到脚本中:
extends Control
func _ready():
# 获取按钮节点并连接它们的按下信号
$VBoxContainer/StartButton.pressed.connect(_on_start_button_pressed)
$VBoxContainer/LoadButton.pressed.connect(_on_load_button_pressed)
$VBoxContainer/ExitButton.pressed.connect(_on_exit_button_pressed)
# 开始游戏按钮功能
func _on_start_button_pressed():
get_tree().change_scene_to_file("res://scenes/game_root.tscn") # 切换到你的游戏场景
# 加载游戏按钮功能(这里先简单打印日志)
func _on_load_button_pressed():
print("加载游戏功能待实现") # 以后这里可以弹出存档界面
# 退出游戏按钮功能
func _on_exit_button_pressed():
get_tree().quit() # 直接退出游戏
- 确保场景路径正确:将代码中
res://scenes/game_root.tscn
替换为你自己的游戏主场景文件名和路径。
完成!
现在点击右上角的播放按钮运行你的游戏吧!你应该能看到一个带有背景、标题和功能按钮的主菜单,点击按钮会执行相应的操作。这就是最简单、最核心的主界面。