Setup

To get started, install the gdscript Haxelib package and add it to a Haxe project.

#What to doWhat to write
1Install via haxelib
haxelib install gdscript 1.0.0-beta
2Add the lib to your .hxml file or compile command.
-lib gdscript
3Set the output folder for the compiled GDScript.
-D gdscript-output=out
4Optionally, generate your code as a Godot plugin.
-D generate_godot_plugin

Adding First Class

Let's go ahead and make a class in Haxe to compile into GDScript!

// MyClass.hx
package;

class MyClass {
	public function new(myNumber: Int) {
		trace('Received number: $myNumber');
	}
}
# Compile.hxml
-p src
-lib gdscript
-D gdscript-output=out

WAIT! There's no main function? Godot doesn't use a main, it just takes GDScript files created by the user. But because of Haxe's DCE, our MyClass class won't be compiled.

Choosing What to Compile

Since GDScript does not rely on a main function, you need to tell Haxe what files it needs to compile for your project. This can be done by listing modules in your .hxml file.

// MyClass.hx
package;

class MyClass {
	public function new(myNumber: Int) {
		trace('Received number: $myNumber');
	}
}
# Compile.hxml
-p src
-lib gdscript
-D gdscript-output=out

MyClass

Just Compile Everything!

This could get annoying when adding new files, so instead you can also place all of your "to-be-compiled" classes in a package and write that.

// game/MyClass.hx
package game;

class MyClass {
	public function new(myNumber: Int) {
		trace('Received number: $myNumber');
	}
}
# Compile.hxml
-p src
-lib gdscript
-D gdscript-output=out

game # Every class in `game` will now be compiled

Output

Aaaand now you should receive some output like this:

class_name MyClass;

func _init(myNumber: int):
	print("game/MyClass.hx:6: Received number: " + myNumber);

Godot API

Okay!! Now let's make a custom Node! ... oh wait, there's no Node2D or Node3D class to extend from?

As the Godot API can change depending on the version, no specific API is packaged with Reflaxe/GDScript. Instead, you need to generate your own Haxe bindings for Godot.

Generating the Bindings

First, install the Haxe Godot Bindings Generator library:

haxelib git godot-api-generator https://github.com/SomeRanDev/Haxe-GodotBindingsGenerator

Next, enter your Haxe source code folder:

cd src

Finally, run this command to generate:

haxelib run godot-api-generator

This will generate all the Godot bindings as .hx Haxe source code files in a local folder named "godot". The files are generated with the expectation they will be in a godot package, so this should be perfect.

Godot Executable Configuration

When you run the command, you will be asked for the path to your Godot engine executable, so be sure to find it first! If you do not want to enter it manually, you can assign it to the GODOT_PATH environment variable before running the command.

Extending from a Node

You can now extend from Node like this:

class MyNode extends godot.Node {
	public override function _ready() {
		trace("MyNode is ready!");
	}
}

Easy Access

If you'd like easy access to all of the Godot API, just import godot.*.

import godot.*;

class MyNode extends Node {
	public override function _ready() {
		trace("MyNode is ready!");
	}
}

First Node

Here's the basic outline for an extended Node in Haxe with Reflaxe/GDScript:

import godot.*;

class MyNode extends Node {
	public override function _ready() {
		// on ready...
	}

	public override function _process(delta: Float) {
		// on update...
	}
}

You can override any functions marked "virtual" in Godot's documentation like this:

import godot.*;

class MyNode extends Node {
	public override function _input(event: InputEvent) {
		// on ready...
	}

	public override function _physics_process(delta: Float) {
		// on physics update...
	}
}

Exporting Properties

@:export can be used like the @export metadata from GDScript:

class MyNode extends godot.Node {
	@:export
	var customNumber: Int = 20;
}

This would be converted to:

extends Node;
class_name MyNode;

@export
var customNumber: int = 20;

On Ready

@:onready can be used like the @on_ready metadata from GDScript:

class MyNode extends godot.Node {
	@:onready
	var customNumber: Int = 20;
}

This would be converted to:

extends Node;
class_name MyNode;

@onready
var customNumber: int = 20;

Loading Nodes

@:onready has a helper feature that can be used to load nodes from a path. Simply pass a String assignment to node:

class MyNode extends godot.Node {
	@:onready(node = "Label")
	var label: Label;
}

This would be converted to:

extends Node;
class_name MyNode;

@onready
var label: Label = $Label;

Signals

A signal can be added using the @:signal metadata:

import godot.*;

class MyNode extends CharacterBody2D {
	// Any code in this function will be ignored
	@:signal
	function onHitGround(speed: Float) {}
}

The emit_signal function from the generated API only supports a String parameter, but you can use emit_signal from the Reflaxe/GDScript API class: gdscript.ObjectEx.

import godot.*;
import gdscript.ObjectEx;

class MyNode extends CharacterBody2D {
	@:signal
	function onHitGround(speed: Float) {}

	public override function _physics_process(delta: Float) {
		var hitGround = false;

		// Do some processing...

		if(hitGround) {
			ObjectEx.emit_signal("onHitGround", velocity.length());
		}
	}
}

Constant Preloads

@:const creates a const variable in GDScript.

class MyNode extends godot.Node {
	@:const
	final MAX_JUMPS = 4;
}

This would be converted to:

extends Node;
class_name MyNode;

const MAX_JUMPS: int = 4;

Preloading Resources

A common pattern in GDScript is to preload resources into a const variable. The @:const metadata provides a helper feature to achieve this:

class MyNode extends godot.Node {
	@:const(preload = "res://scenes/bullet.tscn")
	final BULLET_SCENE: PackedScene;
}

This would be converted to:

extends Node;
class_name MyNode;

const BULLET_SCENE: PackedScene = preload("res://scenes/bullet.tscn");