Godot 免费跨平台游戏引擎 (四、脚本GDScript)
“Godot引擎是一款功能丰富的跨平台游戏引擎,可通过统一界面创建2D和3D游戏。 它提供了一套全面的通用工具,因此用户可以专注于制作游戏,而无需重新发明轮子。 游戏可以一键导出到多个平台,包括主要的桌面平台(Linux、macOS、Windows)以及移动平台(Android、iOS)和基于Web的(HTML5)平台。”
官网:https://godotengine.org
当前版本:3.2.1
官方中文文档(这个比较惊喜,看起来是社区翻译的,也包含一些段落的英文。)
考虑到打开官方的速度确实比较不稳定,我将中文文档放在网站上,有根据需要做一些翻译。
运行程序只有一个文件,若要发行再下载一个模板文件,可以导出多平台程序。
下载示例等,一般晚上速度还可以。看官方文档也一样,白天经常连图都不能出来。
一个教程 https://www.javatpoint.com/godot
在B站也搜索出一些相关视频。也通过wget下载的中英文整站,这样看起来顺畅太多。
这里列出一些新手教程,因为博客暂时不支持视频嵌入。
另外,有视频介绍了一个简单的音效生成网站 https://www.leshylabs.com/apps/sfMaker/
Godot支持哪些平台?
编辑器:Windows、macOS、X11(Linux,*BSD)
导出游戏:Windows(包括 UWP)、macOS系统、X11(Linux,*BSD)、Android、iOS、Web
据说在ARM中也能运行
支持编程语言
Godot官方支持的语言是GDScript、Visual Scripting、C#和C ++。
渐进式教程
编辑器
编辑器提供了多种语言适配。启动界面可以进入项目管理和网上的模板下载,不过看起来仍然乱七八糟,不成体系,而且各个版本夹杂。
看看主界面
F1 访问2D工作区,F2 访问3D工作区,F3访问脚本编辑器,F4搜索API参考手册,F6运行场景。
场景与节点
节点是创建游戏的基本构建块。它有以下属性:名字、可编辑的属性、可接收回调以处理每个帧、可以被扩展、可以作为子节点被添加到其它节点。
场景是由一组分层组织的节点。场景始终有一个根节点,能够保存和载入,能够被实例化。运行游戏意味着运行一个场景,且必须有一个主场景。一个项目可以有多个场景。
在场景中添加节点,选择2D/3D场景。示例这里添加一个标签,所以点击了2D场景,它将添加一个根结点。
配置项目
设置存放在project.godot文件中,这是一个类似ini的文本文件。选择项目-项目设置
在这里可以选择主场景。
实例化
之前讲了场景的创建,我们可以创建任意多的场景保存到磁盘,以这种方式保存的场景被称为“打包场景”,并会有.tscn扩展名。
一旦场景被保存,它就可以被实例化到另一个场景中,就像其它任何节点一样。
通过示例实例化
选择已实例化的部件,Ctrl+D可以复制。
场景中,球体和隔条都是部件的实例化。
部件相关属性,这里需要补一补英语,它可没汉化:
friction:摩擦力
Gravity Scale:重力程度
Mass: 质量
Bounce: 弹性
RigidBody:刚性体
编写脚本
GDScript、可视化脚本、C#、C++
编写场景脚本
脚本为节点添加行为,用于控制节点的功能以及与其它节点的交互。
脚本看起来是这样的,还是比较好理解。
extends Panel
func _ready():
get_node("Button").connect("pressed", self, "_on_Button_pressed")
func _on_Button_pressed():
get_node("Label").text = "HELLO!"
get_node(“Button”) 是用于搜索节点,获取它的句柄。 若Button是Label的子项,则应该是get_node(“Label/Button”)。其中Button是节点名称。
func _process(delta):
pass
此事件是每次绘制帧时都会被调用的,频率受FPS影响。delta包含上次调用后经过的时间秒。
我将代码改成
extends Panel
func _ready():
get_node("Button").connect("pressed",self,"_on_Button_pressed")
func _on_Button_pressed():
get_node("Label").text="Hello!"
func _process(delta):
get_node("Label").text = str(delta)
分组
这里没有太明白,先坑后填吧。
通知
底层虚函数,通常不需放入脚本代码。可能在调试时有用。
func _notification(what):
match what:
NOTIFICATION_READY:
print("This is the same as overriding _ready()...")
NOTIFICATION_PROCESS:
print("This is the same as overriding _process()...")
可重载函数
func _enter_tree():
# When the node enters the Scene Tree, it becomes active
# and this function is called. Children nodes have not entered
# the active scene yet. In general, it's better to use _ready()
# for most cases.
pass
func _ready():
# This function is called after _enter_tree, but it ensures
# that all children nodes have also entered the Scene Tree,
# and became active.
pass
func _exit_tree():
# When the node exits the Scene Tree, this function is called.
# Children nodes have all exited the Scene Tree at this point
# and all became inactive.
pass
func _process(delta):
# This function is called every frame.
pass
func _physics_process(delta):
# This is called every physics frame.
pass
创建节点
可以通过代码来创建节点。
var s
func _ready():
s = Sprite.new()
add_child(s)
删除节点
func _someaction():
s.free()
当一个节点被释放时,它也会释放所有子节点。删除节点最安全方法,将在空闲期间安全删除。
func _someaction():
s.queue_free()
实例化场景
var scene = load("res://myscene.tscn")
var scene = preload("res://myscene.tscn") #预加载
var node = scene.instance() #添加到节点
add_child(node)
将脚本注册为类
命名脚本,并在编辑器中使用class_name 关键字并后跟类名将其注册为类型。
extends Node
class_name ScriptName, "res://path/to/optional/icon.svg" #定义一个类名
func _ready():
var this = ScriptName # 脚本引用
var cppNode = MyCppNode.new() # 类名MyCppNode继承
cppNode.queue_free()
信号
计时器示例
创建一个2D新场景,添加两个子结点:一个时间和一个精灵。
添加一个脚本,实现了定时闪烁精灵。与其它语言有点不同的是,它通过timeout事件来实现定时器。这里通过$Sprite引用结点。
func _on_Timer_timeout():
$Sprite.visible = ! $Sprite.visible
用代码连接信号
先在计时器的节点选项卡中,选中已连接的事件,点右下方断开信号。
然后就可以用过代码,在需要的时候再进行连接。
extends Node2D
func _ready():
$Timer.connect("timeout",self,"_on_Timer_timeout")
func _on_Timer_timeout():
$Sprite.visible = ! $Sprite.visible
自定义信号
声明后,自定义的信号将出现在检查器中
extends Node2D
signal my_signal
要通过代码发出信号,使用 emit_signal 函数:
extends Node2D
signal my_signal
func _ready():
emit_signal("my_signal")