编写脚本(Scripting)

简介

关于无需编程即可创建视频游戏的那些工具的谈论有很多。不用学习编程知识对很多独立开发者来说就是一个梦想。这种需求 - 游戏开发者、甚至在很多公司内部,希望对游戏流程拥有更多控制权,已经有很长一段时间了。

很多引擎产品号称是无需编程的环境,但相对于传统的编码开发流程,这些产品的最终使用结果,经常是做不出完整的作品、或者是能做出也太复杂或太低效。整个过程在这种环节反而耗费太多时间。实际上,游戏引擎的通常趋势是:在这种为了实现特定任务而必须要编码的地方,添加一些工具来尽量减少编码量、提升开发速度。

基于这种理解,Godot针对这个目标采用了一些有效的设计决策。第一点也是最重要的一点就是场景体系。起初它的目标并不明显,但之后很好的发挥了作用:减轻了程序员为实现架构而需要额外编码的工作。

在使用场景体系设计游戏时,整个项目被划分成互补的场景 - 不是独立的。场景之间互补,而不是相互独立。后续会有大量示例,但请先记住这点。

对于已有了专业编程知识的人来说,这是一种与MVC不同的设计模式。Godot承诺:你丢弃MVC编程习惯并换用"场景即complement"模式后,还能拥有高效。

Godot也使用 继承 <http://c2.com/cgi/wiki?EmbedVsExtend>__ 模式进行脚本编程,意味着脚本可以继承所有可用的引擎类。

GDScript

:ref:doc_gdscript 是Godot环境内运行的一种动态类型脚本语言。它的设计目标为:

  • 简单、熟悉、尽可能易于学习
  • 代码可读性高、错误安全处理;语言多数借鉴自Python

开发者通常只需花几天学习它,两周内就能完全适应。

和大多数动态类型语言一样,更高的生产效率 - 易于学习、编码很快、无需编译等,意味着对应的是性能的降低,但引擎的大多数关键代码是由C++编写(矢量运算、物理学、数学、索引等),这使得游戏最后的性能比多数类型的游戏要好。

而且如果真有更高的性能要求,关键部分的代码可以用C++重写并暴露给脚本调用。这时,你只需要将GDScript类替换成C++类即可,不需要修改游戏其它地方。

编写场景脚本

在此之前,请确保你已经读过 :ref:doc_gdscript 参考文档了。它是一种简单的语言,并且参考文档也很短,大致过一遍应该花不了几分钟。

场景设置

本文将开始编写一个简单的GUI场景。用“addnode”对话框创建下述的节点和层级:

  • Panel
    • Label
    • Button

在场景树面板,看起来效果是这样:

在2D编辑器面板中要像这样:

最后保存场景,取名"sayhello.scn"

.. _doc_scripting-adding_a_script:

添加脚本

右键点击Panel节点,然后在右键菜单中选择"Add Script":

弹出“script creation”对话框。对话框中可以选择语言、类名等。脚本文件中,GDScript是不用类名的,所以这个字段是不可编辑的。这个脚本相应的继承自“Panel”,即继承该Panel类型的节点(代码其实会自动填充的)。

填写脚本的路径名然后选择“Create”:

完成操作后,脚本被创建并添加到该节点下。在该节点下可以看到一个额外的图标及“script”属性:

打开脚本编辑器后,你就会发现已经自动填充了一段前面所述的模板代码:

当该节点(包括它所有的子节点)进入当前活跃状态的场景时,"_ready()"函数会被执行。记住哦:这个不是构造函数,构造函数是“_init()”。

脚本的角色

脚本给节点添加了行为,它用于控制该节点以及其它节点(子节点、父节点、同一级的兄弟节点等)的功能。脚本的局部作用域仅是该节点;该节点的那些虚拟函数被该脚本捕捉。

处理信号

在大多数GUI节点中都用到了信号(Signal),其实其它节点也有。当一些特定类型的动作发生时,信号就会被“发射”出来,可以连接到任意脚本实例的任意函数。这一步中,按钮的"pressed"信号会被连接到一个自定义函数。

编辑器中有连接信号到脚本的界面:选中场景树中的节点,然后选择“节点”选项卡,再选中其中的"Signals"选项卡。

此时我们主要对"pressed"信号感兴趣。除了可用可视化界面来完成信号连接操作,也可以通过脚本代码来进行。

针对这种情况,Godot的程序员可能用得最多的一个函数:

:ref:Node.get_node() <class_Node_get_node>.

该函数使用路径来获取该场景中当前树状结构或任意地方的节点。

要获取到该按钮,需要用下述写法:


get_node("Button")

下一步,当按钮被按下时,会添加一个回调 - 改变标签的文本内容:


func _on_button_pressed():
get_node("Label").set_text("HELLO!")

最后,该按钮的"pressed"信号需要在_ready()函数中进行连接, :ref:Object.connect() <class_Object_connect>.


func _ready():
get_node("Button").connect("pressed",self,"_on_button_pressed")

脚本的最终内容大致如下:


extends Panel # member variables here, example: # var a=2
# var b="textvar" func _on_button_pressed():
get_node("Label").set_text("HELLO!") func _ready():
get_node("Button").connect("pressed",self,"_on_button_pressed")

运行场景,按下按钮后应该就能得到预期的结果:

注意: get_node(path)仅会在节点的最直接的下一节范围内查找,即Button必须是Panel子一级节点,否则是访问不到的。假如ButtonLabel的子一级节点,代码就需要修改了:


# not for this case
# but just in case
get_node("Label/Button")

而且要记住,这里引用的是节点的名称而不是节点的类型名。

[译]Godot系列教程四 - 编写脚本的更多相关文章

  1. [译]Godot系列教程六 - 简单的二维游戏

    Pong Godot自带的Demo中有大量更复杂的示例,但这款叫"Pong"的游戏可以对2D游戏的基本特性做一个介绍. 静态资源 本文所用到的一些资源文件:http://files ...

  2. [译]Godot系列教程五 - 制作Godot编辑器插件

    制作插件 下文仅针对2.1版本. 关于插件 插件是为编辑器扩展出更多有用工具的重要方式.它可以完全用GDScript和标准场景开发,甚至都不需重新加载编辑器就可生效.不像模块,你无需创建C++代码.也 ...

  3. [译]Godot系列教程三 - 场景实例化(续)

    场景实例化(续) 要点 场景实例化带来很多便利的用法,总体来说有: 将场景细分,更便于管理 相对于某些引擎中的Prefab组件更灵活,并且在许多方面更强大 是一种设计更复杂的游戏流程甚至UI的方式 这 ...

  4. [译]Godot系列教程二 - 场景实例化(Instancing)

    场景实例化(Instancing) 原理阐述 创建一个场景并将节点扔到里面对于小项目是适用的,但随着项目不断发展,用到越来越多的节点,整个项目很快就会演化成难以管理的状态. 为了解决这个问题,Godo ...

  5. [译]Godot系列教程一 - 场景与节点

    场景(Scene)与节点(Node) 简介 先设想有那么一瞬间你自己不再是一名游戏开发者了,而是一名大厨! 你的装备换成了一套大厨的制服.不要考虑制作游戏的事情,你现在的职责是为你的顾客创建新的可口的 ...

  6. C#微信公众号开发系列教程四(接收普通消息)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  7. webpack4 系列教程(四): 单页面解决方案--代码分割和懒加载

    本节课讲解webpack4打包单页应用过程中的代码分割和代码懒加载.不同于多页面应用的提取公共代码,单页面的代码分割和懒加载不是通过webpack配置来实现的,而是通过webpack的写法和内置函数实 ...

  8. CRL快速开发框架系列教程四(删除数据)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  9. Android Studio系列教程四--Gradle基础

    Android Studio系列教程四--Gradle基础 2014 年 12 月 18 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处!http://stormzhang ...

随机推荐

  1. 人才市场的IT职位分析

    最近要找长沙的工作,于是通过湖南人才市场搜索了一下职位.结果得到的数据让我很难比较,作为一个 IT 业滚爬了多年的程序员,对这样的搜索结果很不满意.于是,我不得不自己来整理数据了.本文内容包括:网页数 ...

  2. Oracle 多行转多列,列值转为列名

    前段时间做调查问卷,客户创建自定义问卷内容,包括题目和选项内容; 之后需要导出问卷明细,,,,麻烦来咯 于是到网上到处搜索,没有直接结果;于是又找各种相似的,,终于功夫不负有心人 然后最终自己写出来了 ...

  3. Drupal8重命名上传的中文名文件

    完整的模块代码文件在Coding.net上,想直接使用的请前往下载:https://coding.net/u/yamus/p/chinese_rename/git/tree/master 最近吧Dru ...

  4. js中的块作用域

    今天我们来一起研究下JavaScript中的变量作用域问题,话不多说,直接上代码. <script type="text/javascript"> (function( ...

  5. python的shutil模块

    shutil模块提供了大量的文件的高级操作.特别针对文件拷贝和删除,主要功能为目录和文件操作以及压缩操作 1.复制文件 def copy(src, dst): """Co ...

  6. UGUI 之Scroll Rect 坑

    由于UGUI没有提供类似Scroll View类似的控件,但提供了ScrollRect主机.可以自定义Scroll View 同时提供了Mask组件来遮罩超出Scroll Rect对象的范围, 之所以 ...

  7. ASP.NET MVC5 网站开发实践(二) Member区域–管理列表、回复及删除

    本来想接着上次把这篇写完的,没想到后来工作的一些事落下了,放假了赶紧补上. 目录: ASP.NET MVC5 网站开发实践 - 概述 ASP.NET MVC5 网站开发实践(一) - 项目框架 ASP ...

  8. 深入学习jQuery动画控制

    × 目录 [1]动画状态 [2]停止动画 [3]动画延迟[4]全局控制 前面的话 jQuery动画可以使用fade.hide.slide等方法实现基本动画效果,可以使用animate实现自定义动画,甚 ...

  9. 深入学习jQuery节点操作

    × 目录 [1]创建节点 [2]插入节点 [3]删除节点[4]复制节点[5]替换节点[6]包裹节点 前面的话 DOM节点操作包括创建节点.插入节点.移除节点.替换节点和复制节点.jQuery也有类似的 ...

  10. 虚拟化 - 每天5分钟玩转 OpenStack(2)

    OpenStack是云操作系统,要学习OpenStack,首先需要掌握一些虚拟化和云计算的相关知识. 虚拟化 虚拟化是云计算的基础.简单的说,虚拟化使得在一台物理的服务器上可以跑多台虚拟机,虚拟机共享 ...