开始菜单
This commit is contained in:
@@ -105,3 +105,19 @@ SubViewportContainer`,输入天然可达** —— 不是把 SubViewport 当后
|
|||||||
遗留待用户拍板:现有预设要不要裁成方形(重映射后必须裁,1024² 里裁 x145..365 y32..251);
|
遗留待用户拍板:现有预设要不要裁成方形(重映射后必须裁,1024² 里裁 x145..365 y32..251);
|
||||||
联机时脸要不要 RPC 同步合成后的 PNG。
|
联机时脸要不要 RPC 同步合成后的 PNG。
|
||||||
|
|
||||||
|
## 新建:游戏开始菜单(只有界面,无逻辑)
|
||||||
|
|
||||||
|
`ui/main_menu.tscn` + `ui/main_menu.gd`(新目录 `ui/`)。
|
||||||
|
|
||||||
|
- 背景用 `GradientTexture2D` 取游戏天空的三段色(zenith 0.09/0.30/0.78 → mid → horizon),
|
||||||
|
和 `world/sky/cartoon_sky.gdshader` 的调色一致。
|
||||||
|
- 结构:`MainMenu(Control) → Background(TextureRect) / Center(CenterContainer) → Box → Title + Buttons`,
|
||||||
|
右下角一个 `Version` Label。
|
||||||
|
- 四个按钮 开始游戏 / 联机 / 设置 / 退出,**只有 `pressed` → 自定义信号**,没有任何开始/退出/联机实现。
|
||||||
|
- 按钮样式用 3 个 `StyleBoxFlat`(normal/hover/pressed)**挂在 `Buttons` 这个 VBoxContainer 上**,
|
||||||
|
靠主题继承一次性作用到四个按钮,不用逐个写。
|
||||||
|
- 实测(跑起来截图 + `get_ui_elements`):版式正确、中文正常渲染。
|
||||||
|
|
||||||
|
**发现**:`Net` autoload 的「联机测试」面板默认可见且在同位置,会把菜单中间的按钮盖住 ——
|
||||||
|
接线时必须先处理它(隐藏,或让菜单的「联机」按钮接管)。这条已记进 MEMORY.md。
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,11 @@
|
|||||||
- 组件的可调参数放在组件自己身上(如 Zipline 的速度 / 刹车 / 吸附半径),控制器只读不定义。
|
- 组件的可调参数放在组件自己身上(如 Zipline 的速度 / 刹车 / 吸附半径),控制器只读不定义。
|
||||||
- 头顶 UI(血条、交互提示)是 `player.tscn` 里的 Label3D 节点,不在代码里动态创建。
|
- 头顶 UI(血条、交互提示)是 `player.tscn` 里的 Label3D 节点,不在代码里动态创建。
|
||||||
- 测试用 `McpTestSuite`(`addons/godot_ai/testing`),脚本放 `res://tests/`。
|
- 测试用 `McpTestSuite`(`addons/godot_ai/testing`),脚本放 `res://tests/`。
|
||||||
|
- 界面放 `res://ui/`。项目没有 Theme 资源,风格一律用节点上的 `theme_override_*` 内联写;
|
||||||
|
给容器(如 VBoxContainer)设 `theme_override_styles/*` 会**向下继承**给子按钮,不用逐个设。
|
||||||
|
- 中文字体不用额外配:Godot 默认主题会回退到系统字体,实测中文正常渲染。
|
||||||
|
- **`Net` 是 autoload,它的「联机测试」面板在 `_ready()` 里就 `visible = true`(CanvasLayer layer=20)**,
|
||||||
|
会盖在任何场景正中间。做开始菜单时要么让菜单的「联机」按钮接管它,要么在菜单期间把它藏起来。
|
||||||
|
|
||||||
## 动画(AnimationPlayer)
|
## 动画(AnimationPlayer)
|
||||||
|
|
||||||
@@ -24,6 +29,17 @@
|
|||||||
第 4 个参数是「按住蹲键」这个输入事实(`crouch` 动作 = Ctrl),蹲着不动 → CROUCH、蹲着走 → SNEAK,
|
第 4 个参数是「按住蹲键」这个输入事实(`crouch` 动作 = Ctrl),蹲着不动 → CROUCH、蹲着走 → SNEAK,
|
||||||
这个区分在表现层做,控制器不需要知道两者差别。优先级:空中 > 蹲 > 移动。
|
这个区分在表现层做,控制器不需要知道两者差别。优先级:空中 > 蹲 > 移动。
|
||||||
|
|
||||||
|
## 模型:mouse.glb
|
||||||
|
|
||||||
|
- `body_mesh` 有**两个 surface**:`s0 "lambert1"`(身体,UV 几乎占满 0~1,贴
|
||||||
|
`mouse_mouse_lambert1_BaseColor.png`)、`s1 "face"`(面部,独立 UV 孤岛
|
||||||
|
u[0.142,0.356] v[0.038,0.238],贴 `mouse_表情测试.png`)。
|
||||||
|
**面部是独立材质槽 → 换脸不用动 Blender**,`set_surface_override_material(1, mat)` 即可。
|
||||||
|
- `mouse_表情测试.png` 是 1024² **RGBA 但 alpha 全 255**(实心蓝 #89B3FF 底 + 黑线脸),
|
||||||
|
不是透明覆盖层,只能当底图,不能当笔画层。
|
||||||
|
- 面部孤岛只占 1024² 的 21%×20%,实际脸分辨率约 219×205 —— 要用 shader 把孤岛重映射到 0~1
|
||||||
|
再用方形小贴图,有效分辨率能翻一倍多。
|
||||||
|
|
||||||
## Godot MCP 踩坑
|
## Godot MCP 踩坑
|
||||||
|
|
||||||
- **数值标量经 MCP 会被字符串化**:`node_set_property` 传 `0.15` 能写进去,但回显是 `"0.15"`;
|
- **数值标量经 MCP 会被字符串化**:`node_set_property` 传 `0.15` 能写进去,但回显是 `"0.15"`;
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 91 KiB |
@@ -0,0 +1,30 @@
|
|||||||
|
extends Control
|
||||||
|
## 游戏开始菜单 —— 只有界面,没有逻辑。
|
||||||
|
##
|
||||||
|
## 四个按钮按下去只把对应信号发出去:谁接、接了之后是加载世界、连服务器还是弹设置面板,
|
||||||
|
## 都不在这个文件里。这样菜单版式可以单独改,主流程也能单独换。
|
||||||
|
##
|
||||||
|
## 接线示例(放在外层,比如以后的主场景或一个菜单流程单例):
|
||||||
|
## menu.start_pressed.connect(_on_start)
|
||||||
|
## menu.multiplayer_pressed.connect(_on_multiplayer)
|
||||||
|
## menu.settings_pressed.connect(_on_settings)
|
||||||
|
## menu.quit_pressed.connect(get_tree().quit)
|
||||||
|
##
|
||||||
|
## 用法:把本场景设成 project.godot 的 application/run/main_scene 即可(这一步也没做)。
|
||||||
|
|
||||||
|
signal start_pressed
|
||||||
|
signal multiplayer_pressed
|
||||||
|
signal settings_pressed
|
||||||
|
signal quit_pressed
|
||||||
|
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
# 从游戏内退回菜单时鼠标可能还是被捕获的,先放出来 —— 不然菜单点不动。
|
||||||
|
# 这不算逻辑,是菜单能不能用的前提。
|
||||||
|
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
|
||||||
|
|
||||||
|
# 按钮只负责把 pressed 转发成信号,不在这里做任何决定。
|
||||||
|
%StartButton.pressed.connect(start_pressed.emit)
|
||||||
|
%MultiplayerButton.pressed.connect(multiplayer_pressed.emit)
|
||||||
|
%SettingsButton.pressed.connect(settings_pressed.emit)
|
||||||
|
%QuitButton.pressed.connect(quit_pressed.emit)
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://bx1ahrgpx5hvg
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
[gd_scene load_steps=7 format=3]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://ui/main_menu.gd" id="1_menu"]
|
||||||
|
|
||||||
|
[sub_resource type="Gradient" id="Gradient_bg"]
|
||||||
|
offsets = PackedFloat32Array(0, 0.55, 1)
|
||||||
|
colors = PackedColorArray(0.09, 0.3, 0.78, 1, 0.28, 0.6, 0.95, 1, 0.78, 0.88, 1, 1)
|
||||||
|
|
||||||
|
[sub_resource type="GradientTexture2D" id="GradientTexture2D_bg"]
|
||||||
|
gradient = SubResource("Gradient_bg")
|
||||||
|
width = 4
|
||||||
|
height = 512
|
||||||
|
fill_from = Vector2(0.5, 0)
|
||||||
|
fill_to = Vector2(0.5, 1)
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_normal"]
|
||||||
|
content_margin_left = 20.0
|
||||||
|
content_margin_top = 10.0
|
||||||
|
content_margin_right = 20.0
|
||||||
|
content_margin_bottom = 10.0
|
||||||
|
bg_color = Color(1, 1, 1, 0.14)
|
||||||
|
border_width_left = 2
|
||||||
|
border_width_top = 2
|
||||||
|
border_width_right = 2
|
||||||
|
border_width_bottom = 2
|
||||||
|
border_color = Color(1, 1, 1, 0.5)
|
||||||
|
corner_radius_top_left = 12
|
||||||
|
corner_radius_top_right = 12
|
||||||
|
corner_radius_bottom_right = 12
|
||||||
|
corner_radius_bottom_left = 12
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_hover"]
|
||||||
|
content_margin_left = 20.0
|
||||||
|
content_margin_top = 10.0
|
||||||
|
content_margin_right = 20.0
|
||||||
|
content_margin_bottom = 10.0
|
||||||
|
bg_color = Color(1, 1, 1, 0.32)
|
||||||
|
border_width_left = 2
|
||||||
|
border_width_top = 2
|
||||||
|
border_width_right = 2
|
||||||
|
border_width_bottom = 2
|
||||||
|
border_color = Color(1, 1, 1, 0.85)
|
||||||
|
corner_radius_top_left = 12
|
||||||
|
corner_radius_top_right = 12
|
||||||
|
corner_radius_bottom_right = 12
|
||||||
|
corner_radius_bottom_left = 12
|
||||||
|
|
||||||
|
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_pressed"]
|
||||||
|
content_margin_left = 20.0
|
||||||
|
content_margin_top = 10.0
|
||||||
|
content_margin_right = 20.0
|
||||||
|
content_margin_bottom = 10.0
|
||||||
|
bg_color = Color(0.05, 0.12, 0.3, 0.35)
|
||||||
|
border_width_left = 2
|
||||||
|
border_width_top = 2
|
||||||
|
border_width_right = 2
|
||||||
|
border_width_bottom = 2
|
||||||
|
border_color = Color(1, 1, 1, 0.95)
|
||||||
|
corner_radius_top_left = 12
|
||||||
|
corner_radius_top_right = 12
|
||||||
|
corner_radius_bottom_right = 12
|
||||||
|
corner_radius_bottom_left = 12
|
||||||
|
|
||||||
|
[node name="MainMenu" type="Control"]
|
||||||
|
layout_mode = 3
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
script = ExtResource("1_menu")
|
||||||
|
|
||||||
|
[node name="Background" type="TextureRect" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
texture = SubResource("GradientTexture2D_bg")
|
||||||
|
expand_mode = 1
|
||||||
|
|
||||||
|
[node name="Center" type="CenterContainer" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 15
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
|
mouse_filter = 2
|
||||||
|
|
||||||
|
[node name="Box" type="VBoxContainer" parent="Center"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_constants/separation = 18
|
||||||
|
|
||||||
|
[node name="Title" type="Label" parent="Center/Box"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_colors/font_color = Color(1, 1, 1, 1)
|
||||||
|
theme_override_colors/font_outline_color = Color(0.05, 0.1, 0.25, 0.85)
|
||||||
|
theme_override_constants/outline_size = 14
|
||||||
|
theme_override_font_sizes/font_size = 72
|
||||||
|
text = "AGAME"
|
||||||
|
horizontal_alignment = 1
|
||||||
|
|
||||||
|
[node name="Buttons" type="VBoxContainer" parent="Center/Box"]
|
||||||
|
layout_mode = 2
|
||||||
|
theme_override_colors/font_color = Color(1, 1, 1, 0.92)
|
||||||
|
theme_override_colors/font_focus_color = Color(1, 1, 1, 0.92)
|
||||||
|
theme_override_colors/font_hover_color = Color(1, 1, 1, 1)
|
||||||
|
theme_override_colors/font_pressed_color = Color(1, 1, 1, 1)
|
||||||
|
theme_override_constants/separation = 12
|
||||||
|
theme_override_font_sizes/font_size = 24
|
||||||
|
theme_override_styles/focus = SubResource("StyleBoxFlat_hover")
|
||||||
|
theme_override_styles/hover = SubResource("StyleBoxFlat_hover")
|
||||||
|
theme_override_styles/normal = SubResource("StyleBoxFlat_normal")
|
||||||
|
theme_override_styles/pressed = SubResource("StyleBoxFlat_pressed")
|
||||||
|
|
||||||
|
[node name="StartButton" type="Button" parent="Center/Box/Buttons"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(280, 54)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "开始游戏"
|
||||||
|
|
||||||
|
[node name="MultiplayerButton" type="Button" parent="Center/Box/Buttons"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(280, 54)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "联机"
|
||||||
|
|
||||||
|
[node name="SettingsButton" type="Button" parent="Center/Box/Buttons"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(280, 54)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "设置"
|
||||||
|
|
||||||
|
[node name="QuitButton" type="Button" parent="Center/Box/Buttons"]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
custom_minimum_size = Vector2(280, 54)
|
||||||
|
layout_mode = 2
|
||||||
|
text = "退出"
|
||||||
|
|
||||||
|
[node name="Version" type="Label" parent="."]
|
||||||
|
layout_mode = 1
|
||||||
|
anchors_preset = 3
|
||||||
|
anchor_left = 1.0
|
||||||
|
anchor_top = 1.0
|
||||||
|
anchor_right = 1.0
|
||||||
|
anchor_bottom = 1.0
|
||||||
|
offset_left = -180.0
|
||||||
|
offset_top = -40.0
|
||||||
|
offset_right = -18.0
|
||||||
|
offset_bottom = -14.0
|
||||||
|
grow_horizontal = 0
|
||||||
|
grow_vertical = 0
|
||||||
|
mouse_filter = 2
|
||||||
|
theme_override_colors/font_color = Color(1, 1, 1, 0.6)
|
||||||
|
theme_override_colors/font_outline_color = Color(0.05, 0.1, 0.25, 0.6)
|
||||||
|
theme_override_constants/outline_size = 4
|
||||||
|
theme_override_font_sizes/font_size = 14
|
||||||
|
text = "v0.1"
|
||||||
|
horizontal_alignment = 2
|
||||||
Reference in New Issue
Block a user