常量和枚举
在学习match语句之前,我们需要先了解什么是常量以及什么是枚举
常量
常量是游戏运行时不可更改的值。与变量不同,常量在定义后,其值不允许再被修改。尝试为常量重新赋值会触发编译错误。
因此,建议使用常量来储存那些不会发生改变的值,比如游戏规则参数、魔法数字等。
常量的定义语法: const 常量名 = 常量表达式
const A = 5
const B = Vector2(20, 20)
const C = 10 + 20 # 常量表达式
const D = Vector2(20, 30).x # 常量表达式: 20.
const E = [1, 2, 3, 4][0] # 常量表达式: 1.
const F = sin(20) # ‘sin()’可用于常量表达式。
const G = x + 20 # 无效赋值,这不是一个常量表达式(标识符 `x` 不是一个常量)
const H = A + 20 # 常量表达式: 25 (`A` 是一个常量).你也可以显式指定类型,但通常类型可以自动推断:
const: 数据类型 常量名 = 常量表达式
const A: int = 5
const B: Vector2 = Vector2()若指定的类型与实际值不匹配,会触发错误。
常量也可以用于函数内部,声明一些局部魔法数字,帮助提升可读性。
常量名应使用有效标识符,常量一般使用全大写命名:MAX_HEALTH_POINT
常量表达式
常量表达式的值必须在编译时即可确定,因此它不能包含变量引用或任何运行时决定的值,也不能依赖对象实例或其成员。
常量字面量
直接使用不可变的固定值:
整数字面量:
1,100浮点数字面量:
1.4,2.1e9字符串字面量:
"Hello","World"唯一字符串字面量:
&"Hello",&"World"节点路径字面量:
^"Hello",^"World"布尔值字面量:
true,false
值类型构造函数
可用于创建如向量、颜色、矩形等值类型对象,但构造参数必须全为常量:
Vector2(0, 0)Color(0, 0, 0, 1)Rect2(0, 0, 100, 100)
集合字面量
仅由常量组成的数组或字典:
数组:
[1, 2, 3, 4, 5, 6]字典:
{"key" : 1, "key_2" : 2, "key_3" : 3}
常量间的运算表达式
运算中所用的全部值都必须是常量:
Vector2(0, 10) * 101 + 1"Hello" + "World"
如果表达式中出现了变量或运行时值(如对象属性、函数参数等),就不能作为常量表达式,将导致编译错误。
内置常量
在GDScript中有很多内置常量,下面列举一部分:
GDScript的全局常量:
PI= 3.14159265358979
- 圆周率,表示圆的周长是直径的多少倍。相当于
TAU/ 2,即 180 度旋转。
- 圆周率,表示圆的周长是直径的多少倍。相当于
TAU = 6.28318530717959
- 圆常量,单位圆的周长,单位为弧度。相当于 PI * 2,即 360 度旋转。
INF = inf
- 正无穷,用于浮点数除以 0 的场景。负无穷为
-INF。
- 正无穷,用于浮点数除以 0 的场景。负无穷为
NAN= nan
- 非数(Not A Number)。如
0.0 / 0.0会得到nan。具有特殊性质,如:NAN != NAN为true,而NAN == NAN为false。
- 非数(Not A Number)。如
注意:INF 和 NAN 是浮点数特有的概念,整数除以 0 会直接触发运行时错误。
Color类中还有很多有意思的颜色常量,这里列举部分:
Color.BLACK = Color(0, 0, 0, 1)
- 黑色。在 GDScript 中,这是所有颜色的默认值。
Color.ALICE_BLUE = Color(0.941176, 0.972549, 1, 1)
- 爱丽丝蓝。
Color.VIOLET= Color(0.933333, 0.509804, 0.933333, 1)
- 紫罗兰色
Vector2中提供了一些常用的向量常量
Vector2.ZERO=
Vector2(0, 0)- 零向量,所有分量都设置为
0的向量。
- 零向量,所有分量都设置为
Vector2.ONE =
Vector2(1, 1)- 单位向量,所有分量都设置为
1的向量。
- 单位向量,所有分量都设置为
Vector2.INF =
Vector2(inf, inf)- 无限向量,所有分量都设置为 @GDScript.INF 的向量。
Vector2.LEFT =
Vector2(-1, 0)- 左单位向量。代表左的方向。
Vector2.RIGHT =
Vector2(1, 0)- 右单位向量。代表右的方向。
Vector2.UP =
Vector2(0, -1)- 上单位向量,Y轴向上(在Godot中是负方向)。在 2D 中 Y 是向下的,所以这个向量指向 -Y。
Vector2.DOWN =
Vector2(0, 1)- 下单位向量, Y轴向下(在Godot中是正方向)。在 2D 中 Y 是向下的,所以这个向量指向 +Y
枚举
枚举(enum)用于定义一组相关联的常量值,通常可用来表示状态、种类、键值等。枚举的每个成员都会自动赋予一个整数值,默认从 0 开始,依次递增。
enum {TILE_BRICK, TILE_FLOOR, TILE_SPIKE, TILE_TELEPORT}
# 等效于
const TILE_BRICK = 0
const TILE_FLOOR = 1
const TILE_SPIKE = 2
const TILE_TELEPORT = 3具名枚举
如果为枚举指定名称,它会生成一个只读字典,可通过键名访问值,也可使用字典的常方法进行遍历查询。
常方法也就是无副作用,不会修改原始对象实例的方法,一般会在文档中标注
const
enum WeekDays
{
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
# 等效于一个常量字典
const WeekDays = {
MONDAY = 0,
TUESDAY = 1,
WEDNESDAY = 2,
THURSDAY = 3,
FRIDAY = 4,
SATURDAY = 5,
SUNDAY = 6
}
func _ready():
# 使用 Name.KEY 来访问常量值, 打印 '5'
print(WeekDays.SATURDAY)
# 使用字典的方法:
# 打印'["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"]'
print(WeekDays.keys())
# 打印'{ "MONDAY": 0, "TUESDAY": 1, "WEDNESDAY": 2, "THURSDAY": 3, "FRIDAY": 4, "SATURDAY": 5, "SUNDAY": 6 }'
print(WeekDays)
# 打印 '[0, 1, 2, 3, 4, 5, 6]'
print(WeekDays.values())指定值
可以为枚举成员显式指定值。后续未指定的成员会在其基础上递增:
enum State {
STATE_IDLE, # 默认是 0
STATE_JUMP = 5, # 显式设为 5
STATE_SHOOT # 自动为 6(前一项 +1)
}
print(State.values()) # 输出: [0, 5, 6]允许重复值
多个成员可拥有相同的值(虽然不推荐,除非你故意需要这样做):
enum Behavior
{
ATTACK = 1
JUMP = 1
RUN = 1
}
print(Behavior.values()) # 输出: [1, 1, 1]虽然值可以重复,但键名必须唯一,不能重复定义相同的枚举
枚举类型变量
你可以声明一个变量,然后指定其类型为你声明的枚举名,赋值时可以用Name.Key或者整数常量赋值
枚举类型变量也可以和整数类型互相转换
enum WeekDays
{
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
var day: WeekDays = WeekDays.SUNDAY # 等同于 var day :WeekDays = 6
var day := WeekDays.FRIDAY # 等同于 var day :WeekDays = 4
var day: WeekDays = 0 # 等同于 WeekDays.MONDAY给枚举值变量赋值时,推荐使用Name.Key的形式赋值,更具可读性
进行if判断时,也只需要将该枚举变量与对应的枚举值进行比较即可,也可将枚举类型变量和整数常量比较,但可读性差,不推荐
enum WeekDays
{
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY
}
var day: WeekDays = WeekDays.SUNDAY # 等同于 var day :WeekDays = 6
if day == WeekDays.MONDAY:
print("周一了,要上班了")
elif day == WeekDays.FRIDAY:
print("周五了,解放了")
elif day == WeekDays.SATURDAY or day == WeekDays.SUNDAY:
print("周末了,好好玩")
else:
print("在上班了TAT")枚举类型变量的比较,实际上就是整数常量间的比较
枚举名一般使用全大写,单词间用下划线分隔。
使用具名枚举可以提高可读性,也便于调试和遍历。
枚举是常量,因此不可被修改。
练习
下面哪些常量定义是合法的?哪些会报错?请说明原因
gdscriptconst A = 5 const B = Vector2(2, 3) const C = A + 10 const D = x + 10 const E = Color(1, 1, 1, alpha) const F = sin(PI)以下哪一行会触发类型不匹配错误?
gdscriptconst A: int = 10 const B: float = 3.14 const C: String = 123 const D: Vector2 = Vector2(1, 1)以下哪些是合法的枚举定义?如果合法,它们分别对应的值是?
gdscriptenum Example1 = { A, B, C } enum Example2 { A = 3, B, C } enum Example3 { A = 3, B = 3, C = 3 } enum Example4 { A = 1, A = 2 }如下给定的枚举,输出的结果分别是什么?
gdscriptenum Colors { RED = 10, GREEN = 12, BLUE } func _ready(): print(Colors.BLUE) print(Colors.keys()) print(Colors.values())反向查找
已知如下枚举:
gdscriptenum Difficulty { EASY = 1, NORMAL = 3, HARD = 5 }请写一段逻辑,查找值为 3 的枚举项名(即找到字符串
"NORMAL")并打印出来。 提示:可以用find_key方法来查找指定值的键请定义一个名为
PlayerState的枚举,表示以下角色状态:待机(IDLE)
移动(MOVE)
攻击(ATTACK)
死亡(DEAD)
然后编写一段逻辑,在
_ready()中模拟以下行为:如果当前状态是 ATTACK,打印 "Player is attacking!" 否则如果是 DEAD,打印 "Player has fallen..." 否则打印 "Player is doing something else."提示:你可以使用
PlayerState.ATTACK来比较当前状态变量