diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9e9c99 --- /dev/null +++ b/.gitignore @@ -0,0 +1,71 @@ +# Compiled class file +*.class + +# Log file +*.log +*.log* +**/logs/ + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + +# 忽略IntelliJ IDEA生成的项目描述文件 +.idea +*.iml +**/target/ + +# 忽略lucene生成的索引文件 +**/lucene-data/ + +# 忽略生成的协议文件 +**/jsProtocol/ +**/CsProtocol/ +**/LuaProtocol/ +**/zapp-user/protocol/ +**/protobuf/ + +# 以下是web前端需要忽略的文件 +# 忽略npm生成的package描述文件 +package-lock.json + + +# 忽略web前端前端package.json,bower.json所有依赖的包 +**/node_modules/ +**/bower_components/ + +# 忽略npm编译后的文件 +**/dist/ + +# 忽略webapp中部署的文件 +**/resources/static/ +**/resources/templates/index.html + +# test文件 +tests/**/coverage/ +tests/e2e/reports + + +# Godot-specific ignores +.import/ +export.cfg +export_presets.cfg + +# Mono-specific ignores +.mono/ +data_*/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2511125 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 jaysunxiao + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index c5048b3..dad2d11 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # godot-util + godot engine util and example + +关于godot的基本使用示例 diff --git a/default_env.tres b/default_env.tres new file mode 100644 index 0000000..20207a4 --- /dev/null +++ b/default_env.tres @@ -0,0 +1,7 @@ +[gd_resource type="Environment" load_steps=2 format=2] + +[sub_resource type="ProceduralSky" id=1] + +[resource] +background_mode = 2 +background_sky = SubResource( 1 ) diff --git a/doc/demo02_base/base.md b/doc/demo02_base/base.md new file mode 100644 index 0000000..8b296d6 --- /dev/null +++ b/doc/demo02_base/base.md @@ -0,0 +1,17 @@ +- 参考资料 +- [godot官方文档](https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/gdscript_basics.html) +- [Godot Tutorials的youtube播放量最高的godot教程视频](https://www.youtube.com/watch?v=JJQa3xrRNM0&list=PLJ690cxlZTgL4i3sjTPRQTyrJ5TTkYJ2_) +- [B站视频](https://www.bilibili.com/video/BV17g4y1z7uS) + +# 数据类型 +![Image text](integer.JPG) +![Image text](integer_overflow.JPG) + + + + + + + + + diff --git a/doc/demo02_base/integer.JPG b/doc/demo02_base/integer.JPG new file mode 100644 index 0000000..d91312d Binary files /dev/null and b/doc/demo02_base/integer.JPG differ diff --git a/doc/demo02_base/integer.JPG.import b/doc/demo02_base/integer.JPG.import new file mode 100644 index 0000000..19da2a2 --- /dev/null +++ b/doc/demo02_base/integer.JPG.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/integer.JPG-43a607bfd4c2c4f83e738b20fb6c9816.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://doc/demo02_base/integer.JPG" +dest_files=[ "res://.import/integer.JPG-43a607bfd4c2c4f83e738b20fb6c9816.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/doc/demo02_base/integer_overflow.JPG b/doc/demo02_base/integer_overflow.JPG new file mode 100644 index 0000000..7961f00 Binary files /dev/null and b/doc/demo02_base/integer_overflow.JPG differ diff --git a/doc/demo02_base/integer_overflow.JPG.import b/doc/demo02_base/integer_overflow.JPG.import new file mode 100644 index 0000000..940e120 --- /dev/null +++ b/doc/demo02_base/integer_overflow.JPG.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/integer_overflow.JPG-08e89d4444868183c3be1155d3451030.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://doc/demo02_base/integer_overflow.JPG" +dest_files=[ "res://.import/integer_overflow.JPG-08e89d4444868183c3be1155d3451030.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/doc/demo03_lifecycle/godot_lifecycle.jpg b/doc/demo03_lifecycle/godot_lifecycle.jpg new file mode 100644 index 0000000..b6b7def Binary files /dev/null and b/doc/demo03_lifecycle/godot_lifecycle.jpg differ diff --git a/doc/demo03_lifecycle/godot_lifecycle.jpg.import b/doc/demo03_lifecycle/godot_lifecycle.jpg.import new file mode 100644 index 0000000..67fca03 --- /dev/null +++ b/doc/demo03_lifecycle/godot_lifecycle.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/godot_lifecycle.jpg-b26541e87e5327f35f02175dab2eb781.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://doc/demo03_lifecycle/godot_lifecycle.jpg" +dest_files=[ "res://.import/godot_lifecycle.jpg-b26541e87e5327f35f02175dab2eb781.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/doc/demo03_lifecycle/godot_node.jpg b/doc/demo03_lifecycle/godot_node.jpg new file mode 100644 index 0000000..aa8a0cb Binary files /dev/null and b/doc/demo03_lifecycle/godot_node.jpg differ diff --git a/doc/demo03_lifecycle/godot_node.jpg.import b/doc/demo03_lifecycle/godot_node.jpg.import new file mode 100644 index 0000000..e1e3432 --- /dev/null +++ b/doc/demo03_lifecycle/godot_node.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/godot_node.jpg-16331f3f19dfee3528c1c8a0616ee82e.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://doc/demo03_lifecycle/godot_node.jpg" +dest_files=[ "res://.import/godot_node.jpg-16331f3f19dfee3528c1c8a0616ee82e.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/doc/demo03_lifecycle/godot_process.jpg b/doc/demo03_lifecycle/godot_process.jpg new file mode 100644 index 0000000..8b67a18 Binary files /dev/null and b/doc/demo03_lifecycle/godot_process.jpg differ diff --git a/doc/demo03_lifecycle/godot_process.jpg.import b/doc/demo03_lifecycle/godot_process.jpg.import new file mode 100644 index 0000000..2dea079 --- /dev/null +++ b/doc/demo03_lifecycle/godot_process.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/godot_process.jpg-0257d8dc365734710f5f2b2802378ee8.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://doc/demo03_lifecycle/godot_process.jpg" +dest_files=[ "res://.import/godot_process.jpg-0257d8dc365734710f5f2b2802378ee8.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/doc/demo03_lifecycle/lifecycle.md b/doc/demo03_lifecycle/lifecycle.md new file mode 100644 index 0000000..c73ece4 --- /dev/null +++ b/doc/demo03_lifecycle/lifecycle.md @@ -0,0 +1,3 @@ +![Image text](./godot_process.jpg) +![Image text](./godot_node.jpg) +![Image text](./godot_lifecycle.jpg) diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..c98fbb6 Binary files /dev/null and b/icon.png differ diff --git a/icon.png.import b/icon.png.import new file mode 100644 index 0000000..96cbf46 --- /dev/null +++ b/icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.png" +dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..9515db7 --- /dev/null +++ b/project.godot @@ -0,0 +1,33 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=4 + +_global_script_classes=[ { +"base": "Reference", +"class": "MyClass", +"language": "GDScript", +"path": "res://script/demo02_base/MyClass.gd" +} ] +_global_script_class_icons={ +"MyClass": "res://icon.png" +} + +[application] + +config/name="godot-util" +run/main_scene="res://scene/demo01_hello/HelloWorld.tscn" +config/icon="res://icon.png" + +[physics] + +common/enable_pause_aware_picking=true + +[rendering] + +environment/default_environment="res://default_env.tres" diff --git a/scene/demo01_hello/HelloWorld.tscn b/scene/demo01_hello/HelloWorld.tscn new file mode 100644 index 0000000..92ae009 --- /dev/null +++ b/scene/demo01_hello/HelloWorld.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://script/demo01_hello/hello_world.gd" type="Script" id=1] + +[node name="Node2D" type="Node2D"] +script = ExtResource( 1 ) + +[node name="Label" type="Label" parent="."] +margin_left = 353.108 +margin_top = 248.378 +margin_right = 589.108 +margin_bottom = 358.378 +text = "Hello World" +align = 1 +valign = 1 +max_lines_visible = 2 +__meta__ = { +"_edit_use_anchors_": false +} diff --git a/scene/demo02_base/Base.tscn b/scene/demo02_base/Base.tscn new file mode 100644 index 0000000..8d9705f --- /dev/null +++ b/scene/demo02_base/Base.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=2] + +[ext_resource path="res://script/demo02_base/base.gd" type="Script" id=1] + +[node name="Node2D" type="Node2D"] +script = ExtResource( 1 ) +a = 9 diff --git a/scene/demo03_lifecycle/LifeCycle.tscn b/scene/demo03_lifecycle/LifeCycle.tscn new file mode 100644 index 0000000..1efdfe2 --- /dev/null +++ b/scene/demo03_lifecycle/LifeCycle.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=4 format=2] + +[ext_resource path="res://script/demo03_lifecycle/sub_node1.gd" type="Script" id=1] +[ext_resource path="res://script/demo03_lifecycle/sub_node2.gd" type="Script" id=2] +[ext_resource path="res://script/demo03_lifecycle/parent.gd" type="Script" id=3] + +[node name="Node2D" type="Node2D"] +script = ExtResource( 3 ) + +[node name="SubNode1" type="Node2D" parent="."] +script = ExtResource( 1 ) + +[node name="SubNode2" type="Node" parent="SubNode1"] +script = ExtResource( 2 ) diff --git a/scene/demo04_signal/Signal.tscn b/scene/demo04_signal/Signal.tscn new file mode 100644 index 0000000..84a8f0c --- /dev/null +++ b/scene/demo04_signal/Signal.tscn @@ -0,0 +1,64 @@ +[gd_scene load_steps=5 format=2] + +[ext_resource path="res://script/demo04_signal/signal.gd" type="Script" id=1] +[ext_resource path="res://script/demo04_signal/mySignal.gd" type="Script" id=2] +[ext_resource path="res://script/demo04_signal/yield.gd" type="Script" id=3] +[ext_resource path="res://script/demo04_signal/thread.gd" type="Script" id=4] + +[node name="Node2D" type="Node2D"] +script = ExtResource( 1 ) + +[node name="Button1" type="Button" parent="."] +margin_left = 322.927 +margin_top = 50.5072 +margin_right = 441.927 +margin_bottom = 90.5072 +text = "button1" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Button2" type="Button" parent="."] +margin_left = 541.436 +margin_top = 44.0454 +margin_right = 661.436 +margin_bottom = 94.0454 +text = "button2" +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="MySignal" type="Button" parent="."] +margin_left = 323.703 +margin_top = 148.643 +margin_right = 430.703 +margin_bottom = 192.643 +text = "mySignal" +script = ExtResource( 2 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Yield" type="Button" parent="."] +margin_left = 322.941 +margin_top = 244.0 +margin_right = 433.941 +margin_bottom = 287.0 +text = "yield" +script = ExtResource( 3 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="Thread" type="Button" parent="."] +margin_left = 321.059 +margin_top = 331.0 +margin_right = 435.059 +margin_bottom = 374.0 +text = "thread" +script = ExtResource( 4 ) +__meta__ = { +"_edit_use_anchors_": false +} + +[connection signal="pressed" from="Button1" to="." method="_on_Button1_pressed"] diff --git a/script/demo01_hello/hello_world.gd b/script/demo01_hello/hello_world.gd new file mode 100644 index 0000000..518a987 --- /dev/null +++ b/script/demo01_hello/hello_world.gd @@ -0,0 +1,11 @@ +extends Node2D + + +# Declare member variables here. Examples: +# var a = 2 +# var b = "text" + + +# Called when the node enters the scene tree for the first time. +func _ready(): + print("Hello World") diff --git a/script/demo02_base/MyClass.gd b/script/demo02_base/MyClass.gd new file mode 100644 index 0000000..b147d69 --- /dev/null +++ b/script/demo02_base/MyClass.gd @@ -0,0 +1,170 @@ +# extends Node2D + +var StringUtils = load("res://util/StringUtils.gd") + +# (optional) class definition with a custom icon +class_name MyClass, "res://icon.png" + + + +# Member variables +# gds有5种基础类型,Boolean,Integer(Java long),Float(Java double),String,Null + +# &&=and ||=or !=not +var a = (true or false) && true +var b = 9223372036854775807 +var c = 1.5 +var s = "Hello" +var arr = [1, 2, 3] +var dict = { + 2: 3, + "key": "字符串作为key", + arr: "数组作为key" +} +var typed_var: int +var inferred_type: String = "String" + +# Constants + +const ANSWER = 42 +const THE_NAME = "Charly" + +# Enums + +enum {LEFT, RRIGHT, FRONT, BACK} +# 等价于 +# const LEFT = 0 +# const RIGHT = 1 +# const FRONT = 2 +# const BACK = 3 +enum FOOD {GOOD, NORMAL, BAD = -1} + +# Built-in vector types + +var v2 = Vector2(1, 2) +var v3 = Vector3(1, 2, 3) + +func _init(): + pass + +static func getAnswer(): + return ANSWER + +func typeInfo(): + var template = "[Variant:{}] [type:{}] [value:{}]" + print(StringUtils.format(template, [TYPE_BOOL, typeof(a), a])) + print(StringUtils.format(template, [TYPE_INT, typeof(b), b])) + print(StringUtils.format(template, [TYPE_INT, typeof(c), c])) + print(StringUtils.format(template, [TYPE_STRING, typeof(s), s])) + print(StringUtils.format(template, [TYPE_ARRAY, typeof(arr), arr])) + print(StringUtils.format(template, [TYPE_DICTIONARY, typeof(dict), dict])) + print(StringUtils.format(template, [TYPE_DICTIONARY, typeof(FOOD), FOOD])) + print(StringUtils.format(template, [TYPE_DICTIONARY, typeof(FOOD.GOOD), FOOD.GOOD])) + print(self is Reference) + print(a is Dog) # 类似于instanceof + +func some_function(param1, param2): + var local_var = 5 + + if param1 < local_var: + print(param1) + elif param2 > 5: + print(param2) + else: + print("Fail!") + + match local_var: + 1: + print("match1") + 2: + print("match2") + 5: + print("match5") + # continue + 6: + print("match6") + _: + print("match_") + + for i in range(20): + print(i) + + while param2 != 0: + param2 -= 1 + + var local_var2 = param1 + 3 + return local_var2 + +# Function +func arrayIterator(): + # range等价于for(int i = 0; i < 20; i++) + print("数组遍历方法1:") + for i in range(3): + print(i) + print("数组遍历方法2:") + for ele in arr: + print(ele) + print("数组遍历方法3:") + for index in range(arr.size()): + print(arr[index]) + + +func dictionaryIterator(): + print("字典遍历方法1:") + for key in dict: + print("key:" + key as String) + print("value:" + dict[key] as String) + + print("字典遍历方法2:") + for key in dict.keys(): + print("key:" + key as String) + print("value:" + dict[key] as String) + + print("字典遍历方法3:") + for value in dict.values(): + print("value:" + value as String) + + + + +func innerClassTest(): + var dog = Dog.new(1) + dog.move() + + dog.info() + dog.height = 2 + dog.info() + +# Inner class,默认继承Object +class Animal: + extends Object # 如果不指定继承的类,默认基础Object + const STATIC_FIELD = "静态变量" + # 属性 + var height: int + + func _init(): + print("Animal 构造方法") + + func move(): + print("animal,移动") + + static func staticFuction(): + pass + +class Dog: + extends Animal + + # Constructor + func _init(height): + self.height = height + print("Dog 构造方法") + + # Functions override functions with the same name on the base/parent class. + func move(): + print("dog,用4个脚跑") + # If you still want to call them, use '.' (like 'super' in other languages). + .move() + + func info(parm = 100): + print("height:" + height as String) + diff --git a/script/demo02_base/base.gd b/script/demo02_base/base.gd new file mode 100644 index 0000000..b174f89 --- /dev/null +++ b/script/demo02_base/base.gd @@ -0,0 +1,59 @@ +extends Node2D + +# Declare member variables here. Examples: +export var a = 1 +export var b:NodePath +export(NodePath) var c +export(String, FILE) var e +export(String, FILE, "*.txt") var d +export(Resource) var f +export(Color, RGB) var g +var arr = [] +# Called when the node enters the scene tree for the first time. +func _ready(): + print("new一个对象--------------------------------") + var myClass = MyClass.new() + print(myClass.to_string()) + + print("类型信息--------------------------------") + myClass.typeInfo() + + print("基础语法--------------------------------") + myClass.some_function(1, 2) + + print("访问静态变量--------------------------------") + var answer = MyClass.ANSWER + print("访问const变量,类似于static变量:" + answer as String) + + print("调用静态方法--------------------------------") + print("调用静态方法:" + MyClass.getAnswer() as String) + + print("数组遍历--------------------------------") + myClass.arrayIterator() + print("字典遍历--------------------------------") + myClass.dictionaryIterator() + + print("内部类测试--------------------------------") + myClass.innerClassTest() + + print("垃圾回收--------------------------------") + # 如果一个类没有指明继承哪个类,则默认继承Reference(可以被自动的垃圾回收,类似其他语言的那种垃圾回收) + for i in range(10000): + var instance = MyClass.new() + arr.append(instance) + # instance.unreference() + # 立即释放对象 + # instance.free() + # 放在队列里,等系统统一释放对象,推荐 + # instance.queue_free() + print("立即输出数组的第一位内容:") + var firstElement = arr[0] + print(arr[0]) + +var frame = 0 +func _process(delta): + frame = frame + 1 + if frame == 300: + print("等待一会数组的第一位内容") + arr[0].typeInfo() + print(typeof(arr[0])) diff --git a/script/demo03_lifecycle/parent.gd b/script/demo03_lifecycle/parent.gd new file mode 100644 index 0000000..9db6cdf --- /dev/null +++ b/script/demo03_lifecycle/parent.gd @@ -0,0 +1,28 @@ +extends Node2D + +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. + print("parent _enter_tree") + +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. + print("parent _ready") + +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. + print("parent _exit_tree") + +func _process(delta): + # This function is called every frame. + pass + +func _physics_process(delta): + # This is called every physics frame. + pass diff --git a/script/demo03_lifecycle/sub_node1.gd b/script/demo03_lifecycle/sub_node1.gd new file mode 100644 index 0000000..3aff6b4 --- /dev/null +++ b/script/demo03_lifecycle/sub_node1.gd @@ -0,0 +1,55 @@ +extends Node2D + + +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. + print("sub node1 _enter_tree") + +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. + print("sub node1 _ready") + nodeUsage() + +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. + print("sub node1 _exit_tree") + +func _process(delta): + # This function is called every frame. + pass + +func _physics_process(delta): + # This is called every physics frame. + pass + +# 申明和存储节点,等价于在_ready()下赋值 +onready var readySubNode = $SubNode2 + +func nodeUsage(): + # 获取当前节点 + var currentNode1 = $"." + var currentNode2 = self + # 获取父节点 + var parentNode1 = get_parent() + var parentNode2 = $"../" + # 获取子节点 + var subNode1 = $SubNode2 + var subNode2 = $"SubNode2" + var subNode3 = get_node("SubNode2") + # 根节点查找法,会返回节点树从上到下找到的第一个节点 + var subNode4 = get_tree().root.find_node("SubNode2", true, false) + print(currentNode1.name) + print(currentNode2.name) + print(parentNode1.name) + print(parentNode2.name) + print(subNode1.name) + print(subNode2.name) + print(subNode3.name) + print(subNode4.name) diff --git a/script/demo03_lifecycle/sub_node2.gd b/script/demo03_lifecycle/sub_node2.gd new file mode 100644 index 0000000..0267f9c --- /dev/null +++ b/script/demo03_lifecycle/sub_node2.gd @@ -0,0 +1,30 @@ +extends Node + + +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. + print("sub node2 _enter_tree") + +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. + print("sub node2 _ready") + +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. + print("sub node2 _exit_tree") + +func _process(delta): + # This function is called every frame. + pass + +func _physics_process(delta): + # This is called every physics frame. + pass + diff --git a/script/demo04_signal/mySignal.gd b/script/demo04_signal/mySignal.gd new file mode 100644 index 0000000..550dfbb --- /dev/null +++ b/script/demo04_signal/mySignal.gd @@ -0,0 +1,22 @@ +extends Button + + +# 自定义信号 +signal mySignal(a, b) + +# 发送信号 +# emit_signal("mySignal", 1, 2) +# disconnect("mySignal", 1, 2) + +# 类似于设计模式中的观察者 +func _ready(): + self.connect("mySignal", self, "onMySingalCallback") + self.connect("pressed", self, "onButton") + + +func onMySingalCallback(a, b): + print("a:" + a as String) + print("b:" + b as String) + +func onButton(): + emit_signal("mySignal", 1, 2) diff --git a/script/demo04_signal/signal.gd b/script/demo04_signal/signal.gd new file mode 100644 index 0000000..db5a351 --- /dev/null +++ b/script/demo04_signal/signal.gd @@ -0,0 +1,16 @@ +extends Node2D + + +# 第一种信号接受方法,通过在场景中配置信号的接收方法 +func _on_Button1_pressed(): + print("hello button1") + + + +# 第二种信号接受方法,通过代码控制信号的接受,更加的灵活,比较推荐方式 +func _ready(): + $Button2.connect("pressed", self, "onButton2") + +func onButton2(): + print("button2 pressed") + diff --git a/script/demo04_signal/thread.gd b/script/demo04_signal/thread.gd new file mode 100644 index 0000000..74092cb --- /dev/null +++ b/script/demo04_signal/thread.gd @@ -0,0 +1,29 @@ +extends Button + +func _ready(): + self.connect("pressed", self, "onButton2") + +func onButton2(): + var myThread = Thread.new() + + print("Create Thread Id: ", myThread) + print("Thread Active: ", myThread.is_active()) + + myThread.start(self, "threadTest", null, 0) + + print() + print("Thread Active: ", myThread.is_active()) + + var waitForThread = myThread.wait_to_finish() # wait for our thread to finish before moving on + + print() + print("Thread is Finished with result: ", waitForThread) + print("Thread Active: ", myThread.is_active()) + + + + +# 使用thread运行的函数必须有一个参数,要不然无法运行 +func threadTest(param): + print("thread test start") + return 999 diff --git a/script/demo04_signal/yield.gd b/script/demo04_signal/yield.gd new file mode 100644 index 0000000..360c896 --- /dev/null +++ b/script/demo04_signal/yield.gd @@ -0,0 +1,31 @@ +extends Button + + +func _ready(): + self.connect("pressed", self, "onButton") + + +# yield(obj, signal),函数立即返回,并且保存当前执行的位置和状态 +# yield返回GDScriptFunctionState类型对象,类似于Java的CompleteFuture +# resume恢复GDScriptFunctionState保存的调用函数状态 +func onButton(): + var yieldResult1 = doSomething1() + yieldResult1.resume() + + var yieldResult2 = doSomething2() + # 等待yieldResult2执行完毕 + yield(yieldResult2, "completed") + print("end") + + +func doSomething1(): + yield() + print("doSomething") + +func doSomething2(): + print(1) + yield(get_tree().create_timer(1), "timeout") + print(2) + yield(get_tree().create_timer(1), "timeout") + print(3) + yield(get_tree().create_timer(1), "timeout") diff --git a/util/ArrayUtils.gd b/util/ArrayUtils.gd new file mode 100644 index 0000000..2fd3cd7 --- /dev/null +++ b/util/ArrayUtils.gd @@ -0,0 +1,5 @@ +extends Object + + +static func isEmpty(array: Array) -> bool: + return array == null or array.size() == 0 diff --git a/util/StringUtils.gd b/util/StringUtils.gd new file mode 100644 index 0000000..a00e57c --- /dev/null +++ b/util/StringUtils.gd @@ -0,0 +1,29 @@ +extends Object + +const ArrayUtils = preload("res://util/ArrayUtils.gd") + +const EMPTY: String = "" +const EMPTY_JSON: String = "{}" + +# Checks if a String is empty ("") or null +static func isEmpty(s: String) -> bool: + return s == null or s.length() == 0 + + +# 检查是否为空的字符串 +static func isBlank(s: String) -> bool: + if isEmpty(s): + return true + + if isEmpty(s.strip_edges(true, true)): + return true + + return false + +# 格式化字符串 +static func format(template: String, args: Array) -> String: + if isEmpty(template) or ArrayUtils.isEmpty(args): + return template + + return template.format(args, EMPTY_JSON) +