godot基础

语法

变量

1
2
3
4
5
var 变量:int #自动转换类型
var 整型:int #限定为整型
var 字符串:String #限定为字符串
var 浮点:float #限定为字符串
var 数组:array

1
2
3
class :
var x
var y

函数

1
2
func 方法()->void:
print("输出")
1
2
3
4
5
#判断类型转换掉用
if (@event is InputEventMouseMotion mouseMotion)
{
_mouseDelta = mouseMotion.Relative;
}

封装

1
2
3
4
5
6
7
8
9
var _width: float = 0.0
@export var 宽度: float=27:
get():
return _width
set(value):
if value==_width:
return
_width=value
_回调_尺寸改变时()

存储系统

  • 代码实例:读取

    1
    2
    3
    4
    5
    6
    7
    8
    9
    extends Node
    class_name 存储类

    func 读取数据(path:String):
    var file:FileAccess=FileAccess.open(path,FileAccess.READ)
    var text=file.get_as_text()
    var json_text=JSON.parse_string(text)
    return json_text
    pass
  • 代码示例:存储

    1
    2
    3
    4
    5
    func 存储数据(conn,path:String):
    var file:FileAccess=FileAccess.open(path,FileAccess.WRITE)
    var json_conn=JSON.stringify(conn)
    file.store_string(json_conn)
    pass

    延时代码 gds

    在Godot引擎中,除了call_deferred()方法外,还有一些其他类似的方法可以用来控制函数的执行时机。这些方法提供了不同的调度和延迟机制,以便开发者能够根据具体需求调整代码的执行顺序。以下是一些与call_deferred()类似的方法:

    1. yield() 和协程

    在GDScript中,你可以使用yield()来创建协程(coroutines),它允许你编写非阻塞的、分步执行的代码。通过yield(),你可以暂停函数的执行,直到某个条件满足或某个事件发生时再继续执行。这对于需要等待某些操作完成或满足某些条件的情况非常有用。

    示例

    1
    2
    3
    4
    5
    6
    func delayed_action():
    # ... 一些初始操作 ...

    yield(get_tree().create_timer(1.0), "timeout") # 等待1秒

    # ... 延迟执行的代码 ...

    2. 使用Timer节点

    Timer节点是Godot中用于定时执行操作的内置节点。你可以设置Timer的等待时间,并在时间到达时连接到一个函数或信号。这种方法通常用于需要定时重复执行或单次执行的操作。

    示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    extends Node

    onready var timer = preload("res://path_to_timer_scene.tscn").instance()

    func _ready():
    add_child(timer)
    timer.connect("timeout", self, "_on_timer_timeout")
    timer.wait_time = 1.0 # 设置等待时间为1秒
    timer.one_shot = true # 设置为单次触发
    timer.start() # 启动计时器

    func _on_timer_timeout():
    # ... 定时器超时时执行的代码 ...

    3. 使用Tween节点

    Tween节点允许你创建平滑的动画过渡效果,也可以用来延迟执行某些操作。通过Tween,你可以指定一个节点的属性值随时间变化的过程。虽然它主要用于动画,但也可以用于延迟或调整属性的变化。

    示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    extends Node2D

    onready var tween = $Tween # 假设你有一个Tween节点作为子节点

    func _ready():
    tween.interpolate_property(self, "position", Vector2(100, 100), 1.0) # 在1秒内移动到(100, 100)
    tween.start()

    yield(tween, "tween_completed") # 等待动画完成

    # ... 动画完成后执行的代码 ...

    4. 在_process_physics_process中使用时间检查

    如果你只是想在特定的时间后执行某个操作,你可以在_process_physics_process函数中使用当前时间与目标时间的比较来实现延迟。这适用于那些不需要精确时间控制的简单延迟需求。

    示例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    extends Node

    var delay_time = 1.0 # 延迟时间(秒)
    var start_time = 0.0 # 开始时间

    func _ready():
    start_time = OS.get_ticks_msec() / 1000.0 # 获取当前时间(秒)

    func _process(delta):
    if OS.get_ticks_msec() / 1000.0 - start_time >= delay_time:
    # ... 延迟执行的代码 ...
    start_time = -1.0 # 重置开始时间,防止重复执行

    这些方法提供了不同的延迟和调度机制,你可以根据具体的应用场景和需求选择最适合的方法。需要注意的是,每种方法都有其适用的场景和限制,因此在使用时应该仔细考虑其适用性和可能的影响。

玩家系统

第三人称相机控制

  • 相机创建一个Node3D为相机Camera3D的父节点,然后创建一个相机
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
extends Node3D


var 鼠标_输入
var 鼠标输入_旋转:float
var 鼠标输入_倾斜:float
var 灵敏度:float=0.25

var 欧拉_旋转:Vector3
@export var tilt_upper_limit := deg_to_rad(-60.0)
@export var tilt_lower_limit := deg_to_rad(60.0)

#开始隐藏鼠标
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
pass



func _physics_process(delta):
欧拉_旋转.x+=鼠标输入_倾斜*delta

#欧拉_旋转.x=clamp(欧拉_旋转.x,tilt_lower_limit,tilt_upper_limit)
欧拉_旋转.y+=鼠标输入_旋转*delta

transform.basis=Basis.from_euler(欧拉_旋转)

#$Camera3D.global_transform=
#$Camera3D.rotation.z=0


#初始化鼠标向量
鼠标输入_倾斜=0.0
鼠标输入_旋转=0.0
pass


func _input(event):
#初始化鼠标输入为 鼠标移动与获取鼠标模式为隐藏锁定鼠标在视口中心
鼠标_输入=event is InputEventMouseMotion and Input.get_mouse_mode()==Input.MOUSE_MODE_CAPTURED

#如果鼠标输入满足条件 执行以下代码
if 鼠标_输入:
鼠标输入_旋转=-event.relative.x*灵敏度 #鼠标x轴旋转
鼠标输入_倾斜=-event.relative.y*灵敏度 #鼠标y轴旋转

  • 玩家脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
extends CharacterBody3D@onready var 相机根:=$camercont
@onready var 角色:MeshInstance3D=$MeshInstance3D
@onready var 旋转向量:=Vector3.FORWARD

@export var 玩家基础速度:=10
@export var 玩家加速度:=20
@export var 玩家旋转速度:=12.0

const 跳跃 = 4.5

var 重力= ProjectSettings.get_setting("physics/3d/default_gravity") #获取重力


func _physics_process(delta):

#########################################################################
#掉落
if not is_on_floor():
velocity.y -= 重力 * delta

跳跃
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = 跳跃

#########################################################################

#########################################################################
#定义一个变量获取相机矩阵向量
var 相机矩阵=相机_返回()

#如果矩阵向量大于0.2 将矩阵向量规格化后赋予向前向量
if 相机矩阵.length()>0.2:
旋转向量=相机矩阵.normalized()

#将向前向量传给函数计算 控制角色的旋转
角色_旋转(旋转向量,delta)

#########################################################################

#########################################################################
#移动实现
#定义一个变量获取角色的Y轴移动向量
var Y_向量分离=velocity.y
velocity.y=0.0 #初始化Y轴向量为0

#角色移动向量=角色移动向量插值(向量*速度,向量*加速度*delta)
velocity=velocity.lerp(-相机矩阵*玩家基础速度,玩家加速度*delta)

#如果输入矩阵向量长度等于0与移动向量长度<1
if 相机矩阵.length()==0 and velocity.length()<1:
#移动向量为0
velocity=Vector3.ZERO

#恢复y轴向量
velocity.y=Y_向量分离

#########################################################################
move_and_slide()

#角色朝向和旋转
func 角色_旋转(向前向量:Vector3,delta:float)-> void:
#定义一个变量获取向前向量的叉积
var 左_对称轴:=Vector3.UP.cross(向前向量)
#定义一个变量获取矩阵(叉积,前常量向量,向前向量) 已四元素返回
var 基础位置 :=Basis(左_对称轴,Vector3.UP,向前向量).get_rotation_quaternion()
#定义一个向量 获取角色的矩阵向量 返回各轴缩放系数的绝对值
var 角色矩阵 :=角色.transform.basis.get_scale()

#角色矩阵向量等于 矩阵(以四元素返回角色矩阵向量 返回四元素插值的结果)帧乘以旋转速度 引入一个3D缩放英子
角色.transform.basis = Basis(角色.transform.basis.get_rotation_quaternion().slerp(基础位置, delta * 玩家旋转速度)).scaled(
角色矩阵
)

#相机矩阵计算返回
func 相机_返回():
#定义变量 获取输入向量
var 按键向量 := Input.get_vector("aa", "dd", "ww", "ss")
#定义向量初始化为0
var input:=Vector3.ZERO
#输入向量计算平方根
input.x= -按键向量.x * sqrt(1.0 - 按键向量.y * 按键向量.y / 2.0)
input.z= -按键向量.y * sqrt(1.0 - 按键向量.x * 按键向量.x / 2.0)

#输入向量等于相机矩阵*输入向量
input=相机根.global_transform.basis*input
#初始化Y轴为0
input.y=0.0
return input
  • 副本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
extends CharacterBody3D

@onready var 相机根: Node3D = $"Node3D"
@onready var 角色: MeshInstance3D = $MeshInstance3D
@onready var 旋转向量: Vector3 = Vector3.FORWARD



@export var 玩家基础速度: float = 10
@export var 玩家加速度: float = 20
@export var 玩家旋转速度: float = 12.0

const 跳跃 = 4.5

var 重力 = ProjectSettings.get_setting("physics/3d/default_gravity") # 获取重力

func _physics_process(delta: float):
## 掉落
#if not is_on_floor():
#velocity.y -= 重力 * delta
## 跳跃
#if Input.is_action_just_pressed("ui_accept") and is_on_floor():
#velocity.y = 跳跃

角色朝向(delta)
角色移动(delta)


move_and_slide()

func 角色_旋转(向前向量: Vector3, delta: float) -> void:
if 向前向量 == Vector3.ZERO:
return

# 计算目标旋转四元数
var 目标旋转 = Basis(Vector3.UP.cross(向前向量), Vector3.UP, 向前向量).get_rotation_quaternion()

# 平滑插值当前旋转到目标旋转,并保留缩放
var 当前旋转 = 角色.transform.basis.get_rotation_quaternion()
角色.transform.basis = Basis(当前旋转.slerp(目标旋转, delta * 玩家旋转速度)).scaled(角色.transform.basis.get_scale())


# 相机矩阵计算返回 获取相机方向
func 相机_返回() -> Vector3:
# 定义变量 获取输入向量
var 按键向量 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down").normalized()
var input:Vector3=Vector3(-按键向量.x ,0,-按键向量.y )
#从世界空间转换到相机空间
input = 相机根.global_transform.basis * input
# 初始化Y轴为0
input.y = 0.0
return input


func 角色朝向(delta:float):
var 相机矩阵:Vector3 = 相机_返回()
if 相机矩阵.length() > 0.2:
旋转向量 = 相机矩阵.normalized()
角色_旋转(旋转向量, delta)
pass

func 角色移动(delta):
var 速度=velocity
var 相机矩阵:Vector3 = 相机_返回()

速度 = 速度.lerp(-相机矩阵 * 玩家基础速度, 玩家加速度 * delta)
velocity=速度
pass

  • 简单旋转朝向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//1.
if velocity.length>0.1:
var chadir=Vector2(velovity.z,velovity.x)
角色网格节点.rotation.y=chadir.angle

//2.
if abs(player.velocity.x) + abs(player.velocity.z) > 0.1:
#获取移动方向
var characterDir = Vector2(player.velocity.z, player.velocity.x)
#转换为四元数
var target_quaternion:Quaternion = Quaternion.from_euler(Vector3(0, characterDir.angle(), 0))

#平滑旋转
player.character_rotation_root.quaternion = player.character_rotation_root.quaternion.slerp(
target_quaternion, delta * 10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
extends CharacterBody3D

@onready var 相机根: Node3D = $"SpringArm3D"
@onready var 角色: MeshInstance3D = $MeshInstance3D

@export var 玩家基础速度: float = 10.0
@export var 玩家加速度: float = 20.0
@export var 玩家旋转速度: float = 12.0
@export var 跳跃强度: float = 4.5

var 重力: float = ProjectSettings.get_setting("physics/3d/default_gravity")

# 保存当前角色朝向
var 目标朝向: Vector3 = Vector3.FORWARD

@export var 控制器:Node
@onready var input: InputClass = $"../Input"

func _physics_process(delta: float) -> void:
# 处理跳跃逻辑
处理跳跃和重力(delta)

# 更新角色朝向和移动
更新角色朝向(delta)
更新角色移动(delta)

# 应用物理
move_and_slide()

func 处理跳跃和重力(delta: float) -> void:
# 如果角色在地面上,允许跳跃
if is_on_floor():
if Input.is_action_just_pressed("ui_accept"):
velocity.y = 跳跃强度
else:
# 如果不在地面,施加重力
velocity.y -= 重力 * delta

func 更新角色朝向(delta: float) -> void:
var 输入方向 = 获取相机方向()
if 输入方向.length() > 0.2:
目标朝向 = 输入方向.normalized()
# 平滑旋转到目标朝向
var 当前旋转 = 角色.transform.basis.get_rotation_quaternion()
var 目标旋转 = Basis(Vector3.UP.cross(目标朝向), Vector3.UP, 目标朝向).get_rotation_quaternion()
var 插值旋转 = 当前旋转.slerp(目标旋转, delta * 玩家旋转速度)
角色.transform.basis = Basis(插值旋转).scaled(角色.transform.basis.get_scale())

func 更新角色移动(delta: float) -> void:
var 输入方向 = 获取相机方向()
var 目标速度 = -输入方向 * 玩家基础速度
velocity.x = lerp(velocity.x, 目标速度.x, 玩家加速度 * delta)
velocity.z = lerp(velocity.z, 目标速度.z, 玩家加速度 * delta)

func 获取相机方向() -> Vector3:
# 获取输入方向
var 按键输入 = Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down").normalized()
var 输入方向 = Vector3(-按键输入.x, 0, -按键输入.y)
# 转换到相机空间
输入方向 = 相机根.global_transform.basis * 输入方向
输入方向.y = 0.0
return 输入方向

装配系统

  • 所需节点Node3D,Marker3D作为部件放置的位置,方便调整位置

  • @tool
    extends Node3D
    class_name 装备模型
    
    @onready var 枪身: Marker3D = $"枪身"
    @onready var 枪管: Marker3D = $"枪管"
    @onready var 瞄准仪: Marker3D = $"瞄准仪"
    
    #资源,每当资源变更时刷新配件节点
    @export var 枪身资源:武器资源类:
        get: 
            return 枪身资源
        set(value):
            if value==枪身资源:
                return
            枪身资源=value
            武器资源更新()
    
    @export var 枪管资源:武器资源类:
        get: 
            return 枪管资源
        set(value):
            if value==枪管资源:
                return
            枪管资源=value
            武器资源更新()
    
    @export var 瞄准仪资源:武器资源类:
        get: 
            return 瞄准仪资源
        set(value):
            if value==瞄准仪资源:
                return
            瞄准仪资源=value
            武器资源更新()
    
    # Called every frame. 'delta' is the elapsed time since the previous frame.
    func _process(delta: float) -> void:
        pass
    func 武器资源更新():
        #初始化节点,将配件全部清除
        if(枪身 and 枪身.get_child_count()>0):
            枪身.get_child(0).queue_free()
        if(枪管 and 枪管.get_child_count()>0):
            枪管.get_child(0).queue_free()
        if(瞄准仪 and 瞄准仪.get_child_count()>0):
            瞄准仪.get_child(0).queue_free()
    
        #检查资源是否存在
        if 枪身!=null and 枪身资源:
            var 武器场景:PackedScene=load(枪身资源.武器场景路径)
            枪身.add_child(武器场景.instantiate())
        else: #如果武器不存在,初始化其他配件
            枪管资源=null
            瞄准仪资源=null
    
        #检查其他配件,如果存在则添加到节点树
        if 枪管!=null and 枪管资源:
            var 枪管场景:PackedScene=load(枪管资源.武器场景路径)
            枪管.add_child(枪管场景.instantiate())
    
        if 瞄准仪!=null and 瞄准仪资源:
            var 瞄准仪场景:PackedScene=load(瞄准仪资源.武器场景路径)
            瞄准仪.add_child(瞄准仪场景.instantiate())
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    + 背包,负责更新装备


    ```python
    extends Control

    @export var 武器展示场景: 装备模型
    @export var 武器装备场景: 装备模型
    @export var 物品背包:Array[Resource]

    # Called when the node enters the scene tree for the first time.
    func _ready() -> void:
    pass # Replace with function body.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # Called every frame. 'delta' is the elapsed time since the previous frame.
    func _process(delta: float) -> void:
    更新装备(武器展示场景);
    更新装备(武器装备场景);
    pass

    func 更新装备(data:装备模型):
    if data:
    data.枪身资源=物品背包[0]
    data.枪管资源=物品背包[1]
    data.瞄准仪资源=物品背包[2]
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    extends PanelContainer

    @onready var texture_rect: TextureRect

    @onready var 背包: Control = $"../../.."
    @export var 索引:int=0
    # Called when the node enters the scene tree for the first time.
    func _ready() -> void:
    texture_rect=get_node("TextureRect")
    pass # Replace with function body.

    # Called every frame. 'delta' is the elapsed time since the previous frame.
    func _process(delta: float) -> void:
    if 背包.物品背包[索引]:
    texture_rect.texture=背包.物品背包[索引].icon
    else:
    texture_rect.texture=preload("res://Icon/空纹理.png")
    pass

    func _get_drag_data(position):
    if 背包.物品背包[索引]:
    var cpb =TextureRect.new()
    cpb.texture=背包.物品背包[索引].icon
    set_drag_preview(cpb)
    return 背包.物品背包[索引]

    func _can_drop_data(position, data):
    # 检查是否为武器基类
    if data is Resource:
    return true
    else:
    return false
    #数据处理
    func _drop_data(position, data):
    print(data)
    if 背包.物品背包[索引]==null:
    var ite=背包.物品背包.find(data)
    背包.物品背包
    [索引]=data
    背包.物品背包[ite]=null
    else :
    var ite=背包.物品背包.find(data)
    var temp=背包.物品背包[索引]
    背包.物品背包[索引]=data
    背包.物品背包[ite]=temp

架构设计

  • 属性系统作为单个场景存在,主要用于管理角色技能,属性,效果,
  • 属性:
    • 属性通过属性资源创建

MVC设计,仿AURA

HUD

  • 属性
属性 描述
叠加层:widgetBase=null 字节点,各种UI的集合
widgetcontrol:widgetControl=null 数据控制层
  • 方法
方法 描述
初始化_叠加层(玩家状态,玩家控制器,玩家,玩家能力系统) 在玩家节点初始化属性完成后调用 公开
_get_数据控制层 初始化时调用,创建控制器单例 私有
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
extends Control
class_name 控制层

#叠加层
@export var 叠加层:WidgetBase

#数据控制层对象
var widgetcontrol:WidgetControl


#创建玩家叠加从和初始化控制层,在玩家初始化时执行
func 初始化_叠加层(玩家状态,玩家控制器,玩家,玩家能力系统):
#检查资源? 检查节点场景路径是否有效

#创建叠加层 可以创建一个UI节点**********

#初始化控制层
var 数据字典:StructTest=StructTest.new(玩家控制器,玩家状态,玩家,玩家能力系统)
widgetcontrol=_get_数据控制层(数据字典)

#初始化叠加层
叠加层.set_widgetControl(widgetcontrol)

#广播初始化
widgetcontrol.广播_初始化()
#广播实时监听
widgetcontrol.实时监听_属性变化()
pass

func _get_数据控制层(字典:StructTest):
if widgetcontrol==null:
widgetcontrol=WidgetControl.new()
widgetcontrol.设置_数据控制器参数(字典)
return widgetcontrol
pass

WidgetBase 用户控件基类

  • 属性
属性 描述
widgetControl:WidgetControl 数据控制器
  • 方法
方法 描述
set_widgetControl(v_Control:WidgetControl) 在HUD设置控制器
控制层被设置时 当控制器被设置时调用,用于绑定控制器事件
_信号_生命值被改变(NewHealth:float) 接收值设置UI显示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
extends ProgressBar
class_name WidgetBase

var widgetControl:WidgetControl

func set_widgetControl(v_Control:WidgetControl):
widgetControl=v_Control
控制层被设置时()
pass

func 控制层被设置时():
widgetControl.委托_玩家生命值改变时.connect(_信号_生命值被改变)
pass

func _信号_生命值被改变(NewHealth:float):
value=NewHealth
pass

WidgetControl 属性控制器

  • 属性
属性 描述
var 玩家控制器:Node
var 玩家控状态:Node
var 玩家对象:Node
var 玩家能力系统:能力系统
  • 信号
信号 描述
signal 委托_玩家生命值改变时(NewHealth:float) 属性改变时发出
  • 方法
方法 描述
func 设置_数据控制器参数(数据结构:StructTest): 初始化控制器携带数据
func 广播_初始化(): 在属性初始化时广播刷新UI显示
func 实时监听_属性变化(): 绑定实时更是UI,在属性集改变属性中发出信号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
extends Object
class_name WidgetControl

var 玩家控制器:Node
var 玩家控状态:Node
var 玩家对象:Node
var 玩家能力系统:能力系统

signal 委托_玩家生命值改变时(NewHealth:float)

func 设置_数据控制器参数(数据结构:StructTest):
玩家控制器=数据结构.玩家控制器
玩家控状态=数据结构.玩家控状态
玩家对象=数据结构.玩家对象
玩家能力系统=数据结构.玩家能力系统


func 广播_初始化():
委托_玩家生命值改变时.emit(16) #示例,实际广播属性集属性
pass

#绑定实时监听事件
func 实时监听_属性变化():
玩家能力系统.属性集节点.委托_属性修改时.connect(func ac(key,v):委托_玩家生命值改变时.emit(v))
pass

StructTest

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
extends Object
class_name StructTest


var 玩家控制器:Node
var 玩家控状态:Node
var 玩家对象:Node
var 玩家能力系统:Node

func _init(参数_玩家控制器,参数_玩家控状态,参数_玩家对象,参数_玩家能力系统) -> void:
玩家控制器=参数_玩家控制器
玩家控状态=参数_玩家控状态
玩家对象=参数_玩家对象
玩家能力系统=参数_玩家能力系统
pass

输入映射单例

1
2
3
4
5
6
7
8
func 添加输入映射(动作名: String, 键值: int) -> void:
# 检查是否已经存在此动作
if not InputMap.has_action(动作名):
InputMap.add_action(动作名)

var 输入事件:InputEventKey = InputEventKey.new()
输入事件.set_physical_keycode(键值)
InputMap.action_add_event(动作名, 输入事件)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
extends Node

# 按键定义
const KEY_MAPPINGS = {
"Key_W": KEY_W,
"Key_A": KEY_A,
"Key_S": KEY_S,
"Key_D": KEY_D,
"Key_E": KEY_E,
"Key_R": KEY_R,
"Key_T": KEY_T,
"Key_Y": KEY_Y,
"Key_U": KEY_U,
"Key_I": KEY_I,
"Key_O": KEY_O,
"Key_P": KEY_P,
"Key_L": KEY_L,
"Key_J": KEY_J,
"Key_K": KEY_K,
"Key_H": KEY_H,
"Key_N": KEY_N,
"Key_B": KEY_B,
"Key_M": KEY_M,
"Key_V": KEY_V,
"Key_X": KEY_X,
"Key_C": KEY_C,
"Key_Z": KEY_Z,
"Key_F": KEY_F,
"Key_G": KEY_G,
"Key_Q": KEY_Q,
"Key_Space": KEY_SPACE,
"Key_Escape": KEY_ESCAPE,
"Key_Enter": KEY_ENTER,
"Key_Backspace": KEY_BACKSPACE,
"Key_Tab": KEY_TAB,
"Key_LeftShift": KEY_SHIFT,
"Key_RightShift": KEY_SHIFT,
"Key_LeftControl": KEY_CTRL,
"Key_RightControl": KEY_CTRL,
"Key_LeftAlt": KEY_ALT,
"Key_RightAlt": KEY_ALT,
"Key_LeftSuper": KEY_META,
"Key_RightSuper": KEY_META,
"Key_Menu": KEY_MENU,
"Key_PageUp": KEY_PAGEUP,
"Key_PageDown": KEY_PAGEDOWN,
"Key_Home": KEY_HOME,
"Key_End": KEY_END,
"Key_Insert": KEY_INSERT,
"Key_Delete": KEY_DELETE,
"Key_Left": KEY_LEFT,
"Key_Right": KEY_RIGHT,
"Key_Up": KEY_UP,
"Key_Down": KEY_DOWN,
"Key_F1": KEY_F1,
"Key_F2": KEY_F2,
"Key_F3": KEY_F3,
"Key_F4": KEY_F4,
"Key_F5": KEY_F5,
"Key_F6": KEY_F6,
"Key_F7": KEY_F7,
"Key_F8": KEY_F8,
"Key_F9": KEY_F9,
"Key_F10": KEY_F10,
"Key_F11": KEY_F11,
"Key_F12": KEY_F12,
"Key_D1": KEY_1,
"Key_D2": KEY_2,
"Key_D3": KEY_3,
"Key_D4": KEY_4,
"Key_D5": KEY_5,
"Key_D6": KEY_6,
"Key_D7": KEY_7,
"Key_D8": KEY_8,
"Key_D9": KEY_9,
"Key_D0": KEY_0,
}

func _enter_tree() -> void:
初始化按键映射()


func 初始化按键映射():
for 动作名 in KEY_MAPPINGS.keys():
添加输入映射(动作名, KEY_MAPPINGS[动作名])

func 添加输入映射(动作名: String, 键值: int) -> void:
# 检查是否已经存在此动作
if not InputMap.has_action(动作名):
InputMap.add_action(动作名)

var 输入事件:InputEventKey = InputEventKey.new()
输入事件.set_physical_keycode(键值)
InputMap.action_add_event(动作名, 输入事件)