Binary Tree in Godot

An extension to the L-System adding a stack so that we can push, and pop, the current state. This is typically denoted with a [ and ].

Binary Tree L-System

Binary Tree L-System

This is a simple as adding a stack array which we push a copy of the current position and angle into, and pop (copy the last of the stack over our current one and delete it) when we encounter those rules.

However, since we're starting to get a little complicated I decided to create a dictionary of commands so I can sub in alternatives when an L-System calls for slightly different behaviours for the same command.

var commands = {}

func _init():
    commands["F"] = func draw_forward_command(current: LNode, stack: Array):
        draw_forward(current, stack)
    commands["A"] = func draw_forward_command(current: LNode, stack: Array):
        draw_forward(current, stack)
    commands["B"] = func draw_forward_command(current: LNode, stack: Array):
        draw_forward(current, stack)
    commands["0"] = func draw_forward_command(current: LNode, stack: Array):
        draw_forward(current, stack)
    commands["1"] = func draw_forward_command(current: LNode, stack: Array):
        draw_forward(current, stack)
    commands["+"] = func rotate_left(current: LNode, stack: Array):
        current.angle -= angle_step
    commands["-"] = func rotate_right(current: LNode, stack: Array):
        current.angle += angle_step
    commands["["] = func push(current: LNode, stack: Array):
        stack.push_back(LNode.new(current.angle, current.position))
        current.angle += angle_step
    commands["]"] = func pop(current: LNode, stack: Array):
        var c = stack[-1]
        current.angle = c.angle
        current.position = c.position
        stack.remove_at(stack.size() - 1)
        current.angle -= angle_step

And the _draw() function is updated to:

func _draw():
    var start_x = (get_window().size.x / 2) * (1 / scale.x)
    var start_y = (get_window().size.y) * (1 / scale.y)
    var position = Vector2(start_x, start_y)
    var angle = 0
    var current = LNode.new(angle, position)
    var stack = []

    for command in axiom:
        commands.get(command, ignore).call(current, stack)

The axiom is set to 0 and the rules are:

0 → 1[+0]-0
1 → 11

The angle change is set to 45 degrees.