Zenva----Godot学习之旅
Zenva----Godot学习之旅
脚本介绍
变量extends Node2D
var score:int = 10
var move_speed : float = 2.53
var game_over : bool = false
var ability : String = "slassh"
func _ready():
move_speed = 0.1123
game_over = true
ability = "attack"
print(move_speed)
print(game_over)
print(ability)
extends Node2D声明这个脚本继承自Node2D节点(Godot引擎中的一种基础节点类型,用于2D场景中的物体,支持位置、旋转、缩放等2D变换)。这意味着这个脚本可以附加到Node2D或其派生节点(如Sprite2D、Area2D等)上,并继承Node2D的所有属性和方法。var score:int = 10定义一个**整数类型**(:int)的变量score,并初始化为10。var是GDScript中声明变量的关键字,:int明确指定变量类型为整数(用于存储没有小数的数值)。var move_speed : float = 2.53定义一个**浮点类型**(:float)的变量move_speed,初始化为2.53。浮点型用于存储带小数的数值(通常用于表示速度、位置等需要精度的属性)。var game_over : bool = false定义一个**布尔类型**(:bool)的变量game_over,初始化为false。布尔型变量只有两个可能的值:true(真)或false(假),通常用于表示状态(这里可能用于标记游戏是否结束)。var ability : String = "slassh"定义一个**字符串类型**(:String)的变量ability,初始化为"slassh"(字符串需要用双引号包裹)。字符串用于存储文本信息(这里可能表示角色的技能名称,注意原词可能是"slash"的拼写错误)。func _ready():定义_ready()函数,这是Godot引擎的**生命周期回调函数**之一。当节点及其所有子节点加载完成、准备好开始运行时,会自动执行这个函数内的代码(通常用于初始化操作)。move_speed = 0.1123在_ready()函数中,修改move_speed变量的值为0.1123(覆盖了之前的初始值2.53)。game_over = true修改game_over变量的值为true(覆盖了之前的初始值false)。ability = "attack"修改ability变量的值为"attack"(覆盖了之前的初始值"slassh")。print(move_speed)调用print()函数,在控制台输出move_speed当前的值(此时已被修改为0.1123)。print(game_over)输出game_over当前的值(此时已被修改为true)。print(ability)输出ability当前的值(此时已被修改为"attack")。
最后将修改后的值打印到控制台。运行后,控制台会输出:0.1123、true、attack。
运算符
extends Node2D
var score :int = 0
var speed :float = 5.5
var text : String = "First"
func _ready():
score = 10
score +=1
score -=5
score *=2
score /=4
print(5)
speed *=2.548
speed /= 2.09
print(speed)
text +="second"
print(text)
输出结果
5
6.70526315789474
Firstsecond
条件
extends Node2D
var score : int = 10
func _ready():
if score == 10:
print("socre is 10")
if score > 5 :
print("score is greater than")
var a :int = 100
var b: int = 100
if a < b:
print("a is less than b")
if a != b:
print("a is not b")
输出:socre is 10
score is greater than
函数
extends Node2D
func _ready():
_add(5,8)
func _process(delta):
pass
func _add(a,b):
var sum = a+b
print(sum)
func _welcome_message():
print("welcome")
extends Node2D
func _ready():
var result = _add(33,91)
print(result)
func _process(delta):
pass
func _add(a:float,b:float):
var sum:float = a+b
return sum
func _welcom_message():
print("wqdadada")
题目
extends Node2D
func _ready():
var game_over = _has_won(120)
print(game_over)
func _process(delta):
pass
func _has_won(score:int) -> bool:
if score > 100:
return true
else:
return false
向量
自己移动
extends Sprite2D
func _process(delta):
position .x+=1
#向右自动移动
extends Sprite2D
#调节速度
var speed : float = 100
func _process(delta):
var direction = Vector2(0,1)
position += direction * delta *speed #方向向量 × 时间间隔(delta) × 速度(speed)
1. extends Sprite2D
声明当前脚本继承自 Sprite2D节点。Sprite2D是 Godot 中用于显示 2D 图像(如角色、道具、背景元素等)的基础节点,自带 position(位置)、texture(纹理,即显示的图片)等属性。继承后,附加该脚本的节点会拥有 Sprite2D的所有功能。
2. var speed : float = 100
定义一个浮点型变量 speed,初始值为 100,注释 “调节速度” 说明其作用是控制精灵的移动速度(单位:像素 / 秒)。
3. func _process(delta):
_process(delta)是 Godot 的每帧回调函数(默认每帧执行一次,帧率通常为 60 帧 / 秒)。
- 参数
delta:当前帧与上一帧的时间间隔(单位:秒),用于确保移动 / 逻辑在不同帧率下速度一致(例如,高帧率时delta小,低帧率时delta大,乘以delta后移动距离会和实际时间挂钩,而非帧数)。
- 函数内部逻辑
var direction = Vector2(0, 1):定义一个 2D 方向向量direction。Vector2(x, y)中,x控制水平方向(正数向右,负数向左),y控制垂直方向(Godot 中 Y 轴正方向是向下,所以y=1表示向下,y=-1表示向上)。这里(0,1)表示 “纯向下” 的方向。position += direction * delta * speed:更新精灵的位置。position是Sprite2D的位置属性(Vector2类型),表示精灵在 2D 场景中的坐标。- 计算逻辑:方向向量 × 时间间隔(
delta) × 速度(speed),得到 “当前帧应该移动的距离”,再叠加到当前位置上。 - 实际效果:精灵会以每秒
100像素的速度持续向下移动(因为direction是向下,且每帧都会执行该逻辑)。
整体效果
当脚本附加到一个 Sprite2D节点上后,运行场景时,该精灵会从初始位置开始,以每秒 100 像素的速度一直向下移动(直到移出屏幕或被其他逻辑停止)。
硬币收藏家游戏
控制玩家上下左右脚本
extends CharacterBody2D
# 继承CharacterBody2D节点(Godot 4 2D角色移动核心节点,自带物理移动、碰撞检测功能,脚本需挂载到该节点上)
var speed : float = 100
# 声明全局浮点型变量speed,初始化值100(单位:像素/秒,控制角色移动快慢)
func _physics_process(delta):
# 物理帧回调函数(固定60次/秒调用,不受帧率影响,专门处理移动、碰撞等物理逻辑;delta是帧间隔时间,此处由move_and_slide自动适配)
velocity.x = 0
# 重置水平速度为0(避免松开方向键后角色因残留速度滑行,实现"松键即停")
velocity.y = 0
# 重置垂直速度为0(同理,清空垂直方向残留速度)
if Input.is_key_pressed(KEY_RIGHT):
# 检测右方向键是否被持续按压(is_key_pressed返回bool值,按住时每帧为true)
velocity.x += speed
# 水平速度 += 移动速度(x正方向=右,此时velocity.x=100,角色向右移动)
if Input.is_key_pressed(KEY_LEFT):
# 检测左方向键是否被持续按压
velocity.x -= speed
# 水平速度 -= 移动速度(x负方向=左,此时velocity.x=-100,角色向左移动)
if Input.is_key_pressed(KEY_UP):
# 检测上方向键是否被持续按压(Godot 2D默认y轴向下为正,上对应y负方向)
velocity.y -= speed
# 垂直速度 -= 移动速度(此时velocity.y=-100,角色向上移动)
if Input.is_key_pressed(KEY_DOWN):
# 检测下方向键是否被持续按压
velocity.y += speed
# 垂直速度 += 移动速度(此时velocity.y=100,角色向下移动)
move_and_slide()
# CharacterBody2D内置移动方法:根据velocity计算移动距离,自动处理碰撞(需搭配CollisionShape2D),触发角色实际移动
这段代码是基于Godot引擎的GDScript脚本,功能是实现一个"触发区域"的逻辑,具体解析如下:
1. 基础结构:extends Area2D
- 表示当前脚本所附加的节点类型是
Area2D(2D碰撞区域节点)。 Area2D是Godot中用于碰撞检测的节点,它本身不参与物理碰撞响应(不会被推开),但可以检测其他物体进入/离开该区域,常用于实现"触发器"效果(比如踩陷阱、触碰道具等)。
2. 核心函数:_on_body_entered(body)
- 这是一个**信号回调函数**,对应
Area2D节点的body_entered信号。 - 当有其他"物理体节点"(如
KinematicBody2D、RigidBody2D等带有碰撞体的节点)进入当前Area2D的碰撞区域时,会自动触发该函数。 - 参数
body:表示进入区域的那个物理体节点(即被检测到的物体)。
3. 逻辑实现
body.scale.x += 0.2和body.scale.y += 0.2:
修改进入区域的物体(body)的缩放比例。scale是节点的缩放属性,x和 y分别对应水平和垂直方向的缩放倍数。这里是在原缩放基础上各增加0.2,即让进入的物体"变大一点"。
queue_free():
销毁当前 Area2D节点(将自身从场景中移除)。这确保该区域只会触发一次效果(触发后自己消失,不会重复检测)。
注意事项
- 要使该逻辑生效,需要在Godot编辑器中手动将
Area2D的body_entered信号连接到脚本中的_on_body_entered函数(否则信号不会触发)。 Area2D和进入的body都必须添加碰撞形状(如CollisionShape2D或CollisionPolygon2D),否则无法检测到碰撞。
总结
这段代码实现了一个"一次性放大触发器":当任何物理体进入该 Area2D区域时,会被放大(x和y方向各增加0.2倍缩放),随后触发器自身会销毁,不再生效。
金币脚本
extends Area2D
func _on_body_entered(body):
body.scale.x +=0.2
body.scale.y +=0.2
queue_free()
这段代码是基于Godot引擎的GDScript脚本,用于实现一个由方向键控制的2D角色移动逻辑,具体解析如下:
1. 基础结构:extends CharacterBody2D
- 表示当前脚本附加的节点类型是
CharacterBody2D。 CharacterBody2D是Godot中专门用于处理**角色移动**的物理节点,适合实现玩家控制的角色(如平台游戏主角、顶视角角色等),它自带碰撞处理和移动方法,比普通节点更适合角色逻辑。
2. 变量定义:var speed : float = 100
- 定义了一个浮点型变量
speed,值为100,用于控制角色的移动速度(单位通常是“像素/秒”,即每秒移动100像素)。 - 变量类型标注
: float是可选的,但能提高代码可读性和编辑器的类型提示能力。
3. 核心函数:_physics_process(delta)
- 这是Godot的**物理帧更新函数**,每帧调用一次(帧率与物理引擎同步,通常默认60帧/秒)。
- 参数
delta表示上一帧到当前帧的时间间隔(单位:秒),用于确保移动速度不受帧率波动影响(比如低帧率时移动距离会自动补偿,保持实际速度一致)。
4. 移动逻辑实现
- 重置速度:
velocity.x = 0和velocity.y = 0
velocity是 CharacterBody2D自带的属性(Vector2类型),表示节点的运动速度(x为水平方向,y为垂直方向)。
每次物理帧先重置速度为0,避免角色在没有输入时继续“惯性移动”。
- 处理方向键输入:
- 右键(
KEY_RIGHT):velocity.x += speed→ 水平速度增加speed,角色向右移动。 - 左键(
KEY_LEFT):velocity.x -= speed→ 水平速度减少speed(即负方向),角色向左移动。 - 上键(
KEY_UP):velocity.y -= speed→ 垂直速度减少speed(Godot中y轴向下为正,所以负y是向上),角色向上移动。 - 下键(
KEY_DOWN):velocity.y += speed→ 垂直速度增加speed,角色向下移动。
这里支持**八方向移动**(比如同时按上和右,角色会斜向移动,此时velocity的x和y分量都有值)。
- 右键(
- 执行移动:
move_and_slide()
这是 CharacterBody2D的核心移动方法,作用是:
- 根据
velocity计算移动距离(自动结合delta时间,无需手动乘以delta); - 自动检测碰撞(如果碰到障碍物,会沿碰撞边缘滑动或停止,避免穿墙);
- 适合实现角色在地面、平台上的移动(比如不会掉穿地面)。
注意事项
- 要使移动生效,
CharacterBody2D必须添加碰撞形状(如CollisionShape2D),否则无法检测碰撞,可能导致角色“穿墙”。 move_and_slide()会自动处理速度与时间的关系,因此代码中无需手动写velocity *= delta。- 若需要限制斜向移动速度(避免斜向比直线快,因为勾股定理会导致斜向速度实际为
√(speed² + speed²) ≈ 1.414*speed),可以在移动前对velocity归一化,例如:velocity = velocity.normalized() * speed(但需注意静止时的特殊处理)。
总结
这段代码实现了一个基础的“方向键控制角色移动”功能:通过 _physics_process实时检测方向键输入,计算角色速度,再通过 move_and_slide完成带碰撞处理的移动,适合顶视角或简单平台游戏的角色控制。
导出游戏
Godot迷你项目
(3D)气球爆破者
初步
气球逐渐变大
ballon.gd:管 “单个气球” 的交互(点击、缩放、销毁),是 “子模块”;
extends Area3D
# 气球副本
@export var clicks_to_pop : int = 5 #引爆所需点击次数
@export var size_increase : float = 0.2 # 次点击的尺寸增加量
@export var score_to_give : int = 1 # 引爆后给予的分
func _on_input_event(camera, event, event_position, normal, shape_idx):
if event is not InputEventMouseButton:
return
if event.button_index != MOUSE_BUTTON_LEFT:
return
if not event_position:
return
scale = Vector3.ONE * size_increase
clicks_to_pop -=1
if clicks_to_pop == 0:
queue_free()
下面逐行拆解这段 ballon.gd 代码(基于 Godot 4 语法),结合 Godot 引擎特性和脚本逻辑,从“是什么”“为什么这么写”“注意点”三个维度解析,新手也能看懂~
1. 脚本继承声明
extends Area3D
- 作用:指定当前脚本的父类是
Area3D节点。 - 关键说明:
Area3D是 Godot 专门用于「检测交互/碰撞」的 3D 节点,**本身不会有物理刚体的碰撞效果**(比如不会被推走、不会掉落),但能捕捉鼠标点击、射线检测等事件——完美适配“点击气球”的需求(只需要检测点击,不需要物理碰撞)。- 脚本必须绑定到场景树中的
Area3D节点上才能生效(比如新建Area3D节点,给它挂载这个脚本)。
2. 导出变量声明(3行)
这3行是「可配置参数」,用 @export 标记后,在编辑器中能直接调整,不用改代码。
第1个导出变量
@export var clicks_to_pop : int = 5 #引爆所需点击次数
- 逐部分解析:
@export:Godot 关键字,让变量在编辑器的「检查器」面板中显示,支持可视化修改(比如把 5 改成 3,不用动代码)。var clicks_to_pop:声明变量名,含义是“引爆气球需要的点击次数”。: int:指定变量类型为「整数」(避免传入小数导致逻辑错误)。= 5:默认值为 5(初始状态下,气球需要点击 5 次才会爆)。# 注释:后面的文字是代码注释,不会执行,用于说明变量用途,方便自己/他人看懂代码。
第2个导出变量
@export var size_increase : float = 0.2 # 次点击的尺寸增加量
- 逐部分解析:
size_increase:变量名,含义是“每次点击后气球的尺寸增加量”。: float:变量类型为「浮点数」(支持小数,比如 0.2、0.15)。= 0.2:默认每次点击放大 0.2 倍(注意:这里有个**潜在错误**,后面会详细说)。- 注释漏了“每”字,实际含义是“每次点击的尺寸增加量”。
第3个导出变量
@export var score_to_give : int = 1 # 引爆后给予的分
- 逐部分解析:
score_to_give:变量名,含义是“气球引爆后应该给玩家加的分数”。: int:整数类型(分数通常是整数)。= 1:默认每次爆气球加 1 分。- 注释多了个空格,不影响执行,只是格式问题。
3. 输入事件回调函数(核心逻辑)
func _on_input_event(camera, event, event_position, normal, shape_idx):
- 作用:
Area3D节点的「内置信号回调函数」——当鼠标在这个Area3D节点的范围的内发生输入事件(点击、移动、滚轮等)时,Godot 会自动调用这个函数。 - 关键说明:
- 函数名不能乱改:必须是
_on_input_event(这是 Godot 约定的信号回调名),且需要在编辑器中「连接信号」才能生效(步骤:选中Area3D节点 → 右侧「信号」面板 → 找到input_event→ 连接到当前脚本的这个函数)。 - 参数不用手动传:Godot 会自动传入 5 个参数(新手不用深究所有参数,重点看
event和event_position):camera:当前渲染场景的相机节点(比如玩家视角的相机)。event:具体的输入事件(比如“鼠标左键按下”“鼠标移动”)。event_position:点击在Area3D节点上的本地位置(是否有效代表“是否真的点到了气球”)。normal:点击位置的表面法向量(3D 场景中用于判断点击方向,这里用不上)。shape_idx:如果Area3D有多个碰撞形状,用于区分点击的是哪个形状(这里气球通常只有一个碰撞形状,用不上)。
- 函数名不能乱改:必须是
4. 事件过滤逻辑(3个 if 判断)
这3行的核心目的是:**只保留“有效点击”(鼠标左键、点在气球上),过滤掉所有无效事件**。
第1个过滤:只保留鼠标按钮事件
if event is not InputEventMouseButton:
return
- 作用:判断当前输入事件是不是“鼠标按钮事件”(比如左键点击、右键点击、中键点击)。
- 逻辑:
- 如果是「非鼠标按钮事件」(比如鼠标移动、键盘按键、滚轮滚动),就执行
return(直接退出函数,后面的代码不执行)。 - 举例:鼠标划过气球(没点击)、按键盘 A 键,都不会触发后续逻辑。
- 如果是「非鼠标按钮事件」(比如鼠标移动、键盘按键、滚轮滚动),就执行
第2个过滤:只保留鼠标左键
if event.button_index != MOUSE_BUTTON_LEFT:
return
- 作用:在“鼠标按钮事件”中,只保留「左键点击」,过滤右键、中键等。
- 关键说明:
event.button_index:获取鼠标按钮的类型(Godot 内置枚举:MOUSE_BUTTON_LEFT=左键,MOUSE_BUTTON_RIGHT=右键,MOUSE_BUTTON_MIDDLE=中键)。- 逻辑:如果点击的不是左键,就退出函数,后续代码不执行。
第3个过滤:只保留有效点击位置
if not event_position:
return
- 作用:判断点击位置是否有效(避免“鼠标刚好在气球边缘”“碰撞形状异常”导致的无效点击)。
- 逻辑:如果
event_position是无效值(比如Vector3.ZERO且无实际意义),就退出函数——确保只有“真的点到气球上”才会触发后续逻辑。
5. 气球缩放逻辑
scale = Vector3.ONE * size_increase
- 作用:每次有效点击后,调整气球的尺寸。
- 逐部分解析:
scale:节点的缩放属性(Vector3类型,(x,y,z)分别代表x、y、z轴的缩放比例,默认(1,1,1)是原始尺寸)。Vector3.ONE:Godot 内置常量,等价于Vector3(1,1,1)(原始缩放比例)。* size_increase:乘以尺寸增加量(默认 0.2),结果是(0.2,0.2,0.2)。
- 关键问题(之前你遇到的“越点越小”的根源):
- 这行代码是「直接覆盖缩放值」,而不是「在原有缩放基础上累加」。
- 比如初始缩放是
1,第一次点击后被设为0.2(变小),之后每次点击都保持0.2——所以气球会越点越小,且不会继续变大。 - 正确写法:
scale += Vector3.ONE * size_increase(用+=累加,每次在当前尺寸上放大 0.2 倍)。
6. 减少点击次数 & 销毁气球
clicks_to_pop -=1
- 作用:每次有效点击后,把“剩余点击次数”减 1。
- 举例:初始
clicks_to_pop=5,第一次点击后变成 4,第二次变成 3,直到减到 0。
if clicks_to_pop == 0:
queue_free()
- 作用:当剩余点击次数为 0 时,销毁气球节点。
- 关键说明:
queue_free():Godot 中安全销毁节点的方法(会等待当前帧结束后再销毁,避免出现“节点还在但已失效”的异常),比直接用free()更安全。- 逻辑:气球被点击足够次数后,从场景树中移除,视觉上“消失”。
整体逻辑流程总结
当你在游戏中点击气球时,代码会按以下顺序执行:
- 检测是否是「鼠标左键点击」且「真的点到了气球」;
- 是 → 调整气球缩放(当前错误逻辑:设为 0.2 倍,变小);
- 剩余点击次数减 1;
- 如果次数减到 0 → 销毁气球。
必须补充的2个关键注意点(否则脚本可能无效)
- 信号必须连接:
_on_input_event是信号回调,必须在编辑器中把Area3D的input_event信号连接到这个函数,否则点击气球没任何反应。 - 碰撞形状必须添加:
Area3D本身没有“可点击范围”,需要给它添加子节点(比如SphereShape3D球体碰撞形状),且碰撞形状的大小要和气球模型匹配,否则点击不到。
balloon_popoerMain.gd:管 “全局分数” 的存储和更新,是 “管理模块”;
extends Node3D
var score:int = 0
func increase_score(amount : int):
score += amount
print(score)
分数计数
balloon_popoerMain.gd
extends Node3D
var score : int = 0
var score_text : Label
func _ready():
score_text = $ScoreText # 第6行:统一用4个空格缩进(删除原混合缩进)
score_text.text = " 分数 : 0 "
func increase_score(amount : int):
score += amount
score_text.text = "分数: " + str(score) # 补充空格,代码更规范(非报错必需)
下面逐行解析这段 **Godot 4 的 GDScript 代码**,结合语法规则、Godot 引擎特性和代码功能,从基础到细节讲清楚每一行的作用:
整体背景
这段代码是一个挂载在 Node3D 节点上的脚本,核心功能是 **管理游戏分数**:初始化分数显示、提供加分方法、实时更新分数文本(对应场景中一个叫 ScoreText 的 Label 节点)。
逐行解析
1. extends Node3D
- 语法作用:GDScript 的「继承声明」,指定当前脚本的父类是
Node3D。 - 实际意义:
Node3D是 Godot 3D 场景的基础节点,自带「位置、旋转、缩放」等 3D 空间属性。- 脚本挂载到任何
Node3D及其子类节点(如CharacterBody3D、StaticBody3D)上都能生效,脚本会继承Node3D的所有功能(比如global_position位置属性、rotate()旋转方法)。
- 注意:必须放在脚本第一行,且只能有一个继承声明。
2. var score : int = 0
- 语法作用:声明一个「带类型注解的全局变量」。
var:GDScript 声明变量的关键字(类似 Python 的var/let)。score:变量名(自定义,语义是“分数”)。: int:类型注解,指定变量是「整数类型」(GDScript 是弱类型语言,可省略,但加注解更规范、能触发编辑器语法检查)。= 0:初始化赋值,分数初始值设为 0。
- 实际意义:全局存储游戏分数,整个脚本的所有函数都能访问和修改它。
3. var score_text : Label
- 语法作用:声明一个「未初始化的 Label 类型全局变量」。
: Label:类型注解指定变量是Label节点类型(Label是 Godot 用于显示文本的基础节点,核心属性是.text)。- 未赋值:因为
Label节点是「场景中的可视化节点」,需要等场景加载完成后才能通过路径找到,所以这里先声明“要用到这个节点”,后续在_ready()中初始化。
- 实际意义:保存场景中显示分数的
Label节点引用,后续通过这个变量操作文本显示(比如更新分数)。
4. 空白行
- 作用:无语法意义,纯粹是「代码分隔符」,让变量声明和函数定义之间有视觉间隔,提升代码可读性(GDScript 忽略空白行,建议养成用空白行分隔代码块的习惯)。
5. func _ready():
- 语法作用:Godot 的「生命周期回调函数」(特殊函数,由 Godot 自动调用,无需手动调用)。
- 核心规则:
- 当脚本所在节点 **及其所有子节点都加载完成后**,Godot 会自动执行
_ready()里的代码(仅执行一次,相当于“初始化函数”)。 - 函数名
_ready是固定的(以下划线开头,Godot 内置回调),不能自定义。
- 当脚本所在节点 **及其所有子节点都加载完成后**,Godot 会自动执行
- 实际意义:用于脚本初始化操作(比如查找场景节点、设置初始状态)。
6. score_text = $ScoreText
- 语法作用:给
score_text变量赋值,通过「节点路径」找到场景中的Label节点。$:Godot 特有的「节点路径查找运算符」,等价于get_node()方法,用于查找「当前节点的子节点」(或相对路径节点)。ScoreText:是你在场景编辑器中给Label节点起的「名称」(必须和场景中节点名称完全一致,大小写敏感)。
- 实际意义:把场景中显示文本的
Label节点“绑定”到脚本的score_text变量上,后续通过score_text就能操作这个节点(比如改文本、改颜色)。 - 补充:之前的缩进错误就是这里导致的,现在已统一用 4 个空格缩进(GDScript 要求函数内代码必须缩进,且不能混合 Tab 和空格)。
7. score_text.text = " 分数 : 0 "
- 语法作用:修改
Label节点的text属性,设置初始显示文本。score_text:已绑定的Label节点对象。.text:Label节点的核心属性,用于控制显示的字符串内容。" 分数 : 0 ":字符串字面量,前后的空格是为了美观(非语法必需,可去掉写成"分数:0")。
- 实际意义:游戏启动时,分数文本框默认显示“ 分数 : 0 ”,告诉玩家初始分数是 0。
8. func increase_score(amount : int):
- 语法作用:声明一个「自定义函数」,用于实现“增加分数”的功能。
func:GDScript 声明函数的关键字。increase_score:函数名(自定义,语义是“增加分数”,建议用下划线命名法,符合 GDScript 规范)。(amount : int):函数参数,amount是参数名(表示“增加的分数值”),: int是类型注解(指定参数必须是整数)。
- 实际意义:提供一个可复用的“加分接口”,其他脚本或当前脚本可通过调用这个函数,传入要加的分数(比如
increase_score(10)就是加 10 分)。
9. score += amount
- 语法作用:「复合赋值运算」,等价于
score = score + amount。score:全局变量(当前分数)。+=:加赋值运算符,把右边的amount(增加的分数)加到左边的score上,更新score的值。
- 实际意义:修改全局分数(比如当前分数是 0,调用
increase_score(5)后,score就变成 5)。
10. score_text.text = "分数: " + str(score)
- 语法作用:更新
Label节点的文本,显示最新分数。str(score):类型转换函数,把整数类型的score转为字符串(因为.text属性只接受字符串,不能直接拼接整数和字符串)。"分数: " + str(score):字符串拼接,把固定文本“分数: ”和转换后的分数字符串连起来(比如score=5时,结果是“分数: 5”)。
- 实际意义:分数更新后,实时刷新文本显示,让玩家能看到最新分数。
- 补充:这里的空格(“分数: ”)是为了排版美观,非必需,可根据需求调整。
代码逻辑串联(整体流程)
- 游戏启动 → 场景加载完成 → Godot 自动调用
_ready(); _ready()中:- 找到场景中的
ScoreText(Label 节点),绑定到score_text变量; - 给
score_text设置初始文本“ 分数 : 0 ”;
- 找到场景中的
- 游戏过程中(比如玩家捡道具、杀敌人),调用
increase_score(amount)函数(比如increase_score(10)); - 函数执行:
- 把
amount加到score上(更新分数); - 把新分数转为字符串,拼接后更新
score_text的文本,玩家看到分数变化。
- 把
关键注意点(新手容易踩坑)
- 节点名称匹配:
$ScoreText必须和场景中 Label 节点的名称完全一致(大小写、空格都不能错),否则会报“节点未找到”错误; - 缩进规范:函数内代码必须缩进(推荐 4 个空格),不能混合 Tab 和空格(之前的报错根源);
- 类型转换:
score是整数,必须用str(score)转为字符串才能拼接,否则会报错; - 全局变量:
score和score_text是全局变量(在函数外声明),所有函数都能访问;如果声明在函数内,就是局部变量,其他函数无法使用。
(2D)内部物理小游戏
# 1. 类继承声明:当前脚本挂载的节点必须是 RigidBody2D 或其派生类(如 CharacterBody2D 不适用)
# 作用:让脚本拥有 RigidBody2D 的所有内置属性(如 global_position、mass)和方法(如 apply_impulse)
extends RigidBody2D
# 2. 变量定义:声明一个用于控制冲量大小的浮点型变量
# hit_force:变量名(语义化命名,表“撞击力”);float:类型标注(指定为浮点型,可选但推荐,提升代码可读性)
# 50.0:初始值(冲量的基础大小,值越大,物体被推动的速度越快)
var hit_force : float = 50.0
# 3. 帧更新回调函数:每帧(与帧率同步,如60帧/秒)自动调用一次,用于处理非物理相关的逻辑
# _process:Godot 内置回调函数名,不可自定义;delta:参数(帧间隔时间,单位秒,用于帧率补偿)
# 🔴 注意:RigidBody2D 是物理体,物理操作(如施加冲量)不推荐放这里,建议改用 _physics_process(与物理引擎同步)
func _process (delta):
# 4. 输入检测条件:判断鼠标左键是否被按住
# Input:Godot 输入系统的全局类(提供所有输入相关方法)
# is_mouse_button_pressed:Input 类的静态方法(检测指定鼠标按键是否处于“按住”状态)
# MOUSE_BUTTON_LEFT:Godot 内置常量(表“鼠标左键”,其他可选值如 MOUSE_BUTTON_RIGHT 是右键)
if Input.is_mouse_button_pressed(MOUSE_BUTTON_LEFT):
# 5. 获取鼠标全局位置:获取当前鼠标在屏幕上的全局坐标(Vector2 类型,含 x/y 轴)
# get_global_mouse_position():节点的内置方法(无论节点层级,直接返回全局坐标,避免局部坐标计算错误)
var mouse_pos = get_global_mouse_position()
# 6. 计算方向向量:获取“当前节点”指向“鼠标位置”的单位向量(长度为1,只保留方向信息)
# global_position:节点的内置属性(当前节点的全局坐标,与 mouse_pos 坐标体系一致)
# direction_to(mouse_pos):Vector2 类的方法(计算从自身到目标点的单位向量,自动归一化,避免距离影响力的大小)
var dir = global_position.direction_to(mouse_pos)
# 7. 施加冲量:给 RigidBody2D 施加瞬时力,使其产生运动
# apply_impulse:RigidBody2D 的内置方法(专门用于施加冲量,瞬时改变物体速度)
# 🔴 原代码错误:该方法需要 2 个参数,原代码只传了 1 个(会导致运行报错)
# 正确格式:apply_impulse(作用点, 冲量向量)
# 作用点:相对节点自身的坐标(如 Vector2.ZERO 表示重心);冲量向量:dir(方向)* hit_force(大小)
apply_impulse(dir * hit_force)
(3D)3D滑雪小游戏
# 声明当前脚本继承自 3D 刚体节点(用于模拟物理运动的核心节点)
extends RigidBody3D
# @export 让变量可在编辑器面板修改,定义移动速度(浮点型,默认值 2.0)
@export var move_speed : float = 2.0
# 物理帧更新函数(默认 60 次/秒,专门处理物理相关逻辑)
# delta:物理帧时间间隔,用于抵消不同设备帧率差异(此处未直接使用)
func _physics_process(delta):
# 检测物理按键「方向右键」是否按下(物理按键检测更适配跨平台)
if Input.is_physical_key_pressed(KEY_RIGHT):
# 给刚体施加向右的力(Vector3.RIGHT = (1,0,0),乘以速度系数控制力的大小)
apply_force(Vector3.RIGHT * move_speed)
# 若右键未按下,检测物理按键「方向左键」是否按下
elif Input.is_physical_key_pressed(KEY_LEFT):
# 给刚体施加向左的力(Vector3.LEFT = (-1,0,0))
apply_force(Vector3.LEFT * move_speed)
# 碰撞体进入当前刚体碰撞区域时触发的回调函数
# body:参数表示进入碰撞的那个节点(如 Tree 节点)
func _on_body_entered(body):
# 判断碰撞的节点是否属于 "Tree" 分组(分组需在编辑器给目标节点设置)
if body.is_in_group("Tree"):
# 延迟重载当前场景(call_deferred 避免物理帧中修改场景树导致异常)
get_tree().reload_current_scene.call_deferred()
reload_current_scene 是 Godot 引擎中 SceneTree 类的内置方法,属于引擎核心 API,专门用于重载(重启)当前正在运行的场景。下面详细拆解它的来源、调用逻辑和使用规则:
(2D)随机生成小星星
# 解析:声明当前脚本继承Node2D(2D节点基类),拥有position/scale/add_child等2D节点核心属性/方法,
# 脚本需挂载到场景中的Node2D(或其子类)节点上才能生效
extends Node2D
# 解析:@export标记让变量暴露到编辑器「检查器」面板,可可视化修改;
# var声明变量spawn_count,:int指定整型类型,=200是默认值,控制星星生成总数
@export var spawn_count : int = 200
# 解析:声明变量star_scene并指定类型为PackedScene(Godot预制体场景类型);
# preload()是预加载函数,脚本加载时就加载指定路径的星星预制体场景,避免运行时加载卡顿;
# 路径res://LoopsdotTSCN/star.tscn需确保和项目中星星场景的实际路径一致,否则会报资源找不到错误
var star_scene : PackedScene = preload("res://LoopsdotTSCN/star.tscn")
# 解析:_ready()是Godot内置生命周期函数,节点加入场景树且所有子节点加载完成后仅执行一次,
# 是初始化(如生成星星)的核心入口函数
func _ready():
# 解析:for循环,i是循环变量(从0到spawn_count-1),循环次数等于spawn_count(默认200次),
# 每次循环生成1颗星星,最终生成指定数量的星星
for i in spawn_count:
# 解析:调用PackedScene的instantiate()方法,实例化星星预制体,返回一个星星节点实例;
# 此时星星节点还未加入场景树,仅在内存中
var star = star_scene.instantiate()
# 解析:调用当前Node2D节点的add_child()方法,将实例化的星星节点添加为自己的子节点;
# 执行后星星才会显示在场景中,且继承当前节点的坐标/缩放等变换属性
add_child(star)
# 解析:给星星节点的position.x(x轴坐标)赋值,randf_range(-280,280)生成-280到280之间的随机浮点数;
# 固定范围导致星星仅分布在x轴±280区域,是星星集中的核心原因之一
star.position.x = randf_range(-280,280)
# 解析:同理,给星星y轴坐标赋值,随机范围-150到150,范围过小加剧星星集中问题
star.position.y = randf_range(-150,150)
# 解析:生成0.5到5.0之间的随机浮点数,作为星星的缩放系数
var star_scale = randf_range(0.5,5.0)
# 解析:设置星星x轴缩放值为随机系数,控制星星宽度大小
star.scale.x = star_scale
# 解析:设置星星y轴缩放值为同一随机系数,保证星星等比缩放(不拉伸变形)
star.scale.y = star_scale
- 感谢你赐予我前进的力量

