🐸 《青蛙过河》AI Agent 实操工作台 Godot 4.7

全流程 14 步跟练指南与 AI Agent 提示词

按顺序完成编辑器设置并复制提示词发给 Agent(通过 MCP 或文件写入自动改好工程)
#00

导入外部素材包(贴图/音频/字体)、像素滤镜设置与新建场景

上篇 P4 · (工程与素材准备)
🛠️ Godot 4.7 编辑器操作步骤 目标:project.godot, res://scenes/game.tscn & player.tscn
  1. 1. 导入外部素材文件夹到 Godot(如何添加素材):
    • 打开 Finder(访达)/ 资源管理器,找到解压后的 课程素材/ 文件夹(内含 audio、fonts、graphics 三个子文件夹)。
    • 直接用鼠标将这三个文件夹拖拽到 Godot 左下角的 FileSystem(文件系统) 面板的 res:// 根目录下(或者直接复制到工程文件夹根目录中,Godot 会自动扫描并生成 .import 导入文件)。
    • 在 FileSystem 面板右键点击 res:// → 选择 New Folder...(新建文件夹) → 输入 scenes 点击 OK,用于存放后续所有的场景(.tscn)和脚本(.gd)。
  2. 2. 设置像素高清滤镜与窗口分辨率(如何设置工程):
    • 点击顶部菜单 Project(项目) → Project Settings(项目设置)。
    • 窗口尺寸设置:在左侧找到 General → Display → Window,将 Size → Viewport Width 设为 1280,Viewport Height 设为 720。
    • 像素画去模糊设置:在左侧找到 General → Rendering → Textures → Canvas Textures,将 Default Texture Filter 从默认的 Linear 下拉修改为 Nearest(最近邻过滤),点击 Close 保存。
  3. 3. 创建主场景 game.tscn 并添加地图背景贴图:
    • 在左上角 Scene(场景) 面板点击 2D Scene(2D 场景) 创建根节点,双击将名称从 Node2D 改为 Game。
    • 右键点击 Game → 选择 Add Child Node...(添加子节点,快捷键 Cmd/Ctrl + A) → 搜索并双击 Sprite2D(精灵节点,专门用于显示 2D 图片素材)。
    • 在左下角 FileSystem 中展开 res://graphics/,按住 map.png(尺寸 384×640)直接拖拽到右侧 Inspector(检查器) 的 Texture(纹理) 槽位中。
    • 按 Cmd/Ctrl + S 保存场景,路径选择 res://scenes/game.tscn。
  4. 4. 创建玩家场景 player.tscn 并实例化到主场景:
    • 点击 2D 视口顶部标签栏右侧的 + 号新建场景 → 点击 2D Scene 创建根节点并改名为 Player。
    • 为 Player 添加子节点 Sprite2D,将 res://graphics/player/player_simple.png 拖拽到右侧检查器的 Texture 槽位中,按 Cmd/Ctrl + S 保存为 res://scenes/player.tscn。
    • 切回顶部 game 场景标签页,选中根节点 Game,点击左上角场景面板顶部的「锁链图标」(Instantiate Child Scene / 实例化子场景,快捷键 Cmd/Ctrl + Shift + A),双击选择 player.tscn,将玩家放入地图中!
🤖 AI Agent 提示词(MCP / 文件写入)
请通过 Godot MCP 或直接读写项目文件的方式,帮我检查并配置当前 Godot 4.7 工程的基础设置与初始场景:

1. 检查 `project.godot`:
   - 确保 `[display]` 下窗口视口尺寸设置为 `window/size/viewport_width=1280` 和 `window/size/viewport_height=720`
   - 确保 `[rendering]` 下默认纹理过滤设置为最近邻像素模式:`textures/canvas_textures/default_texture_filter=0`(Nearest)
2. 检查 `res://scenes/player.tscn` 和 `res://scenes/game.tscn`:
   - 确保 `player.tscn` 包含根节点 `Player` 及挂载了 `res://graphics/player/player_simple.png` 的子节点
   - 确保 `game.tscn` 包含挂载了 `res://graphics/map.png` 的背景 `Sprite2D` 以及实例化的 `Player` 节点。
✅ 验证标准:按 F5 运行项目(首次运行弹窗点击 Select Current 将 game.tscn 设为主场景):窗口以 1280×720 打开,地图和玩家小人边缘呈现锐利清晰的像素颗粒感,不再模糊!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/00.[初始项目]frogger)· 标准参考代码 点击展开 / 收起
📌 核心原理:从零开发游戏的第一步是把美术贴图(graphics)、音效(audio)、字体(fonts)导入 Godot 的 res:// 资源根目录,并把默认的平滑双线性过滤(Linear)改为像素最近邻过滤(Nearest),否则低分辨率像素画放大后会严重模糊发虚。
📂 防掉队快照工程:项目文件/00.[初始项目]frogger(节点:FileSystem 素材导入 / Project Settings / Sprite2D)
📄 project.godot, res://scenes/game.tscn & player.tscn(标准参考内容 / 备用直接复制)
# project.godot 核心配置项参考:
[display]
window/size/viewport_width=1280
window/size/viewport_height=720

[rendering]
textures/canvas_textures/default_texture_filter=0
#01

为节点附加 GDScript 脚本与首段坐标位移

上篇 P4 · 00:05:30
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/player.gd & exercise_object.gd
  1. 如何在 Godot 中为节点创建并附加脚本:
    • 打开 res://scenes/player.tscn,在左侧场景树点击选中根节点 Player。
    • 点击场景面板右上角的「带绿色 + 号的卷轴图标」(Attach Script / 附加脚本)。
    • 在弹出的窗口中核对:Language = GDScript,Inherits = Node2D,Template = Empty(取消勾选或选空模板),Path = res://scenes/player.gd,点击 Create。
  2. 让 Agent 直接写入首段位移代码:复制下方【Prompt #01】发送给你的 AI Agent,让 Agent 直接通过文件写入或 MCP 工具修改 res://scenes/player.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接修改当前 Godot 4.7 工程中的 `res://scenes/player.gd` 文件(挂载在 `Node2D` 类型的 `Player` 节点上),实现《青蛙过河》角色的基础坐标位移测试:

1. 定义成员变量:
   - `var direction: Vector2 = Vector2(1, 1)`(默认朝右下方移动)
   - `var speed: int = 5`(每帧移动像素步长)
2. 编写物理帧函数 `func _physics_process(_delta: float) -> void:`:
   - 每帧更新自身坐标:`position += direction * speed`

如果工程中存在 `res://scenes/exercise_object.gd`,也请将其更新为在 `_physics_process` 中执行 `scale = scale * 1.001`。
✅ 验证标准:按 F5 运行项目:小青蛙无需按键就会自动沿着右下方对角线方向(Vector2(1, 1))平滑移动;若同时测试了 exercise_object.gd,练习物体会每帧自动缓慢放大。
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/01.frogger basic setup)· 标准参考代码 点击展开 / 收起
📌 核心原理:场景搭好后需要用脚本赋予节点行为。Godot 的 _physics_process(_delta) 函数默认每秒固定执行 60 次,在其中修改 position 或 scale 属性,就能让节点每帧发生位移或缩放。
📂 防掉队快照工程:项目文件/01.frogger basic setup(节点:Player (Node2D) 附加脚本)
📄 res://scenes/player.gd & exercise_object.gd(标准参考内容 / 备用直接复制)
# --- res://scenes/player.gd ---
extends Node2D

var direction: Vector2 = Vector2(1, 1)
var speed: int = 5

func _physics_process(_delta: float) -> void:
	position += direction * speed


# --- res://scenes/exercise_object.gd (可选) ---
extends Node2D

func _physics_process(_delta: float) -> void:
	scale = scale * 1.001
#02

Input Map 按键映射设置与玩家八向按键控制

上篇 P4 · 00:12:09
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/player.gd & project.godot
  1. 如何在 Godot 中配置键盘输入映射(Input Map):
    • 点击顶部菜单 Project(项目) → Project Settings(项目设置),切换到顶部的 Input Map(输入映射) 标签页。
    • 在顶部 Add New Action 输入框中依次输入动作名并点击右侧 Add 按钮添加(注意字母全部小写):left、right、up、down、confirm。
    • 点击每个动作名右侧的 + 号图标(Add Event),直接按下键盘对应按键并点击 OK 完成绑定:
    - left:绑定 A 键 与 ← 左方向键
    - right:绑定 D 键 与 → 右方向键
    - up:绑定 W 键 与 ↑ 上方向键
    - down:绑定 S 键 与 ↓ 下方向键
    - confirm:绑定 Space(空格键)
  2. 让 Agent 直接更新 player.gd:复制下方【Prompt #02】发送给 Agent,直接写入 res://scenes/player.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接修改当前 Godot 4.7 工程中的 `res://scenes/player.gd` 文件,将固定方向移动升级为通过 Input Map 获取玩家键盘输入:

1. 保留成员变量 `var direction: Vector2 = Vector2(1, 1)` 和 `var speed: int = 5`。
2. 在 `_physics_process(_delta: float) -> void` 中:
   - 使用 `Input.get_vector("left", "right", "up", "down")` 获取玩家的四向/八向输入向量并赋值给 `direction`
   - 更新坐标:`position += direction * speed`
   - 检测如果刚刚按下 `"confirm"` 动作(`Input.is_action_just_pressed("confirm")`),则在控制台打印 `print('something')`
✅ 验证标准:按 F5 运行游戏:松开键盘时青蛙静止不动;按 W/A/S/D 或方向键可朝 8 个方向移动;按下空格键(confirm)时,底部 Output 控制台打印出 'something'。
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/02.frogger input)· 标准参考代码 点击展开 / 收起
📌 核心原理:通过 Input Map(输入映射)将键盘 W/A/S/D、方向键和空格键绑定为语义化的动作名称(left/right/up/down/confirm),再用 Input.get_vector() 即可一行代码自动处理斜向移动的速度归一化。
📂 防掉队快照工程:项目文件/02.frogger input(节点:Project Settings -> Input Map)
📄 res://scenes/player.gd & project.godot(标准参考内容 / 备用直接复制)
extends Node2D

var direction: Vector2 = Vector2(1, 1)
var speed: int = 5

func _physics_process(_delta: float) -> void:
	direction = Input.get_vector("left", "right", "up", "down")
	position += direction * speed
	
	if Input.is_action_just_pressed("confirm"):
		print('something')
#03

添加 Camera2D 跟随相机、4倍缩放与地图边界锁定设置

上篇 P4 · 00:20:38
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/player.tscn
  1. 1. 添加 Camera2D 节点:打开 res://scenes/player.tscn,右键根节点 Player → 选择 Add Child Node... → 搜索并双击添加 Camera2D。
  2. 2. 设置 4 倍镜头缩放(Zoom):选中 Camera2D,在右侧 Inspector(检查器) 找到 Zoom,将 x 和 y 均设为 4.0(画面放大 4 倍)。
  3. 3. 设置相机边界(Limit)不超出地图:在检查器中展开 Limit 折叠栏(地图宽 384、高 640,中心在原点,因此左/右各 ±192,上/下各 ±320):
    • Left = -192  |  Top = -320
    • Right = 192  |  Bottom = 320
  4. 4. 开启平滑跟随(Position Smoothing):展开检查器中的 Position Smoothing,勾选 Enabled = On,将 Speed 设为 20.0 px/s,按 Cmd/Ctrl + S 保存场景。
🤖 AI Agent 提示词(MCP / 文件写入)
请通过 Godot MCP 或直接修改 `res://scenes/player.tscn` 场景文件,确保 `Player` 节点下包含名为 `Camera2D` 的子节点,并为其配置好以下属性:

1. `zoom = Vector2(4, 4)`
2. 相机边界限制:`limit_left = -192`、`limit_top = -320`、`limit_right = 192`、`limit_bottom = 320`
3. 开启平滑跟随:`position_smoothing_enabled = true`,平滑速度 `position_smoothing_speed = 20.0`
✅ 验证标准:按 F5 运行游戏:画面以清晰的 4 倍街机视角跟随青蛙平滑移动,且当青蛙靠近地图四周边缘时,镜头自动停在地图边界内,绝不露出外部灰底!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/03.frogger camera)· 标准参考代码 点击展开 / 收起
📌 核心原理:将 Camera2D 挂载为 Player 的子节点后,相机会自动跟随青蛙移动。通过设置 Zoom = (4, 4) 放大像素画面,并用 Limit 属性锁死相机上下左右边界,就能防止镜头拍到地图外的黑边。
📂 防掉队快照工程:项目文件/03.frogger camera(节点:Player -> Camera2D)
📄 res://scenes/player.tscn(标准参考内容 / 备用直接复制)
# player.tscn 中的 Camera2D 节点配置参考:
[node name="Camera2D" type="Camera2D" parent="."]
zoom = Vector2(4, 4)
limit_left = -192
limit_top = -320
limit_right = 192
limit_bottom = 320
position_smoothing_enabled = true
position_smoothing_speed = 20.0
#04

物理引擎与机械能实验:添加碰撞体与重构 CharacterBody2D

上篇 P4 · 00:26:18
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/player.gd, player.tscn & tree.tscn
  1. 1. 【教师现场演示 / 学员体验】机械能物理实验:双击打开 res://scenes/physics_demo.tscn 按 F6 运行,观察 FallingBox_RigidBody2D 在重力作用下加速下落(重力势能 → 动能),并在检查器中调节 Physics Material Override → Bounce(0.0 ~ 1.0) 观察碰撞反弹中的机械能转化。
  2. 2. 制作带碰撞体的树木场景(tree.tscn):
    • 新建或打开 res://scenes/tree.tscn,根节点选 StaticBody2D 并改名为 Tree。
    • 添加子节点 Sprite2D,从 FileSystem 将 res://graphics/objects/tree1.png 拖入右侧检查器 Texture。
    • 右键根节点 Tree 添加子节点 CollisionShape2D(碰撞形状) → 在右侧检查器点击 Shape 旁的 <empty> → 选择 New RectangleShape2D → 点击该矩形资源展开,将 Size 设为 x = 10, y = 18 px,按 Cmd/Ctrl + S 保存。
  3. 3. 将 Player 升级为 CharacterBody2D 并添加脚部碰撞框:
    • 打开 res://scenes/player.tscn,右键根节点 Player → 选择 Change Type...(更改类型) → 搜索并双击 CharacterBody2D。
    • 右键 Player 添加子节点 CollisionShape2D → 右侧检查器 Shape 新建 New RectangleShape2D → 将 Size 设为 x = 12, y = 8 px(只框住角色下半身脚部,这样头部靠近树干时更自然)。
  4. 4. 让 Agent 重构 player.gd 为物理速度驱动:复制下方【Prompt #04】发送给 Agent,直接修改 res://scenes/player.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
我已经将 `Player` 节点的类型更改为 `CharacterBody2D`,请直接修改当前 Godot 4.7 工程中的 `res://scenes/player.gd` 文件,使用物理引擎驱动角色移动:

1. 将脚本第一行继承声明改为 `extends CharacterBody2D`。
2. 成员变量:
   - `var direction: Vector2 = Vector2(1, 1)`
   - `var speed: int = 200`(物理速度单位为像素/秒)
3. 在 `_physics_process(_delta: float) -> void` 中:
   - 使用 `Input.get_vector("left", "right", "up", "down")` 获取输入向量赋给 `direction`
   - 将内置速度属性 `velocity` 设为 `direction * speed`
   - 调用 `move_and_slide()` 执行物理碰撞移动(移除原有的 `position += ...`)
   - 保留按下 `"confirm"` 打印 `'something'` 的测试逻辑
✅ 验证标准:按 F5 运行主游戏:操控小青蛙撞向树木(Tree)或地图四周空气墙(Borders),青蛙会被稳稳挡住不再穿模,斜向撞墙时还会顺滑地沿墙滑动!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/04.physics)· 标准参考代码 点击展开 / 收起
📌 核心原理:直接改 position 会无视墙壁穿模而过!本步先通过刚体(RigidBody2D)实验观察重力势能转化为动能与弹性碰撞反弹,再为树木和地图边界添加 StaticBody2D 碰撞框,并将玩家重构为受 velocity 和 move_and_slide() 驱动的 CharacterBody2D。
📂 防掉队快照工程:项目文件/04.physics(节点:CharacterBody2D / StaticBody2D / CollisionShape2D)
📄 res://scenes/player.gd, player.tscn & tree.tscn(标准参考内容 / 备用直接复制)
extends CharacterBody2D

var direction: Vector2 = Vector2(1, 1)
var speed: int = 200

func _physics_process(_delta: float) -> void:
	direction = Input.get_vector("left", "right", "up", "down")
	velocity = direction * speed
	move_and_slide()
	
	if Input.is_action_just_pressed("confirm"):
		print('something')
#05

导入精灵表(SpriteSheet)切帧设置与四向行走动画状态机

上篇 P4 · 00:37:40
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/player.tscn & player.gd
  1. 1. 在 player.tscn 中添加 AnimatedSprite2D 并导入精灵表素材:
    • 打开 res://scenes/player.tscn,删除原有的静态 Sprite2D 节点(或隐藏),右键 Player 添加子节点 AnimatedSprite2D。
    • 在右侧检查器找到 Animation → Sprite Frames,点击 <empty> 选择 New SpriteFrames,然后再次点击它打开底部的 SpriteFrames(精灵帧) 动画面板。
  2. 2. 网格切分精灵表(如何切帧设置动画):
    • 在底部 Animations 列表将默认的 default 改名为 down。
    • 点击底部面板工具栏上的「小网格图标」(Add frames from sprite sheet / 从精灵表添加帧),在弹窗中选择 res://graphics/player/player_tileset.png。
    • 在切帧弹窗右上角将分割网格设置为 Horizontal(水平列数) = 3、Vertical(垂直行数) = 3(此时 48×48 的图片被精准切成 9 个 16×16 的格子)。
    • 按顺序点选中间一列的帧组成 down 动画(5 FPS,开启循环 Loop);同理点击左上角新增动画按钮,分别创建 left(左列帧)和 up(右列帧)动画。
  3. 3. 让 Agent 编写四向动画切换函数 animation():复制下方【Prompt #05】发送给 Agent,直接更新 res://scenes/player.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接修改当前 Godot 4.7 工程中的 `res://scenes/player.gd` 文件,为子节点 `$AnimatedSprite2D` 增加四向行走动画切换与静止立定控制:

1. 在 `_physics_process(_delta: float) -> void` 中,在计算出 `velocity = direction * speed` 之后、`move_and_slide()` 之前,调用自定义函数 `animation()`。
2. 编写 `func animation() -> void:`:
   - 当 `direction` 不为零向量(`if direction:`,角色正在移动)时:
     - 根据 `direction.x > 0` 设置水平镜像翻转:`$AnimatedSprite2D.flip_h = direction.x > 0`
     - 如果水平方向有移动(`if direction.x != 0:`),将 `$AnimatedSprite2D.animation` 设为 `'left'`
     - 否则(纯上下移动),如果 `direction.y < 0` 则设为 `'up'`,否则设为 `'down'`
   - 当 `direction` 为零向量(`else:`,角色静止)时:
     - 将动画帧固定在第 0 帧站立姿态:`$AnimatedSprite2D.frame = 0`
✅ 验证标准:按 F5 运行游戏:按上/下/左/右移动时自动播放对应方向的迈步帧动画,朝右走时自动水平翻转 left 动画;松开按键的瞬间,角色立即锁定在 frame = 0 的双脚站立帧!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/05.animation)· 标准参考代码 点击展开 / 收起
📌 核心原理:如何把一张包含 9 个小人的大图(player_tileset.png)变成会动的小青蛙?Godot 的 AnimatedSprite2D 支持按行列网格自动切分精灵表,配合代码判断 direction 的正负与镜像翻转(flip_h),即可实现四向行走与松手立定。
📂 防掉队快照工程:项目文件/05.animation(节点:Player -> AnimatedSprite2D (SpriteFrames))
📄 res://scenes/player.tscn & player.gd(标准参考内容 / 备用直接复制)
extends CharacterBody2D

var direction: Vector2 = Vector2(1, 1)
var speed: int = 200

func _physics_process(_delta: float) -> void:
	direction = Input.get_vector("left", "right", "up", "down")
	velocity = direction * speed
	animation()
	move_and_slide()
	
	if Input.is_action_just_pressed("confirm"):
		print('something')

func animation() -> void:
	if direction:
		$AnimatedSprite2D.flip_h = direction.x > 0
		if direction.x != 0:
			$AnimatedSprite2D.animation = 'left'
		else:
			$AnimatedSprite2D.animation = 'up' if direction.y < 0 else 'down'
	else:
		$AnimatedSprite2D.frame = 0
#06

Signal 信号通信机制:添加北侧终点传感器区域(FinishArea2D)

上篇 P4 · 00:49:32
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/game.tscn & game.gd
  1. 1. 在 game.tscn 中添加终点传感器 Area2D:
    • 打开 res://scenes/game.tscn,右键 Borders 节点 → Add Child Node... → 选择 Area2D 并重命名为 FinishArea2D。
    • 右键 FinishArea2D 添加子节点 CollisionShape2D,在右侧检查器 Shape 新建 New RectangleShape2D,将尺寸设为 x = 385, y = 117 px,位置拖到地图最北侧红砖安全区(Position = (0, -259.5))。
  2. 2. 为 Game 根节点附加脚本并连接信号:
    • 选中根节点 Game,点击右上角「附加脚本」图标,路径设为 res://scenes/game.gd 点击 Create。
    • 选中 Borders/FinishArea2D → 点击右侧检查器旁的 Node(节点) → Signals(信号) 标签页 → 双击 body_entered(body: Node2D) → 在弹窗中选中 Game 根节点,点击 Connect。
  3. 3. 让 Agent 编写信号测试回调:复制下方【Prompt #06】发给 Agent,直接更新 res://scenes/game.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接创建或修改当前 Godot 4.7 工程中的 `res://scenes/game.gd` 文件(挂载在 `Game` 根节点 `Node2D` 上),并确保 `Borders/FinishArea2D` 的 `body_entered` 信号已连接到 `_on_finish_area_2d_body_entered`:

1. 脚本继承自 `Node2D`。
2. 编写终点区域信号回调函数 `func _on_finish_area_2d_body_entered(body: Node2D) -> void:`:
   - 在控制台打印进入该区域的物理体对象 `print(body)`
   - 在控制台打印提示字符串 `print("has entered")`
✅ 验证标准:按 F5 运行游戏:操纵小青蛙穿过马路跑进最北侧红砖终点区,底部 Output 控制台立即打印出进入区域的节点信息 `Player:` 和 `has entered`!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/06.signals)· 标准参考代码 点击展开 / 收起
📌 核心原理:Area2D 是不会阻挡玩家移动的“隐形感应区”。当玩家的 CharacterBody2D 踏入北侧终点 Area2D 时,它会自动发出 body_entered 信号通知 Game 根节点执行通关逻辑。
📂 防掉队快照工程:项目文件/06.signals(节点:Borders/FinishArea2D (Area2D) -> Game)
📄 res://scenes/game.tscn & game.gd(标准参考内容 / 备用直接复制)
extends Node2D

func _on_finish_area_2d_body_entered(body: Node2D) -> void:
	print(body)
	print("has entered")
#07

新建独立汽车场景(car.tscn)、双向自动调头与出屏自动销毁

下篇 P5 · 00:00:00
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/car.tscn & car.gd
  1. 1. 从零新建汽车场景 car.tscn 并添加贴图素材:
    • 点击顶部场景标签栏的 + 号新建场景 → 点击 Other Node(其他节点) → 搜索并选择 Area2D,将根节点改名为 Car。
    • 添加子节点 Sprite2D,从左下角 FileSystem 将 res://graphics/cars/yellow.png 拖拽到右侧检查器 Texture 槽位。
    • 添加子节点 CollisionShape2D,右侧新建 New RectangleShape2D,设置尺寸为 x = 24, y = 10 px,Position = (0, 1)。
    • 添加子节点 VisibleOnScreenNotifier2D(屏幕可见性通知器),按 Cmd/Ctrl + S 保存为 res://scenes/car.tscn。
  2. 2. 附加 car.gd 脚本并连接出屏信号:
    • 选中根节点 Car 附加脚本 res://scenes/car.gd。
    • 选中 VisibleOnScreenNotifier2D → 右侧 Node → Signals 双击 screen_exited() → 连接到 Car 根节点。
  3. 3. 让 Agent 写入汽车移动与销毁代码:复制下方【Prompt #07】发给 Agent,直接修改 res://scenes/car.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接创建或修改当前 Godot 4.7 工程中的 `res://scenes/car.gd` 文件(挂载在 `car.tscn` 的根节点 `Car` `Area2D` 上),实现汽车双向行驶判断与出屏自动销毁:

1. 定义成员变量:
   - `var direction = Vector2.LEFT`(默认向左行驶)
   - `var speed = 2`(基础测试速度)
2. 在 `_ready() -> void` 中自动根据出生坐标判断行驶方向:
   - 如果 `position.x < 0`(说明出生在马路左侧边缘),则将 `direction.x = 1`(改为向右行驶),并将 `$Sprite2D.flip_h = true`(水平翻转车头贴图朝右)
3. 在 `_process(delta: float) -> void` 中更新位置:
   - `position += direction * speed`
4. 在 `VisibleOnScreenNotifier2D` 的屏幕退出信号回调 `func _on_visible_on_screen_notifier_2d_screen_exited() -> void:` 中:
   - 调用 `queue_free()` 销毁当前汽车节点
✅ 验证标准:在 car.tscn 标签页按 F6 单独运行汽车场景:小黄车自动向左行驶,并在驶出窗口边界的瞬间触发 queue_free() 自动销毁!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/07.spawning)· 标准参考代码 点击展开 / 收起
📌 核心原理:游戏里会有几十辆汽车同时在马路上跑,因此必须把汽车单独做成一个可复用的 car.tscn 场景模板!同时添加 VisibleOnScreenNotifier2D 节点,当汽车驶出屏幕时调用 queue_free() 自动销毁,防止内存无限增长。
📂 防掉队快照工程:项目文件/07.spawning(节点:Car (Area2D) -> VisibleOnScreenNotifier2D)
📄 res://scenes/car.tscn & car.gd(标准参考内容 / 备用直接复制)
extends Area2D

var direction = Vector2.LEFT
var speed = 2

func _ready() -> void:
	if position.x < 0:
		direction.x = 1
		$Sprite2D.flip_h = true

func _process(delta: float) -> void:
	position += direction * speed

func _on_visible_on_screen_notifier_2d_screen_exited() -> void:
	queue_free()
#08

添加 Marker2D 9车道出生点与 CarTimer 定时随机车流生成器

下篇 P5 · 00:07:30
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/game.tscn & game.gd
  1. 1. 在 game.tscn 中布置 9 个车道出生点(Marker2D):
    • 在 game.tscn 下新建一个 Node2D 容器并命名为 CarStartPositions。
    • 在其下添加 9 个 Marker2D 子节点(选中一个按 Cmd/Ctrl + D 可快速复制),分别拖放到上下两段马路共 9 条车道的左边缘(x = -205)和右边缘(x = 203)。
    • 同时在 Game 下新建一个 Node2D 容器命名为 Objects(把 Player 拖入其中,后续生成的汽车也放入其中)。
  2. 2. 添加并设置 CarTimer 定时器:
    • 在 Game(或 Timer 容器)下添加子节点 Timer 并改名为 CarTimer。
    • 在右侧检查器设置:Wait Time = 0.25 s(每 0.25 秒刷一辆车),勾选 Autostart = On(游戏启动自动开始计时)。
    • 在右侧 Node → Signals 双击 CarTimer 的 timeout() 信号,连接到 Game 根节点的 _on_car_timer_timeout。
  3. 3. 让 Agent 编写随机车道刷车逻辑:复制下方【Prompt #08】发给 Agent,直接更新 res://scenes/game.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接修改当前 Godot 4.7 工程中的 `res://scenes/game.gd` 文件,新增基于 `CarTimer` 和 `$CarStartPositions` 的汽车定时随机生成系统:

1. 在脚本顶部使用 `preload("res://scenes/car.tscn")` 预加载汽车场景:`var car_scene: PackedScene = preload("res://scenes/car.tscn")`。
2. 保留原有的 `_on_finish_area_2d_body_entered(body: Node2D)` 函数。
3. 编写 `CarTimer` 的超时回调函数 `func _on_car_timer_timeout() -> void:`:
   - 实例化汽车场景:`var car = car_scene.instantiate() as Area2D`
   - 从 `$CarStartPositions.get_children()` 中调用 `.pick_random()` 随机抽取一个 `Marker2D` 出生点:`var pos_marker = $CarStartPositions.get_children().pick_random() as Marker2D`
   - 将 `car.position` 设为 `pos_marker.position`
   - 将 `car` 添加为 `$Objects` 节点的子节点:`$Objects.add_child(car)`
✅ 验证标准:按 F5 运行主游戏:马路上的 9 条车道每隔 0.25 秒随机刷出汽车,左侧车道自动向右行驶,右侧车道自动向左行驶!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/07.spawning)· 标准参考代码 点击展开 / 收起
📌 核心原理:Marker2D 是专门用于在编辑器里标记坐标位置的轻量级十字节点。我们在 9 条车道的左右起点各放一个 Marker2D,再用 Timer 定时器每隔 0.25 秒随机挑一个 Marker2D 的坐标生成汽车,就能形成变幻莫测的双向车流!
📂 防掉队快照工程:项目文件/07.spawning(节点:CarStartPositions (9×Marker2D) & Timer/CarTimer)
📄 res://scenes/game.tscn & game.gd(标准参考内容 / 备用直接复制)
extends Node2D

var car_scene: PackedScene = preload("res://scenes/car.tscn")

func _on_finish_area_2d_body_entered(body: Node2D) -> void:
	print(body)
	print("has entered")

func _on_car_timer_timeout() -> void:
	var car = car_scene.instantiate() as Area2D
	var pos_marker = $CarStartPositions.get_children().pick_random() as Marker2D
	car.position = pos_marker.position
	$Objects.add_child(car)
#09

Delta 帧间隔时间修正:实现跨刷新率设备的绝对匀速运动

下篇 P5 · 00:15:46
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/car.gd
  1. 理解帧间隔时间(Delta Time)公式:每秒位移 = 每秒帧数(FPS) × speed × delta。因为 FPS × delta ≡ 1,所以乘上 delta 后可彻底消除不同显示器刷新率带来的速度差异。
  2. 让 Agent 修改 car.gd 引入 delta:复制下方【Prompt #09】发给 Agent,直接更新 res://scenes/car.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接修改当前 Godot 4.7 工程中的 `res://scenes/car.gd` 文件,引入帧间隔时间 `delta` 修正汽车行驶速度:

1. 将成员变量 `speed` 从 `2` 修改为 `100`(代表每秒移动 100 像素)。
2. 在 `_process(delta: float) -> void` 中,将位置更新公式修改为:
   `position += direction * speed * delta`
3. 保持 `_ready()` 和 `_on_visible_on_screen_notifier_2d_screen_exited()` 不变。
✅ 验证标准:按 F5 运行游戏:所有汽车以每秒 100 像素的标准街机速度平稳行驶,不再受帧率波动影响!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/08.delta)· 标准参考代码 点击展开 / 收起
📌 核心原理:_process(delta) 的执行频率取决于电脑帧率(30FPS 下 delta=0.033s,120FPS 下 delta=0.008s)。如果不乘 delta,高刷屏上的汽车会变成失控超跑!乘上 delta 后,speed = 100 就严格等于「每秒移动 100 像素」。
📂 防掉队快照工程:项目文件/08.delta(节点:Car (_process delta 参数))
📄 res://scenes/car.gd(标准参考内容 / 备用直接复制)
extends Area2D

var direction = Vector2.LEFT
var speed = 100

func _ready() -> void:
	if position.x < 0:
		direction.x = 1
		$Sprite2D.flip_h = true

func _process(delta: float) -> void:
	position += direction * speed * delta

func _on_visible_on_screen_notifier_2d_screen_exited() -> void:
	queue_free()
#10

配置 Collision Layer/Mask 碰撞层矩阵与代码动态绑定人车碰撞信号

下篇 P5 · 00:24:20
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/game.gd, player.tscn & car.tscn
  1. 1. 如何在 Godot 检查器中设置碰撞层与掩码(Collision Layer & Mask):
    • 选中任一物理/区域节点,在右侧检查器展开 CollisionObject2D → Collision,你会看到 Layer 和 Mask 两排数字按钮:
    - 第 1 层(墙与树):选中 Borders 和 Tree,将 Layer 勾选 1,Mask 取消全部勾选。
    - 第 2 层(玩家青蛙):打开 player.tscn 选中 Player,将 Layer 设为 2(取消 1),将 Mask 勾选 1、3、4。
    - 第 3 层(汽车):打开 car.tscn 选中 Car,将 Layer 设为 3,将 Mask 仅勾选 2(只检测第 2 层玩家!)。
    - 第 4 层(北侧终点):在 game.tscn 选中 FinishArea2D,将 Layer 设为 4,将 Mask 仅勾选 2。
  2. 2. 让 Agent 在 game.gd 中添加动态碰撞信号绑定:复制下方【Prompt #10】发给 Agent,直接修改 res://scenes/game.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接修改当前 Godot 4.7 工程中的 `res://scenes/game.gd`(并可同步检查 `player.tscn`、`car.tscn`、`game.tscn` 的碰撞层设置),为动态生成的汽车绑定碰撞信号:

1. 在 `game.gd` 的 `_on_car_timer_timeout()` 函数末尾(`$Objects.add_child(car)` 之后),使用代码动态连接信号:
   `car.connect("body_entered", go_to_title)`
2. 在 `game.gd` 中新增碰撞回调函数 `func go_to_title(body) -> void:`:
   - 打印碰撞体 `print(body)`
   - 打印提示 `print('player car collision')`
3. 确保碰撞层配置正确:`Player` (`collision_layer = 2`, `collision_mask = 13`),`Car` (`collision_layer = 4`, `collision_mask = 2`),`FinishArea2D` (`collision_layer = 8`, `collision_mask = 2`)。
✅ 验证标准:按 F5 运行游戏:汽车开过马路边的树或围栏时安然无恙;而当玩家小青蛙碰到任何一辆汽车时,底部 Output 控制台立即打印 `player car collision`!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/09.collisions)· 标准参考代码 点击展开 / 收起
📌 核心原理:动态生成的汽车无法提前在编辑器面板里用鼠标连信号,必须在生成它的那一刻用代码 car.connect("body_entered", go_to_title) 动态绑定!同时必须配置 Collision Layer(我是谁)和 Mask(我检测谁),防止汽车撞到路边的树也触发游戏结束。
📂 防掉队快照工程:项目文件/09.collisions(节点:CollisionObject2D -> Collision & car.connect())
📄 res://scenes/game.gd, player.tscn & car.tscn(标准参考内容 / 备用直接复制)
extends Node2D

var car_scene: PackedScene = preload("res://scenes/car.tscn")

func _on_finish_area_2d_body_entered(body: Node2D) -> void:
	print(body)
	print("has entered")

func _on_car_timer_timeout() -> void:
	var car = car_scene.instantiate() as Area2D
	var pos_marker = $CarStartPositions.get_children().pick_random() as Marker2D
	car.position = pos_marker.position
	$Objects.add_child(car)
	car.connect("body_entered", go_to_title)

func go_to_title(body) -> void:
	print(body)
	print('player car collision')
#11

布置关卡装饰素材、开启 Y-Sort 深度遮挡与汽车三色随机换装

下篇 P5 · 00:33:49
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/car.gd, player.gd & game.tscn
  1. 1. 如何布置关卡静态装饰素材(box.tscn / Stuff):
    • 在 res://graphics/objects/ 目录下有长椅(bench.png)、路障(barrier.png)、垃圾桶(bin.png)、房屋(house1~3.png)、路灯(light.png)、红绿灯(traffic.png)等丰富素材,可拖入 Objects/Stuff 下丰富街道细节,并在 Stuff/StaticBody2D 下添加对应矩形碰撞框。
  2. 2. 开启 Y-Sort 前后遮挡排序:
    • 在 game.tscn 中选中 Objects 节点(以及其下的 Player 和 Stuff 节点)。
    • 在右侧检查器展开 CanvasItem → Ordering,将 Y Sort Enabled 勾选为 On。
  3. 3. 让 Agent 升级 car.gd 三色随机贴图并调优 player.gd 速度:复制下方【Prompt #11】发给 Agent 直接执行。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接修改当前 Godot 4.7 工程中的 `res://scenes/car.gd` 和 `res://scenes/player.gd`:

1. 在 `res://scenes/car.gd` 中:
   - 新增成员变量 `colors` 数组,使用 `preload` 预加载三张汽车贴图:
     `preload("res://graphics/cars/green.png")`、`preload("res://graphics/cars/red.png")`、`preload("res://graphics/cars/yellow.png")`
   - 在 `_ready() -> void` 末尾添加:`$Sprite2D.texture = colors.pick_random()`,使每辆生成的汽车随机显示一种颜色。
2. 在 `res://scenes/player.gd` 中:
   - 将玩家移动速度 `speed` 从 `200` 调整为 `100`,使过马路节奏更符合街机难度。
✅ 验证标准:按 F5 运行游戏:马路上随机出现绿色、红色、黄色三种汽车;操控青蛙绕着树木和路灯行走,前后遮挡层次关系完全符合真实透视!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/10.level setup)· 标准参考代码 点击展开 / 收起
📌 核心原理:在 2D 俯视角游戏中,当青蛙走到树后面时应该被树冠挡住,走到树前面时应该挡住树干。只需开启父节点的 Y Sort Enabled,Godot 就会自动按 Y 坐标高低实时排列绘制先后顺序!同时用 preload 数组让每辆车随机抽取红/黄/绿贴图。
📂 防掉队快照工程:项目文件/10.level setup(节点:Objects (Y Sort Enabled) & colors.pick_random())
📄 res://scenes/car.gd, player.gd & game.tscn(标准参考内容 / 备用直接复制)
# --- res://scenes/car.gd ---
extends Area2D

var direction = Vector2.LEFT
var speed = 100
var colors = [
	preload("res://graphics/cars/green.png"),
	preload("res://graphics/cars/red.png"),
	preload("res://graphics/cars/yellow.png"),
]

func _ready() -> void:
	if position.x < 0:
		direction.x = 1
		$Sprite2D.flip_h = true
	$Sprite2D.texture = colors.pick_random()

func _process(delta: float) -> void:
	position += direction * speed * delta

func _on_visible_on_screen_notifier_2d_screen_exited() -> void:
	queue_free()
#12

导入自定义字体设置 UI 布局:CanvasLayer 秒表 HUD 与 Title.tscn 标题界面

下篇 P5 · 00:47:45
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/game.gd & res://scenes/Title.tscn
  1. 1. 如何在游戏内添加固定不动的顶部计分 UI(CanvasLayer + Label):
    • 在 game.tscn 选中根节点 Game,添加子节点 CanvasLayer,再为其添加子节点 Label。
    • 设置自定义字体与字号:选中 Label,在右侧检查器展开 Control → Theme Overrides → Fonts,从左下角 FileSystem 将 res://fonts/Better VCR 9.0.1.ttf 拖入 Font 槽位;展开 Font Sizes 将 Font Size 设为 40;在顶部设置文本水平居中(Horizontal Alignment = Center)。
    • 设置顶部居中锚点:在 2D 视口顶部工具栏点击绿色锚点图标(或右侧 Layout → Anchors Preset),选择 Center Top(顶部居中)。
  2. 2. 添加 ScoreTimer 秒表定时器:
    • 在 Timer 节点下添加子节点 Timer 并改名为 ScoreTimer,右侧设置 Wait Time = 1.0 s,勾选 Autostart = On,并将其 timeout() 信号连接到 Game 的 _on_score_timer_timeout。
  3. 3. 如何搭建开始标题界面(res://scenes/Title.tscn):
    • 新建场景 → 点击 User Interface(用户界面,即 Control 节点) 并改名为 Title,保存为 res://scenes/Title.tscn。
    • 添加背景子节点 ColorRect:锚点预设选 Full Rect(铺满全屏),右侧 Color 设为深紫色 #633c65。
    • 添加游戏名子节点 Label:Text 输入 Car Game,拖入字体 res://fonts/Crackman.otf,字号设为 140,锚点设为居中偏上。
    • 添加角色图标子节点 TextureRect:将 res://graphics/player/player_simple.png 拖入 Texture,锚点设为正中央 Center。
    • 添加最高分子节点 Label2:Text 输入 High score: 123,拖入字体 Better VCR 9.0.1.ttf,字号设为 30,锚点设为居中偏下。
  4. 4. 让 Agent 更新 game.gd 实现秒表读秒:复制下方【Prompt #12】发给 Agent 直接修改 res://scenes/game.gd。
🤖 AI Agent 提示词(MCP / 文件写入)
请直接修改当前 Godot 4.7 工程中的 `res://scenes/game.gd` 文件,新增秒表计分变量与 `ScoreTimer` 超时回调以实时刷新顶部 UI 分数:

1. 新增整型成员变量 `var score: int` 用于记录当前局耗时秒数。
2. 新增 `ScoreTimer` 的超时回调函数 `func _on_score_timer_timeout() -> void:`:
   - 令 `score += 1`
   - 将 `$CanvasLayer/Label.text` 更新为 `str(score)`
3. 保留原有的 `car_scene`、`_on_finish_area_2d_body_entered`、`_on_car_timer_timeout` 和 `go_to_title` 逻辑。
✅ 验证标准:按 F5 运行主游戏:屏幕顶部正中央以复古像素字体实时显示耗时秒数(1, 2, 3...),且跟随青蛙移动时 UI 稳稳固定在屏幕上方!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/11.layout)· 标准参考代码 点击展开 / 收起
📌 核心原理:普通节点会随 Camera2D 移动,而放在 CanvasLayer(画布层)下的 UI 节点永远固定在屏幕视口上!同时本步学习 Control 节点的相对锚点(Anchor Preset)布局与自定义字体(.ttf/.otf)导入设置。
📂 防掉队快照工程:项目文件/11.layout(节点:CanvasLayer/Label, ScoreTimer & Title (Control))
📄 res://scenes/game.gd & res://scenes/Title.tscn(标准参考内容 / 备用直接复制)
extends Node2D

var car_scene: PackedScene = preload("res://scenes/car.tscn")
var score: int

func _on_finish_area_2d_body_entered(body: Node2D) -> void:
	print(body)
	print("has entered")

func _on_car_timer_timeout() -> void:
	var car = car_scene.instantiate() as Area2D
	var pos_marker = $CarStartPositions.get_children().pick_random() as Marker2D
	car.position = pos_marker.position
	$Objects.add_child(car)
	car.connect("body_entered", go_to_title)

func go_to_title(body) -> void:
	print(body)
	print('player car collision')

func _on_score_timer_timeout() -> void:
	score += 1
	$CanvasLayer/Label.text = str(score)
#13

配置 Autoload 全局单例、添加音频素材(BGM 与 2D 空间车流声)与胜负场景切换

下篇 P5 · 01:19:34
🛠️ Godot 4.7 编辑器操作步骤 目标:res://scenes/global.gd, title.gd & game.gd
  1. 1. 如何创建并注册全局单例场景(Global Autoload)与背景音乐:
    • 新建或打开 res://scenes/global.tscn(根节点为 Node 改名为 Global,附加脚本 res://scenes/global.gd)。
    • 添加全局背景音乐素材:为 Global 添加子节点 AudioStreamPlayer,从 FileSystem 将音频文件 res://audio/S31-City on Speed.ogg(或 happy.mp3)拖入右侧检查器 Stream 槽位;设置 Volume dB = -10.0 dB,勾选 Autoplay = On,展开 Parameters 勾选 Looping = On(循环播放),保存场景。
    • 注册到全局 Autoload:点击顶部菜单 Project → Project Settings → Globals(全局 / Autoload) 标签页 → 在 Path 选择 res://scenes/global.tscn,Node Name 填 Global,点击右侧 Add!
  2. 2. 如何为汽车添加越近越响的 2D 空间音效(AudioStreamPlayer2D):
    • 打开 res://scenes/car.tscn,右键根节点 Car 添加子节点 AudioStreamPlayer2D(注意带 2D 后缀,具备距离衰减与左右声道立体声!)。
    • 从 FileSystem 将 res://audio/car.mp3 拖入右侧检查器 Stream 槽位。
    • 设置属性:Volume dB = -20.0 dB,勾选 Autoplay = On,将 Max Distance(最大可听距离) 设为 100 px,展开 Parameters 勾选 Looping = On,保存场景。
  3. 3. 让 Agent 一次性写入 global.gd、title.gd 与终极版 game.gd:复制下方【Prompt #13】发给 Agent 直接完成全部脚本收尾!
🤖 AI Agent 提示词(MCP / 文件写入)
请直接创建或修改当前 Godot 4.7 工程中的 `res://scenes/global.gd`、`res://scenes/title.gd` 和 `res://scenes/game.gd` 三个脚本文件,完成全局最高分记录、标题界面交互与安全场景切换闭环:

1. 修改 `res://scenes/global.gd`(继承自 `Node`,挂载于 Autoload 全局单例 `Global`):
   - 定义全局变量 `var score: int = 10` 用于存储最佳通关耗时纪录。

2. 修改 `res://scenes/title.gd`(继承自 `Control`,挂载于 `res://scenes/Title.tscn` 根节点):
   - 在 `_ready() -> void` 中,将子节点 `$Label2.text` 设置为 `'High score: ' + str(Global.score)`
   - 在 `_process(_delta: float) -> void` 中,检测如果刚刚按下 `"confirm"` 动作(`Input.is_action_just_pressed("confirm")`),则调用 `get_tree().change_scene_to_file("res://scenes/game.tscn")` 进入主游戏场景。

3. 修改 `res://scenes/game.gd`(继承自 `Node2D`,挂载于 `res://scenes/game.tscn` 根节点):
   - 在终点回调 `_on_finish_area_2d_body_entered(_body: Node2D) -> void` 中:
     - 调用 `call_deferred("change_scene")`
     - 如果当前局耗时 `score < Global.score`(用时更短破纪录),则更新 `Global.score = score`
   - 在人车碰撞回调 `go_to_title(_body) -> void` 中:
     - 调用 `call_deferred("change_scene")`
   - 新增场景切换函数 `func change_scene() -> void:`:
     - 调用 `get_tree().change_scene_to_file("res://scenes/Title.tscn")`
   - 保留原有的 `car_scene`、`_on_car_timer_timeout()` 和 `_on_score_timer_timeout()` 逻辑。
✅ 验证标准:🎉 终极完整游戏验收!按 F5 启动:伴随动感背景音乐,靠近车流能听到由远及近的引擎呼啸声;被车撞击或抵达北侧终点会安全跳转至紫色标题页 Title.tscn;若过河用时短于 High score(初始 10 秒)将自动刷新纪录;在标题页按空格键即可重新开局!
💡 展开查看:本步原理说明 · 防掉队快照(项目文件/12.transition & 13.sound)· 标准参考代码 点击展开 / 收起
📌 核心原理:切换场景时会销毁当前场景的数据和音乐播放器。通过 Project Settings -> Globals (Autoload) 注册 Global 全局场景,不仅能跨场景保存最佳纪录 Global.score,还能让背景音乐在切换场景时无缝持续播放!
📂 防掉队快照工程:项目文件/12.transition & 13.sound(节点:Globals (Autoload) / AudioStreamPlayer2D)
📄 res://scenes/global.gd, title.gd & game.gd(标准参考内容 / 备用直接复制)
# ==========================================
# 1. res://scenes/global.gd
# ==========================================
extends Node

var score: int = 10


# ==========================================
# 2. res://scenes/title.gd
# ==========================================
extends Control

func _ready() -> void:
	$Label2.text = 'High score: ' + str(Global.score)

func _process(_delta: float) -> void:
	if Input.is_action_just_pressed("confirm"):
		get_tree().change_scene_to_file("res://scenes/game.tscn")


# ==========================================
# 3. res://scenes/game.gd (终极完整版)
# ==========================================
extends Node2D

var car_scene: PackedScene = preload("res://scenes/car.tscn")
var score: int

func _on_finish_area_2d_body_entered(_body: Node2D) -> void:
	call_deferred("change_scene")
	if score < Global.score:
		Global.score = score

func change_scene() -> void:
	get_tree().change_scene_to_file("res://scenes/Title.tscn")

func _on_car_timer_timeout() -> void:
	var car = car_scene.instantiate() as Area2D
	var pos_marker = $CarStartPositions.get_children().pick_random() as Marker2D
	car.position = pos_marker.position
	$Objects.add_child(car)
	car.connect("body_entered", go_to_title)

func go_to_title(_body) -> void:
	call_deferred("change_scene")

func _on_score_timer_timeout() -> void:
	score += 1
	$CanvasLayer/Label.text = str(score)
✅ 已复制到剪贴板!