From 8af43d446ec2afb9d5dbb4a978a976e682399a4d Mon Sep 17 00:00:00 2001 From: Wichamir <53086728+Wichamir@users.noreply.github.com> Date: Mon, 1 Nov 2021 22:12:55 +0100 Subject: [PATCH] [GDScript/en] Add GDScript (#4261) * [GDScript/en] Add GDScript * Added missing comment about Dictionary * Fixed mismatched types * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine * Update gdscript.html.markdown Co-authored-by: Andre Polykanine Co-authored-by: Andre Polykanine --- gdscript.html.markdown | 321 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 gdscript.html.markdown diff --git a/gdscript.html.markdown b/gdscript.html.markdown new file mode 100644 index 00000000..ed779c8a --- /dev/null +++ b/gdscript.html.markdown @@ -0,0 +1,321 @@ +--- +language: GDScript +contributors: + - ["Wichamir", "https://github.com/Wichamir/"] +filename: learngdscript.gd +--- + +GDScript is a dynamically typed scripting language made specifically for +free and open source game engine Godot. GDScript's syntax is similar to +Python's. Its main advantages are ease of use and tight integration with +the engine. It's a perfect fit for game development. + +## Basics + +```nim +# Single-line comments are written using hash symbol. +""" + Multi-line + comments + are + written + using + docstrings. +""" + +# Script file is a class in itself and you can optionally define a name for it. +class_name MyClass + +# Inheritance +extends Node2D + +# Member variables +var x = 8 # int +var y = 1.2 # float +var b = true # bool +var s = "Hello World!" # String +var a = [1, false, "brown fox"] # Array - similar to list in Python, + # it can hold different types + # of variables at once. +var d = { + "key" : "value", + 42 : true +} # Dictionary holds key-value pairs. +var p_arr = PoolStringArray(["Hi", "there", "!"]) # Pool arrays can + # only hold a certain type. + +# Built-in vector types: +var v2 = Vector2(1, 2) +var v3 = Vector3(1, 2, 3) + +# Constants +const ANSWER_TO_EVERYTHING = 42 +const BREAKFAST = "Spam and eggs!" + +# Enums +enum { ZERO, ONE , TWO, THREE } +enum NamedEnum { ONE = 1, TWO, THREE } + +# Exported variables are visible in the inspector. +export(int) var age +export(float) var height +export var person_name = "Bob" # Export type hints are unnecessary + # if you set a default value. + +# Functions +func foo(): + pass # pass keyword is a placeholder for future code + +func add(first, second): + return first + second + +# Printing values +func printing(): + print("GDScript ", "is ", " awesome.") + prints("These", "words", "are", "divided", "by", "spaces.") + printt("These", "words", "are", "divided", "by", "tabs.") + printraw("This gets printed to system console.") + +# Math +func doing_math(): + var first = 8 + var second = 4 + print(first + second) # 12 + print(first - second) # 4 + print(first * second) # 32 + print(first / second) # 2 + print(first % second) # 0 + # There are also +=, -=, *=, /=, %= etc., + # however no ++ or -- operators. + print(pow(first, 2)) # 64 + print(sqrt(second)) # 2 + printt(PI, TAU, INF, NAN) # built-in constants + +# Control flow +func control_flow(): + x = 8 + y = 2 # y was originally a float, + # but we can change it's type to int + # using the power of dynamic typing! + + if x < y: + print("x is smaller than y") + elif x > y: + print("x is bigger than y") + else: + print("x and y are equal") + + var a = true + var b = false + var c = false + if a and b or not c: # alternatively you can use &&, || and ! + print("This is true!") + + for i in range(20): # GDScript's range is similar to Python's + print(i) # so this will print numbers from 0 to 19 + + for i in ["two", 3, 1.0]: # iterating over an array + print(i) + + while x > y: + printt(x, y) + y += 1 + + x = 2 + y = 10 + while x < y: + x += 1 + if x == 6: + continue # 6 won't get printed because of continue statement + prints("x is equal to:", x) + if x == 7: + break # loop will break on 7, so 8, 9 and 10 won't get printed + + match x: + 1: + print("Match is similar to switch.") + 2: + print("However you don't need to put cases before each value.") + 3: + print("Furthermore each case breaks on default.") + break # ERROR! Break statement is unnecessary! + 4: + print("If you need fallthrough use continue.") + continue + _: + print("Underscore is a default case.") + + # ternary operator (one line if-else statement) + prints("x is", "positive" if x >= 0 else "negative") + +# Casting +func casting_examples(): + var i = 42 + var f = float(42) # cast using variables constructor + var b = i as bool # or using "as" keyword + +# Override functions +# By a convention built-in overridable functions start with an underscore, +# but in practice you can override virtually any function. + +# _init is called when object gets initialized +# This is the object's constructor. +func _init(): + # Initialize object's internal stuff here. + pass + +# _ready gets called when script's node and +# its children have entered the scene tree. +func _ready(): + pass + +# _process gets called on every frame. +func _process(delta): + # The delta argument passed to this function is a number of seconds, + # which passed between the last frame and the current one. + print("Delta time equals: ", delta) + +# _physics_process gets called on every physics frame. +# That means delta should be constant. +func _physics_process(delta): + # Simple movement using vector addition and multiplication. + var direction = Vector2(1, 0) # or Vector2.RIGHT + var speed = 100.0 + self.global_position += direction * speed * delta + # self refers to current class instance + +# When overriding you can call parent's function using the dot operator +# like here: +func get_children(): + # Do some additional things here. + var r = .get_children() # call parent's implementation + return r + +# Inner class +class InnerClass: + extends Object + + func hello(): + print("Hello from inner class!") + +func use_inner_class(): + var ic = InnerClass.new() + ic.hello() + ic.free() # use free for memory cleanup +``` + +## Accessing other nodes in the scene tree + +```nim +extends Node2D + +var sprite # This variable will hold the reference. + +# You can get references to other nodes in _ready. +func _ready() -> void: + # NodePath is useful for accessing nodes. + # Create NodePath by passing String to its constructor: + var path1 = NodePath("path/to/something") + # Or by using NodePath literal: + var path2 = @"path/to/something" + # NodePath examples: + var path3 = @"Sprite" # relative path, immediate child of the current node + var path4 = @"Timers/Firerate" # relative path, child of the child + var path5 = @".." # current node's parent + var path6 = @"../Enemy" # current node's sibling + var path7 = @"/root" # absolute path, equivalent to get_tree().get_root() + var path8 = @"/root/Main/Player/Sprite" # absolute path to Player's Sprite + var path9 = @"Timers/Firerate:wait_time" # accessing properties + var path10 = @"Player:position:x" # accessing subproperties + + # Finally, to get a reference use one of these: + sprite = get_node(@"Sprite") as Sprite # always cast to the type you expect + sprite = get_node("Sprite") as Sprite # here String gets + # implicitly casted to NodePath + sprite = get_node(path3) as Sprite + sprite = get_node_or_null("Sprite") as Sprite + sprite = $Sprite as Sprite + +func _process(delta): + # Now we can reuse the reference in other places. + prints("Sprite has global_position of", sprite.global_position) + +# Use onready keyword to assign a value to +# a variable just before _ready executes. +# This is a commonly used syntax sugar. +onready var tween = $Tween as Tween + +# You can export NodePath, so you can assign it within the inspector. +export var nodepath = @"" +onready var reference = get_node(nodepath) as Node +``` + +## Signals + +Signal system is Godot's implementation of the observer programming +pattern. Here's an example: + +```nim +class_name Player extends Node2D + +var hp = 10 + +signal died() # define signal +signal hurt(hp_old, hp_new) # signals can take arguments + +func apply_damage(dmg): + var hp_old = hp + hp -= dmg + emit_signal("hurt", hp_old, hp) # emit signal and pass arguments + if hp <= 0: + emit_signal("died") + +func _ready(): + # connect signal "died" to function "_on_death" defined in self + self.connect("died", self, "_on_death") + +func _on_death(): + self.queue_free() # destroy Player on death +``` + +## Type hints + +GDScript can optionally use static typing. +```nim +extends Node + +var x: int # define typed variable +var y: float = 4.2 +var z := 1.0 # infer type based on default value using := operator + +onready var node_ref_typed := $Child as Node + +export var speed := 50.0 + +const CONSTANT := "Typed constant." + +func _ready() -> void: + # function returns nothing + x = "string" # ERROR! Type can't be changed! + return + +func join(arg1: String, arg2: String) -> String: + # function takes two Strings and returns a String + return arg1 + arg2 + +func get_child_at(index: int) -> Node: + # function takes an int and returns a Node + return get_children()[index] + +signal example(arg: int) # ERROR! Signals can't take typed arguments! +``` + +## Further Reading + +* [Godot's Website](https://godotengine.org/) +* [Godot Docs](https://docs.godotengine.org/en/stable/) +* [Getting started with GDScript](https://docs.godotengine.org/en/stable/getting_started/scripting/gdscript/index.html) +* [NodePath](https://docs.godotengine.org/en/stable/classes/class_nodepath.html) +* [Signals](https://docs.godotengine.org/en/stable/getting_started/step_by_step/signals.html) +* [GDQuest](https://www.gdquest.com/) +* [GDScript.com](https://gdscript.com/) \ No newline at end of file