GDScript

File size
12.4KB
Lines of code
361

GDScript

Comments

# ---------- COMMENT ----------

# single-line comments

"""
multi-line comments
are written using
docstrings like 
this
"""

Quickstart

# ---------- QUICKSTART ----------
    # GDScript shares a lot of similarities syntax-wise with Python
    # file structure
    # inheritance
    # export

# every GDScript file is a class in itself
    # class_name defines a class for it explicitly

class_name MyClass

# extends specifies which node the GDScript file inherits behaviour from

extends Node2D

# export makes specified variables visible in the godot inspector
    # export variable data types are specified by convention
    # type hints are not required if a default value is set upon exporting

export(int) var age # type hints are required
export(float) var height
export var person_name = "Bob" # type specified since default value of "Bob" can be inferred to be a string upon exporting

Printing

# ---------- PRINT STATEMENT ----------
    # print() works by default as in Python, does not separate elements by anything
    # printraw() prints the specified message to stdout with no fancy reformatting
    # prints() prints elements and separates them by spaces
    # printt() prints elements and separates them by tabs

print("This works as ", "you'd expect in Python") # "This works as you'd expect in Python"
printraw("This also works") # "This also works"
prints("This", "adds", "spaces", "between", "elements") # "This adds spaces between elements"
printt("This", "adds", "tabs", "between", "elements") # "This adds tabs between elements"

Variables and Constants

# ---------- VARIABLE and CONSTANT ----------
    # var declares a variable
        # a variable's value can be changed after assignment
        # snake_case names by convention
    # const declares a constant
        # a constant's value cannot be changed after assignment
        # FULLY CAPITALISED names by convention

var a_variable:String = "i am a variable"
const BREAKFAST:String = "eggs and ham!"

Types

# ---------- TYPE ----------
    # static typing is optional but encouraged, can be achieved with :
    # := allows for type inference based on value provided at assignment
    # int
    # float
    # bool (0 is false, every other non-0 integer is true)
    # String (chars are also strings)
    # NodePath (NodePath() or @ specifies the nodepath literal to another node)
        # specified nodepath is a relative path unless otherwise stated
        # @"/root" specifies an absolute path from the project's root folder
        # : allows us to access a variable's properties and subproperties via nodepath
    # null (absence of a value)
        # it has no data type specified for it since it represents the absence of a value, and is a special unique value

var x:int = 8
var y:float = 1.2
var b:bool = true # can also be false
var s:String = "hello world!"
var c:String = "a" # this is also a string
var relative_nodepath:NodePath = @"this is a nodepath literal" # note that this denotes the relative path
var absolute_nodepath:NodePath = @"/root/Main/Player/Sprite" # absolute path to the player's sprite
var firerate_properties:NodePath = @"Timers/Firerate:wait_time" # accessing properties
var player_position_subproperties:NodePath = @"Player:position:x" # accessing subproperties
var i_am_null = null # note there is no static typing since null is a special value by itself with no inherent data type

# TYPE CASTING
    # type casting refers to explicit type conversion
    # variables constructor (similar to Python)

var an_int_to_a_float = float(200) # 200 type casted to 200.0 through variable constructor syntax
var an_int_to_a_bool = bool(42) # 42 type casted to a true through variable constructor syntax

Data structures

# ---------- DATA STRUCTURE ----------
    # array (dynamic list that can store variables of multiple types, similar to Python lists)
    # pool array (list that can only store variables of one type, more memory-efficient than an array)
        # declared with PoolStringArray() syntax
    # vector (dynamic list that can also store variables of multiple types similar to arrays, though arrays offer more functionality)
        # Vector2() specifies a 2D-vector
        # Vector3() specifies a 3D-vector
        # commonly used to represent positions of game entities on a 2D or 3D plane
    # dictionary (hash map that stores key-value pairs, similar to dictionaries in Python or tables in Lua)

var an_array = [1, false, "i can hold values of multiple types"]
var a_pool_array = PoolStringArray(["Hello", "there", "brother", "in", "Christ"])
var a_2d_vector = Vector2(1,2)
var a_3d_vector = Vector3(1,2,3)
var a_dictionary = {
    "key":"value",
    42: true,
    "i work how you'd expect as well": 4
}

Functions

# ---------- FUNCTION ----------
    # func declares a function block
    # pass
    # return
    # functions can benefit from static typing too for argument and return values

func foo() -> void: # void functions return nothing
    pass # works the same as in Python

func add(first:int, second:int) -> int:
    return first + second

Operators

# ---------- OPERATOR ----------

# ARITHMETIC OPERATOR

    # + for addition
    # - for subtraction
    # * for multiplication
    # / for division
    # % for modulo
    # += for increment
    # -= for decrement
    # *= for multiplication and reassignment
    # /= for division and reassignment
    # %= for modulo and reassignment
    # pow() for exponentiation
    # sqrt() for squareroot of a value

var first = 8
var second = 4
first + second # evaluates to 12
first - second # evaluates to 4
first * second # evaluates to 32
first / second # evaluates to 2
first % second # evaluates to 0
first += first # evaluates to 16
first -= first # evaluates to 0
first *= first # evaluates to 64
first /= first # evaluates to 1
first %= first # evaluates to 0
pow(first, 2) # evaluates to 64
sqrt(second) # evaluats to 2

# LOGICAL OPERATOR
    # and
    # or
    # not

true and false or not false # evaluates to true

Control structures

# ---------- CONTROL FLOW ----------
    # if elif else
    # for loop
    # while loop
        # continue
        # break
    # match case statement

# CONDITIONAL CHECK

x = 8
y = 2
if x < y:
    print("x is smaller than y")
elif x > y:
    print("x is bigger than y")
else:
    print("x is equals to y")

## LOOP

for el in ["two", 3, 1.0]:
    print(el)

x = 2
y = 10
while x < y:
    x += 1

## MATCH CASE
    # syntax similar to Rust's pattern matching
    # break statements are unnecessary after each case, continue is used to fallthrough to the next case
    # _ for default case

match x:
    1: 
        print("x is equals to 1")
    2: 
        print("x is equals to 2")
    3:
        print("x is equals to 3")
    _: 
        print("this is the default case")

Useful tips

# ---------- TIP ----------
    # range() exists and operates similarly as in Python
        # you can also iterate over a number directly as an implicit range

for i in range(20): # this is valid, printing 0 to 19
    print(i)

for q in 20: # this does the exact same thing as the range() above, printing 0 to 19
    print(q)

OOP

# ---------- OBJECT ORIENTED PROGRAMMING ----------
    # override
    # self specifies the variable is an object attribute unique to the specific object
    # extends allows for a child class to inherit a parent class' attributes and methods
    # .new() instantiates a new instance object off the class
    # func _init()
    # func _ready()
    # func _process(delta)
    # func _physics_process(delta)
    # signal system

# OVERRIDE 
    # built-in overridable functions are specified by starting with _ an underscore by convention
    # technically any function is overridable

# IMPORTANT FUNCTIONS

func _init(): # object constructor, specifies contents to be called when object is instantiated, similar to Python
    pass

func _ready(): # called when script's node and children nodes have entered scene tree
    pass

func _process(delta); # function called every single frame, delta is the number of seconds passed between the last frame and the current one, similar to love.update(dt) in Lua
    print("dt equals:", delta)

func _physics_process(delta): # function called on every physics frame, delta should be constant
    var direction = Vector2(1,0)
    var speed = 100.0
    self.global_position += direction * speed * delta

# SIGNAL
    # the signal system is godot's equivalent of the observer programming pattern
    # signal defines a signal with its name, () included in case of arguments to be accepted
    # emit_signal() used to call the specified signal with its arguments
    # .connect() connects a signal to a function 

class_name Player extends Node2D

var hp = 10

signal died() # defines the signal died with 0 arguments
signal hurt(hp_old, hp_new) # defines the signal died with 2 arguments

func apply_damage(dmg):
    var hp_old = hp
    hp -= dmg
    emit_signal("hurt", hp_old, hp) # emits the predefined signal with its arguments
    if hp <= 0:
        emit_signal("died") # emits the predefined signal

function _ready():
    self.connect("died"), self, "_on_death")

function _on_death(): # signal died() is called when the _on_death() function occurs
    self.queue_free() # destroys player on death by removing them from the queue

More on

  • as
  • enum
  • ternary operator
  • . dot operator to call parent function's implementation of an overriden function
  • onready
  • $
  • .free()
  • .queue_free()
  • GDScript docs
  • Godot docs